/* ============================================================================
   COMS — Centro de Otorrinolaringología y Medicina del Sueño
   Sistema de diseño
   Paleta: noche #222B4E · índigo #4059C9 · luna #8FA0EE · fondo #F5F6FA
           menta #0FA98D · ámbar #DE9B2D · rojo #D64550 · tinta #262B39
   ============================================================================ */

/* ---------------------------------------------------------------------------
   Tipografía Manrope, servida DESDE ACÁ y no desde fonts.googleapis.com.

   Por qué: la hoja de estilo de Google era el único recurso externo del sitio
   y se cargaba bloqueando el dibujado — si Google tardaba en responder (red
   móvil lenta, DNS, un ISP con el día raro), el navegador no pintaba nada y la
   página parecía trabada unos segundos. Ahora la fuente viaja con el sitio: no
   hay pedido a terceros, no hay handshake extra a fonts.gstatic.com, y de paso
   queda listo para poner la CSP que quedó pendiente.

   Manrope es una fuente VARIABLE: un solo archivo cubre los pesos 500 a 800,
   por eso hay una sola declaración con el rango y no cuatro. Se bajaron solo
   los subconjuntos latin y latin-ext (40 KB entre los dos); cirílico, griego y
   vietnamita no se usan en un sitio en español.

   font-display: swap → si la fuente demorara, el texto se ve igual con la
   tipografía del sistema y cambia al llegar. Nunca deja la pantalla en blanco.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 500 800;
  font-display: swap;
  src: url('/assets/fonts/manrope-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 500 800;
  font-display: swap;
  src: url('/assets/fonts/manrope-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --noche: #222B4E;
  --noche-2: #2C3763;
  --noche-3: #1A2140;
  --indigo: #4059C9;
  --indigo-osc: #3348A8;
  --luna: #8FA0EE;
  --fondo: #F5F6FA;
  --blanco: #FFFFFF;
  --tinta: #262B39;
  --tinta-2: #5A6172;
  --tinta-3: #9AA1B2;
  --linea: #E4E7EF;
  --menta: #0FA98D;
  --menta-suave: #E2F6F1;
  --ambar: #DE9B2D;
  --ambar-suave: #FBF2DF;
  --rojo: #D64550;
  --rojo-suave: #FBE9EA;
  --azul-suave: #E8ECFB;
  /* La paleta de los graficos del panel. Highcharts la lee de aca (ver
     assets/js/dashboard.js), asi el mismo archivo sirve a las dos
     instalaciones y cada una pinta con su marca. El orden es el de las series:
     los tres primeros son los que mas se ven. */
  --grafico-1: #4059C9;
  --grafico-2: #0FA98D;
  --grafico-3: #8FA0EE;
  --grafico-4: #DE9B2D;
  --grafico-5: #D64550;
  --grafico-6: #222B4E;
  --grafico-7: #6BC5B2;
  --grafico-8: #B58AD6;
  --grafico-9: #5A6172;
  --grafico-10: #E4A0A6;
  --grilla: #EEF0F5;
  --radio: 14px;
  --radio-s: 9px;
  --sombra: 0 1px 2px rgba(34, 43, 78, .06), 0 8px 24px rgba(34, 43, 78, .07);
  --sombra-flotante: 0 12px 40px rgba(26, 33, 64, .22);
  /* La curva de easing de iOS: arranca rápido y asienta suave. La usa el
     portal para que todo el movimiento sea de una sola familia. */
  --curva: cubic-bezier(.22, 1, .36, 1);
  --fuente: 'Manrope', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--fuente);
  font-size: 15px;
  line-height: 1.55;
  color: var(--tinta);
  background: var(--fondo);
}
h1, h2, h3, h4 { margin: 0 0 .4em; font-weight: 800; letter-spacing: -.015em; }
h1 { font-size: 26px; }
h2 { font-size: 20px; }
h3 { font-size: 16px; }
p { margin: 0 0 1em; }
a { color: var(--indigo); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 3px solid var(--luna); outline-offset: 2px; border-radius: 4px; }

/* ---------------------------------------------------------------- Layout */
.app { display: flex; min-height: 100vh; }

/* Barra lateral: cielo nocturno (firma visual del centro).
   SIN estrellitas: los puntos de 1px sobre fondo oscuro se leen como píxeles
   muertos (regla de Santino, misma que en el hero del portal) — la
   profundidad la dan los resplandores radiales grandes. */
.sidebar {
  width: 236px;
  flex-shrink: 0;
  background:
    radial-gradient(420px 260px at 85% -6%, rgba(143, 160, 238, .22), transparent 70%),
    radial-gradient(360px 240px at -12% 26%, rgba(64, 89, 201, .25), transparent 72%),
    linear-gradient(178deg, var(--noche-3) 0%, var(--noche) 42%, var(--noche-2) 100%);
  color: #C7CEE6;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
}
.marca {
  padding: 22px 20px 18px;
  display: flex;
  align-items: center;
  gap: 12px;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.logo-coms {
  width: 42px; height: 42px; flex-shrink: 0;
  border-radius: 10px;
  object-fit: contain;
}
.marca strong { display: block; color: #fff; font-size: 16px; line-height: 1.25; letter-spacing: .04em; }
.marca span  { display: block; font-size: 11.5px; color: #97A2CC; }

.nav-panel { padding: 14px 12px; flex: 1; }
.nav-panel .seccion { font-size: 10.5px; text-transform: uppercase; letter-spacing: .14em; color: #7683B3; margin: 16px 10px 6px; }
.nav-panel a {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; margin-bottom: 2px;
  color: #C7CEE6; border-radius: 10px; font-weight: 600; font-size: 14px;
  transition: background .15s, color .15s;
}
.nav-panel a:hover { background: rgba(255,255,255,.07); color: #fff; text-decoration: none; }
.nav-panel a.activo { background: var(--indigo); color: #fff; }
.nav-panel a .fa { width: 18px; text-align: center; font-size: 15px; opacity: .9; }
.sidebar .pie {
  padding: 14px 20px; font-size: 12.5px; color: #7683B3;
  border-top: 1px solid rgba(255,255,255,.08);
}
.sidebar .pie a { color: #AEB9E2; }
/* ------------------------------------------- El pie del menú (cambiar de panel) */
/* Los accesos del pie eran <a> sueltos dentro de un div: en el celular salían
   TODOS PEGADOS en un renglón corrido —"COMS IES Myrna Odontología Ver el sitio
   público"— sin separación y sin dónde apretar. Ahora es una lista: una fila por
   panel, con su blanco de toque, y el que estás mirando marcado con un tilde.
   Los colores van en blanco con transparencia y no en el lila de COMS: este pie
   también se dibuja sobre el bordó de Myrna. */
.sidebar .pie {
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 10px calc(12px + env(safe-area-inset-bottom, 0px));
}
.sidebar .pie .subtexto {
  margin: 2px 6px 6px;
  font-size: 10.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .12em;
  color: rgba(255, 255, 255, .45);
}
.sidebar .pie a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 9px;
  color: rgba(255, 255, 255, .74);
  font-size: 13.5px; font-weight: 600; line-height: 1.25;
  transition: background .15s, color .15s;
}
.sidebar .pie a:hover { background: rgba(255, 255, 255, .09); color: #fff; text-decoration: none; }
.sidebar .pie a .fa { width: 16px; flex-shrink: 0; text-align: center; opacity: .85; }
/* El panel que estás mirando: no se puede confundir con los otros dos. */
.sidebar .pie a.activo { background: rgba(255, 255, 255, .13); color: #fff; }
.sidebar .pie a.activo::after {
  content: '✓'; margin-left: auto; font-size: 12px; opacity: .75;
}
/* "Ir a Helsek" y "Ver el sitio público" son otra cosa que cambiar de
   consultorio o de punto de vista: los dos salen del panel. Van separados por
   una línea, pero UNA sola — de ahí la segunda regla, que le saca el borde al
   de abajo cuando los dos están (el de Helsek sólo lo ve el admin global). */
.sidebar .pie .pie-helsek,
.sidebar .pie .pie-sitio {
  margin-top: 8px; padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, .1);
}
.sidebar .pie .pie-helsek + .pie-sitio {
  margin-top: 0; padding-top: 9px; border-top: 0;
}


.principal { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  background: var(--blanco);
  border-bottom: 1px solid var(--linea);
  padding: 0 28px;
  height: 62px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  position: sticky; top: 0; z-index: 40;
}
/* El bloque de la izquierda de la barra: el botón del menú y el título en
   línea. Venía como estilo suelto en el layout; vive acá desde la tanda 79.
   ⚠️ SIN esta regla el título se cae FUERA de la barra blanca, en celular y en
   escritorio: el layout ya no trae el `style="display:flex"` que lo sostenía. */
.topbar-izq { display: flex; align-items: center; gap: 12px; min-width: 0; }
.topbar .titulo-pagina { font-size: 17px; font-weight: 800; }
.topbar .usuario { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--tinta-2); }
.topbar .usuario .avatar {
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--azul-suave); color: var(--indigo);
  display: flex; align-items: center; justify-content: center; font-weight: 800;
}

.contenido { padding: 26px 28px 60px; max-width: 1280px; width: 100%; margin: 0 auto; }

/* --------------------------------------------------------------- Tarjetas */
.tarjeta {
  background: var(--blanco);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  padding: 22px;
  margin-bottom: 22px;
}
.tarjeta .encabezado {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 16px; flex-wrap: wrap;
}
.tarjeta .encabezado h2 { margin: 0; }
.subtexto { color: var(--tinta-2); font-size: 13.5px; }

.grilla { display: grid; gap: 22px; }
.grilla-2 { grid-template-columns: 1fr 1fr; }
.grilla-3 { grid-template-columns: repeat(3, 1fr); }
.grilla-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1100px) { .grilla-4 { grid-template-columns: 1fr 1fr; } .grilla-3 { grid-template-columns: 1fr; } }
@media (max-width: 760px)  { .grilla-2, .grilla-4 { grid-template-columns: 1fr; } }

/* KPIs */
.kpi { padding: 18px 20px; }
.kpi .valor { font-size: 30px; font-weight: 800; letter-spacing: -.02em; line-height: 1.1; }
.kpi .etiqueta { font-size: 13px; color: var(--tinta-2); margin-top: 2px; }
.kpi .icono {
  float: right; width: 42px; height: 42px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center; font-size: 18px;
}
.kpi .icono.indigo { background: var(--azul-suave); color: var(--indigo); }
.kpi .icono.menta  { background: var(--menta-suave); color: var(--menta); }
.kpi .icono.ambar  { background: var(--ambar-suave); color: var(--ambar); }
.kpi .icono.rojo   { background: var(--rojo-suave); color: var(--rojo); }

/* ---------------------------------------------------------------- Botones */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--fuente); font-weight: 700; font-size: 14px;
  padding: 9px 16px; border-radius: 10px; border: 1px solid transparent;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, transform .12s ease-out;
  text-decoration: none !important; line-height: 1.3; background: none;
}
/* El apretón: el botón cede mientras el dedo está abajo. El PORTAL lo tiene desde la tanda 64
   (`.portal-body .btn:active`) y el panel no, que es donde se aprietan botones todo el día —
   guardar una consulta, tildar un turno, subir un adjunto. Se sube acá para que valga en los
   dos y la regla del portal quede redundante pero inofensiva.
   Va sobre `transform`, que el compositor resuelve sin repintar: no cuesta nada en el listado
   de pacientes. El bloque `prefers-reduced-motion: reduce` de más abajo ya lo apaga solo. */
.btn:active { transform: scale(.97); }
.btn[disabled]:active { transform: none; }
.btn-primario { background: var(--indigo); color: #fff; }
.btn-primario:hover { background: var(--indigo-osc); color: #fff; }
.btn-secundario { background: var(--blanco); color: var(--tinta); border-color: var(--linea); }
.btn-secundario:hover { border-color: var(--tinta-3); }
.btn-peligro { background: var(--rojo-suave); color: var(--rojo); }
.btn-peligro:hover { background: #F6D7D9; }
.btn-menta { background: var(--menta); color: #fff; }
.btn-menta:hover { background: #0C8A73; color: #fff; }
.btn-chico { padding: 5px 11px; font-size: 13px; border-radius: 8px; }
.btn[disabled] { opacity: .55; cursor: not-allowed; }

/* ------------------------------------------------------------ Formularios */
.campo { margin-bottom: 15px; }
.campo label { display: block; font-weight: 700; font-size: 13px; margin-bottom: 5px; color: var(--tinta); }
.campo .ayuda { font-size: 12.5px; color: var(--tinta-3); margin-top: 4px; }
.campo input[type=text], .campo input[type=email], .campo input[type=date],
.campo input[type=time], .campo input[type=number], .campo input[type=password],
.campo input[type=tel], .campo select, .campo textarea {
  width: 100%;
  font-family: var(--fuente); font-size: 14.5px; color: var(--tinta);
  background: var(--blanco);
  border: 1.5px solid var(--linea); border-radius: var(--radio-s);
  padding: 9px 12px;
  transition: border-color .15s, box-shadow .15s;
}
/* ⚠️ El `outline: none` de acá es lo que obliga al anillo. Sin él, el `:focus-visible` global
   del principio de esta hoja queda pisado por esta regla —más específica— y lo único que marca
   el campo activo es un borde de 1,5 px azul contra uno gris: en una historia clínica de 40
   campos, tabulando, no se ve dónde estás parado. El anillo va en `box-shadow` y no en
   `outline` porque así sigue el radio redondeado del campo en vez de dibujar un rectángulo. */
.campo input:focus, .campo select:focus, .campo textarea:focus {
  border-color: var(--indigo); outline: none;
  box-shadow: 0 0 0 3px var(--azul-suave);
}
.campo textarea { min-height: 96px; resize: vertical; }
.fila-campos { display: grid; gap: 0 16px; grid-template-columns: 1fr 1fr; }
.fila-campos-3 { display: grid; gap: 0 16px; grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 700px) { .fila-campos, .fila-campos-3 { grid-template-columns: 1fr; } }

/* Fila de "acepto los términos y condiciones": un cuadradito al lado de un
   párrafo largo. La usan las tres pantallas del portal (turno, estudios y
   cuestionario).

   El `flex: 0 0 auto` del checkbox NO es cosmético: sin él, el navegador del
   iPhone achica el cuadradito hasta hacerlo desaparecer —no respeta el tamaño
   mínimo de un control de formulario cuando compite por lugar con un texto
   largo dentro de un flex—, y el paciente ve el texto pero no tiene qué tocar.
   En la computadora sobra el ancho y por eso no se notaba. */
.campo-consentimiento { display: flex; gap: 10px; align-items: flex-start; }
.campo-consentimiento input[type=checkbox] {
  flex: 0 0 auto;
  width: 20px; height: 20px; margin: 1px 0 0;
  accent-color: var(--indigo);
}
.campo-consentimiento label { font-weight: 400; font-size: 13.5px; line-height: 1.5; }
@media (max-width: 700px) {
  /* Superficie de dedo: un checkbox nativo es de ~13 px y en el celular se le
     erra. */
  .campo-consentimiento input[type=checkbox] { width: 24px; height: 24px; }
  .campo-consentimiento label { font-size: 14px; }
}

/* ----------------------------------------- Evaluación clínica (HC pestañas) */
.fs-consulta {
  border: 1px solid var(--linea); border-radius: 12px;
  padding: 14px 16px 6px; margin: 0 0 16px;
}
.fs-consulta legend {
  font-size: 12.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--indigo); padding: 0 8px;
}
.fs-consulta .sub-titulo {
  font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--tinta-3); margin: 8px 0 6px;
}
.grilla-sintomas { display: grid; gap: 8px 16px; grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .grilla-sintomas { grid-template-columns: 1fr; } }
.sintoma-item { display: grid; grid-template-columns: 1.3fr auto 1.4fr auto; gap: 6px; align-items: center; }
.sintoma-item .sintoma-label { font-size: 13px; }
.sintoma-item select, .sintoma-item input { padding: 5px 8px; font-size: 13px; }
.sintoma-item input { min-width: 0; }
/* Evaluación miofuncional (fonoaudiología, 085). Son ~55 ítems de "etiqueta +
   una opción de una lista corta": la grilla de síntomas de la evaluación
   clínica no sirve tal cual porque sus 4 columnas dejan el select aplastado
   contra la etiqueta. Dos columnas de ítems, cada ítem con su label arriba del
   control en el celular. */
.grilla-fono { display: grid; gap: 8px 18px; grid-template-columns: 1fr 1fr; align-items: start; }
.fono-item { display: grid; grid-template-columns: 1fr auto; gap: 8px; align-items: center; min-width: 0; }
.fono-item .fono-label { font-size: 13px; }
.fono-item select { padding: 5px 8px; font-size: 13px; max-width: 220px; }
/* Los campos de texto y las casillas múltiples ocupan el ancho entero: son las
   líneas largas del papel (piezas ausentes, Godin) y las listas de opciones. */
.grilla-fono .campo { margin: 0; }
.grilla-fono .campo-ancho { grid-column: 1 / -1; }
.grilla-fono .grilla-check { margin-bottom: 0; }
/* Las medidas (093): índice de Marchesan en % y fuerza lingual en kPa. Cada
   una en su renglón, una debajo de la otra, con el recuadro chico y la unidad
   pegada a la etiqueta — a lo ancho de la fila quedaría lejísimos. */
.grilla-fono .fono-numero { grid-column: 1 / -1; grid-template-columns: max-content auto; justify-content: start; gap: 12px; }
.fono-numero-control { display: inline-flex; align-items: center; gap: 6px; }
.fono-numero-control input {
  width: 96px; padding: 5px 8px; font-family: var(--fuente); font-size: 13px; text-align: right;
  color: var(--tinta); background: var(--blanco);
  border: 1.5px solid var(--linea); border-radius: var(--radio-s);
}
.fono-numero-control input:focus { border-color: var(--indigo); }
.fono-unidad { font-size: 13px; font-weight: 700; color: var(--tinta-2); }
@media (max-width: 900px) {
  .grilla-fono { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .fono-item {
    grid-template-columns: 1fr;
    gap: 4px;
    padding: 8px 0;
    border-bottom: 1px dashed var(--linea);
  }
  .fono-item .fono-label { font-weight: 700; }
  .fono-item select { max-width: none; width: 100%; font-size: 15px; padding: 8px; }
  .grilla-fono .fono-numero { grid-template-columns: 1fr; gap: 4px; }
  .fono-numero-control input { width: 120px; font-size: 15px; padding: 8px; }
}
.grilla-check { display: grid; gap: 6px 16px; grid-template-columns: 1fr 1fr 1fr; margin-bottom: 10px; }
@media (max-width: 900px) { .grilla-check { grid-template-columns: 1fr 1fr; } }
.check-item { display: flex; align-items: center; gap: 6px; font-size: 13px; }
.check-item input { width: auto; }

/* ------------------------------------------------------------------ Tabla */
.tabla-envoltura { overflow-x: auto; }
table.tabla { width: 100%; border-collapse: collapse; font-size: 14px; }
.tabla th {
  text-align: left; font-size: 11.5px; text-transform: uppercase; letter-spacing: .09em;
  color: var(--tinta-3); font-weight: 800;
  padding: 10px 12px; border-bottom: 1.5px solid var(--linea); white-space: nowrap;
}
.tabla td { padding: 12px; border-bottom: 1px solid var(--linea); vertical-align: middle; }
.tabla tbody tr { transition: background .12s; }
.tabla tbody tr:hover { background: #FAFBFE; }
/* Fichas de fonoaudiología (su pestaña y la Historia completa): dos columnas,
   etiqueta y valor. En el celular las etiquetas largas en mayúscula (nowrap)
   empujaban el valor fuera de la pantalla: se apilan, etiqueta arriba. */
@media (max-width: 700px) {
  .tabla-fono th, .tabla-fono td { display: block; width: auto !important; white-space: normal; }
  .tabla-fono th { padding: 10px 0 2px; border-bottom: 0; }
  .tabla-fono td { padding: 0 0 10px; }
}
.tabla .sin-datos { text-align: center; color: var(--tinta-3); padding: 34px 12px; }

/* ------------------------------------------------------------------ Pills */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 800; padding: 3px 10px; border-radius: 999px;
  white-space: nowrap;
}
.pill::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.pill-menta { background: var(--menta-suave); color: var(--menta); }
.pill-ambar { background: var(--ambar-suave); color: #A87516; }
.pill-rojo  { background: var(--rojo-suave); color: var(--rojo); }
.pill-indigo{ background: var(--azul-suave); color: var(--indigo); }
.pill-gris  { background: #EEF0F5; color: var(--tinta-2); }
.pill-violeta { background: #ECE7FB; color: #6A44D6; }

/* CPAP en uso: pulso de "respiración" */
.pill-respira::before { animation: respirar 3.4s ease-in-out infinite; }
@keyframes respirar {
  0%, 100% { transform: scale(.75); opacity: .55; }
  50%      { transform: scale(1.25); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .pill-respira::before { animation: none; }
  /* Este barrido apaga todo lo que no decidio nada por su cuenta. Lo que SI
     decide —hoy el emblema del hero— queda EXENTO y resuelve su propio bloque
     `reduce` mas abajo.

     ⚠️ Sin esa excepcion, este `*` con !important le gana a cualquier regla
     por especifica que sea, y no apaga la animacion: la hace correr .01ms una
     sola vez. O sea deja el dibujo **clavado en su ultimo frame**, que se ve
     como un adorno roto, no como un adorno quieto. Costo una ronda entera de
     la tanda 78, con la escena del oso congelada en produccion.

     Al agregar una animacion que deba sobrevivir a "menos movimiento", hay que
     sumar su raiz a este :not() Y probarla con la preferencia activada contra
     ESTE archivo completo, no contra la animacion sola. */
  *:not(.hero-escena, .hero-escena *, .fondo-lineas, .fondo-lineas *) {
    transition: none !important;
    animation-duration: .01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
  }
}

/* ------------------------------------------------------------------ Tabs */
.tabs { display: flex; gap: 4px; border-bottom: 1.5px solid var(--linea); margin-bottom: 20px; flex-wrap: wrap; }
.tabs a {
  padding: 9px 16px; font-weight: 700; font-size: 14px; color: var(--tinta-2);
  border-bottom: 2.5px solid transparent; margin-bottom: -1.5px;
}
.tabs a:hover { color: var(--tinta); text-decoration: none; }
.tabs a.activo { color: var(--indigo); border-bottom-color: var(--indigo); }
.panel-tab { display: none; }
.panel-tab.activo { display: block; }

/* ----------------------------------------------------------------- Modal */
.modal-fondo {
  position: fixed; inset: 0; background: rgba(26, 33, 64, .5);
  display: none; align-items: flex-start; justify-content: center;
  padding: 6vh 16px; z-index: 100; overflow-y: auto;
}
.modal-fondo.abierto { display: flex; }
.modal-caja {
  background: var(--blanco); border-radius: var(--radio);
  box-shadow: var(--sombra-flotante);
  width: 100%; max-width: 560px; padding: 24px;
  animation: modal-entra .18s ease-out;
}
@keyframes modal-entra { from { transform: translateY(10px); opacity: 0; } to { transform: none; opacity: 1; } }
.modal-caja .encabezado { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.modal-caja .cerrar { background: none; border: 0; font-size: 22px; color: var(--tinta-3); cursor: pointer; line-height: 1; }

/* ----------------------------------------------------------------- Toast */
#toasts { position: fixed; bottom: 22px; right: 22px; z-index: 200; display: flex; flex-direction: column; gap: 10px; }
.toast {
  background: var(--noche); color: #fff; font-size: 14px; font-weight: 600;
  padding: 12px 18px; border-radius: 12px; box-shadow: var(--sombra-flotante);
  animation: modal-entra .2s ease-out; max-width: 360px;
}
.toast.error { background: var(--rojo); }
.toast.exito { background: var(--menta); }

/* ------------------------------------------------------------ Agenda día */
.agenda-controles { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.agenda-fecha { font-size: 17px; font-weight: 800; min-width: 220px; text-align: center; text-transform: capitalize; }
.slot {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 14px; border: 1px solid var(--linea); border-radius: var(--radio-s);
  margin-bottom: 8px; background: var(--blanco);
}
.slot .hora { font-weight: 800; font-size: 15px; width: 56px; color: var(--noche); }
.slot .paciente-nombre { font-weight: 700; }
.slot .detalle { flex: 1; min-width: 0; }
.slot .detalle .meta { font-size: 12.5px; color: var(--tinta-2); }
.slot.libre { border-style: dashed; color: var(--tinta-3); background: transparent; }
.slot.libre:hover { border-color: var(--indigo); color: var(--indigo); cursor: pointer; }
.slot .acciones { display: flex; gap: 6px; flex-wrap: wrap; }
/* El botón "Apartar" solo se ve al pasar por encima del horario libre (en el
   celular no hay hover, así que ahí queda siempre visible: ver más abajo). */
.slot.libre .acciones { opacity: 0; transition: opacity .12s; }
.slot.libre:hover .acciones, .slot.libre:focus-within .acciones { opacity: 1; }
/* Horario apartado a mano mientras se acuerda el turno con la persona */
.slot.reservado { border-left: 4px solid var(--ambar); background: var(--ambar-suave); }
.slot.reservado .hora { color: #8A5F10; }
.chip-hora.reservado { border-style: dashed; border-color: var(--ambar); color: #8A5F10; }
.chip-hora.reservado.elegido { background: var(--ambar); border-color: var(--ambar); color: #fff; }

/* Cabecera de la agenda con el día destacado */
.agenda-cabecera {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
  flex-wrap: wrap; margin-bottom: 14px;
}
.agenda-dia-semana { font-size: 13px; font-weight: 700; color: var(--indigo); text-transform: uppercase; letter-spacing: .5px; }
.agenda-dia-num { font-size: 26px; font-weight: 800; color: var(--noche); line-height: 1.1; }
.agenda-dia-num span { font-size: 16px; font-weight: 600; color: var(--tinta-2); text-transform: capitalize; }
.chip-hoy { display:inline-block; background: var(--menta); color:#fff; font-size:10.5px; font-weight:700;
  padding: 1px 8px; border-radius: 10px; letter-spacing:0; vertical-align: middle; margin-left:6px; }
.agenda-nav { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Configuración: una ficha de horario por médico */
.ficha-horario .encabezado h2 { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.ficha-horario .encabezado h2 .fa { color: var(--indigo); }
.ficha-horario.ficha-sin-horario { border-style: dashed; }
.ficha-horario.ficha-sin-horario .encabezado h2 .fa { color: var(--tinta-3); }
/* Botones del encabezado de una ficha (agregar horario / habilitar turnos) */
.acciones-ficha { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Médico que no toma turnos (residente): la ficha queda apagada */
.ficha-horario.ficha-sin-turnos { background: #FbFbFd; border-style: dashed; }
.ficha-horario.ficha-sin-turnos .encabezado h2 { color: var(--tinta-2); }
.ficha-horario.ficha-sin-turnos .encabezado h2 .fa { color: var(--tinta-3); }
.encabezado-chico { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.encabezado-chico h3 { font-size: 13.5px; margin: 0; color: var(--tinta-2); text-transform: uppercase; letter-spacing: .06em; }
.ficha-bloqueos { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--linea); }

/* Selector "agenda de qué médico" + su franja horaria del día (recepción) */
.agenda-selector-medico {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--blanco); border: 1px solid var(--linea); border-radius: var(--radio-s);
  padding: 10px 14px; margin-bottom: 14px;
}
.agenda-selector-medico label { margin: 0; font-size: 13px; font-weight: 700; color: var(--tinta-2); }
.agenda-selector-medico label .fa { color: var(--indigo); margin-right: 4px; }
.agenda-selector-medico select {
  border: 1.5px solid var(--linea); border-radius: 8px; padding: 7px 10px;
  font-family: inherit; font-size: 14px; font-weight: 600; color: var(--tinta);
  background: var(--blanco); min-width: 240px;
}
.agenda-franja { font-size: 13px; color: var(--tinta); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.agenda-franja .fa { color: var(--menta); }
.agenda-franja small { color: var(--tinta-3); font-weight: 600; }
.agenda-franja .franja-vacia { color: var(--tinta-3); font-style: italic; }
.agenda-franja .franja-vacia .fa { color: var(--tinta-3); }
.agenda-franja .franja-generica {
  font-size: 11.5px; color: var(--tinta-3); background: #EEF0F6;
  border-radius: 10px; padding: 2px 8px; font-style: normal;
}
/* En qué sede es cada franja del día (tanda 71). Ámbar, el mismo color que la
   pill de sede de los turnos, para que se lean como la misma cosa. */
.agenda-franja .franja-sede {
  font-size: 11.5px; color: #8A6100; background: #FFF4DB;
  border-radius: 10px; padding: 2px 8px; font-style: normal; font-weight: 700;
}

/* Resumen del día */
.agenda-resumen {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 16px;
}
.resumen-item {
  background: var(--blanco); border: 1px solid var(--linea); border-radius: var(--radio-s);
  padding: 8px 14px; display: flex; align-items: baseline; gap: 7px;
}
.resumen-num { font-size: 19px; font-weight: 800; color: var(--noche); }
.resumen-lbl { font-size: 12.5px; color: var(--tinta-2); }
.resumen-cirugia { border-color: rgba(214,69,80,.4); }
.resumen-cirugia .resumen-num { color: var(--rojo); }

/* Acento de color por tipo de turno (borde izquierdo) */
.slot.slot-tipo-consulta { border-left: 4px solid var(--indigo); }
.slot.slot-tipo-cirugia  { border-left: 4px solid var(--rojo); }
.slot.slot-tipo-estudio  { border-left: 4px solid var(--menta); }
.slot.slot-tipo-control  { border-left: 4px solid var(--ambar); }
.slot.slot-sin-medico { background: #FbFbFd; }
.slot.slot-sin-medico .hora { color: var(--tinta-3); }

/* --------------------------------------------------- Historia clínica */
.hc-entrada { display: flex; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--linea); }
.hc-entrada:last-child { border-bottom: 0; }
.hc-entrada .punto {
  flex-shrink: 0; width: 10px; height: 10px; border-radius: 50%;
  background: var(--luna); margin-top: 6px;
}
.hc-entrada .cuerpo { flex: 1; }
.hc-entrada .meta { font-size: 12.5px; color: var(--tinta-3); margin-bottom: 3px; }
.hc-entrada .texto { white-space: pre-wrap; }
.hc-entrada .punto-estudio { background: var(--indigo); }

/* Adjuntos de una entrada de historia / estudio */
.adjuntos { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.adjunto { position: relative; }
.adjunto img {
  width: 84px; height: 84px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--linea); display: block;
}
.adjunto-doc {
  display: inline-flex; align-items: center; gap: 7px; padding: 8px 12px;
  background: var(--fondo); border: 1px solid var(--linea); border-radius: 8px;
  text-decoration: none; color: var(--tinta-2, #5A6172); font-size: 12.5px; max-width: 220px;
}
.adjunto-doc i { color: #C0392B; font-size: 18px; }
.adjunto-doc span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adjunto form { position: absolute; top: -7px; right: -7px; margin: 0; }
.adjunto-borrar {
  width: 20px; height: 20px; border-radius: 50%; border: 0; cursor: pointer;
  background: #C0392B; color: #fff; font-size: 14px; line-height: 1;
  display: flex; align-items: center; justify-content: center; padding: 0;
}
.adjunto-borrar:hover { background: #a12020; }

/* Zona de arrastrar-y-soltar archivos */
.dropzone {
  border: 2px dashed var(--luna); border-radius: 12px; padding: 20px 16px;
  text-align: center; cursor: pointer; background: var(--fondo);
  transition: border-color .12s, background .12s; color: var(--tinta-2, #5A6172);
}
.dropzone:hover { border-color: var(--indigo); }
.dropzone.arrastrando { border-color: var(--indigo); background: rgba(64,89,201,.06); }
.dropzone input[type="file"] { display: none; }
.dropzone .dropzone-txt { font-size: 13.5px; }
.dropzone .dropzone-txt i { font-size: 22px; color: var(--luna); display: block; margin-bottom: 6px; }
.dropzone .dropzone-txt b { color: var(--indigo); }
.dropzone .dropzone-lista { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; justify-content: center; }
.dropzone .dropzone-chip {
  background: #fff; border: 1px solid var(--linea); border-radius: 8px;
  padding: 3px 10px; font-size: 12px; color: var(--tinta);
}

/* Barra de descarga PDF en "Historia completa" */
.barra-pdf { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.barra-pdf-acciones { display: flex; gap: 8px; flex-wrap: wrap; }
.chk-sel { margin-right: 4px; }
.chk-sel input { width: auto; }

/* Endoscopía del sueño */
.hc-entrada .punto-endoscopia { background: var(--menta); }
/* Evaluación clínica y cirugía en el timeline "Historia completa" */
.hc-entrada .punto-consulta { background: var(--menta); }
.hc-entrada .punto-cirugia { background: #A87516; }
/* Fichas de fonoaudiología: el violeta de su píldora (.pill-violeta). */
.hc-entrada .punto-fono { background: #6A44D6; }
.metricas-estudio { margin: 4px 0 2px; font-size: 12.5px; color: var(--tinta-2, #5A6172); }
.metricas-estudio b { color: var(--indigo); }
.tabla-endoscopia select, .tabla-endoscopia input { width: 100%; min-width: 90px; }
.tabla-endoscopia td, .tabla-endoscopia th { padding: 6px 8px; vertical-align: top; }
.tabla-endoscopia-ver { font-size: 12.5px; }
.tabla-endoscopia-ver td, .tabla-endoscopia-ver th { padding: 5px 8px; }
.endoscopia-item { padding: 14px 0; border-bottom: 1px solid var(--linea); }
.endoscopia-item:last-child { border-bottom: 0; }

/* ================================================================ PORTAL
   Rediseño 2026-08-05 (tanda 64), aprobado por Santino sobre un boceto en
   localhost. Las tres decisiones grandes:

   1. **Nadie es dueño del ancho salvo cada sección.** El encajonado venía de
      un max-width: 1000px repetido en nav, hero y contenido. Ahora hay UNA
      medida compartida (.portal-ancho, hasta 1680px) para la home, y una
      angosta (.portal-angosto) para las páginas de leer y completar — un
      formulario de 1680px de ancho es peor, no mejor.

   2. **Azul noche con resplandores suaves, SIN estrellitas.** Se probó llevar
      el cielo estrellado del login al hero y Santino los leyó como píxeles
      muertos ("puntitos sueltos... errorcitos"): un punto blanco de 1px sobre
      fondo oscuro parece mugre de pantalla. La profundidad la dan los
      resplandores radiales grandes.

   3. **El panel no se toca.** Los tokens compartidos (--radio, --sombra) se
      redefinen SOLO bajo .portal-body: el mismo .tarjeta rinde distinto en el
      portal sin que ninguna pantalla del panel cambie un píxel. */
.portal-body {
  /* ⚠️ El color de piso tiene que vivir ACÁ, en el <body>, y no en `html`:
     `html` no declara background (línea 93), así que este color se propaga al
     canvas del navegador y recién por eso el telón de líneas puede irse a
     z-index:-1 sin que nada lo tape. Si alguien le pone un `background` a
     `html`, ese piso queda DELANTE del telón y las líneas desaparecen sin que
     falle nada ni avise nadie. */
  background: var(--portal-lienzo);
  /* Le avisa al navegador que lo que dibuja él —barra de scroll, resaltado de
     selección, el chrome de los date pickers— va en su versión oscura. Ojo:
     esto se hereda, y justo después del cierre de esta regla las tarjetas, los
     modales y la lámina lo devuelven a `light`, porque adentro siguen siendo
     papel blanco. Las dos declaraciones son una sola decisión: no se toca una
     sin la otra. */
  color-scheme: dark;
  --radio: 16px;
  --radio-s: 10px;
  /* Sombra en capas: contacto, cuerpo y ambiente. Una sola sombra grande se
     ve como un borrón; tres chicas se ven como luz.
     ⚠️ Ahora tiran a negro y no al azul de la marca: una sombra sólo existe si
     es MÁS oscura que el fondo sobre el que cae, y rgba(34,43,78,…) sobre el
     lienzo #1A2140 no dibujaba absolutamente nada. */
  --sombra: 0 1px 2px rgba(6, 9, 20, .28),
            0 4px 12px rgba(6, 9, 20, .26),
            0 14px 36px rgba(6, 9, 20, .34);

  /* ── PORTAL OSCURO (2026-09-18) ─────────────────────────────────────────
     Tokens NUEVOS, y a propósito: acá NO se redefine --fondo, --blanco,
     --tinta ni --borde, aunque sería más corto.

     --fondo: lo usan la .dropzone, el cebrado de la lámina impresa, el
       .lamina-pie y un style inline en portal/solicitar.php:408 que ninguna
       regla de hoja revierte sin !important. Teñirlo deja el resumen del turno
       de un color que nadie eligió.
     --blanco: en tres lugares es color de TEXTO, no de fondo
       (.lamina-cabecera, .lamina-titulo, .diario-cal-num). Oscurecerlo borra
       esos textos contra su propio fondo.
     --borde: no existe en esta hoja, pero tiene 19 usos inline en las vistas
       del portal (cuestionario, diario, estudios, solicitar) que hoy caen al
       fallback #E4E7EF. Definirlo en claro-sobre-oscuro rompería esos 19
       separadores, porque viven adentro de tarjetas que siguen siendo BLANCAS.

     El orden no importa: las custom properties de una misma regla se resuelven
     todas juntas, así que el `background` de arriba ve este valor igual. */
  --portal-lienzo:  #1A2140;                   /* = --noche-3 */
  --portal-tinta:   #FFFFFF;
  --portal-tinta-2: #C8D2F2;
  --portal-tinta-3: #AEB8D8;
  --portal-linea:   rgba(255, 255, 255, .10);
  --portal-vidrio:  rgba(255, 255, 255, .06);
  --portal-vidrio-borde: rgba(255, 255, 255, .12);
  /* Los tres de abajo los consume fondo-lineas.css (.fondo-lineas--portal),
     que los lee por herencia desde acá: el telón ES el cielo y se trae el
     degradé puesto. Si alguien los borra, esa hoja cae a sus fallbacks —los
     mismos valores— y el bug queda invisible hasta que se cambie la marca. */
  --portal-cielo:   linear-gradient(168deg, #1A2140, #222B4E 58%, #1A2140);
  --portal-brillo-a: rgba(143, 160, 238, .26);
  --portal-brillo-b: rgba( 64,  89, 201, .26);
}
.portal-body img { max-width: 100%; }
/* ⚠️ Esto NO es opcional. El `color-scheme: dark` de arriba se hereda, y los
   <input type="date"> / <select> de /turno lo obedecen: quedan con el chrome
   oscuro del navegador adentro de una tarjeta blanca, y se lee como un bug del
   sistema, no como una decisión. Las tarjetas, los modales y la lámina son
   papel: ahí adentro el navegador vuelve a dibujar en claro. */
.portal-body .tarjeta,
.portal-body .modal-caja,
.portal-body .lamina { color-scheme: light; }

/* LAS medidas del portal. min() elige lo más chico: monitor grande → tope
   centrado; notebook → 100% menos margen proporcional; celular → 100% - 36px. */
.portal-ancho   { width: min(1680px, 100% - clamp(36px, 6vw, 128px)); margin-inline: auto; }
.portal-angosto { width: min(1080px, 100% - clamp(36px, 6vw, 128px)); margin-inline: auto; }

/* Botones del portal: responden al apretarlos (instantáneo, 100ms), no al
   soltarlos; el verde tiene cuerpo (degradé + brillo de borde superior). */
.portal-body .btn {
  justify-content: center;
  transition: transform .1s ease-out, background .18s var(--curva),
              border-color .18s var(--curva), box-shadow .18s var(--curva);
}
.portal-body .btn:active { transform: scale(.97); }
.portal-body .btn-secundario { box-shadow: 0 1px 2px rgba(34, 43, 78, .06); }
.portal-body .btn-secundario:hover { box-shadow: 0 2px 8px rgba(34, 43, 78, .1); }
.portal-body .btn-menta {
  background: linear-gradient(180deg, #14B697, var(--menta));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), 0 2px 10px rgba(15, 169, 141, .35);
  /* ⚠️ Verde oscuro y no blanco. El blanco sobre el menta da 2,97:1 y viene
     fallando AA desde siempre, pero mientras el portal era claro el botón era
     un elemento más; con la página entera de noche "Pedir turno online" pasa a
     ser lo más mirado de la pantalla y no se puede dejar ilegible. Esta tinta
     da 4,93:1 contra el pie del degradé (--menta) y 5,69:1 contra el techo
     (#14B697): AA en el peor caso.
     Va scopeado a .portal-body a propósito: el botón verde del PANEL no se
     toca, porque eso sería cambiar la marca y no arreglar un fondo. */
  color: #0B2E27;
}
/* El hover oscurece el degradé y no volvía a declarar el color: #0B2E27 sobre
   #0C8A73 da 3,42:1, o sea que el botón más mirado de la home fallaba AA
   justo mientras el mouse está encima. Con #00150F da 4,40:1 en el piso del
   degradé y 5,9:1 en el techo. */
.portal-body .btn-menta:hover { background: linear-gradient(180deg, #10A385, #0C8A73); color: #00150F; }
.portal-body .tarjeta { padding: clamp(22px, 2vw, 30px); }
.portal-body .subtexto { font-size: 14.5px; max-width: 62ch; }

/* Cabecera pegada arriba y traslúcida: el "Pedir turno" queda al alcance sin
   importar cuánto se haya bajado. Antes se fundía con el hero azul arriba y se
   leía como vidrio oscuro sobre el contenido claro de abajo; desde que la
   página entera es del color de la marca, abajo ya no hay contra qué recortarse.
   ⚠️ Esta barra tiene backdrop-filter, o sea que es bloque contenedor de
   cualquier `position: fixed` que viva adentro: el telón de líneas NO puede
   moverse acá adentro o deja de estar fijo al viewport, y el síntoma (el dibujo
   scrolleando con la página) no se parece en nada a la causa. */
.portal-topbar {
  position: sticky; top: 0; z-index: 60;
  background: rgba(26, 33, 64, .97); /* respaldo si no hay blur */
  /* El único motivo por el que la barra existe como objeto. Su vidrio contra el
     lienzo da 1,03:1: sin este filo, al scrollear no se ve una cabecera pegada,
     se ve el título flotando sobre la nada. */
  border-bottom: 1px solid var(--portal-linea);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .portal-topbar {
    background: rgba(24, 30, 58, .78);
    -webkit-backdrop-filter: blur(18px) saturate(160%);
    backdrop-filter: blur(18px) saturate(160%);
  }
}
.topbar-adentro {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 12px 0;
}
.portal-topbar .marca { border: 0; padding: 0; }
.portal-acciones { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* Sobre la banda oscura, los botones blancos van sin borde gris. */
.portal-topbar .btn-secundario { border-color: transparent; background: rgba(255, 255, 255, .93); }
.portal-topbar .btn-secundario:hover { background: #fff; }

/* Con cuatro accesos la barra no entra en una línea en el celular: la marca
   arriba y los botones en 2×2 con superficie de dedo. Y deja de estar pegada:
   dos filas fijas se comerían media pantalla. */
@media (max-width: 780px) {
  .portal-topbar { position: static; }
  .topbar-adentro { flex-wrap: wrap; }
  .topbar-adentro .marca { flex: 1 0 100%; }
  .portal-acciones { width: 100%; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .portal-acciones .btn { padding: 11px 10px; }
}

/* Hero de la home: banda de borde a borde con el azul noche de la marca. El
   texto se corta en una medida legible (px y no ch: ch se mide en la fuente
   del propio elemento y acá cambia de tamaño con la pantalla). */
.portal-hero-banda {
  position: relative;
  /* ⚠️ Sin fondo propio, y es EL cambio de esta tanda. El cielo con los dos
     resplandores que vivía acá se mudó al telón fijo al viewport
     (.fondo-lineas--portal en fondo-lineas.css): antes esta banda era una
     franja de color que cortaba a blanco a media altura, ahora es una ventana
     al mismo cielo que tiene la página entera. Si se le devuelve un background,
     vuelve la juntura — el telón sigue corriendo debajo, pero tapado.
     Todo lo demás se queda: `position: relative` y `overflow: hidden` los pide
     la escena del oso, y el padding es lo que le deja aire al título. */
  background: none;
  color: #fff;
  padding: clamp(56px, 7vw, 116px) 0 clamp(120px, 11vw, 190px);
  overflow: hidden;
}
.portal-hero { position: relative; }
.portal-hero h1 {
  font-size: clamp(30px, 2.6vw + 14px, 58px);
  line-height: 1.08;
  letter-spacing: -.022em; /* cuanto más grande el título, más se cierra */
  color: #fff;
  max-width: 760px;
  margin-bottom: 18px;
}
/* Título con degradé blanco → lavanda, el recurso de los titulares de Apple:
   de lejos es blanco, de cerca tiene material. Sin soporte queda blanco. */
@supports (-webkit-background-clip: text) {
  .portal-hero h1 {
    background: linear-gradient(180deg, #FFFFFF 55%, #C2CCF2);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}
.portal-hero .hero-bajada {
  color: #B9C2E4;
  font-size: clamp(16px, .5vw + 14px, 19px);
  max-width: 620px;
  margin-bottom: 6px;
}
.portal-hero .hero-coordinacion {
  color: #8FA0EE;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .02em;
  margin: 10px 0 0;
}
.portal-hero .hero-accion { margin: 30px 0 0; }
.btn-hero { padding: 14px 26px; font-size: 16px; border-radius: 13px; }

/* ============================================================================
   LA ESCENA DEL OSO Y LA LUNA, arriba a la derecha del hero. Reemplaza a la
   luna que cambiaba de fase al clic (2026-08-05/06): Santino la quiso continua,
   "como un carrusel que vaya rotando entre el oso y la luna", con el oso
   durmiendo bien al final. Ya no es interactiva — no hay nada que tocar.

   El cuento, en 18 segundos: el oso entra corriendo por la izquierda, salta a
   la cama, se acurruca, se tapa y se duerme. Ahí sube a la luna, que se le
   llena detrás mientras la cama se apaga, y se queda durmiendo casi 7 segundos
   antes de que la luna vuelva a menguar y empiece de nuevo.

   Cómo está armado, que es lo que hay que entender antes de tocarlo:

   - **Una sola línea de tiempo de 18s** (`--ciclo`) que comparten TODAS las
     animaciones largas. El porcentaje de un keyframe es un minuto del cuento:
     11% es "llegó al pie de la cama", 48% es "está en la luna". Si se mueve un
     porcentaje hay que mover los de las otras capas o el cuento se desarma.
   - **Cada elemento anima UNA sola propiedad**, y las capas van anidadas
     (`escena-flota` respira, `oso-viaje` traslada, `oso-escala` acerca). Dos
     animaciones de `transform` sobre el mismo nodo se pisan, no se suman.
   - **Hay dos osos**, no uno que se transforma: `.pose-corre` (de pie, con las
     patas en un loop rápido) y `.pose-duerme` (acostado). El cambio es un
     CORTE en el pico del salto, no un crossfade: dos osos a media opacidad se
     transparentan y se ve la luna a través del que salta. Cortado en el aire
     se lee como que recoge las patas para caer. Y por eso los loops rápidos de
     las patas pueden ser infinitos: cuando no corresponden, ese oso no se ve.
   - **El oso cambia de color** con el cuento (`--oso-tinta` y compañía): claro
     mientras corre contra el cielo, oscuro cuando la luna se enciende detrás y
     lo deja a contraluz. Un oso azul noche corriendo sobre el azul noche del
     hero sería invisible.
   - **La luna sigue siendo un disco y una sombra que se desplaza** dentro de
     una máscara, igual que antes. No son dibujos que se funden: por eso el
     cambio de fase se ve como la sombra barriendo el disco, que es lo que pasa
     de verdad. Acá además crece durante todo el cuento, de hoz a llena.
   - **Flota la escena entera**, no cada pieza por su cuenta: con animaciones
     separadas el oso se despegaba del colchón mientras dormía.
   ========================================================================== */
.hero-escena {
  --ciclo: 18s;
  --oso-tinta: #C9D3F6;
  --oso-detalle: #97A6EC;
  --oso-linea: #232B4E;

  position: absolute;
  top: -10px;
  right: clamp(0px, 4vw, 90px);
  width: clamp(253px, 22vw, 396px);
  height: auto;
  filter: drop-shadow(0 0 70px rgba(143, 160, 238, .34));
  /* Es un adorno y nada más: no se toca, no se selecciona, no roba el clic. */
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}

/* Los colores del oso son variables porque cambian a mitad del cuento.
   Registrarlas es lo que hace que el cambio DEGRADE en vez de saltar: una
   custom property sin registrar no interpola. Sin soporte salta, y salta justo
   cuando la luna aparece, que es adonde va el ojo. */
@property --oso-tinta   { syntax: "<color>"; inherits: true; initial-value: #C9D3F6; }
@property --oso-detalle { syntax: "<color>"; inherits: true; initial-value: #97A6EC; }
@property --oso-linea   { syntax: "<color>"; inherits: true; initial-value: #232B4E; }

/* ---- Los colores de la escena ---- */
.hero-escena .luna-hueco { fill: #1F2848; stroke: #8FA0EE; stroke-opacity: .45; stroke-width: 2; }
.hero-escena .luna-disco { fill: #DDE3F9; opacity: .92; }

.hero-escena .cama-colchon  { fill: #D7DEF8; }
.hero-escena .cama-almohada { fill: #F2F5FE; }
.hero-escena .cama-madera   { fill: #8FA0EE; }
.hero-escena .cama-pata     { fill: #6D7DCE; }
.hero-escena .manta-tela    { fill: #7C8DE4; }
.hero-escena .manta-doblez  { fill: #AEBBF3; }

.hero-escena .cuerpo,
.hero-escena .cabeza,
.hero-escena .oreja,
.hero-escena .cola          { fill: var(--oso-tinta); }
.hero-escena .hocico,
.hero-escena .oreja-in,
.hero-escena .patita        { fill: var(--oso-detalle); }
.hero-escena .ojo           { fill: var(--oso-linea); }
.hero-escena .nariz         { fill: #1A2140; }
.hero-escena .ojos-cerrados { fill: none; stroke: var(--oso-linea); stroke-width: 2; stroke-linecap: round; }
.hero-escena .pata path     { fill: none; stroke: var(--oso-tinta); stroke-width: 8.5; stroke-linecap: round; }
.hero-escena .pata-lejos .pata path { stroke: var(--oso-detalle); }
.hero-escena .rastro path   { fill: none; stroke: var(--oso-tinta); stroke-width: 2.5; stroke-linecap: round; }
.hero-escena .zzz text {
  fill: var(--oso-detalle);
  font-family: Manrope, 'Segoe UI', sans-serif;
  font-weight: 800;
}

/* ---- Las animaciones largas: todas sobre la misma línea de 18s ---- */
.hero-escena .oso-viaje {
  animation: escena-viaje var(--ciclo) infinite,
             escena-tono  var(--ciclo) linear infinite;
}
.hero-escena .oso-escala  { animation: escena-escala var(--ciclo) var(--curva) infinite; }
.hero-escena .pose-corre  { animation: escena-corre-vis var(--ciclo) linear infinite; }
.hero-escena .pose-duerme { animation: escena-duerme-vis var(--ciclo) linear infinite; }
.hero-escena .zzz         { animation: escena-zzz-vis var(--ciclo) linear infinite; }
.hero-escena .cama,
.hero-escena .piso        { animation: escena-mueble var(--ciclo) linear infinite; }
.hero-escena .manta {
  transform-origin: 100px 0;
  animation: escena-mueble var(--ciclo) linear infinite,
             escena-manta  var(--ciclo) var(--curva) infinite;
}
.hero-escena .luna-sombra {
  transform-origin: 146px 74px;
  animation: escena-luna var(--ciclo) var(--curva) infinite;
}
.hero-escena .escena-flota { animation: escena-flotar 7s ease-in-out infinite alternate; }

/* ---- Los loops cortos: solo se ven cuando su oso está en pantalla ---- */
.hero-escena .pata        { animation: escena-trote .3s ease-in-out infinite alternate; }
.hero-escena .pata-b      { animation-delay: -.15s; }
.hero-escena .oso-rebote  { animation: escena-rebote .3s ease-in-out infinite alternate; }
.hero-escena .rastro      { animation: escena-rastro-vis var(--ciclo) linear infinite; }
.hero-escena .rastro path { animation: escena-rastro .45s linear infinite; }
.hero-escena .rastro path:nth-child(2) { animation-delay: -.15s; }
.hero-escena .rastro path:nth-child(3) { animation-delay: -.3s; }
.hero-escena .respira {
  transform-origin: 0 20px;
  animation: escena-respirar 3.6s ease-in-out infinite alternate;
}
/* fill-box: sin esto el scale de la zeta se calcularía desde el origen del
   viewBox y la letra saldría disparada al ángulo del SVG. */
.hero-escena .zzz text {
  transform-box: fill-box;
  transform-origin: center;
  animation: escena-zeta 3s linear infinite;
}
.hero-escena .z2 { animation-delay: 1s; }
.hero-escena .z3 { animation-delay: 2s; }

/* ---- El cuento ---- */
@keyframes escena-viaje {
  /* entra corriendo: 1,6s para cruzar el cuadro. Más lento se leía como un oso
     pedaleando en el lugar, porque el trote de las patas es de 0,3s */
  0%, 2%       { transform: translate(-64px, 232px); animation-timing-function: linear; }
  11%          { transform: translate(42px, 232px);  animation-timing-function: cubic-bezier(.15,.65,.4,1); }
  /* salta a la cama: en el pico cambia de pose */
  13.5%        { transform: translate(98px, 190px);  animation-timing-function: cubic-bezier(.55,0,.85,.45); }
  17%          { transform: translate(144px, 228px); animation-timing-function: cubic-bezier(.3,0,.5,1); }
  18.5%        { transform: translate(144px, 221px); animation-timing-function: ease-in; }
  /* se acomoda, se tapa y duerme en la cama */
  20%, 34%     { transform: translate(144px, 228px); animation-timing-function: cubic-bezier(.45,0,.15,1); }
  /* sube a la luna y se queda ahí casi 7 segundos */
  48%, 93%     { transform: translate(107px, 114px); }
  /* vuelve al principio ya invisible: el salto de posición no se ve */
  93.01%, 100% { transform: translate(-64px, 232px); }
}
@keyframes escena-escala {
  0%, 36%      { transform: scale(1); }
  48%, 93%     { transform: scale(1.34); }
  93.01%, 100% { transform: scale(1); }
}
@keyframes escena-tono {
  0%, 36%      { --oso-tinta: #C9D3F6; --oso-detalle: #97A6EC; --oso-linea: #232B4E; }
  48%, 93%     { --oso-tinta: #2C3763; --oso-detalle: #46538A; --oso-linea: #DDE3F9; }
  93.01%, 100% { --oso-tinta: #C9D3F6; --oso-detalle: #97A6EC; --oso-linea: #232B4E; }
}
@keyframes escena-corre-vis {
  0%, 13.7%   { opacity: 1; }
  13.71%, 94% { opacity: 0; }
  96%, 100%   { opacity: 1; }
}
@keyframes escena-duerme-vis {
  0%, 13.7%   { opacity: 0; }
  13.71%, 86% { opacity: 1; }
  90%, 100%   { opacity: 0; }
}
/* Las líneas de velocidad se apagan al despegar: horizontales mientras el oso
   sube, se leen como un error de dibujo. */
@keyframes escena-rastro-vis {
  0%, 10%   { opacity: 1; }
  12%, 100% { opacity: 0; }
}
@keyframes escena-zzz-vis {
  0%, 24%   { opacity: 0; }
  28%, 84%  { opacity: 1; }
  88%, 100% { opacity: 0; }
}
@keyframes escena-mueble {
  0%, 36%   { opacity: 1; }
  44%, 95%  { opacity: 0; }
  99%, 100% { opacity: 1; }
}
/* La manta no sube: se estira desde la piecera sobre el oso ya acostado. Un
   translateY la dejaría colgando por debajo del colchón. */
@keyframes escena-manta {
  0%, 19%   { transform: scaleX(.3); }
  25%, 93%  { transform: scaleX(1); }
  95%, 100% { transform: scaleX(.3); }
}
@keyframes escena-luna {
  /* crece durante todo el cuento: hoz fina cuando el oso entra corriendo, un
     cuarto cuando salta, gibosa mientras se duerme, llena justo cuando llega
     arriba. Y recién mengua DESPUÉS de que el oso se apagó: si menguan a la
     vez, el oso a medio desvanecer queda sucio sobre la mitad oscura. */
  0%        { transform: translate(-16px, 16px); }
  12%       { transform: translate(-4px, 8px); }
  26%       { transform: translate(10px, -6px); }
  36%       { transform: translate(24px, -26px); }
  48%, 90%  { transform: translate(50px, -176px); animation-timing-function: cubic-bezier(.5,0,.4,1); }
  100%      { transform: translate(-16px, 16px); }
}
@keyframes escena-trote    { from { transform: rotate(-30deg); } to { transform: rotate(28deg); } }
@keyframes escena-rebote   { from { transform: translateY(0) rotate(1.5deg); } to { transform: translateY(-3px) rotate(-2deg); } }
@keyframes escena-respirar { from { transform: scaleY(1); }      to { transform: scaleY(1.05); } }
@keyframes escena-flotar   { from { transform: translateY(0); }  to { transform: translateY(-8px); } }
@keyframes escena-rastro   { 0%, 100% { opacity: 0; } 40% { opacity: .5; } }
@keyframes escena-zeta {
  0%   { opacity: 0;   transform: translate(0, 0) scale(.6); }
  18%  { opacity: .95; }
  100% { opacity: 0;   transform: translate(8px, -16px) scale(1.15); }
}

/* Solo en computadora: de 1100px para abajo pisa el texto del hero y se va,
   igual que la luna vieja. */
@media (max-width: 1100px) { .hero-escena { display: none; } }

/* "Menos movimiento" NO apaga el cuento. La escena es chica, lenta y vive en
   una esquina; apagarla la deja como una lamina muerta para la mucha gente que
   tiene los efectos de Windows apagados por velocidad y no por sensibilidad
   —Santino es uno—, y ya se perdio una ronda por eso con el carrusel de
   Novedades. Lo que se reduce es el ritmo: el ciclo se estira a 26s y
   desaparecen el rebote, el rastro, la respiracion y el flote, que son el
   temblor rapido.

   ⚠️ **Los `!important` de este bloque no son de adorno.** Mas arriba en este
   mismo archivo hay un apagon global —`* { animation-duration: .01ms
   !important; animation-iteration-count: 1 !important; animation-delay: 0s
   !important }`— que le gana a cualquier regla normal por especifica que sea.
   Con el, la escena entera se ejecuta en diez microsegundos, UNA vez, y queda
   congelada en su ultimo frame: cama y luna quietas y el oso encimado a la
   luna, porque su `transform` tampoco corre. Cada duracion, cada repeticion y
   cada delay de aca abajo esta devolviendo una de esas tres propiedades.

   Si se toca este bloque, hay que probarlo con la preferencia ACTIVADA y
   contra ESTE archivo completo. Probarlo contra la escena sola no sirve: el
   apagon esta arriba, y sin el todo parece andar. */
@media (prefers-reduced-motion: reduce) {
  .hero-escena { --ciclo: 26s; }
  .hero-escena .oso-viaje,
  .hero-escena .oso-escala,
  .hero-escena .pose-corre,
  .hero-escena .pose-duerme,
  .hero-escena .zzz,
  .hero-escena .cama,
  .hero-escena .piso,
  .hero-escena .manta,
  .hero-escena .rastro,
  .hero-escena .luna-sombra {
    animation-duration: var(--ciclo) !important;
    animation-iteration-count: infinite !important;
  }
  .hero-escena .pata {
    animation-duration: .5s !important;
    animation-iteration-count: infinite !important;
  }
  .hero-escena .pata-b { animation-delay: -.25s !important; }
  .hero-escena .zzz text {
    animation-duration: 3s !important;
    animation-iteration-count: infinite !important;
  }
  .hero-escena .z2 { animation-delay: 1s !important; }
  .hero-escena .z3 { animation-delay: 2s !important; }
  /* Estos si se apagan a proposito: son el temblor rapido. */
  .hero-escena .oso-rebote,
  .hero-escena .rastro path,
  .hero-escena .escena-flota,
  .hero-escena .respira { animation: none !important; }
}

/* Entrada escalonada al cargar la home: título, bajada, coordinación y botón
   aparecen en cascada de 80ms. Corre una sola vez, dura menos de un segundo. */
@media (prefers-reduced-motion: no-preference) {
  .portal-hero h1,
  .portal-hero .hero-bajada,
  .portal-hero .hero-coordinacion,
  .portal-hero .hero-accion { animation: entrar .7s var(--curva) backwards; }
  .portal-hero .hero-bajada       { animation-delay: .08s; }
  .portal-hero .hero-coordinacion { animation-delay: .16s; }
  .portal-hero .hero-accion       { animation-delay: .24s; }
  .hero-escena { animation: entrar 1s var(--curva) backwards; }
}
@keyframes entrar {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Al scrollear, el hero se queda atrás: se apaga y sube más lento que la
   página (el efecto de las páginas de producto de Apple) mientras las
   tarjetas le pasan por encima. Sin scroll-timeline: scroll normal, nada roto. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .portal-hero {
      animation: hero-se-queda linear both;
      animation-timeline: scroll();
      animation-range: 0px 640px;
    }
    @keyframes hero-se-queda {
      to { opacity: .12; transform: translateY(-46px); }
    }
  }
}

/* Las subpáginas (turno, indicaciones, cuestionario, estudios...) no llevan
   hero: llevan esta banda corta, para que las tarjetas tengan de dónde
   asomarse y toda página abra igual.
   ⚠️ Ya no pinta el cielo —ahora lo pinta el telón, detrás de todo— pero los
   130px se QUEDAN: es un espaciador, y de esa medida cuelga el solape de
   -78px de .portal-contenido.portal-angosto. Bajarla a 0 porque "ya no se ve"
   le sube la primera tarjeta hasta meterla debajo de la topbar. */
.portal-banda-corta {
  height: 130px;
  background: none;
}

/* El contenido se mete en la banda de arriba (margen negativo): el solapado
   da profundidad y ata las dos mitades de la página. En la home el hero es
   alto y aguanta un solape grande; en las subpáginas la banda mide 130px y el
   solape es fijo y más chico. */
.portal-contenido {
  position: relative; z-index: 1;
  margin-top: clamp(-120px, -8vw, -64px);
  padding-bottom: clamp(56px, 6vw, 96px);
}
.portal-contenido.portal-angosto { margin-top: -78px; }

/* La grilla de la home: 12 columnas para que "3 tarjetas arriba, una banda
   ancha abajo" y sus variantes por pantalla salgan de UNA declaración. */
.grilla-inicio {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(16px, 1.4vw, 24px);
}
.grilla-inicio > * { grid-column: span 12; }
@media (min-width: 720px)  { .tarjeta-tercio { grid-column: span 6; } }
@media (min-width: 1120px) { .tarjeta-tercio { grid-column: span 4; } }

/* El ícono deja de ser un dibujito suelto al lado del título: va en una
   pastilla de color, la misma pieza que ya usan los KPI del panel. */
.tarjeta-icono {
  width: 46px; height: 46px; border-radius: 13px;
  display: flex; align-items: center; justify-content: center;
  font-size: 19px; margin-bottom: 14px;
}
.tarjeta-icono.indigo { background: var(--azul-suave); color: var(--indigo); }
.tarjeta-icono.menta  { background: var(--menta-suave); color: var(--menta); }
.tarjeta-icono.ambar  { background: var(--ambar-suave); color: var(--ambar); }
.grilla-inicio .tarjeta h2 { font-size: 19px; margin: 0 0 8px; }
.tarjeta .dato-destacado { font-size: 17px; font-weight: 800; margin: 0 0 4px; }

/* Sedes (tanda 71). Una debajo de otra dentro de la tarjeta de la home, con
   una línea suave entre medio: con dos direcciones seguidas y sin separación
   se leen como una sola de tres renglones. */
.sede-item + .sede-item {
  margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--linea);
}
.sede-nombre {
  margin: 0 0 2px; font-size: 12.5px; font-weight: 800; letter-spacing: .4px;
  text-transform: uppercase; color: var(--indigo);
}
/* En la home la dirección de una sede acompaña al nombre: no necesita el
   tamaño de un dato suelto. */
.sede-item .dato-destacado { font-size: 15.5px; font-weight: 700; }

/* "Te operaste hace poco": banda horizontal — pastilla + texto a la
   izquierda, el botón a la derecha, verticalmente centrados. */
.tarjeta-banda { display: flex; align-items: center; gap: clamp(16px, 2vw, 28px); }
.tarjeta-banda .tarjeta-icono { margin-bottom: 0; flex-shrink: 0; }
.tarjeta-banda .banda-texto { flex: 1; min-width: 0; }
.tarjeta-banda .banda-texto p { margin: 0; }
.tarjeta-banda .btn { flex-shrink: 0; }
@media (max-width: 719px) {
  .tarjeta-banda { flex-wrap: wrap; }
  .tarjeta-banda .btn { flex: 1 0 100%; }
}

/* El cierre ya no "repite el cielo del hero": ahora lo comparte. Con la página
   entera de noche, dibujarle su propio degradé encima del telón lo convertía en
   un parche de un azul apenas distinto, con el borde del parche a la vista. Sin
   fondo, deja pasar las líneas y el botón verde sigue siendo lo único saturado
   de la sección — que era la idea original.
   El filo de arriba es lo que lo mantiene como pieza: sin él, este bloque deja
   de existir y queda texto centrado al final de la página. */
.tarjeta-cierre {
  background: none;
  border: 1px solid var(--portal-linea);
  color: #fff;
  text-align: center;
  padding: clamp(40px, 4.5vw, 64px) 22px;
}
.tarjeta-cierre h2 { color: #fff; font-size: clamp(22px, 1.6vw + 12px, 30px); margin-bottom: 8px; }
.tarjeta-cierre .subtexto { color: #B9C2E4; margin: 0 auto 24px; }

/* ═══ LA REGLA DE ORO DEL PORTAL OSCURO ═════════════════════════════════════
   Una tarjeta se vuelve vidrio SÓLO si no tiene un control adentro. Donde hay
   un input, un select, un chip de horario o el widget de Turnstile, la hoja
   queda BLANCA.

   No es timidez: este portal lo usan pacientes mayores para sacar un turno y
   para subir estudios. La tarjeta blanca de /turno, /estudios, /cuestionario y
   /diario no es un olvido del rediseño, es un papel iluminado — es lo que hace
   que un formulario de 29 campos se pueda completar. Ese mismo corte deja el
   config de Turnstile en 'light', que sigue siendo lo correcto en las 6
   pantallas donde se dibuja (las 6 lo tienen adentro de una tarjeta blanca), y
   evita tener que meterle un parámetro `tema` a un helper que comparten el
   portal y los tres logins.

   Por eso el scope es `.grilla-inicio >` y `.experiencias-grilla >` y no
   `.tarjeta` a secas: esas dos grillas viven únicamente en portal/index.php y
   no tienen ni un control adentro. Así no hubo que tocar una sola vista.

   ⚠️ El vidrio NO usa `brightness()` adentro del backdrop-filter. Sin blur
   —navegador viejo, o el blur deshabilitado— la tarjeta sigue siendo
   rgba(255,255,255,.06) sobre el lienzo y el contraste no se mueve un punto.
   Con brightness sí se movería, y `@supports` no puede detectar ese caso.
   ════════════════════════════════════════════════════════════════════════ */
.portal-body .grilla-inicio > .tarjeta:not(.tarjeta-cierre),
.portal-body .experiencias-grilla > .experiencia {
  background: var(--portal-vidrio);
  border-color: var(--portal-vidrio-borde);
  /* Sin sombra: una pieza translúcida no se levanta del fondo, se recorta
     contra él. La sombra la dibujaría igual y se vería como un manchón. */
  box-shadow: none;
  color: var(--portal-tinta);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.portal-body .grilla-inicio > .tarjeta h2,
.portal-body .experiencias-grilla .experiencia b { color: var(--portal-tinta); }
.portal-body .grilla-inicio > .tarjeta .subtexto,
.portal-body .experiencias-grilla .experiencia-texto { color: var(--portal-tinta-2); }
.portal-body .experiencias-grilla .experiencia-nota,
.portal-body .experiencias-grilla .experiencia-pie span { color: var(--portal-tinta-3); }
/* El rótulo de sede sigue siendo el acento de la marca, pero el índigo #4059C9
   sobre el vidrio da 2,3:1 y desaparece: sobre oscuro el acento es la luna. */
.portal-body .grilla-inicio > .tarjeta .sede-nombre { color: var(--luna); }
.portal-body .grilla-inicio > .tarjeta .sede-item + .sede-item { border-top-color: var(--portal-vidrio-borde); }
/* Los botones blancos macizos —en la tarjeta de sedes y en la topbar— eran
   cuatro parches de papel sobre la noche y se llevaban toda la mirada, que en
   esta página tiene que ir al verde de "Pedir turno". Pasan a vidrio: el texto
   blanco sobre ese apilado da 10,9:1, así que no se pierde nada de legibilidad.
   Las pastillas de ícono (.tarjeta-icono.indigo/.menta/.ambar) NO se tocan a
   propósito: sobre vidrio dejan de ser un detalle y son el único color saturado
   de la tarjeta, que es justo lo que se quiere. */
.portal-body .grilla-inicio > .tarjeta .btn-secundario,
.portal-body .portal-topbar .btn-secundario {
  background: rgba(255, 255, 255, .13); color: #fff; border-color: var(--portal-vidrio-borde);
}
.portal-body .grilla-inicio > .tarjeta .btn-secundario:hover,
.portal-body .portal-topbar .btn-secundario:hover {
  background: rgba(255, 255, 255, .20); border-color: rgba(255, 255, 255, .30);
}

/* Al pasar el mouse la tarjeta se despega apenas: 3px y una sombra más honda.
   El cierre oscuro no (es una banda, no una pieza que se levanta). Las
   novedades tampoco: desde que son slides adentro de un scroller, levantarlas
   al pasar el mouse las recortaba contra el borde del carrusel. */
.tarjeta-tercio, .tarjeta-banda {
  transition: transform .25s var(--curva), box-shadow .25s var(--curva), border-color .25s var(--curva);
}
/* ⚠️ El selector NO es `.tarjeta-tercio:hover, .tarjeta-banda:hover` (0,2,0)
   como era hasta ahora: la regla del vidrio de abajo pesa (0,4,0) y le ganaba
   el `border-color` y el `box-shadow` a cualquier hover más flojo, sin importar
   el orden en el archivo. Quedaba una tarjeta que se levanta 3px y no cambia
   nada más. Con el `:not()` adentro suma (0,5,0) y gana siempre, mire quien
   mire y esté donde esté el bloque. Cubre exactamente al mismo conjunto que se
   vuelve vidrio, así que los dos no se pueden desincronizar. */
.portal-body .grilla-inicio > .tarjeta:not(.tarjeta-cierre):hover {
  transform: translateY(-3px);
  /* Sobre oscuro el borde se aclara en vez de oscurecerse, y la sombra tira a
     negro: la azulada de antes era invisible contra el lienzo. */
  border-color: rgba(255, 255, 255, .22);
  box-shadow: 0 2px 4px rgba(6, 9, 20, .26),
              0 10px 26px rgba(6, 9, 20, .32),
              0 26px 60px rgba(6, 9, 20, .40);
}

/* Las tarjetas de la home y el bloque de novedades suben y se revelan al
   entrar a la pantalla, sin JS. TODO adentro del @supports: un navegador sin
   animation-timeline (Firefox) tiene que ver la página entera, no tarjetas
   invisibles esperando una animación que nunca va a correr.
   Ojo: acá va la SECCIÓN de novedades (título + carrusel), no los slides. Los
   slides viven en un scroller horizontal y view() los mediría contra ese
   scroller: los de más allá del borde quedarían invisibles para siempre. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .grilla-inicio > *,
    .novedades-seccion > * {
      animation: aparecer both;
      animation-timeline: view();
      animation-range: entry 0% entry 50%;
    }
    @keyframes aparecer {
      from { opacity: 0; transform: translateY(22px); }
      to   { opacity: 1; transform: none; }
    }
  }
}

/* Pedir turno en el pulgar, solo en el celular y solo en la home: apenas el
   botón del hero sale de pantalla, aparece uno fijo abajo, donde llega el
   dedo. Si el navegador no sabe de scroll-timeline queda visible siempre —
   apenas menos fino, no roto. */
.cta-flotante { display: none; }
@media (max-width: 780px) {
  .cta-flotante {
    display: inline-flex;
    position: fixed; z-index: 70;
    left: 16px; right: 16px;
    bottom: calc(14px + env(safe-area-inset-bottom, 0px));
    padding: 15px; font-size: 16px; border-radius: 14px;
    box-shadow: 0 10px 30px rgba(15, 169, 141, .4), 0 3px 10px rgba(0, 0, 0, .3);
  }
}
@supports (animation-timeline: scroll()) {
  @media (max-width: 780px) and (prefers-reduced-motion: no-preference) {
    .cta-flotante {
      animation: cta-aparece both;
      animation-timeline: scroll();
      animation-range: 260px 460px;
    }
    @keyframes cta-aparece {
      from { opacity: 0; transform: translateY(80px); }
      to   { opacity: 1; transform: translateY(0); }
    }
  }
}

/* Pie del portal.
   ⚠️ El `position: relative; z-index: 1` no es decorativo: el <footer> no tenía
   `position`, así que pintaba en el paso 4 del orden de pintado, antes que
   cualquier cosa posicionada. El telón vive en z-index:-1 y por eso hoy le pasa
   por detrás igual, pero esto lo deja atado explícitamente: si alguien sube el
   telón a 0 buscando "que se vea más", el pie no se le va abajo del dibujo. */
.portal-pie {
  position: relative; z-index: 1;
  /* El filo de arriba pasa de --linea (#E4E7EF) a la línea del portal. Sobre el
     lienzo, ese gris claro daba 12,7:1: no leía como separador, leía como un
     rayón blanco cruzando la página de lado a lado. */
  border-top: 1px solid var(--portal-linea);
  padding: 28px 0 46px;
  text-align: center;
  color: var(--portal-tinta-3);
  font-size: 13px;
}
.portal-pie .fa { color: var(--portal-tinta-3); }

/* El ÚNICO <a> de todo el portal que vive a la intemperie sobre el lienzo: el
   "Escribir por WhatsApp" del pie (layout/portal.php). Todos los demás links
   están adentro de tarjetas blancas. Sin esta regla gana el `a { color:
   var(--magenta) }` de arriba y queda en 2,75:1 sobre el borgoña, con 13px —
   cuando antes pasaba, porque el pie estaba sobre --fondo claro.
   Con --portal-tinta-2 da 10,78:1. El subrayado va porque sobre una superficie
   de color el link deja de distinguirse sólo por el tono. */
.portal-pie a { color: var(--portal-tinta-2); text-decoration: underline; }
.portal-pie div { margin-top: 6px; }

/* Pasos del turno online (y de cuestionario, diario y estudios: es el mismo
   componente).

   La barra vive SOBRE la banda azul de la subpágina, así que sus colores son
   los de un fondo oscuro. Antes eran los de fondo blanco y el paso en curso
   —índigo sobre el azul noche— casi no se leía.

   En el celular los seis rótulos no entran: envolvían en tres renglones, con
   un guión suelto colgando al principio de cada uno, y la tercera fila quedaba
   cortada al medio por el borde de la banda (el contenido sube 78px y la barra
   medía 94px). De 900px para abajo pasa a ser una barra de progreso —círculo,
   línea, círculo— con el nombre del paso en curso debajo, que es el único que
   hace falta leer mientras se saca el turno. */
.pasos {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 22px; flex-wrap: wrap;
}
.paso {
  display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700;
  color: #A9B4DA;
}
.paso .num {
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(255, 255, 255, .13); color: #C9D1EC;
  display: flex; align-items: center; justify-content: center; font-size: 12.5px;
  flex: 0 0 auto;
  transition: background .18s var(--curva), color .18s var(--curva);
}
.paso.activo { color: #fff; }
.paso.activo .num {
  background: var(--luna); color: var(--noche);
  box-shadow: 0 0 0 4px rgba(143, 160, 238, .2);
}
.paso.hecho { color: #6BD9C0; }
/* Blanco sobre #0FA98D son 2,97:1 y viene fallando desde siempre; es el mismo
   par que se corrigió en .btn-menta. Con #04241E da 5,55:1. */
.paso.hecho .num { background: var(--menta); color: #04241E; }
.paso + .paso::before { content: '—'; color: rgba(255, 255, 255, .3); margin-right: 8px; }

@media (max-width: 900px) {
  .pasos {
    flex-wrap: nowrap; gap: 0;
    padding-bottom: 26px;   /* el renglón del rótulo, que va absoluto */
    margin-bottom: 16px;
  }
  .paso { flex: 0 0 auto; gap: 0; }
  .paso + .paso { flex: 1 1 auto; }  /* crece el que trae la línea de unión */
  .paso .rot { display: none; }
  .paso.activo .rot {
    display: block; position: absolute; left: 0; bottom: 0;
    font-size: 15px; font-weight: 800; color: #fff; white-space: nowrap;
  }
  /* La línea de unión reemplaza al guión: se estira hasta 64px y se va
     pintando de menta a medida que el paciente avanza. El tope es para que
     con dos pasos (cuestionario, diario, estudios) no quede una línea de
     punta a punta con un círculo en cada extremo. */
  .paso + .paso::before {
    content: ''; flex: 1 1 auto; min-width: 10px; max-width: 64px;
    height: 2px; border-radius: 2px; margin: 0 7px;
    background: rgba(255, 255, 255, .22);
    transition: background .25s var(--curva);
  }
  .paso.hecho + .paso::before { background: var(--menta); }
}

.panel-paso { display: none; }
.panel-paso.activo { display: block; }

/* Cuestionario de sueño del portal (/cuestionario). Cada síntoma es una fila
   con tres opciones excluyentes: en escritorio la pregunta a la izquierda y
   Sí/No/A veces a la derecha; en el celular —que es donde se completa de
   verdad, en la sala de espera— la pregunta arriba y las tres opciones abajo,
   a lo ancho y con superficie de dedo. Los radios nativos se ocultan y el
   recuadro entero es el botón. */
.cuest-titulo {
  margin: 30px 0 14px; padding-top: 18px; border-top: 1px solid var(--linea);
  font-size: 16px; color: var(--noche);
}
.cuest-lista { display: flex; flex-direction: column; gap: 10px; }
.cuest-pregunta {
  display: grid; grid-template-columns: 1fr auto; gap: 8px 16px; align-items: center;
  padding: 12px 14px; border: 1px solid var(--linea); border-radius: var(--radio-s);
  background: var(--blanco);
}
.cuest-txt { font-size: 14px; font-weight: 600; color: var(--tinta); }
.cuest-ops { display: flex; gap: 6px; }
.cuest-op { position: relative; }
.cuest-op input { position: absolute; opacity: 0; width: 0; height: 0; }
.cuest-op span {
  display: block; padding: 7px 14px; border: 1.5px solid var(--linea); border-radius: 999px;
  font-size: 13px; font-weight: 700; color: var(--tinta-2); cursor: pointer;
  transition: all .12s; white-space: nowrap;
}
.cuest-op span:hover { border-color: var(--indigo); color: var(--indigo); }
.cuest-op input:checked + span { background: var(--indigo); border-color: var(--indigo); color: #fff; }
/* Foco visible al recorrer el formulario con el teclado (el radio está oculto) */
.cuest-op input:focus-visible + span { outline: 2px solid var(--luna); outline-offset: 2px; }
/* El detalle ocupa la fila entera, debajo de la pregunta y las opciones */
.cuest-detalle { grid-column: 1 / -1; }
.cuest-detalle input, .cuest-detalle select {
  width: 100%; border: 1px solid var(--linea); border-radius: var(--radio-s);
  padding: 7px 10px; font-family: var(--fuente); font-size: 13px; color: var(--tinta);
  background: var(--blanco);
}
.cuest-detalle input:focus, .cuest-detalle select:focus { outline: none; border-color: var(--indigo); }
@media (max-width: 700px) {
  .cuest-pregunta { grid-template-columns: 1fr; }
  .cuest-ops { width: 100%; }
  .cuest-op { flex: 1; }
  .cuest-op span { text-align: center; padding: 11px 6px; font-size: 14px; }
  .cuest-detalle input, .cuest-detalle select { font-size: 16px; padding: 10px 12px; }
}

/* ---------------------------------------------------------------------------
   CARRUSEL (lo usa Novedades del centro, al pie de la home)

   La base es un scroller horizontal con scroll-snap, no JavaScript: la tira
   existe y se arrastra con el dedo o con la rueda aunque el script no cargue.
   portal-novedades.js le agrega arriba el avance solo, las flechas, los
   puntitos y el botón de pausa, y esos controles los CREA él: si el archivo no
   carga, no queda ni una flecha muerta en pantalla. Por eso acá hay estilos de
   elementos que en el HTML del servidor no existen.

   scroll-snap-type va en 'x mandatory' para que nunca quede medio slide a la
   vista; la scrollbar horizontal se esconde porque los controles ya dicen
   dónde estás y en escritorio una barra gris debajo de las fotos ensucia.
   --------------------------------------------------------------------------- */
.carrusel { position: relative; }
.carrusel-pista {
  display: flex;
  gap: 18px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Aire arriba y abajo para que la sombra de las tarjetas no quede cortada
     por el overflow, devuelto con margen negativo.
     A los costados NO va padding, a propósito: el padding horizontal de un
     scroller desplaza el origen del scroll, y entonces "estar en el slide 0"
     deja de ser scrollLeft = 0. El JS mide posiciones con offsetLeft y ese
     desfase le rompía la cuenta —el último slide y la vuelta al primero
     quedaban corridos—. Lo único que se pierde es la sombra lateral, que con
     blur 24 al 7% y el borde de 1px puesto no se extraña. */
  padding: 4px 0 14px;
  margin: -4px 0 -14px;
  scrollbar-width: none;
}
.carrusel-pista::-webkit-scrollbar { display: none; }
/* Quien pidió menos movimiento igual ve pasar las novedades —si no, el
   carrusel le queda muerto—, pero sin el barrido lateral: el slide cambia de
   golpe. Lo que molesta de un carrusel es el desplazamiento, no que el
   contenido cambie. El JS hace lo mismo del lado suyo. */
@media (prefers-reduced-motion: reduce) {
  .carrusel-pista { scroll-behavior: auto; }
  .novedad-foto img { transition: none; }
}
/* La tira se puede recorrer con el teclado (flechas), así que tiene que
   mostrar el foco — pero solo cuando se llegó tabulando, no al hacer clic. */
.carrusel-pista:focus { outline: none; }
.carrusel-pista:focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; border-radius: var(--radio); }
/* 'start' y no 'center': el slide se pega al borde izquierdo y el siguiente
   asoma a la derecha. Además hace que la posición de cada slide sea
   exactamente su offsetLeft, que es lo que mide el JS para saber dónde está —
   con 'center' los extremos no pueden centrarse y el número no cierra. */
.carrusel-slide {
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: start;
}

/* Flechas: círculos flotando sobre los bordes del slide. Las dibuja el JS.
   En el celular no van (ocupan lugar sobre la foto y ahí se usa el dedo). */
.carrusel-flecha {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--linea); background: rgba(255, 255, 255, .92);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  color: var(--noche); font-size: 20px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: var(--sombra);
  transition: background .18s var(--curva), transform .18s var(--curva), opacity .18s var(--curva);
}
.carrusel-flecha:hover { background: #fff; transform: translateY(-50%) scale(1.06); }
.carrusel-flecha:focus-visible { outline: 2px solid var(--indigo); outline-offset: 3px; }
.carrusel-antes { left: -10px; }
.carrusel-despues { right: -10px; }

/* Pie: puntitos a la izquierda y pausa a la derecha. También lo dibuja el JS. */
.carrusel-pie {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin-top: 18px;
}
.carrusel-puntos { display: flex; align-items: center; gap: 8px; }
.carrusel-punto {
  width: 9px; height: 9px; padding: 0; border: 0; border-radius: 999px;
  background: #CFD5E6; cursor: pointer;
  transition: width .3s var(--curva), background .3s var(--curva);
}
.carrusel-punto:hover { background: var(--luna); }
.carrusel-punto:focus-visible { outline: 2px solid var(--indigo); outline-offset: 3px; }
/* El activo se estira en vez de solo cambiar de color: se ve de reojo, sin
   depender de distinguir dos grises. Y ADEMÁS es el reloj: se llena de índigo
   de izquierda a derecha mientras corre el tiempo del slide, y se congela si
   se pausa. Va acá y no en una barra aparte para no sumar otro elemento que
   diga lo mismo — el JS solo mueve la variable --llenado. */
.carrusel-punto[aria-selected="true"] {
  width: 28px;
  background-color: #CFD5E6;
  background-image: linear-gradient(var(--indigo), var(--indigo));
  background-repeat: no-repeat;
  background-size: var(--llenado, 100%) 100%;
  transition: width .3s var(--curva), background-size .12s linear;
}
.carrusel-pausa {
  width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--tinta-3); font-size: 13px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .18s var(--curva), color .18s var(--curva);
}
.carrusel-pausa:hover { background: var(--azul-suave); color: var(--indigo); }
.carrusel-pausa:focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; }

@media (max-width: 900px) {
  .carrusel-flecha { display: none; }
}

/* ---------------------------------------------------------------------------
   Novedades del centro — cada novedad es un slide GRANDE: la foto ocupa el
   rectángulo entero y el texto se apoya encima, abajo, chico, sobre un
   degradado oscuro. Antes eran tarjetas de 280px con la foto recortada a
   180px, donde una foto de equipamiento no se entendía.

   La altura va en vh y no en px: la idea es que la sección se coma un buen
   pedazo de pantalla en cualquier monitor, pero con tope para que en una
   pantalla 4K no quede una foto de dos metros. El mínimo en px es para que en
   una notebook baja y apaisada no se aplaste a una banda.
   --------------------------------------------------------------------------- */
.novedades-seccion { margin-top: clamp(44px, 4.5vw, 72px); }
.novedades-titulo { margin-bottom: 22px; }
.novedades-titulo h2 { font-size: clamp(21px, 1.2vw + 14px, 27px); margin-bottom: 4px; }
.novedades-titulo p { margin: 0; }
/* Los dos encabezados que viven SUELTOS sobre el lienzo, sin tarjeta que los
   contenga: el de Novedades y el de Experiencias, que reusa esta misma pieza.
   Hasta ayer heredaban la tinta oscura del panel y sobre el azul quedaban en
   2,2:1 — el título más grande de la mitad de abajo, ilegible.
   ⚠️ Va scopeado a `.novedades-titulo`, NO a `.subtexto` suelta: esa clase
   también se usa adentro de las tarjetas blancas de los formularios, y teñirla
   de claro ahí deja el texto de ayuda en blanco sobre blanco. */
.portal-body .novedades-titulo h2 { color: var(--portal-tinta); }
.portal-body .novedades-titulo p  { color: var(--portal-tinta-2); }

.novedad {
  position: relative;
  min-height: clamp(380px, 58vh, 620px);
  border-radius: var(--radio);
  overflow: hidden;
  box-shadow: var(--sombra);
  /* Azul noche debajo de la foto: mientras la imagen baja, el slide ya tiene
     el color de la marca en vez de un rectángulo gris. */
  background: var(--noche-3);
  /* El texto vive abajo; por eso la caja empuja su contenido al piso. */
  display: flex; flex-direction: column; justify-content: flex-end;
}

/* La foto, de fondo y a sangre. Con inset:0 no aporta altura —la manda el
   min-height del slide— así que da igual lo que suban desde el panel: una foto
   de celular vertical o una lámina alta y angosta se recortan para llenar. */
.novedad-foto {
  position: absolute; inset: 0; z-index: 1;
  display: block; overflow: hidden; background: var(--noche-3);
}
.novedad-foto img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  transition: transform .6s var(--curva);
}
/* Velo apenas perceptible sobre la foto entera. Está por las fotos CLARAS: una
   lámina de fondo blanco dejaba el texto de abajo ilegible aun con el
   degradado, porque el degradado suma poco sobre blanco puro. Al 12% no se
   nota en una foto normal y salva el caso feo. */
.novedad-foto::after {
  content: ''; position: absolute; inset: 0;
  background: rgba(14, 19, 38, .12);
}
.novedad:hover .novedad-foto img { transform: scale(1.04); }
.novedad-foto:focus-visible { outline: 3px solid var(--luna); outline-offset: -6px; }

/* El texto va ARRIBA del <a> de la foto en el orden de capas (z-index 2 contra
   1). Así tocar la foto la abre en grande y tocar el texto no dispara nada: se
   puede leer y seleccionar tranquilo. El degradado nace transparente bien
   arriba para que el corte no se vea como una banda pegada. */
/* El degradado es fuerte y con recorrido largo a propósito: el texto blanco
   tiene que leerse sobre CUALQUIER foto que suban del panel, y no hay forma de
   saber de antemano si el pie de la imagen va a ser un cielo oscuro o una
   pared blanca. Abajo es casi opaco y se apaga recién arriba, así que el
   corte no se ve como una banda pegada sino como sombra de la propia foto. */
.novedad-cuerpo {
  position: relative; z-index: 2;
  padding: clamp(56px, 10vh, 120px) clamp(22px, 3vw, 46px) clamp(20px, 2.4vw, 34px);
  background: linear-gradient(to top,
              rgba(10, 14, 30, .97) 0%,
              rgba(10, 14, 30, .94) 34%,
              rgba(10, 14, 30, .90) 56%,
              rgba(10, 14, 30, .55) 74%,
              rgba(10, 14, 30, 0) 100%);
  color: #fff;
}
/* La sombra del texto es el cinturón de seguridad: si alguna vez sube una foto
   blanquísima y el degradado no alcanza, el texto igual se despega del fondo. */
/* La fecha es el renglón de arriba de todo, o sea el que cae en la parte más
   floja del degradado, y encima es chica y en mayúsculas. Medida contra una
   foto de fondo blanco quedaba en 4,17:1 —por debajo del 4,5:1 que pide AA
   para texto chico—, así que va bastante más clara que el azul luna. */
.novedad-fecha {
  font-size: 11.5px; font-weight: 800; color: #DCE4FB;
  text-transform: uppercase; letter-spacing: .8px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .55);
}
.novedad-cuerpo h3 {
  margin: 8px 0 0; font-size: clamp(20px, 1.5vw + 12px, 32px); line-height: 1.2;
  color: #fff; max-width: 24ch;
  text-shadow: 0 2px 10px rgba(0, 0, 0, .5), 0 1px 2px rgba(0, 0, 0, .4);
  /* Un título kilométrico no puede tapar media foto */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
/* El detalle es letra chica y corta a propósito: dos renglones que dan el
   contexto. Lo que manda en el slide es la foto, no el párrafo — para leer
   todo está la novedad completa. El texto entero sigue en el HTML (buscadores
   y lectores de pantalla lo leen igual). */
.novedad-cuerpo p {
  margin: 8px 0 0; font-size: 14px; color: #CFD6EC; line-height: 1.5;
  max-width: 56ch;
  text-shadow: 0 1px 4px rgba(0, 0, 0, .5);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}

/* Una novedad sin foto es un aviso de texto, no una tarjeta a la que le falta
   algo: toma el cielo del hero, el texto se centra y crece, y mide igual que
   las demás (la tira es flex con stretch). Sin esto quedaba un rectángulo
   enorme vacío que parecía una foto que no cargó. */
.novedad-sin-foto {
  background:
    radial-gradient(700px 380px at 50% -20%, rgba(143, 160, 238, .28), transparent 70%),
    linear-gradient(168deg, var(--noche-3), var(--noche) 60%, var(--noche-2));
  justify-content: center;
}
.novedad-sin-foto .novedad-cuerpo {
  background: none;
  text-align: center;
  padding: clamp(30px, 4vw, 56px) clamp(24px, 5vw, 72px);
}
.novedad-sin-foto .novedad-cuerpo h3 { max-width: none; -webkit-line-clamp: 3; }
.novedad-sin-foto .novedad-cuerpo p {
  margin-inline: auto; max-width: 62ch; font-size: 15px; -webkit-line-clamp: 4;
}

/* Celular: el slide se estira a lo alto (una foto apaisada en una pantalla
   angosta es una franja fina) y no ocupa el 100% del ancho a propósito —
   asoma el borde del siguiente, que es lo que avisa "esto se corre" sin
   ningún cartel. */
@media (max-width: 820px) {
  .carrusel-slide { flex-basis: 90%; }
  .novedad { min-height: clamp(400px, 62vh, 560px); }
  .novedad-cuerpo { padding: 56px 20px 22px; }
  /* Las paradas del degradado van comprimidas hacia arriba, no copiadas del
     escritorio: acá el bloque de texto es más bajo, así que con la rampa larga
     la fecha caía en la zona floja y medía 4,43:1 contra una foto blanca —
     abajo del 4,5:1 de AA. Con estas paradas queda en 11:1. */
  .novedad-cuerpo {
    background: linear-gradient(to top,
                rgba(10, 14, 30, .97) 0%,
                rgba(10, 14, 30, .95) 46%,
                rgba(10, 14, 30, .90) 68%,
                rgba(10, 14, 30, .50) 86%,
                rgba(10, 14, 30, 0) 100%);
  }
  .novedad-sin-foto .novedad-cuerpo { background: none; }
  /* Tres líneas y no dos: en una pantalla angosta un título de largo normal
     entraba justo y se cortaba con puntos suspensivos a media palabra. */
  .novedad-cuerpo h3 { font-size: 22px; max-width: none; -webkit-line-clamp: 3; }
  .novedad-cuerpo p { font-size: 13.5px; }
  .novedad-sin-foto .novedad-cuerpo { padding: 28px 22px; }
}

/* Experiencias de pacientes (página principal). Misma lógica que las
   novedades: cantidad variable cargada desde el panel, grilla auto-fill.
   Reusa .novedades-titulo para el encabezado, así los dos bloques del pie
   de la home se ven hermanos. */
.experiencias-seccion { margin-top: clamp(44px, 4.5vw, 72px); }
.experiencias-grilla {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 18px;
}
.experiencia {
  background: var(--blanco); border: 1px solid var(--linea); border-radius: var(--radio);
  box-shadow: var(--sombra); padding: 20px 22px;
  display: flex; flex-direction: column; gap: 12px;
}
.experiencia-carita { display: flex; align-items: center; gap: 9px; }
.experiencia-carita span[aria-hidden] { font-size: 28px; line-height: 1; }
.experiencia-nota {
  font-size: 12px; font-weight: 800; color: var(--tinta-3);
  text-transform: uppercase; letter-spacing: .4px;
}
.experiencia-texto {
  margin: 0; font-size: 14.5px; color: var(--tinta-2); line-height: 1.6; flex: 1;
}
.experiencia-pie { display: flex; flex-direction: column; gap: 2px; font-size: 13.5px; }
.experiencia-pie span { color: var(--tinta-3); font-size: 12.5px; }
.experiencias-cta { text-align: center; margin: 26px 0 0; }
@media (max-width: 700px) {
  .experiencias-grilla { grid-template-columns: 1fr; }
}

/* Formulario de /experiencia */
/* La trampa anti-bots: fuera de pantalla, no display:none — algunos bots
   saltean lo que está display:none y justo a ese campo lo tienen que "ver". */
.campo-trampa {
  position: absolute; left: -9999px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
}
.exp-caritas legend, .exp-radios { margin-bottom: 6px; }
.caritas-fila { display: flex; gap: 8px; flex-wrap: wrap; }
.carita {
  position: relative; /* contiene al input escondido */
  flex: 1 1 0; min-width: 74px; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  border: 1.5px solid var(--linea); border-radius: 12px; padding: 12px 6px 9px;
  transition: border-color .12s, background .12s, transform .12s;
}
.carita:hover { border-color: var(--luna); transform: translateY(-1px); }
.carita-emoji { font-size: 30px; line-height: 1; filter: grayscale(.55); transition: filter .12s, transform .12s; }
.carita-label { font-size: 12px; font-weight: 700; color: var(--tinta-3); text-align: center; }
/* El radio queda accesible (foco con teclado incluido) pero no se dibuja:
   la carita entera es el control. */
.carita input {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.carita:has(input:checked) { border-color: var(--indigo); background: rgba(64,89,201,.06); }
.carita:has(input:checked) .carita-emoji { filter: none; transform: scale(1.12); }
.carita:has(input:checked) .carita-label { color: var(--indigo); }
.carita:has(input:focus-visible) { outline: 2px solid var(--indigo); outline-offset: 2px; }
/* Sin :has (navegadores viejos) las caritas no marcan el borde, pero el
   emoji igual se ve elegido: */
.carita input:checked + .carita-emoji { filter: none; transform: scale(1.12); }
.exp-radios { display: flex; gap: 18px; flex-wrap: wrap; }
.exp-radios label { display: flex; align-items: center; gap: 8px; cursor: pointer; font-weight: 600; }
.exp-radios input { width: auto; margin: 0; accent-color: var(--indigo); transform: scale(1.15); }
.exp-radios-columna { flex-direction: column; gap: 9px; align-items: flex-start; }

.grilla-horarios { display: grid; grid-template-columns: repeat(auto-fill, minmax(86px, 1fr)); gap: 9px; }
/* El aviso de "elegí una fecha primero" es texto, no un horario: si entra en la
   grilla queda en una columna de 86 px y se lee en seis renglones. */
.grilla-horarios > .subtexto { grid-column: 1 / -1; }
.chip-hora {
  border: 1.5px solid var(--linea); background: var(--blanco); border-radius: 10px;
  padding: 9px 4px; text-align: center; font-weight: 700; font-size: 14px;
  cursor: pointer; font-family: var(--fuente); transition: all .12s;
}
.chip-hora:hover { border-color: var(--indigo); color: var(--indigo); }
.chip-hora.elegido { background: var(--indigo); border-color: var(--indigo); color: #fff; }

/* Opciones de médico (paso del wizard) */
.opciones-medico { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.opcion-medico {
  display: flex; align-items: center; gap: 12px; cursor: pointer;
  border: 1.5px solid var(--linea); border-radius: 12px; padding: 14px 16px;
  transition: border-color .12s, background .12s;
}
.opcion-medico:hover { border-color: var(--luna); }
.opcion-medico input { width: auto; margin: 0; accent-color: var(--indigo); transform: scale(1.2); }
.opcion-medico.elegida { border-color: var(--indigo); background: rgba(64,89,201,.05); }
.opcion-medico-cuerpo { display: flex; flex-direction: column; }
.opcion-medico-nombre { font-weight: 700; color: var(--tinta); }
.opcion-medico-esp { font-size: 12.5px; color: var(--tinta-2); }

/* Navegación mes a mes del paso "elegí el día" del wizard público */
.nav-meses {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-bottom: 14px; flex-wrap: wrap;
}
.nav-meses-titulo { font-weight: 800; color: var(--tinta); text-transform: capitalize; }

.grilla-dias { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 9px; }
.chip-dia {
  border: 1.5px solid var(--linea); background: var(--blanco); border-radius: 12px;
  padding: 10px 6px; text-align: center; cursor: pointer; font-family: var(--fuente); transition: all .12s;
}
.chip-dia .dia-semana { font-size: 11.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--tinta-3); font-weight: 800; }
.chip-dia .dia-num { font-size: 19px; font-weight: 800; }
.chip-dia .dia-mes { font-size: 12px; color: var(--tinta-2); }
.chip-dia:hover { border-color: var(--indigo); }
.chip-dia.elegido { background: var(--indigo); border-color: var(--indigo); }
.chip-dia.elegido * { color: #fff; }

/* Las tres alertas, PERO sólo las que quedan a la intemperie: las que son hijas
   directas de .portal-contenido en estudios.php:28, cuestionario.php:26 y
   diario.php:116. Ésas son las únicas que no tienen una tarjeta blanca abajo;
   las de adentro de un formulario siguen pastel sobre papel, que es correcto.
   Sobre el lienzo el pastel dejaba de ser un aviso: un rectángulo casi blanco
   con texto casi blanco, y el rojo del error se leía como un cartel apagado.
   Ahora son tinta clara sobre el propio color al 18%, con el borde marcando el
   recorte (8,2:1 el rojo, el peor de los tres).
   ⚠️ La posición en el archivo da igual: estos selectores pesan (0,3,0) y las
   reglas base `.alerta-rojo` etc. pesan (0,1,0), así que ganan estén donde
   estén — no hay que acordarse de mantenerlas debajo. */
.portal-body .portal-contenido > .alerta-rojo  { background: rgba(214, 69, 80, .18);  border: 1px solid rgba(214, 69, 80, .42);  color: #FFB9BE; }
.portal-body .portal-contenido > .alerta-menta { background: rgba(15, 169, 141, .18); border: 1px solid rgba(15, 169, 141, .42); color: #8FE6D2; }
.portal-body .portal-contenido > .alerta-ambar { background: rgba(222, 155, 45, .18); border: 1px solid rgba(222, 155, 45, .42); color: #F5D296; }

/* ---------------------------------------------------------------- Login */
.login-fondo {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  /* Sin estrellitas (parecen píxeles muertos): resplandores grandes, como el hero. */
  background:
    radial-gradient(900px 480px at 82% -10%, rgba(143, 160, 238, .26), transparent 68%),
    radial-gradient(700px 420px at -8% 108%, rgba(64, 89, 201, .28), transparent 70%),
    linear-gradient(160deg, var(--noche-3), var(--noche) 60%, var(--noche-2));
  padding: 20px;
}
.login-caja {
  background: var(--blanco); border-radius: 20px; box-shadow: var(--sombra-flotante);
  width: 100%; max-width: 410px; padding: 36px 34px 26px;
  position: relative; overflow: hidden;
}
/* Filete de color arriba de la caja */
.login-caja::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: linear-gradient(90deg, var(--indigo), var(--menta));
}
.login-marca { display: flex; align-items: center; gap: 12px; padding-bottom: 18px; }
.login-marca .logo-coms { width: 46px; height: 46px; }
.login-marca-txt strong { display: block; color: var(--tinta); font-size: 18px; line-height: 1.2; letter-spacing: .04em; }
.login-marca-txt span { color: var(--tinta-2); font-size: 12.5px; }

.login-bienvenida { padding-bottom: 20px; }
.login-bienvenida h1 { font-size: 20px; color: var(--noche); margin: 0 0 3px; }
.login-bienvenida p { font-size: 13.5px; color: var(--tinta-2); margin: 0; line-height: 1.45; }

/* Inputs con ícono a la izquierda (la pantalla de entrada).

   Dos cosas que este bloque tiene que resolver, y que antes resolvía mal:

   1) El ícono NO se ubica a mano con un `top: <px>` fijo. Ese número tenía que
      adivinar cuánto mide el label de arriba más el padding del campo, y en el
      celular —donde el input crece a 16 px de fuente para que el teléfono no
      haga zoom al tocarlo— quedaba corrido hacia arriba. Acá el ícono y el
      input comparten la MISMA celda de un grid: `align-self: center` lo centra
      contra la altura real del campo, mida lo que mida.

   2) El hueco del ícono se declara con `.campo.campo-icono` (la clase repetida)
      y no con `.campo-icono` a secas. Más abajo, el bloque del celular pisa el
      padding de todos los campos con el atajo `padding: 11px 12px`, y un atajo
      reescribe también el `padding-left`: en el teléfono el texto arrancaba a
      12 px, es decir ENCIMA del ícono, y el monito se comía la primera letra
      del usuario y el candado el primer punto de la contraseña (10 px de
      superposición, medidos a 390 px de ancho). Con la clase repetida esta
      regla gana por especificidad y ya no depende de quién se declaró último. */
.campo-icono { display: grid; position: relative; }
.campo-icono > label { grid-column: 1; grid-row: 1; }
.campo-icono > .campo-ico {
  grid-column: 1; grid-row: 2;
  align-self: center; justify-self: start;
  margin-left: 12px;
  /* El input viene después en el HTML y tiene fondo opaco: sin esto se dibuja
     encima y el ícono desaparece en vez de quedar mal puesto. */
  position: relative; z-index: 2;
  color: var(--tinta-3); font-size: 14px; pointer-events: none;
}
.campo-icono > input { grid-column: 1; grid-row: 2; }
.campo.campo-icono input[type=text], .campo.campo-icono input[type=email],
.campo.campo-icono input[type=password], .campo.campo-icono input[type=tel] { padding-left: 36px; }

.btn-login { width: 100%; justify-content: center; padding: 12px; font-size: 15px; margin-top: 4px; }

.login-pie {
  text-align: center; font-size: 11.5px; color: var(--tinta-3);
  margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--linea);
}
.login-pie i { color: var(--menta); }

/* --- Paso 2 del login: el código que llegó por mail (tanda 87) --- */

/* Los 6 dígitos, grandes y separados. El `ch` del letter-spacing es a
   propósito: con una tipografía de ancho variable, un espaciado en px deja los
   números bailando y cuesta leer si son cinco o seis. */
.campo-codigo {
  text-align: center; font-size: 30px; font-weight: 700;
  letter-spacing: .35ch; font-variant-numeric: tabular-nums;
  padding: 12px 10px; color: var(--noche);
}
.campo-codigo::placeholder { color: var(--linea); letter-spacing: .35ch; font-weight: 600; }

.login-check { display: flex; align-items: flex-start; gap: 9px; margin: 2px 0 14px; font-size: 13.5px; color: var(--tinta); }
.login-check input { margin-top: 3px; flex-shrink: 0; }
.login-check small { display: block; font-size: 12px; color: var(--tinta-3); line-height: 1.4; margin-top: 2px; }

.login-reenviar { text-align: center; font-size: 12.5px; color: var(--tinta-3); margin-top: 14px; }
.login-reenviar a { color: var(--indigo); font-weight: 600; text-decoration: none; }
.login-reenviar a:hover { text-decoration: underline; }
.login-reenviar .sep { margin: 0 6px; color: var(--linea); }

.alerta { border-radius: var(--radio-s); padding: 11px 14px; font-size: 13.5px; font-weight: 600; margin-bottom: 15px; }
.alerta-rojo { background: var(--rojo-suave); color: var(--rojo); }
.alerta-menta { background: var(--menta-suave); color: #0B7A66; }
.alerta-ambar { background: var(--ambar-suave); color: #8A5F10; }

/* Cinta del punto de vista: el admin mirando el panel como otro rango.
   Ámbar y pegada abajo de la topbar (sticky, arriba del contenido) porque
   tiene que verse SIEMPRE: es el aviso de que faltan cosas a propósito. */
.cinta-vista {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 28px;
  background: var(--ambar-suave);
  border-bottom: 1px solid #EBD9AE;
  color: #8A5F10; font-size: 13px; font-weight: 600;
  position: sticky; top: 62px; z-index: 39;
}
.cinta-vista .fa { font-size: 14px; }
.cinta-vista strong { font-weight: 800; }
.cinta-vista a {
  margin-left: auto;
  color: #8A5F10; font-weight: 800; text-decoration: underline;
  white-space: nowrap;
}
/* La salida, también en el pie del menú: la cinta se puede perder de vista al
   bajar en una pantalla larga, el menú no. */
.sidebar .pie a.pie-salir-vista { color: #fff; font-weight: 800; }
@media (max-width: 760px) {
  /* La topbar baja de 62 a 56px en el celular (bloque "EL PANEL EN EL
     CELULAR"), así que la cinta la sigue: con 62 quedaba una franja de fondo
     asomando entre las dos al hacer scroll. */
  .cinta-vista { padding: 9px 12px; top: 56px; font-size: 12.5px; }
  .cinta-vista a { margin-left: 0; }
}

/* Campo con un dato inválido (ej. un email mal escrito en el portal) */
.campo-invalido, .campo input.campo-invalido {
  border-color: var(--rojo) !important;
  background: var(--rojo-suave);
}
.error-campo { font-size: 12.5px; font-weight: 600; color: var(--rojo); margin-top: 5px; }

/* Responsive del panel: TODO junto al final de esta hoja, en el bloque
   "EL PANEL EN EL CELULAR" (tanda 79). Acá queda solo el botón escondido,
   que es lo que decide si el panel está en modo escritorio o en modo cajón. */
.menu-movil { display: none; }

/* ------------------------------------------------------------------------
   Celular: la agenda del día y el alta de turno, que es lo que recepción usa
   todo el día. El objetivo es que se pueda operar con el pulgar y sin zoom.
   ------------------------------------------------------------------------ */
@media (max-width: 700px) {
  /* Los inputs por debajo de 16px hacen que el navegador del celular haga
     zoom al tocarlos, y después la página queda corrida. */
  .campo input[type=text], .campo input[type=email], .campo input[type=date],
  .campo input[type=time], .campo input[type=number], .campo input[type=password],
  .campo input[type=tel], .campo select, .campo textarea { font-size: 16px; padding: 11px 12px; }

  /* Botones y controles con superficie de dedo (~44 px) */
  .btn { padding: 11px 16px; }
  .btn-chico { padding: 9px 13px; font-size: 13.5px; }
  .agenda-nav .btn-chico { flex: 1; text-align: center; }
  .agenda-nav input[type=date] { flex: 1 0 100%; font-size: 16px; padding: 10px 12px; }

  .agenda-cabecera { flex-direction: column; align-items: stretch; gap: 12px; }
  .agenda-cabecera .agenda-nav { width: 100%; }
  /* "Nuevo turno" es la acción principal: ocupa todo el ancho, al alcance del pulgar */
  .agenda-nav [data-abrir-modal="modal-turno"] { flex: 1 0 100%; padding: 13px; font-size: 15px; }

  .agenda-selector-medico { flex-wrap: wrap; }
  .agenda-selector-medico select { flex: 1 0 100%; font-size: 16px; }
  .agenda-selector-medico .agenda-franja { flex: 1 0 100%; }
  .agenda-selector-medico a { margin-left: 0 !important; }

  /* Cada turno pasa a ocupar el ancho completo: hora arriba, datos abajo y
     los botones en su propia fila, en vez de tres columnas apretadas. */
  .slot { flex-wrap: wrap; gap: 8px 12px; padding: 12px; }
  .slot .hora { width: auto; font-size: 17px; }
  .slot .detalle { flex: 1 0 calc(100% - 70px); }
  .slot .acciones { flex: 1 0 100%; }
  .slot .acciones .btn { flex: 1; justify-content: center; }
  /* Sin hover en el celular: el botón de apartar tiene que verse siempre */
  .slot.libre .acciones { opacity: 1; }

  /* El modal ocupa la pantalla: se aprovecha el alto y no queda nada cortado */
  .modal-fondo { padding: 0; align-items: flex-end; }
  .modal-caja { max-width: 100%; border-radius: 18px 18px 0 0; padding: 18px 16px 28px; max-height: 94vh; overflow-y: auto; }
  .modal-caja .encabezado h2 { font-size: 18px; }
  .modal-caja .btn-primario { width: 100%; justify-content: center; padding: 13px; font-size: 15px; }

  /* Horarios del modal: menos columnas y más grandes, para no errarle */
  .grilla-horarios { grid-template-columns: repeat(auto-fill, minmax(78px, 1fr)); gap: 8px; }
  .chip-hora { padding: 12px 6px; font-size: 15px; }

  /* Sugerencias del buscador de pacientes: filas cómodas de tocar */
  #nt-sugerencias > div { padding: 13px 14px !important; font-size: 15px; }

  .agenda-resumen { flex-wrap: wrap; gap: 10px; }
  .agenda-resumen .resumen-item { margin-left: 0 !important; }
}

/* ============================================================================
   La marca (logo + nombre) es un link al inicio — tanda 69
   ----------------------------------------------------------------------------
   Pasó de <div> a <a> en las tres pantallas donde aparece (barra del portal,
   sidebar del panel y login). Sin esto heredaría el color y el subrayado de
   los links, y el logo del panel se vería celeste sobre el azul noche.
   ============================================================================ */
.marca, .login-marca {
  text-decoration: none;
  color: inherit;
  transition: opacity .15s ease;
}
.marca:hover, .login-marca:hover { opacity: .82; }
/* El foco por teclado tiene que verse: es un link real. */
.marca:focus-visible, .login-marca:focus-visible {
  outline: 2px solid var(--luna);
  outline-offset: 3px;
  border-radius: var(--radio-s);
}

/* ============================================================================
   Diario de sueño (/diario + pestaña de la ficha) — tanda 68
   ============================================================================ */

/* El botón de guardar, bien grande (pedido de Santino: que nadie se vaya sin
   guardar). Full-width y más alto que cualquier otro botón del portal. */
.btn-guardar-diario {
  width: 100%;
  justify-content: center;
  padding: 16px 20px;
  font-size: 17px;
  font-weight: 800;
  margin-top: 14px;
}

/* Grilla de las 14 noches del ciclo (portal: pantalla del día y de éxito) */
.diario-grilla {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  margin: 14px 0 6px;
}
.diario-celda {
  width: 34px;
  height: 34px;
  border-radius: 9px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 700;
  background: var(--fondo);
  border: 1px solid var(--linea);
  color: var(--tinta-3);
}
.diario-celda.cargada {
  background: var(--menta-suave);
  border-color: var(--menta);
  color: var(--menta);
}
.diario-celda.hoy {
  background: var(--azul-suave);
  border-color: var(--indigo);
  color: var(--indigo);
}
.diario-celda.futura { opacity: 0.55; }

/* Selector de noche (anoche / antenoche) */
.diario-noches { display: flex; flex-direction: column; gap: 8px; margin-bottom: 6px; }
.diario-noche-op {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  cursor: pointer;
  background: var(--blanco);
}
.diario-noche-op:has(input:checked) {
  border-color: var(--indigo);
  background: var(--azul-suave);
}
.diario-noche-op input { margin-top: 3px; }
.diario-ya-cargada {
  display: block;
  font-style: normal;
  font-size: 12.5px;
  color: var(--menta);
  font-weight: 700;
}

/* Calidad del sueño 1-5: botones grandes, tocables desde el celular */
.diario-calidad { display: flex; gap: 8px; flex-wrap: wrap; }
.diario-cal-op {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  min-width: 56px;
  position: relative;
}
.diario-cal-op input { position: absolute; opacity: 0; pointer-events: none; }
.diario-cal-num {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 800;
  background: var(--fondo);
  border: 1.5px solid var(--linea);
  color: var(--tinta-2);
}
.diario-cal-lbl { font-size: 11.5px; color: var(--tinta-2); text-align: center; }
.diario-cal-op:has(input:checked) .diario-cal-num {
  border-color: var(--indigo);
  background: var(--indigo);
  color: var(--blanco);
}
.diario-cal-op:has(input:checked) .diario-cal-lbl { color: var(--indigo); font-weight: 700; }

/* Gráfico del ciclo en la ficha del panel: 14 barras CSS (alto = horas
   dormidas, color = calidad), sin ninguna librería. */
.diario-barras {
  display: flex;
  align-items: flex-end;
  gap: 5px;
  height: 120px;
  padding: 8px 4px 0;
  border-bottom: 1px solid var(--linea);
}
.diario-barra {
  flex: 1;
  min-width: 10px;
  border-radius: 4px 4px 0 0;
  background: var(--luna);
}
.diario-barra.sin-dato { background: var(--fondo); border: 1px dashed var(--linea); height: 100% !important; }
.diario-barra.cal-1 { background: var(--rojo); }
.diario-barra.cal-2 { background: #E07B47; }
.diario-barra.cal-3 { background: var(--ambar); }
.diario-barra.cal-4 { background: #6FBF9A; }
.diario-barra.cal-5 { background: var(--menta); }
.diario-barras-pie {
  display: flex;
  gap: 5px;
  padding: 4px 4px 0;
  font-size: 10.5px;
  color: var(--tinta-3);
}
.diario-barras-pie span { flex: 1; min-width: 10px; text-align: center; }

/* ===========================================================================
   ÍNDICE DE MASA CORPORAL
   ===========================================================================

   Dos piezas que comparten los colores de categoría:

   1. `.imc-vivo` — el resultado que aparece solo debajo de peso/altura en los
      formularios de carga (lo pinta app.js).
   2. `.imc-tarjeta` y la escala — la pantalla "Calculadora de IMC" del panel.

   El color NO es decorativo: dice de un vistazo en qué franja cayó el paciente.
   Se toman los mismos verde/ámbar/rojo que ya usa el resto del sistema para
   normal / atención / fuera de rango, para que signifiquen lo mismo acá. */
/* El aviso de "esto está en la otra unidad". No es un resultado ni un error de
   validación: es la pantalla diciendo qué esperaba. Va en ámbar, como el resto
   de los avisos del sistema, y NO en rojo — no se rompió nada. */
.imc-aviso     { --imc-fondo: var(--ambar-suave); --imc-texto: #A87516; font-weight: 600; }

.imc-bajo      { --imc-color: var(--ambar);  --imc-fondo: var(--ambar-suave); --imc-texto: #A87516; }
.imc-normal    { --imc-color: var(--menta);  --imc-fondo: var(--menta-suave); --imc-texto: var(--menta); }
.imc-sobrepeso { --imc-color: var(--ambar);  --imc-fondo: var(--ambar-suave); --imc-texto: #A87516; }
.imc-obesidad  { --imc-color: var(--rojo);   --imc-fondo: var(--rojo-suave);  --imc-texto: var(--rojo); }

/* EL IMC COMO UNA CASILLA MÁS de la grilla (pedido de Santino, 2026-08-14):
   al lado de FTP o de Epworth, con su etiqueta arriba y su ayuda abajo, para
   que se lea como parte del formulario y no como un cartel suelto.

   Tiene la MISMA caja que un input (alto, radio, tipografía) pero se distingue
   a simple vista de uno editable: fondo gris, borde punteado y sin el cursor de
   texto. Es un resultado, no algo que se completa — y si se pareciera del todo
   a un campo, alguien iba a intentar escribir adentro. */
.imc-campo {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--fuente);
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.35;
  padding: 9px 12px;
  min-height: 41px;              /* el alto exacto de un input al lado */
  display: flex;
  align-items: center;
  border: 1.5px dashed var(--linea);
  border-radius: var(--radio-s);
  background: var(--imc-fondo, var(--fondo));
  color: var(--imc-texto, var(--tinta-3));
  transition: background .2s var(--curva), color .2s var(--curva), border-color .2s var(--curva);
}
/* Con resultado, el borde se vuelve sólido y del color de la categoría: se ve
   de lejos que la casilla ya tiene un valor. */
.imc-campo.imc-bajo, .imc-campo.imc-normal,
.imc-campo.imc-sobrepeso, .imc-campo.imc-obesidad {
  border-style: solid;
  border-color: var(--imc-color);
}

/* La línea de ayuda cuando trae un aviso (la talla en la unidad equivocada).
   Ámbar y no rojo: no se rompió nada, la pantalla está diciendo qué esperaba. */
.ayuda-aviso { color: #A87516 !important; font-weight: 600; }

/* El resultado en vivo, debajo del par peso/altura. Nace oculto (`hidden` lo
   pone el JS) para que no haya un hueco reservado en un formulario vacío. */
.imc-vivo {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.4;
  background: var(--imc-fondo, #EEF0F5);
  color: var(--imc-texto, var(--tinta-2));
  /* Entra sin sobresaltar: el número cambia mientras se tipea y un parpadeo
     fuerte a cada tecla distrae de lo que se está cargando. */
  animation: imc-aparece .18s var(--curva);
}
.imc-vivo[hidden] { display: none; }
@keyframes imc-aparece { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .imc-vivo { animation: none; } }

/* El resultado grande de la calculadora. */
.imc-tarjeta {
  text-align: center;
  padding: 26px 20px;
  border-radius: var(--radio);
  background: var(--imc-fondo, var(--fondo));
  border: 1px solid var(--linea);
  transition: background .25s var(--curva);
}
.imc-tarjeta .imc-numero {
  font-size: clamp(44px, 8vw, 64px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--imc-texto, var(--tinta));
  font-variant-numeric: tabular-nums; /* el número no baila al cambiar de dígito */
}
.imc-tarjeta .imc-nombre {
  margin-top: 8px;
  font-size: 17px;
  font-weight: 700;
  color: var(--imc-texto, var(--tinta-2));
}
.imc-tarjeta .imc-vacio { font-size: 15px; color: var(--tinta-3); font-weight: 500; }

/* La escala: las 6 franjas en una barra, con la que corresponde encendida. */
.imc-escala { display: flex; gap: 3px; margin-top: 18px; }
.imc-escala li {
  flex: 1;
  list-style: none;
  padding: 8px 4px;
  text-align: center;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--tinta-3);
  background: var(--fondo);
  border: 1px solid var(--linea);
  border-radius: 6px;
  transition: background .2s var(--curva), color .2s var(--curva), border-color .2s var(--curva);
}
.imc-escala li.activa {
  background: var(--imc-fondo);
  border-color: var(--imc-color);
  color: var(--imc-texto);
}
.imc-escala li span { display: block; font-weight: 500; font-size: 10.5px; opacity: .85; }
@media (max-width: 640px) {
  .imc-escala { flex-wrap: wrap; }
  .imc-escala li { flex: 1 1 30%; }
}

/* ===========================================================================
   LÁMINA "HIGIENE DEL SUEÑO" (portal → /indicaciones)
   ===========================================================================

   Es la única lámina del sitio dibujada con HTML y no servida como imagen, y
   la diferencia es deliberada: las post operatorias son documentos ajenos
   (láminas del Hospital Italiano rebrandeadas) que se reproducen tal cual;
   ésta es contenido propio.

   Qué se gana escribiéndola en vez de exportarla a JPG:
     - Se lee en un celular SIN hacer zoom. Una infografía de 1280 px metida en
       una pantalla de 390 px obliga a ampliar y arrastrar, y era exactamente
       el problema de la foto que reemplaza.
     - La puede leer un lector de pantalla y la encuentra Google.
     - Pesa ~4 KB de HTML en vez de 222 KB de JPG.
     - Se imprime en A4 de verdad (ver @media print, más abajo), que es como la
       reparte el consultorio en mano.

   Estructura: cabecera nocturna (la misma noche del hero) + 10 consejos en dos
   columnas + pie con la fuente. */
.lamina {
  background: var(--blanco);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  overflow: hidden;
}

.lamina-cabecera {
  position: relative;
  padding: clamp(26px, 4vw, 42px) clamp(20px, 4vw, 44px);
  background: var(--noche);
  color: var(--blanco);
  text-align: center;
  overflow: hidden;
}
/* La profundidad la da UN resplandor grande y difuso, no motas chicas: un
   punto claro de 1-2px sobre fondo oscuro se lee como un píxel muerto de la
   pantalla (ya pasó con el cielo estrellado del hero). */
.lamina-cabecera::before {
  content: '';
  position: absolute;
  inset: -60% -20% auto -20%;
  height: 200%;
  background: radial-gradient(ellipse at 50% 0%, rgba(143, 160, 238, .34), transparent 62%);
  pointer-events: none;
}
.lamina-cabecera > * { position: relative; }
.lamina-logo { height: 54px; width: auto; margin: 0 auto 16px; display: block; }
.lamina-titulo {
  margin: 0;
  font-size: clamp(28px, 5vw, 44px);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.08;
  color: var(--blanco);
}
.lamina-bajada {
  margin: 10px auto 0;
  max-width: 46ch;
  font-size: clamp(14.5px, 1.6vw, 17px);
  line-height: 1.5;
  color: var(--luna);
}

.lamina-cuerpo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(4px, 1vw, 10px);
  padding: clamp(16px, 2.4vw, 26px);
}
@media (max-width: 760px) { .lamina-cuerpo { grid-template-columns: 1fr; } }

.lamina-consejo {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 14px;
  align-items: start;
  padding: clamp(12px, 1.4vw, 16px);
  border-radius: var(--radio-s);
}
/* Cebrado por FILA, no por posición en la lista: con dos columnas, alternar
   uno por uno deja un damero y no se lee como filas. */
.lamina-consejo:nth-child(4n+1),
.lamina-consejo:nth-child(4n+2) { background: var(--fondo); }
/* En una sola columna eso mismo pinta DE A PARES (dos grises, dos blancos),
   que se lee como si los consejos vinieran agrupados de a dos. Ahí se vuelve
   al alternado simple. */
@media (max-width: 760px) {
  .lamina-consejo:nth-child(4n+1),
  .lamina-consejo:nth-child(4n+2) { background: transparent; }
  .lamina-consejo:nth-child(odd)  { background: var(--fondo); }
}

.lamina-numero {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--azul-suave);
  color: var(--indigo);
  font-size: 15px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.lamina-consejo h3 {
  margin: 0 0 3px;
  font-size: clamp(15px, 1.5vw, 16.5px);
  font-weight: 700;
  line-height: 1.32;
  color: var(--tinta);
}
.lamina-consejo h3 .fa { color: var(--indigo); margin-right: 7px; }
.lamina-consejo p {
  margin: 0;
  font-size: clamp(13.5px, 1.35vw, 14.5px);
  line-height: 1.5;
  color: var(--tinta-2);
}

.lamina-pie {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
  justify-content: space-between;
  align-items: baseline;
  padding: 16px clamp(20px, 3vw, 30px);
  border-top: 1px solid var(--linea);
  background: var(--fondo);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--tinta-3);
}
.lamina-pie strong { color: var(--tinta-2); }

/* ---------------------------------------------------------------------------
   La lámina en papel (A4).
   ---------------------------------------------------------------------------
   El consultorio la imprime y la entrega en mano, así que la hoja tiene que
   salir con la lámina SOLA: sin la barra de navegación, sin los botones, sin
   el bloque de WhatsApp y sin las láminas post operatorias.

   ⚠️ Va con `display:none` y NO con `visibility:hidden`. Se probó primero con
   visibility (que evita recalcular el layout) sacando la lámina del flujo con
   position:absolute, y la hoja 1 salía perfecta pero **el trabajo se mandaba a
   la impresora con 3 hojas: la lámina y dos en blanco**. Es lo que hace
   visibility — el elemento se deja de ver pero sigue ocupando su alto, y ese
   alto son páginas de papel. Verificado contando las páginas del PDF.

   Se ocultan los HIJOS DIRECTOS de .portal-contenido en vez de confiar en que
   cada tarjeta lleve .no-imprimir: así una tarjeta que se agregue mañana a
   /indicaciones tampoco sale impresa, sin que haya que acordarse de marcarla. */
/* ===========================================================================
   EL PANEL EN EL CELULAR (tanda 79, 2026-09-04)
   ---------------------------------------------------------------------------
   Hasta acá el panel tenía UNA sola regla de celular: la barra lateral se
   escondía a los 920 px. Todo lo demás entraba como podía. Medido con Chrome
   real a 390 px, antes de tocar nada:

     · la topbar desbordaba la pantalla en TODAS las páginas (el bloque del
       usuario terminaba entre 393 y 421 px sobre 390 de ancho: "Cerrar
       sesión" quedaba cortado por el borde);
     · el título se partía en tres renglones ("Agenda / de / turnos");
     · las 13 pestañas de la ficha del paciente ocupaban 306 px en 7 filas
       —más de un tercio de la pantalla— antes de que empezara el contenido;
     · el listado de pacientes mostraba 3 de sus 6 columnas y las otras 3
       quedaban en un scroll lateral que nadie ve;
     · los 4 KPIs del inicio, uno abajo del otro, hacían 5.458 px de página.

   Los cortes, y por qué:
     920 px → la barra lateral pasa a ser un cajón (el corte que ya existía).
     760 px → la topbar y el contenido se compactan.
     700 px → las tablas dejan de ser tablas y pasan a ser tarjetas.
     560 px → lo último que quedaba de a dos pasa a una sola columna.
   =========================================================================== */

/* --------------------------------------------------- El cajón del menú */
/* El velo es lo que faltaba: sin él la barra se abría encima del contenido y
   la única forma de cerrarla era volver a apuntarle al botón de 20 px. */
.velo-menu { display: none; }

@media (max-width: 920px) {
  .sidebar {
    position: fixed; z-index: 90; left: -300px;
    width: min(84vw, 292px);
    height: 100vh; height: 100dvh;
    transition: left .22s ease;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .sidebar.abierta { left: 0; box-shadow: 0 0 40px rgba(15, 20, 40, .45); }

  .velo-menu {
    display: block;
    position: fixed; inset: 0;
    background: rgba(26, 33, 64, .55);
    z-index: 85;
    opacity: 0; pointer-events: none;
    transition: opacity .22s ease;
  }
  body.menu-abierto .velo-menu { opacity: 1; pointer-events: auto; }
  /* El fondo no puede scrollear detrás del cajón abierto. */
  body.menu-abierto { overflow: hidden; }

  .menu-movil {
    display: inline-flex; align-items: center; justify-content: center;
    width: 40px; height: 40px; margin-left: -8px;
    background: none; border: 0; border-radius: 10px;
    font-size: 20px; color: var(--tinta); cursor: pointer;
  }
  .menu-movil:active { background: var(--fondo); }

  /* Blancos de toque de 44 px en el menú: se navega con el pulgar. */
  .nav-panel a { padding: 12px; font-size: 14.5px; }
  .contenido { padding: 20px 16px 60px; }
  .topbar { padding: 0 16px; }
}

/* ------------------------------------------------------------- La topbar */
/* Lo que desbordaba. En el celular quedan sólo las dos cosas que no se pueden
   resolver desde el menú: quién está adentro (el avatar) y la salida. */
@media (max-width: 760px) {
  .topbar {
    height: 56px;
    padding: 0 10px 0 12px;
    gap: 10px;
  }
  .topbar-izq { min-width: 0; flex: 1 1 auto; }
  .topbar .titulo-pagina {
    font-size: 16px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .topbar .usuario { gap: 6px; flex: 0 0 auto; }
  /* El nombre ya está en el menú: acá sobra, y es lo que empujaba los botones
     fuera de la pantalla. */
  .topbar .usuario .usuario-nombre { display: none; }
  .topbar .usuario .avatar { width: 32px; height: 32px; font-size: 14px; }
  /* "Inicio" desaparece: el logo del menú y su primera entrada hacen lo mismo. */
  .topbar .usuario .btn-inicio { display: none; }
  /* "Cerrar sesión" queda como ícono, con blanco de toque de 40 px. */
  .topbar .usuario .btn-salir {
    width: 40px; height: 40px; padding: 0;
    justify-content: center; font-size: 16px;
  }
  .topbar .usuario .btn-salir .rot { display: none; }
}

/* ------------------------------------------------- El cuerpo, más angosto */
@media (max-width: 760px) {
  .contenido { padding: 16px 14px 72px; }
  .tarjeta { padding: 16px 14px; border-radius: 14px; margin-bottom: 14px; }
  .tarjeta .encabezado { margin-bottom: 12px; }
  h1 { font-size: 23px; }
  h2 { font-size: 19px; }
  h3 { font-size: 16px; }

  /* Blanco de toque: 40 px de alto, el mínimo cómodo con el pulgar. */
  .btn { min-height: 40px; padding: 9px 14px; }
  .btn-chico { min-height: 34px; }

  /* Los 4 KPIs del inicio, uno abajo del otro y con 110 px cada uno, hacían
     una página de 5.458 px. Acostados —número, rótulo, ícono— entran los
     cuatro en lo que antes ocupaban dos. */
  .kpi {
    display: grid; grid-template-columns: auto 1fr auto;
    align-items: center; gap: 12px;
    padding: 14px 16px;
  }
  .kpi .valor { font-size: 26px; }
  .kpi .etiqueta { margin-top: 0; font-size: 12.5px; line-height: 1.3; }
  .kpi .icono { float: none; width: 36px; height: 36px; font-size: 16px; }

  /* Los 16 px no son estéticos: abajo de 16, iOS hace zoom solo al tocar un
     campo y deja la pantalla corrida. Es la mitad de la sensación de "se ve
     mal" al cargar una consulta desde el teléfono. */
  .campo input[type=text], .campo input[type=email], .campo input[type=date],
  .campo input[type=time], .campo input[type=number], .campo input[type=password],
  .campo input[type=tel], .campo select, .campo textarea {
    font-size: 16px;
  }
}

/* --------------------------------------- Las pestañas: una fila que corre */
/* 13 pestañas en la ficha = 7 filas y 306 px de alto. Envolver no era la
   solución: acá corren en una sola fila, la activa se pinta con fondo (la
   línea de abajo sola no se ve entre tanto texto) y el JS la trae al centro
   al abrir la ficha. */
@media (max-width: 900px) {
  .tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    gap: 3px;
    padding-bottom: 2px;
  }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs a {
    flex: 0 0 auto;
    scroll-snap-align: center;
    padding: 9px 14px;
    border-radius: 10px 10px 0 0;
  }
  .tabs a.activo { background: var(--azul-suave); }
  /* Mientras quede pestaña a la derecha, ese borde se desvanece: es la única
     pista de que la fila sigue. El JS saca la clase al llegar al final. */
  .tabs.hay-mas-der {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 30px), transparent);
            mask-image: linear-gradient(to right, #000 calc(100% - 30px), transparent);
  }
}

/* ------------------------------------- Las tablas se vuelven tarjetas */
/* Una tabla de 973 px no entra en 390. Con scroll lateral se ven 3 columnas
   de 6 y las otras 3 no existen para el que mira. Cada fila pasa a ser una
   tarjeta: el nombre de título y el resto como "rótulo · valor".
   La clase `tabla-tarjetas` la pone el JS (app.js) después de copiar cada
   encabezado a su celda. Si el JS no corre, la tabla queda como estaba y
   scrollea: peor, pero no roto. */
@media (max-width: 700px) {
  .tabla-envoltura.envoltura-suelta { overflow-x: visible; }

  table.tabla-tarjetas,
  table.tabla-tarjetas tbody,
  table.tabla-tarjetas tr,
  table.tabla-tarjetas td { display: block; width: auto; }

  table.tabla-tarjetas thead { display: none; }

  table.tabla-tarjetas tr {
    border: 1px solid var(--linea);
    border-radius: 12px;
    padding: 12px 14px;
    margin-bottom: 10px;
    background: var(--blanco);
  }
  table.tabla-tarjetas tbody tr:hover { background: var(--blanco); }

  table.tabla-tarjetas td {
    border: 0;
    padding: 3px 0;
    display: grid;
    grid-template-columns: minmax(84px, 34%) 1fr;
    gap: 10px;
    align-items: baseline;
    font-size: 14px;
  }
  table.tabla-tarjetas td::before {
    content: attr(data-etiqueta);
    font-size: 10.5px; font-weight: 800;
    text-transform: uppercase; letter-spacing: .08em;
    color: var(--tinta-3);
    line-height: 1.5;
  }
  /* La primera celda es siempre de quién se trata: va de título, sin rótulo. */
  table.tabla-tarjetas td.celda-titulo {
    display: block;
    font-size: 16px; font-weight: 800;
    margin-bottom: 8px;
  }
  table.tabla-tarjetas td.celda-titulo::before { content: none; }
  table.tabla-tarjetas td.celda-titulo a { font-weight: 800; }
  /* Los botones de la fila, abajo de todo y separados por una línea. */
  table.tabla-tarjetas td.celda-acciones {
    display: flex; flex-wrap: wrap; gap: 8px;
    margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--linea);
  }
  table.tabla-tarjetas td.celda-acciones::before { content: none; }
  table.tabla-tarjetas td.celda-acciones .btn { flex: 1 1 auto; justify-content: center; }
  /* Una celda vacía en una tabla es un guión; en una tarjeta sería un rótulo
     suelto sin nada al lado. Se va. */
  table.tabla-tarjetas td.celda-vacia { display: none; }
  table.tabla-tarjetas td.sin-datos {
    display: block; text-align: center; padding: 26px 12px;
  }
  table.tabla-tarjetas td.sin-datos::before { content: none; }
}

/* ------------------------------------------------- La agenda del día */
@media (max-width: 700px) {
  .slot { flex-wrap: wrap; row-gap: 6px; padding: 12px; gap: 10px; }
  .slot .hora { width: auto; min-width: 46px; font-size: 16px; }
  .slot .detalle { flex: 1 1 60%; }
  /* Los botones bajan a su propia fila y se reparten el ancho: dar un turno
     no puede depender de acertarle a 90 px pegados al borde. */
  .slot .acciones { flex: 1 1 100%; display: flex; flex-wrap: wrap; gap: 8px; }
  .slot .acciones .btn { flex: 1 1 auto; justify-content: center; }
  /* En el celular no existe "pasar por encima": el botón de apartar, que sólo
     aparecía con el mouse, acá se ve siempre. */
  .slot.libre .btn-reservar { opacity: 1; visibility: visible; }

  .agenda-fecha { min-width: 0; flex: 1 1 100%; font-size: 16px; }
  .agenda-controles .btn { flex: 1 1 auto; justify-content: center; }
}

/* --------------------------------------- Formularios de la historia clínica */
@media (max-width: 700px) {
  /* Era una grilla de 4 columnas (rótulo, sí/no, detalle, extra) que nunca
     colapsaba: a 390 px el "Detalle" quedaba de 60 px. */
  .sintoma-item {
    grid-template-columns: 1fr 1fr;
    gap: 6px;
    padding: 8px 0;
    border-bottom: 1px dashed var(--linea);
  }
  .sintoma-item .sintoma-label { grid-column: 1 / -1; font-weight: 700; }
  .sintoma-item select, .sintoma-item input { font-size: 15px; padding: 8px; }
  .fs-consulta { padding: 12px 12px 4px; }
}
@media (max-width: 560px) {
  .grilla-check { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------- Modal y avisos */
/* Un modal centrado con 6vh arriba, con el teclado abierto, es una caja que
   baila. En el celular es una hoja que sube desde abajo. */
@media (max-width: 700px) {
  .modal-fondo { padding: 0; align-items: flex-end; }
  .modal-caja {
    max-width: none;
    border-radius: 18px 18px 0 0;
    padding: 18px 16px calc(18px + env(safe-area-inset-bottom, 0px));
    max-height: 92vh; overflow-y: auto;
    animation: hoja-entra .22s ease-out;
  }
  .modal-caja .cerrar { font-size: 26px; padding: 4px 8px; margin: -4px -8px; }

  #toasts { left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .toast { max-width: none; }
}
@keyframes hoja-entra {
  from { transform: translateY(26px); opacity: .5; }
  to   { transform: none; opacity: 1; }
}

@media print {
  body { background: var(--blanco); }

  body.imprimiendo-lamina .portal-topbar,
  body.imprimiendo-lamina .portal-banda-corta,
  body.imprimiendo-lamina .portal-pie,
  body.imprimiendo-lamina .portal-contenido > *       { display: none !important; }
  body.imprimiendo-lamina .portal-contenido > .lamina { display: block !important; }

  /* El contenedor deja de encajonar: la lámina usa la hoja entera (el margen
     lo pone @page, más abajo). */
  body.imprimiendo-lamina .portal-contenido {
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0;
  }
  body.imprimiendo-lamina .lamina {
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  /* Los fondos de color se imprimen: sin esto, Chrome descarta la cabecera
     nocturna y el cebrado, y la hoja sale como una lista pelada. */
  .lamina, .lamina * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  /* Nada de cortar un consejo a la mitad entre dos hojas. */
  .lamina-consejo { break-inside: avoid; page-break-inside: avoid; }
  .lamina-cabecera { break-after: avoid; page-break-after: avoid; }
  .no-imprimir { display: none !important; }
  @page { margin: 12mm; }

  /* ⚠️ LA LÁMINA IMPRESA VA A DOS COLUMNAS, SIEMPRE.
     Una A4 con 12mm de margen deja 186mm de ancho, que en píxeles CSS son
     ~703 — por debajo del breakpoint de 760px. O sea que al imprimir se
     activaba el layout de CELULAR: los 10 consejos en una sola columna, y la
     lámina pasaba a ocupar DOS hojas (verificado contando las páginas del
     PDF). Un papel no es un celular angosto: acá siempre entran dos columnas.
     Va después del media query de 760px, así que lo pisa. */
  .lamina-cuerpo { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px; padding: 10px; }
  .lamina-consejo:nth-child(odd)  { background: transparent; }
  .lamina-consejo:nth-child(4n+1),
  .lamina-consejo:nth-child(4n+2) { background: var(--fondo); }

  /* Medidas en pt: en papel el clamp() con vw no significa nada (no hay
     viewport) y deja los cuerpos en el mínimo. */
  .lamina-cabecera { padding: 16pt 20pt; }
  .lamina-logo     { height: 34pt; margin-bottom: 8pt; }
  .lamina-titulo   { font-size: 24pt; }
  .lamina-bajada   { font-size: 10pt; margin-top: 5pt; }
  .lamina-consejo  { padding: 7pt 8pt; gap: 8pt; }
  .lamina-numero   { width: 24pt; height: 24pt; border-radius: 7pt; font-size: 9.5pt; }
  .lamina-consejo h3 { font-size: 10.5pt; margin-bottom: 1.5pt; }
  .lamina-consejo p  { font-size: 9pt; line-height: 1.4; }
  .lamina-pie      { font-size: 7.5pt; padding: 8pt 20pt; }

  /* ── EL PORTAL, EN PAPEL ────────────────────────────────────────────────
     ⚠️ Esto arregla un bug que ya existía antes del portal oscuro: el
     `body { background: var(--blanco) }` de arriba pesa (0,0,1) y perdía
     contra `.portal-body` (0,1,0). Las media queries NO suman especificidad,
     así que ese reset NUNCA corrió. Hasta ahora no se notaba porque el portal
     era claro; con el lienzo azul, imprimir /indicaciones o el resumen de un
     turno saldría con el fondo de la marca o —peor, según el navegador— con
     el texto claro sobre papel blanco, o sea en blanco.
     Va con !important porque las reglas que revierte son de una hoja que se
     carga después en el orden de cascada del propio documento, y acá no hay
     margen para pelear especificidad regla por regla: en papel se imprime
     tinta oscura sobre blanco y punto.
     (El telón de líneas no hace falta apagarlo acá: fondo-lineas.css ya tiene
     su propio @media print y su bloque de forced-colors.) */
  body.portal-body { background: #FFFFFF !important; color: var(--tinta) !important; }
  body.portal-body .portal-hero-banda,
  body.portal-body .portal-banda-corta,
  body.portal-body .tarjeta-cierre,
  body.portal-body .grilla-inicio > .tarjeta,
  body.portal-body .experiencias-grilla > .experiencia {
    background: #FFFFFF !important; color: var(--tinta) !important;
    border-color: var(--linea) !important;
    -webkit-backdrop-filter: none !important; backdrop-filter: none !important;
    box-shadow: none !important;
  }
  body.portal-body .novedades-titulo h2,
  body.portal-body .tarjeta-cierre h2,
  body.portal-body .paso, body.portal-body .paso.activo,
  body.portal-body .paso.hecho, body.portal-body .paso.activo .rot { color: var(--tinta) !important; }
  body.portal-body .novedades-titulo p,
  body.portal-body .portal-pie { color: var(--tinta-2) !important; }
  body.portal-body .portal-pie { border-top-color: var(--linea) !important; }
  body.portal-body .paso .num { background: #E9EBF3 !important; color: var(--tinta) !important; }

  /* ⚠️ Lo de arriba pinta los CONTENEDORES, y no alcanza: los colores claros
     del portal están declarados sobre los HIJOS (h2, .subtexto, los textos de
     las experiencias), así que la herencia nunca entra en juego y sobreviven al
     papel. Sin esto, la home impresa sale con el fondo blanco y los títulos y
     los textos en blanco: hoja en blanco.

     El `-webkit-text-fill-color` NO es opcional para el h1: el título del hero
     usa `background-clip: text`, y con eso un `color` solo no lo pinta. */
  body.portal-body .grilla-inicio > .tarjeta h2,
  body.portal-body .grilla-inicio > .tarjeta .subtexto,
  body.portal-body .grilla-inicio > .tarjeta .sede-nombre,
  body.portal-body .experiencias-grilla b,
  body.portal-body .experiencias-grilla .experiencia-texto,
  body.portal-body .experiencias-grilla .experiencia-nota,
  body.portal-body .experiencias-grilla .experiencia-pie span,
  body.portal-body .portal-hero h1,
  body.portal-body .portal-hero .hero-bajada {
    color: var(--tinta) !important;
    -webkit-text-fill-color: var(--tinta) !important;
  }
}


/* ---------------------------------------------------------------------------
   Red de confianza entre consultorios (tanda 082, 2026-09-17)

   Los chips de "quien ve esta ficha". `pill-propio` es el consultorio en el
   que estas parado; se llama igual en las dos instalaciones y cada hoja le
   pone su propio acento, porque los tokens de color NO son los mismos (COMS
   tiene --indigo, Myrna lo renombro a --magenta con el rebranding borgona).
   Pedir `pill-indigo` desde el PHP compartido dejaria el chip sin fondo en
   Myrna, sin fallar ni avisar.
   --------------------------------------------------------------------------- */
.pill-chica       { font-size: 11px; padding: 2px 8px; font-weight: 700; }
.accesos-paciente { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.accesos-rotulo   { font-size: 12px; font-weight: 700; color: var(--tinta-2); }
.accesos-extra    { display: inline-flex; gap: 4px; flex-wrap: wrap; margin-top: 4px; }
.pill-propio      { background: var(--azul-suave); color: var(--indigo); }

/* --- Pantalla "Quien ve que pacientes" (segunda version, 2026-09-17) -------
   La primera version era una matriz consultorio x consultorio y no se
   entendia: para leer una celda habia que cruzar dos ejes. Esto es una lista
   con una casilla por consultorio, mas el resumen en castellano arriba. --- */
.red-resumen   { display: flex; flex-direction: column; gap: 10px; }
.red-frase     { display: flex; align-items: flex-start; gap: 10px; margin: 0; line-height: 1.5; }
.red-frase i   { margin-top: 4px; color: var(--indigo); width: 16px; text-align: center; }
.red-frase-apagada i { color: var(--tinta-2); }
.red-frase-suelta i  { color: #6A44D6; }

.red-lista     { display: flex; flex-direction: column; gap: 2px; }
.red-item      { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px;
                 border-radius: 10px; cursor: pointer; transition: background .12s ease; }
.red-item:hover{ background: #F4F6FA; }
.red-item input[type="checkbox"] { margin-top: 3px; width: 17px; height: 17px; flex: none; }
.red-item-cuerpo { display: flex; flex-direction: column; gap: 2px; }
.red-item-nombre { font-weight: 800; }
.red-sueltos   { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
.red-avanzado-titulo { font-weight: 800; cursor: pointer; display: inline-flex; align-items: center; gap: 8px; }

/* Tanda 93 · A — La Historia completa es de todos los rangos (2026-09-25) ----
   "La gracia de la página es que todos aparezcan con todos" (Santino). Lo que
   carga cualquier perfil, en cualquiera de las dos instalaciones, entra a la
   Historia completa de las dos. Acá: lo que hace falta para LEER la ficha
   dental de Myrna desde COMS, y el desplegable del cuestionario y el diario
   para el rango que no tiene esas pestañas.
   --------------------------------------------------------------------------- */

/* La ficha dental, en sólo lectura. En Myrna estas reglas viven en su
   assets/css/odontograma.css, junto con las del editor. COMS no tiene editor
   ni esa hoja: acá va sólo lo necesario para dibujar (los tokens, las caras
   del diente, la miniatura y el diálogo), colgado de .odo para no tocar nada
   más del panel. Los valores son los de Myrna: el dibujo tiene que decir lo
   mismo en las dos instalaciones. */
.odo {
  --odo-linea:        var(--linea, #E4E7EF);
  --odo-linea-2:      var(--tinta-3, #9AA1B2);
  --odo-tinta:        var(--tinta, #262B39);
  --odo-tinta-2:      var(--tinta-2, #5A6172);
  --odo-diente:       #FFFFFF;
  --odo-diente-borde: #8B8083;
  --odo-rojo:         #D93A2B;
  --odo-azul:         #1B5FA8;
}
.odo .cara        { fill: var(--odo-diente); stroke: var(--odo-diente-borde); stroke-width: .9; }
.odo .cara.mk     { fill: var(--mk); }
.odo .cara.o100   { fill-opacity: 1; }
.odo .cara.o70    { fill-opacity: .7; }
.odo .cara.o45    { fill-opacity: .45; }
.odo .cara.o20    { fill-opacity: .2; }
.odo .cara.borde  { stroke: var(--mk); stroke-width: 2.2; }
.odo .ov          { fill: none; stroke: var(--mk); stroke-width: 2.4; stroke-linecap: round; }
.odo .ov.lleno    { fill: var(--mk); stroke: none; }
/* Las siglas (TC, Pd, IM, P) traen su color en el atributo fill del SVG: no
   hay --mk en ningún ancestro del <text>, así que acá no se les pisa. */
.odo .ov-txt      { font-size: 10px; font-weight: 700; text-anchor: middle; }

.odo-bloque { margin-bottom: 22px; }
.odo-cab {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding-bottom: 6px; margin-bottom: 10px; border-bottom: 2px solid var(--odo-tinta);
}
.odo-cab h5 { margin: 0; font-size: 13px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; }
/* La arcada mide 768 px fijos: en el celular se desliza adentro de su caja
   en vez de ensanchar la página. */
.odo-wrap { overflow-x: auto; padding-bottom: 4px; }
.odo-wrap svg { display: block; margin: 0 auto; }

/* La miniatura del timeline: la arcada entera achicada a 168 px. */
.odo-miniatura {
  display: inline-block; width: 168px; max-width: 100%; padding: 5px;
  border: 1px solid var(--linea); border-radius: 8px;
  background: #fff; cursor: pointer; margin-top: 6px;
}
.odo-miniatura:hover { border-color: var(--indigo); }
.odo-miniatura svg { display: block; width: 100%; height: auto; }
.odo-cambios { margin: 4px 0 0; padding-left: 16px; font-size: 12.5px; color: var(--tinta-2); line-height: 1.55; }
.pill-odo { background: #F9EAEF; color: #8C2136; }
.hc-entrada .punto-odo { background: #8C2136; }

dialog.odo-dialogo {
  border: none; border-radius: 14px; padding: 0; max-width: min(1080px, 94vw);
  width: 100%; box-shadow: 0 24px 70px -20px rgba(0,0,0,.45);
  color: var(--tinta); background: var(--blanco, #fff);
}
dialog.odo-dialogo::backdrop { background: rgba(20, 24, 40, .55); }
dialog.odo-dialogo .cabecera {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 18px; border-bottom: 1px solid var(--linea);
}
dialog.odo-dialogo .cabecera h4 { margin: 0; font-size: 15px; }
dialog.odo-dialogo .cuerpo { padding: 18px; max-height: 78vh; overflow: auto; }

/* Cuestionario y diario completos adentro de la Historia completa, para el
   rango que no tiene esas pestañas (antes el "Ver completo" era un link que
   no llevaba a ningún lado). Se lee igual que el link al que reemplaza. */
.hc-desplegable { margin-top: 6px; }
.hc-desplegable > summary { cursor: pointer; font-size: 12.5px; font-weight: 700; color: var(--tinta-3); }
.hc-desplegable[open] > summary { margin-bottom: 8px; }

/* En el celular, el cuerpo de cada entrada es un ítem flex: sin min-width:0
   toma el ancho de su contenido más largo (una tabla del diario, la arcada) y
   empuja la página hacia la derecha, aunque la tabla tenga su propio scroll. */
.hc-entrada .cuerpo,
.hc-entrada .cuerpo > div > div { min-width: 0; }
@media (max-width: 700px) {
  dialog.odo-dialogo .cabecera { padding: 12px 14px; }
  dialog.odo-dialogo .cuerpo { padding: 12px; }
}

/* Tanda 93 · B ──────────────────────────────────────────────────────────────
   "¿Es tu primera vez con nosotros?" (views/portal/_bienvenida.php): subir los
   estudios y completar el cuestionario de sueño, para el paciente NUEVO que
   acaba de sacar turno. La misma pieza vive en dos fondos y rinde distinto:

   - adentro de una tarjeta BLANCA (la pantalla del turno y los "listo" de
     /estudios y /cuestionario): caja celeste propia con los pasos en blanco.
     Esas tarjetas centran el texto; esto no, porque son renglones con un botón.
   - en la HOME (.tarjeta-bienvenida, primera de la grilla): la tarjeta ya es de
     vidrio sola —la alcanza la regla de oro del portal oscuro por ser
     `.grilla-inicio > .tarjeta`—, así que la caja se apaga y los colores pasan
     a los de fondo oscuro (.bienvenida-oscura).

   El botón va AL LADO del texto sólo si la caja mide 500px o más, y eso lo mide
   un container query y no el ancho de la pantalla: en el "listo" de /estudios la
   tarjeta mide 480px aun en un monitor grande, y ahí el texto quedaba en una
   columna de 120px. Sin soporte de container queries queda apilado, que es lo
   que anda en cualquier ancho.

   Contrastes (WCAG, texto): bajada #3B4466 sobre #E8ECFB 8,1:1; pie #4A5374
   6,4:1; "Listo" #0B6E5C sobre #E2F6F1 5,5:1. En la home el texto secundario
   es --portal-tinta-2, el mismo del .subtexto de las otras tarjetas de vidrio
   (7,3:1 sobre el renglón), y "Listo" #A5F0DD 6,4:1. --portal-tinta-3 quedó
   descartado: bajo el resplandor del telón caía a 3,7:1. */
.bienvenida {
  container: bienvenida / inline-size;
  text-align: left;
  max-width: 560px;
  margin: 22px auto 4px;
  padding: 18px 16px 14px;
  background: var(--azul-suave);
  border: 1px solid #D3DAF6;
  border-radius: 14px;
  color: var(--tinta);
}
.bienvenida-cabeza { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
.bienvenida-sello {
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  background: var(--indigo); color: #fff; font-size: 19px;
}
/* #0B8A73 y no --menta: el tilde blanco sobre el menta da 2,97:1 y un ícono
   que es lo único que dice "listo" necesita 3:1. Con este verde da 4,3:1. */
.bienvenida-completa .bienvenida-sello { background: #0B8A73; }
.bienvenida-completa .bienvenida-cabeza { margin-bottom: 0; }
.bienvenida-titulo { margin: 0 0 3px; font-size: 17px; line-height: 1.3; color: var(--noche); }
.bienvenida-bajada { margin: 0; font-size: 14.5px; line-height: 1.5; color: #3B4466; }

.bienvenida-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.bienvenida-item {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px;
  background: #fff; border: 1px solid #DCE2F5; border-radius: 11px;
  padding: 12px;
}
.bienvenida-marca {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--azul-suave); color: var(--indigo); font-size: 15px;
}
.bienvenida-item.hecho .bienvenida-marca { background: var(--menta-suave); color: #0B7A66; }
.bienvenida-texto { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.bienvenida-texto b { font-size: 14.5px; line-height: 1.35; color: var(--tinta); }
.bienvenida-texto span { font-size: 13px; line-height: 1.45; color: var(--tinta-2); }
/* Apilado por defecto: el botón ocupa su propio renglón, a todo el ancho, donde
   llega el dedo. */
.bienvenida-accion { flex: 1 0 100%; }
.bienvenida-listo {
  flex-shrink: 0; margin-left: auto;
  font-size: 12.5px; font-weight: 800; letter-spacing: .02em;
  padding: 5px 12px; border-radius: 999px;
  background: var(--menta-suave); color: #0B6E5C;
}
.bienvenida-pie { margin: 10px 2px 0; font-size: 12.5px; line-height: 1.5; color: #4A5374; }

@container bienvenida (min-width: 500px) {
  .bienvenida-item { flex-wrap: nowrap; }
  .bienvenida-accion { flex: 0 0 auto; }
}

/* ── En la home: la tarjeta de vidrio es la caja ─────────────────────────── */
.tarjeta-bienvenida { position: relative; }
.bienvenida-oscura {
  max-width: none; margin: 0; padding: 0;
  background: none; border: 0; border-radius: 0;
  color: var(--portal-tinta);
}
/* Lugar para la cruz, que va arriba a la derecha de la tarjeta. */
.bienvenida-oscura .bienvenida-cabeza { padding-right: 46px; }
.bienvenida-oscura .bienvenida-titulo { color: var(--portal-tinta); font-size: 19px; }
.bienvenida-oscura .bienvenida-bajada { color: var(--portal-tinta-2); }
.bienvenida-oscura .bienvenida-item {
  background: rgba(255, 255, 255, .06);
  border-color: var(--portal-vidrio-borde);
}
.bienvenida-oscura .bienvenida-marca { background: rgba(143, 160, 238, .18); color: var(--luna); }
.bienvenida-oscura .bienvenida-item.hecho .bienvenida-marca { background: rgba(15, 169, 141, .22); color: #6FDDC4; }
.bienvenida-oscura .bienvenida-texto b { color: var(--portal-tinta); }
.bienvenida-oscura .bienvenida-texto span,
.bienvenida-oscura .bienvenida-pie { color: var(--portal-tinta-2); }
.bienvenida-oscura .bienvenida-listo { background: rgba(15, 169, 141, .22); color: #A5F0DD; }
/* Con la tarjeta a todo el ancho de la home, los dos pasos van uno al lado del
   otro en vez de uno abajo del otro: si no, cada renglón mide 1500px y el botón
   queda a un metro del texto que lo explica. */
@container bienvenida (min-width: 860px) {
  .bienvenida-oscura .bienvenida-lista { grid-template-columns: 1fr 1fr; }
}

.bienvenida-cerrar-form { position: absolute; top: 12px; right: 12px; margin: 0; z-index: 1; }
/* 40px: la cruz se toca con el dedo y no hay otra forma de sacar el aviso. */
.bienvenida-cerrar {
  width: 40px; height: 40px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; line-height: 1; cursor: pointer;
  color: var(--portal-tinta);
  background: rgba(255, 255, 255, .08);
  border: 1px solid var(--portal-vidrio-borde);
  transition: background .15s, border-color .15s;
}
.bienvenida-cerrar:hover { background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .30); }

/* En papel no va: es para hacer algo en la web, y en la home impresa sería un
   renglón de botones que no se pueden tocar. */
@media print {
  .tarjeta-bienvenida, .bienvenida { display: none !important; }
}
