/* ============================================================
   Artmedica — Portal de pacientes (/portal/)

   NO confundir con portal.css: aquél es el armazón del panel
   del EQUIPO. Éste es el portal de PACIENTES, y no comparten ni
   una regla.

   ── DESDE LA #49 ESTA HOJA ES EL ARMAZÓN ENTERO ──────────────
   Hasta la #49 el portal cargaba login.css (la puerta del EQUIPO)
   y encima corregía lo que no le servía con reglas
   `body.esta-dentro`. Dentro de la sesión parecía un formulario
   de ingreso estirado, y en el móvil login.css ganaba sobre
   `.panel` sin que se le pudiera ganar de forma fiable (trampa 3
   de docu/contexto/como-se-diseña-para-pacientes.md). Ahora el
   portal no la carga: login.css sigue siendo del ingreso y la
   recuperación del equipo, y aquí no se toca.

   El sistema visual es el de la maqueta de la #49 (el estilo del
   gestor de tareas de Artmedica): cabecera oscura única,
   tarjetas blancas con franja de color, insignias en píldora y
   botones de 44 px o más.

   ── LAS REGLAS QUE ESTA HOJA CUMPLE, Y POR QUÉ ────────────────
   · LETRA: 16 px de base y NADA por debajo de 0,875rem (14 px).
     Los pacientes de una IPS de autoinmunes son, en buena parte,
     mayores; 10 y 11 px en la barra y en los sellos no se leían.
   · OBJETIVOS TÁCTILES DE 44 PX o más: un pulgar no acierta
     menos.
   · UN SOLO ROJO (--peligro), y solo en `.btn--peligro`: el
     último paso de cancelar. Si el rojo sale antes, deja de
     significar «esto no se deshace». Los errores van en ámbar
     con icono.
   · TRAMPA 1: nada de transform, filter, backdrop-filter,
     perspective, contain ni will-change en `.pantalla`,
     `#pantallaDentro`, `.portal`, `.marco` ni `body`: la barra
     de abajo (`#modulos`) es `position: fixed` en el móvil y vive
     dentro de `.marco` (hasta la #48, dentro de la cabecera).
     Por eso `aparecer` es solo de opacidad.
   · TRAMPA 2: cada `env()` va detrás de una declaración con el
     valor llano. Si el motor no entiende el `calc()` con `env()`,
     invalida esa declaración entera y queda la llana.
   ============================================================ */

/* ============================================================
   1. TOKENS
   Los de marca (--brand-*, --font-*) vienen de tokens.css.
   ============================================================ */
:root {
  --primario: #4d61e6;
  --primario-fuerte: #3d51d4;
  --primario-tinte: #eff1fd;
  --degradado: linear-gradient(102deg, #4753bf 0%, #506bd6 100%);
  --fondo: #f6f8fc;
  --superficie: #ffffff;
  --borde: #e2e6f0;
  --borde-fuerte: #cdd4e4;
  /* Solo bordes de campo y franja neutra; nunca texto. ≥3:1 sobre fondo,
     blanco y tinte, que es lo que pide un borde que delimita un control. */
  --borde-campo: #83889f;
  --titulo: #0b1030;
  --texto: #3a4170;
  --texto-suave: #555971;
  --exito: #12704b;
  --exito-tinte: #e7f3ed;
  --aviso: #8a5a00;
  --aviso-tinte: #fdf5e6;
  /* EL ÚNICO ROJO. Solo lo usa `.btn--peligro`. */
  --peligro: #b3261e;
  --info: #1d5d8f;
  --info-tinte: #ecf5fb;
  --neutro-tinte: #eef2f8;
  --cabecera: #0b1030;
  --sombra-tarjeta: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  --sombra-tarjeta-hover: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
  --sombra-cta: 0 4px 16px rgba(77, 97, 230, 0.4);
  --sombra-flotante: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
  --sombra-barra: 0 -10px 20px -16px rgba(11, 16, 48, 0.35);
  --anillo: 0 0 0 3px rgba(77, 97, 230, 0.25);
  --fuente-titulo: var(--font-display, "Sora", system-ui, -apple-system, "Segoe UI", sans-serif);
  --fuente: var(--font-body, "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", sans-serif);

  /* Iconos para pintar con máscara, en lo que el JS reescribe con
     `textContent` (un icono hijo se perdería). Van en data: porque la CSP
     admite `img-src 'self' data:` y no hay que servir ficheros sueltos. */
  --m-alerta: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 8v4M12 16h.01'/%3E%3C/svg%3E");
  --m-hecho: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='m16 9-5.5 5.5L8 12'/%3E%3C/svg%3E");
  --m-pendiente: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3C/svg%3E");
  --m-info: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 16v-4M12 8h.01'/%3E%3C/svg%3E");
  /* «Confirmar asistencia», «Cambiar fecha» y «Ver detalle»: el JS reescribe
     el texto del botón mientras trabaja, así que su icono va por CSS. */
  --m-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  --m-calendario: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2v4M16 2v4'/%3E%3Crect width='18' height='18' x='3' y='4' rx='2'/%3E%3Cpath d='M3 10h18'/%3E%3C/svg%3E");
  --m-flecha: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M12 5l7 7-7 7'/%3E%3C/svg%3E");
  /* «Descargar PDF»: `bajarElPdf` reescribe el texto del botón mientras baja. */
  --m-descarga: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 15V3'/%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/%3E%3Cpath d='m7 10 5 5 5-5'/%3E%3C/svg%3E");
}

/* ============================================================
   2. BASE
   Lo que el portal tomaba de login.css, reescrito aquí.
   ============================================================ */
*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; color-scheme: light; }

/* Con una ventana abierta, la página de debajo no se desplaza. */
html:has(dialog[open]) { overflow: hidden; }

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--fondo);
  color: var(--texto);
  font: 400 1rem/1.55 var(--fuente);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--fuente-titulo);
  color: var(--titulo);
  letter-spacing: -0.01em;
}

p { margin: 0; }

img { display: block; max-width: 100%; }

a { color: var(--primario-fuerte); }

button, input, select { font: inherit; color: inherit; }
button { cursor: pointer; }

/* GUARDA OBLIGATORIA. Una regla de autor con `display` le gana a la del
   navegador para [hidden], así que sin esto un <svg hidden> o un bloque con
   `display: flex` se siguen pintando: los dos iconos del botón de la clave
   (ojo y ojo tachado) salían a la vez y el botón parecía no hacer nada. */
[hidden] { display: none !important; }

:focus-visible {
  outline: 3px solid var(--primario-fuerte);
  outline-offset: 2px;
}
/* Lo que se enfoca por programa —títulos, avisos— para que el lector de
   pantalla lo anuncie; un anillo sobre algo que no se pulsa solo despista. */
[tabindex="-1"]:focus { outline: none; }

/* Solo para lectores de pantalla. */
.sr {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Los iconos del sprite. En línea con el texto, no en bloque: van dentro de
   botones y rótulos. */
.ico {
  width: 20px;
  height: 20px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* El sprite no se pinta, pero NO con display:none: con él, algunos
   navegadores dejan de resolver los <use> que apuntan a sus símbolos. Y
   esta regla sustituye al `style=` de la maqueta, que la CSP no admite. */
.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* ============================================================
   3. ARMAZÓN
   ============================================================ */
.contenedor {
  width: 100%;
  max-width: 1180px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 16px;
  padding-right: 16px;
}
@media (min-width: 720px) {
  .contenedor { padding-left: 24px; padding-right: 24px; }
}
@media (min-width: 1024px) {
  .contenedor { padding-left: 32px; padding-right: 32px; }
}

/* Lo de fuera (ingreso) y lo de dentro se turnan: `mostrar()` pone
   `body.esta-dentro`, y con sesión la puerta entera se va. */
body.esta-dentro .puerta { display: none; }

/* SOLO OPACIDAD, sin `transform`: la trampa 1. La entrada de `.pantalla`
   con un desplazamiento dejaba la barra de módulos flotando a 67 px del
   fondo (21/09/2026). */
.pantalla,
.hub { animation: aparecer 0.18s ease-out; }
@keyframes aparecer {
  from { opacity: 0; }
  to { opacity: 1; }
}

#contenido { padding-top: 24px; }
@media (min-width: 720px) {
  #contenido { padding-top: 32px; }
}

/* ---------- El marco: panel lateral y página (#48) ----------
   Con sesión, la cabecera, el marco y el pie se ensanchan hasta 1.460 px:
   son los 1.180 de siempre más lo que ocupa el panel (248 + 32 de hueco).
   Así, en una pantalla grande la página del módulo conserva el ancho que
   tenía antes de la #48 (1.116 px) en vez de estrecharse para dejar sitio
   al panel. El ingreso, sin sesión, no cambia. */
body.esta-dentro .contenedor { max-width: 1460px; }

/* En el móvil `.marco` es un bloque sin más: `#modulos` es la barra fija y la
   página ocupa el ancho, exactamente como antes de la #48. En ancho, dos
   columnas: el panel a la izquierda y la página a la derecha. `minmax(0, …)`
   para que una tabla o un nombre largo no empujen la página fuera del marco.
   Sin transform, filter ni compañía (trampa 1): es ancestro de la barra.

   ANCHO Y ADEMÁS ALTO (541 px o más). El panel es `sticky` dentro del marco,
   y al final de la página el marco se acaba antes que el pie: en una pantalla
   baja —un teléfono apaisado, 844×340— el panel subía y la cabecera le tapaba
   tres de los cuatro destinos. Por debajo de 541 px de alto va la barra de
   abajo, como en el móvil (ver «Los cuatro destinos»); es un celular.

   224 px Y NO 200 entre 720 y 959: con la letra del navegador en «Muy
   grande» (24 px), «Agendar» con su cuenta no cabía en 200 y se cortaba. */
@media (min-width: 720px) and (min-height: 541px) {
  .marco {
    display: grid;
    grid-template-columns: 224px minmax(0, 1fr);
    column-gap: 24px;
    align-items: start;
  }
}
@media (min-width: 960px) and (min-height: 541px) {
  .marco { grid-template-columns: 248px minmax(0, 1fr); column-gap: 32px; }
}

/* ---------- El pie ---------- */
.pie {
  margin-top: 48px;
  padding-top: 20px;
  padding-bottom: 24px;
  border-top: 1px solid var(--borde);
  color: var(--texto-suave);
  font-size: 0.875rem;
  line-height: 1.5;
}
.pie__seguro {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  max-width: 80ch;
}
.pie__seguro .ico { width: 18px; height: 18px; margin-top: 1px; color: var(--exito); }
.pie__enlaces {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
  margin: 10px 0;
}
.pie__enlaces a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 600;
}

/* ============================================================
   4. CABECERA, MÓDULOS Y MENÚ DE LA CUENTA
   ============================================================ */
/* 45 Y NO 30 DESDE LA #48. Mientras `#modulos` vivía dentro de la cabecera,
   el menú de la cuenta (50) y la barra de abajo (40) se ordenaban en el
   contexto de ella y el menú quedaba siempre encima. Ahora la barra vive en
   el marco, hermano de la cabecera: con la cabecera en 30, la barra (40)
   taparía el pie del menú abierto POR SI llegara hasta ella en una pantalla
   baja o con zoom. No se ha visto (a 390×330 el menú acaba 13 px por encima
   de la barra), pero con 45 el menú queda por encima pase lo que pase; la
   cabecera y la barra no se tocan (una arriba, otra abajo). */
.cabecera {
  position: sticky;
  top: 0;
  z-index: 45;
  background: var(--cabecera);
  color: #fff;
  padding-top: 0;
  padding-top: env(safe-area-inset-top, 0px);
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
}
.cabecera--fuera { position: relative; }

.cabecera__fila {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 56px;
}

.marca {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: none;
  min-height: 44px;
  margin-right: auto;
  border-radius: 8px;
  color: #fff;
  text-decoration: none;
}
.marca:focus-visible { outline-color: #fff; }
.marca__logo { width: auto; height: 24px; }
.marca__sep { width: 1px; height: 24px; background: rgba(255, 255, 255, 0.2); }
.marca__portal { font: 600 1rem/1.2 var(--fuente-titulo); color: #c9cad1; }
/* Entre 720 y 960 px no caben a la vez el logo, «Portal de pacientes», el
   nombre entero, «Mi perfil» y «Cerrar sesión»: se va el rótulo. */
@media (max-width: 959px) {
  .marca__sep,
  .marca__portal { display: none; }
}
@media (min-width: 720px) {
  .cabecera__fila { min-height: 64px; }
  .marca__logo { height: 28px; }
  .marca__portal { font-size: 1.125rem; }
}

/* De quién es la sesión: texto, no botón. Se recorta con puntos
   suspensivos en vez de partirse: un nombre en dos renglones descuadra la
   barra entera. */
.cuenta__quien {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 600 1rem/1.3 var(--fuente);
  color: #e3e5ee;
}

.zona-cuenta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}

/* «Mi perfil» y «Cerrar sesión»: icono Y texto, siempre. */
.boton-cab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 4px 14px 4px 12px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font: 600 1rem/1.2 var(--fuente);
  white-space: nowrap;
  text-decoration: none;
}
.boton-cab:hover { background: rgba(255, 255, 255, 0.16); }
.boton-cab:focus-visible { outline-color: #fff; }
/* Estando en «Mi perfil», el enlace se marca con una raya blanca, que es lo
   que contrasta sobre la cabecera oscura. */
.boton-cab[aria-current="page"] {
  background: rgba(255, 255, 255, 0.16);
  box-shadow: inset 0 -3px 0 #fff;
}
.boton-cab .chev { width: 18px; height: 18px; transition: transform 0.15s; }
.boton-cab[aria-expanded="true"] .chev { transform: rotate(180deg); }

/* El menú cuelga del botón y NO empuja la pantalla: si empujara, abrirlo
   movería el módulo entero hacia abajo. Por encima de la barra de abajo
   (la cabecera, 45, sobre la barra, 40; ver `.cabecera`), y con alto máximo para
   que en pantallas bajas o con zoom se desplace por dentro. */
.cuenta { position: relative; }
.cuenta__menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 50;
  display: grid;
  gap: 4px;
  width: 340px;
  width: min(360px, calc(100vw - 32px));
  max-height: calc(100vh - 160px);
  max-height: calc(100dvh - 160px);
  overflow: auto;
  padding: 8px;
  border: 1px solid var(--borde);
  border-radius: 16px;
  background: var(--superficie);
  color: var(--texto);
  box-shadow: var(--sombra-flotante);
  text-align: left;
}
.cuenta__nota {
  padding: 6px 12px 4px;
  color: var(--texto-suave);
  font: 500 0.875rem/1.4 var(--fuente);
}

/* Las dos formas de salir: el MISMO peso, y cada una dice su alcance. */
.salida {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  min-height: 48px;
  padding: 12px;
  border: 0;
  border-radius: 12px;
  background: none;
  text-align: left;
  color: var(--titulo);
}
.salida:hover:not([disabled]) { background: var(--fondo); }
.salida[disabled] { cursor: not-allowed; }
.salida[data-loading] { cursor: progress; }
.salida__icono { display: grid; place-items: center; flex: none; color: var(--primario-fuerte); }
.salida__texto { flex: 1 1 auto; min-width: 0; }
.salida__que { display: block; font: 600 1rem/1.3 var(--fuente); color: var(--titulo); }
.salida__cual {
  display: block;
  margin-top: 2px;
  font: 500 0.875rem/1.35 var(--fuente);
  color: var(--texto-suave);
}
/* El hilandero de `.btn__spinner` es blanco porque nació para el botón azul;
   aquí el fondo es claro y se repinta. */
.salida__giro {
  flex: none;
  margin-top: 2px;
  border-color: rgba(61, 81, 212, 0.25);
  border-top-color: var(--primario-fuerte);
}
.salida:not([data-loading]) .salida__giro { display: none; }
.cuenta__menu .alert { margin: 6px 4px 4px; }

/* ---------- Los cuatro destinos ----------
   Lo común a las dos anchuras va aquí; lo que es de cada una, en su
   `@media`. El móvil (más abajo) es la barra fija de la #49 SIN CAMBIOS: sus
   reglas pisan lo mismo que pisaban cuando esta parte era la fila de
   pastillas de la cabecera, y lo que no pisan vale lo mismo que entonces. */
.modulos__carril { max-width: 100%; }
.modulo {
  position: relative;
  display: inline-flex;
  align-items: center;
  font: 600 1rem/1.2 var(--fuente);
  text-decoration: none;
  white-space: nowrap;
}
/* La cuenta de lo que hay dentro. Solo se pinta cuando el dato ya existe. */
.modulo__cuenta {
  display: inline-grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding: 0 6px;
  border-radius: 999px;
  font: 700 0.875rem/22px var(--fuente);
  font-variant-numeric: tabular-nums;
}

/* ---------- En el computador: el panel lateral (#48) ----------
   Una tarjeta blanca con los cuatro destinos uno debajo de otro, como la
   barra lateral del gestor de tareas de Artmedica: fondo de superficie,
   borde, y el destino actual en píldora de ancho completo.

   SIEMPRE VISIBLE, NO ES UN CAJÓN: nada se pliega ni se abre (regla de
   como-se-diseña-para-pacientes.md). PEGAJOSO: al bajar por una lista larga
   de citas, el panel sigue a la vista debajo de la cabecera (64 px) con el
   mismo aire que tiene la página arriba (32 px). `sticky` en el propio
   `#modulos` no afecta a la trampa 1, que es de sus ANCESTROS. Con alto
   máximo y desplazamiento propio por si el zoom no lo dejara caber. Solo con
   541 px de alto o más: por debajo, la barra de abajo (ver `.marco`). */
@media (min-width: 720px) and (min-height: 541px) {
  .modulos {
    position: sticky;
    top: 96px;
    margin-top: 32px;
    max-height: calc(100vh - 120px);
    max-height: calc(100dvh - 120px);
    overflow-y: auto;
    padding: 8px;
    border: 1px solid var(--borde);
    border-radius: 16px;
    background: var(--superficie);
    box-shadow: var(--sombra-tarjeta);
  }
  .modulos__carril {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .modulo {
    display: flex;
    gap: 12px;
    min-height: 48px;
    padding: 12px 14px;
    border-radius: 12px;
    color: var(--texto-suave);
  }
  .modulo:hover { background: var(--neutro-tinte); color: var(--titulo); }
  /* El sitio actual se marca con `aria-current` (lo dice el lector de
     pantalla) y con `.modulo--aqui`; las dos cosas las pone `irAlModulo`.
     `.modulo.modulo--aqui` y no la clase sola: `irAlModulo` también se la
     pone a «Mi perfil» de la cabecera, que tiene su propia marca. COLOR Y
     FONDO a la vez: la píldora del degradado con la letra blanca, que no
     depende de distinguir un tono. */
  .modulo[aria-current="page"],
  .modulo.modulo--aqui {
    background: var(--primario);
    background: var(--degradado);
    color: #fff;
    box-shadow: var(--sombra-cta);
  }
  .modulo__icono { flex: none; width: 20px; height: 20px; }
  /* El texto se come el hueco y empuja la cuenta al borde derecho. SIN
     PUNTOS SUSPENSIVOS: con la letra del navegador grande, «Mis ci…» era un
     destino mutilado justo para quien más lo necesita. Si no cabe, pasa a
     dos líneas; nunca se corta. */
  .modulo__texto {
    flex: 1 1 auto;
    min-width: 0;
    white-space: normal;
    overflow-wrap: break-word;
  }
  .modulo__cuenta {
    flex: none;
    background: var(--primario-tinte);
    color: var(--primario-fuerte);
  }
  .modulo[aria-current="page"] .modulo__cuenta,
  .modulo.modulo--aqui .modulo__cuenta {
    background: #fff;
    color: var(--primario-fuerte);
  }
}

/* ---------- En el móvil ---------- */
@media (max-width: 719px) {
  .cabecera__fila { flex-wrap: wrap; gap: 4px; }
  .zona-cuenta { gap: 4px; }
  /* El nombre baja a su propia línea, debajo de la marca y los botones. */
  .cuenta__quien {
    order: 3;
    flex: 1 1 100%;
    padding: 0 0 8px;
    font-size: 0.875rem;
  }
  /* Icono encima del texto: caben los dos botones junto al logo a 320 px. */
  .boton-cab {
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    min-width: 56px;
    min-height: 50px;
    padding: 3px 8px;
    border-color: transparent;
    border-radius: 12px;
    background: transparent;
    font-size: 0.875rem;
    line-height: 1.15;
  }
  .boton-cab:hover,
  .boton-cab[aria-expanded="true"] { background: rgba(255, 255, 255, 0.12); }
  .boton-cab > .ico { width: 24px; height: 24px; }
  .boton-cab .chev { display: none; }
  /* El menú se ancla a la fila entera, no al botón, para caber en pantalla. */
  .cuenta { position: static; }
  .cuenta__menu { top: calc(100% - 2px); right: 16px; }
}

/* ---------- La barra de abajo: el móvil y las pantallas bajas ----------
   También con menos de 541 px de alto aunque la pantalla sea ancha (un
   teléfono apaisado): ahí el panel lateral no cabe entero bajo la cabecera
   al final de la página (ver `.marco`). La cabecera sigue siendo la de
   ancho; solo cambian los destinos. */
@media (max-width: 719px), (max-height: 540px) {
  /* ABAJO Y FIJA: donde llega el pulgar y donde la esperan los portales de
     salud que el paciente ya usa. El relleno llano primero y el del recorte
     de pantalla después (trampa 2). */
  .modulos {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    padding: 6px;
    padding-bottom: 6px;
    padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--borde);
    background: var(--superficie);
    box-shadow: var(--sombra-barra);
  }
  .modulos__carril {
    display: flex;
    gap: 2px;
    width: 100%;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
  }
  .modulo {
    flex: 1 1 0;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    min-width: 0;
    min-height: 56px;
    padding: 4px 2px;
    border-radius: 14px;
    color: var(--texto-suave);
    font-size: 0.875rem;
  }
  .modulo:hover { background: var(--fondo); color: var(--titulo); }
  .modulo:focus-visible { outline-color: var(--primario-fuerte); }
  /* El tinte solo da 1,12:1 sobre blanco: lo que marca el destino actual es
     la raya de arriba (6,31:1) y el peso de la letra. */
  .modulo[aria-current="page"],
  .modulo.modulo--aqui {
    background: var(--primario-tinte);
    color: var(--primario-fuerte);
    font-weight: 700;
    box-shadow: inset 0 3px 0 var(--primario-fuerte);
  }
  .modulo__icono { width: 24px; height: 24px; }
  .modulo__cuenta {
    position: absolute;
    top: 2px;
    left: calc(50% + 4px);
    background: var(--primario-fuerte);
    color: #fff;
  }

  /* EL HUECO DE LA BARRA, en un elemento nuestro (trampa 3): el último botón
     de la página no puede quedar debajo de ella. */
  body.esta-dentro .portal {
    padding-bottom: 100px;
    padding-bottom: calc(100px + env(safe-area-inset-bottom, 0px));
  }
  /* Y EL FOCO TAMPOCO. Quien avanza con el tabulador —o con el teclado de un
     lector de pantalla— lleva la página hasta el elemento enfocado, y sin esto
     el navegador lo dejaba DETRÁS de la barra: un «Ver detalle» al 0 % a
     360 px (WCAG 2.4.11). */
  html {
    scroll-padding-bottom: 100px;
    scroll-padding-bottom: calc(100px + env(safe-area-inset-bottom, 0px));
  }
}
/* A 320 px el logo y los dos botones caben en una fila apretando el logo, el
   relleno y los huecos; sin esto los botones bajaban a una segunda línea. */
@media (max-width: 359px) {
  .marca__logo { height: 16px; }
  .cabecera__fila,
  .zona-cuenta { gap: 2px; }
  .boton-cab { min-width: 48px; padding: 3px 4px; }
}

/* ============================================================
   5. BOTONES
   ============================================================ */
/* El principal. Ancho de su texto y a la izquierda: un control estirado de
   lado a lado se ve mal (German, tres veces). Ancho completo solo en el
   móvil, donde uno estrecho se falla con el pulgar. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 12px 24px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--primario);
  background: var(--degradado);
  color: #fff;
  font: 700 1rem/1.2 var(--fuente);
  text-align: center;
  text-decoration: none;
  box-shadow: var(--sombra-cta);
}
.btn:hover { background: var(--primario-fuerte); }
.btn[disabled] { opacity: 0.55; cursor: not-allowed; box-shadow: none; }
/* TRABAJANDO: opacidad entera. `cargando()` además lo deshabilita, y con la
   opacidad de deshabilitado «Ingresando…» quedaba por debajo de 4,5:1. */
.btn[data-loading] { opacity: 1; cursor: progress; }

.btn__spinner {
  width: 16px;
  height: 16px;
  flex: none;
  border: 2px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: girar 0.7s linear infinite;
}
.btn:not([data-loading]) .btn__spinner { display: none; }
/* Solo gira el hilandero: dentro no hay nada `fixed`. */
@keyframes girar { to { transform: rotate(360deg); } }

/* Secundario: lo que no es la acción principal de su sitio. */
.btn--sobrio {
  border-color: var(--borde-fuerte);
  background: var(--superficie);
  color: var(--texto);
  box-shadow: none;
}
.btn--sobrio:hover:not([disabled]) {
  border-color: var(--primario);
  background: var(--primario-tinte);
  color: var(--primario-fuerte);
}
.btn--sobrio .btn__spinner {
  border-color: rgba(61, 81, 212, 0.25);
  border-top-color: var(--primario-fuerte);
}

/* EL ÚNICO ROJO DEL PORTAL: «Sí, cancelar la cita», el último paso. */
.btn--peligro {
  background: var(--peligro);
  color: #fff;
  box-shadow: none;
}
.btn--peligro:hover { background: var(--peligro); box-shadow: inset 0 0 0 999px rgba(0, 0, 0, 0.12); }

/* Botón con forma de enlace: «Pedir otro código» es una acción, no una
   navegación, y tiene que ser <button> para el teclado y los lectores. */
.enlace {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 10px 4px;
  border: 0;
  background: none;
  color: var(--primario-fuerte);
  font: 700 1rem/1.3 var(--fuente);
  text-align: left;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.enlace:hover { text-decoration-thickness: 2px; }
.enlace[disabled] { opacity: 0.6; cursor: not-allowed; }
/* CANCELAR ES SOBRIO HASTA EL ÚLTIMO PASO. En el detalle es un enlace más, en
   el color del texto: hasta la #49 salía en rojo, en contra de este mismo
   comentario, y el rojo dejaba de significar «esto no se deshace». */
.enlace--peligro { color: var(--texto); }

/* Las acciones de una tarjeta. Secundarias salvo las marcadas. */
.accion {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 18px;
  border: 1px solid var(--borde-fuerte);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--texto);
  font: 700 1rem/1.2 var(--fuente);
}
.accion:hover:not([disabled]) {
  border-color: var(--primario);
  background: var(--primario-tinte);
  color: var(--primario-fuerte);
}
.accion[disabled] { opacity: 0.6; cursor: not-allowed; }
/* «Confirmar asistencia»: lo que corre prisa en la tarjeta. */
.accion--si {
  border-color: transparent;
  background: var(--primario);
  background: var(--degradado);
  color: #fff;
  box-shadow: var(--sombra-cta);
}
.accion--si:hover:not([disabled]) {
  border-color: transparent;
  background: var(--primario-fuerte);
  color: #fff;
}
/* LOS ICONOS DE LOS BOTONES CUYO TEXTO REESCRIBE EL JS van por máscara:
   `confirmarCita` cambia el `textContent` del botón («Confirmando…») y un
   icono hijo se perdería. El icono y el texto van juntos, siempre. */
.accion--si::before,
#citaAcciones .btn:not(.btn--sobrio)::before,
#citaAcciones .btn--sobrio::before,
.cita__acciones .accion:not(.accion--si)::after {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  background: currentColor;
}
.accion--si::before,
#citaAcciones .btn:not(.btn--sobrio)::before {
  -webkit-mask: var(--m-check) center / contain no-repeat;
  mask: var(--m-check) center / contain no-repeat;
}
#citaAcciones .btn--sobrio::before {
  -webkit-mask: var(--m-calendario) center / contain no-repeat;
  mask: var(--m-calendario) center / contain no-repeat;
}
/* «Ver detalle» lleva la flecha DETRÁS: dice «esto abre algo». */
.cita__acciones .accion:not(.accion--si)::after {
  -webkit-mask: var(--m-flecha) center / contain no-repeat;
  mask: var(--m-flecha) center / contain no-repeat;
}
/* «Ver horarios»: primario solo en el control que le corresponde ahora; en
   los demás, secundario con el color de la marca. */
.accion--principal { border-color: var(--primario); color: var(--primario-fuerte); }
.control--suya .accion--principal {
  border-color: transparent;
  background: var(--primario);
  background: var(--degradado);
  color: #fff;
  box-shadow: var(--sombra-cta);
}
.control--suya .accion--principal:hover:not([disabled]) { background: var(--primario-fuerte); color: #fff; }

.volver {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  margin: -8px 0 8px;
  padding: 8px 4px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--primario-fuerte);
  font: 700 1rem/1.2 var(--fuente);
}
.volver svg { width: 20px; height: 20px; }
.volver:hover { text-decoration: underline; text-underline-offset: 3px; }

/* ============================================================
   6. CAMPOS
   ============================================================ */
.field { margin-bottom: 18px; }
.field__head { margin-bottom: 6px; }
.field__label { font: 600 1rem/1.3 var(--fuente); color: var(--titulo); }
.field__control { position: relative; }

/* 16 px de letra: con menos, iOS amplía la página al enfocar el campo. */
.input {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  border: 1px solid var(--borde-campo);
  border-radius: 12px;
  background: var(--superficie);
  color: var(--titulo);
  font: 400 1rem/1.3 var(--fuente);
}
.input::placeholder { color: var(--texto-suave); opacity: 1; }
.input:focus { outline: none; border-color: var(--primario-fuerte); box-shadow: var(--anillo); }
.input[aria-invalid="true"] { border-color: var(--aviso); box-shadow: inset 0 0 0 1px var(--aviso); }

/* La flecha del desplegable va en una imagen de fondo: un ::after no se
   puede poner sobre un <select>, porque el navegador no pinta hijos dentro. */
.input--select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 44px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23555971' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 20px;
}
/* En Firefox el <option> hereda el color del sistema con appearance:none. */
.input--select option { color: var(--titulo); }

/* El código de seis dígitos: se lee de un WhatsApp y se teclea en un móvil.
   Grande, centrado y tabular para que no baile al escribir. */
.input--codigo {
  font: 600 1.5rem/1.2 var(--fuente-titulo);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.34em;
  text-indent: 0.34em;
  text-align: center;
}
.input--codigo::placeholder { letter-spacing: 0.34em; font-size: 1.25rem; }

/* Sitio para el botón del ojo, que lleva icono y texto («Ocultar» es el largo). */
.input--password { padding-right: 116px; }

/* 44 px, el mínimo táctil. Centrado con `top` y no con `transform`. Icono Y
   texto, «Mostrar» / «Ocultar» (regla 2): un ojo solo no lo entiende todo el
   mundo. */
.reveal {
  position: absolute;
  top: 2px;
  right: 2px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 44px;
  height: 44px;
  padding: 0 10px;
  border: 0;
  border-radius: 10px;
  font: 600 0.875rem/1 var(--fuente);
  background: none;
  color: var(--texto-suave);
}
.reveal:hover { color: var(--primario-fuerte); background: var(--fondo); }

/* El error de un campo, en ámbar y con icono: el rojo es solo del último
   paso de cancelar. El icono va por máscara porque el texto lo escribe el JS. */
.field__error {
  display: flex;
  gap: 6px;
  align-items: flex-start;
  margin-top: 6px;
  color: var(--aviso);
  font: 600 0.875rem/1.4 var(--fuente);
}
.field__error::before {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  background: currentColor;
  -webkit-mask: var(--m-alerta) center / contain no-repeat;
  mask: var(--m-alerta) center / contain no-repeat;
}
.field__error:empty { display: none; }

.field__ayuda {
  margin-top: 6px;
  color: var(--texto-suave);
  font: 500 0.875rem/1.4 var(--fuente);
}

/* Los requisitos de la clave. El estado NO va solo en el color: cambia
   también el icono, para quien no distingue verde de gris. */
.reglas {
  display: grid;
  gap: 6px;
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
}
.reglas li {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  color: var(--texto-suave);
  font: 500 0.875rem/1.45 var(--fuente);
}
.reglas li::before {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  background: currentColor;
  -webkit-mask: var(--m-pendiente) center / contain no-repeat;
  mask: var(--m-pendiente) center / contain no-repeat;
}
.reglas li[data-ok="si"] { color: var(--exito); font-weight: 600; }
.reglas li[data-ok="si"]::before {
  -webkit-mask-image: var(--m-hecho);
  mask-image: var(--m-hecho);
}
/* La regla que la pantalla NO puede comprobar se enuncia sin marca de
   estado: un círculo vacío prometería una comprobación que no se hace. */
.reglas li.reglas__fija::before {
  -webkit-mask-image: var(--m-info);
  mask-image: var(--m-info);
}

/* ============================================================
   7. AVISOS Y ESTADOS
   ============================================================ */
/* El aviso de error: ámbar, con icono y con el texto en su color de
   siempre. `--tono` lo cambia cada variante. */
.alert {
  --tono: var(--aviso);
  --tono-tinte: var(--aviso-tinte);
  display: flex;
  gap: 12px;
  align-items: flex-start;
  max-width: 68ch;
  margin-bottom: 20px;
  padding: 14px 16px;
  border: 1px solid var(--borde);
  border-left: 4px solid var(--tono);
  border-radius: 16px;
  background: var(--tono-tinte);
  color: var(--titulo);
}
.alert > svg { flex: none; width: 20px; height: 20px; margin-top: 2px; color: var(--tono); }
.alert--ok { --tono: var(--exito); --tono-tinte: var(--exito-tinte); }
/* El aviso recibe el foco por programa, para que se lea; sin anillo. */
#agendaError:focus { outline: none; }

/* «Esto no se puede deshacer»: ámbar, como un aviso, no rojo. */
.aviso {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  max-width: 68ch;
  margin: 0 0 20px;
  padding: 14px 16px;
  border: 1px solid var(--borde);
  border-left: 4px solid var(--aviso);
  border-radius: 16px;
  background: var(--aviso-tinte);
  color: var(--texto);
}
.aviso > .ico { margin-top: 2px; color: var(--aviso); }
.aviso__que { color: var(--titulo); }
.aviso__mas { margin-top: 6px; }

.panel__nota { margin-top: 16px; color: var(--texto-suave); }
/* Un enlace dentro de una frase no se separa del punto que la cierra, y los
   dos enlaces seguidos del ingreso van juntos: el área de 44 px ya los aparta. */
.panel__nota .enlace { padding-left: 0; padding-right: 0; }
.panel__nota + .panel__nota { margin-top: 0; }
.panel__nota--pegado { margin: 0; flex: 1 1 200px; font-size: 0.9375rem; }

/* Mientras se pregunta al ERP. Solo gira el anillo. */
.cargando {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 20px;
  padding: 16px 0;
  color: var(--texto-suave);
  font-weight: 600;
}
.cargando__giro {
  width: 18px;
  height: 18px;
  flex: none;
  border: 2px solid var(--borde-fuerte);
  border-top-color: var(--primario-fuerte);
  border-radius: 50%;
  animation: girar 0.8s linear infinite;
}
.cargando--dentro { margin: 0; padding: 14px 16px; }

/* El estado vacío: explica, y da una salida que no pasa por aquí. A la
   izquierda, como todo lo demás. */
.vacio {
  padding: 24px 20px;
  border: 1px dashed var(--borde-fuerte);
  border-radius: 16px;
  background: var(--superficie);
}
.vacio__que { font: 600 1.125rem/1.35 var(--fuente-titulo); color: var(--titulo); }
.vacio__mas { max-width: 60ch; margin-top: 8px; color: var(--texto-suave); }
.vacio__que + .vacio__mas + .vacio__mas { margin-top: 4px; }
/* El dibujo del vacío: en tinte de la marca, no en gris. Un vacío no es un
   error; dice «aquí no hay nada» con calma. */
.vacio__icono {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin: 0 0 12px;
  border-radius: 50%;
  background: var(--primario-tinte);
  color: var(--primario-fuerte);
}
.vacio__icono .ico { width: 28px; height: 28px; }

/* ============================================================
   8. LAS PÁGINAS DE DENTRO
   ============================================================ */
.panel__title {
  margin: 0 0 8px;
  font: 700 1.5rem/1.25 var(--fuente-titulo);
  letter-spacing: -0.022em;
  color: var(--titulo);
}
@media (min-width: 720px) {
  .panel__title { font-size: 1.75rem; }
}
.hub > .panel__title { margin-bottom: 8px; }
.hub__lede { max-width: 68ch; margin: 0 0 24px; color: var(--texto); }
.hub__ayuda {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  max-width: 68ch;
  margin-top: 32px;
  color: var(--texto-suave);
}
.hub__ayuda .ico { margin-top: 2px; color: var(--info); }
/* Las páginas de leer y decidir (cancelar) van en una columna de lectura:
   una ficha de 1.200 px de ancho obliga a mover los ojos de lado a lado. */
.hub--estrecho { max-width: 720px; }
.hub--estrecho .field { max-width: 460px; }

/* Una tarjeta blanca con franja a la izquierda. La franja la pone cada
   variante con `--franja`; el estado nunca va SOLO en el color. */
.cita,
.siguiente,
.control,
.atencion {
  position: relative;
  border: 1px solid var(--borde);
  border-left: 5px solid var(--franja, var(--borde));
  border-radius: 16px;
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
}

/* ============================================================
   9. TARJETAS DE CITA
   ============================================================ */
.cita { --franja: var(--borde-campo); padding: 16px; }
@media (min-width: 720px) {
  .cita { padding: 20px; }
}
.cita--proxima { --franja: var(--primario); }
/* LA FRANJA DICE EL ESTADO DE UN VISTAZO (#49), y siempre con la insignia
   que lo dice en palabras: confirmada en verde, la de hoy o mañana en ámbar,
   la de aplicación de medicamentos —la que se lleva por WhatsApp— en azul.
   Van DESPUÉS de `.cita--proxima` para ganarle con el mismo peso. */
.cita--confirmada { --franja: var(--exito); }
.cita--cerca { --franja: var(--aviso); }
.cita--whatsapp { --franja: var(--info); }
.cita--falto { --franja: var(--borde-campo); }

.cita__cabeza {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
}
/* Las insignias juntas y, si caben, a la derecha de la fecha. */
.cita__insignias {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-left: auto;
}
@media (max-width: 519px) {
  /* En el móvil bajan a su línea, alineadas con la fecha: a la derecha
     quedaban sueltas en mitad de la tarjeta. */
  .cita__cabeza .cita__insignias { flex-basis: 100%; margin-left: 0; }
}
.cita__fecha { font: 600 1.125rem/1.3 var(--fuente-titulo); color: var(--titulo); }
.cita--falto .cita__fecha { color: var(--texto); }
.cita__hora { font: 700 1rem/1.3 var(--fuente); color: var(--primario-fuerte); font-variant-numeric: tabular-nums; }

/* Las insignias, en píldora. La palabra ya dice el estado. */
.cita__cuando,
.cita__sello {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 999px;
  font: 600 0.875rem/1.3 var(--fuente);
  white-space: nowrap;
}
.cita__cuando .ico,
.cita__sello .ico { width: 16px; height: 16px; }
/* «Hoy» y «Mañana»: lo único que hace falta leer con prisa. */
.cita__cuando { background: var(--aviso-tinte); color: var(--aviso); }
/* «En N días» con la misma forma, en neutro: no corre prisa. */
.cita__cuando--lejos { background: var(--neutro-tinte); color: var(--texto); }
.cita__sello { background: var(--exito-tinte); color: var(--exito); }
/* «Atendida» es constancia, no aviso. */
.cita__sello--ida { background: var(--neutro-tinte); color: var(--texto-suave); }
/* «No asistió» en gris y con borde, NO en rojo: no es el último paso de
   nada, y el rojo es solo de cancelar. */
.cita__sello--falto {
  background: var(--superficie);
  color: var(--texto);
  box-shadow: inset 0 0 0 1px var(--borde-campo);
}

.cita__que { margin-top: 8px; font: 600 1rem/1.4 var(--fuente); color: var(--texto); }
/* Dónde es y quién atendió: una línea con su icono delante. */
.cita__medico,
.cita__donde {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin-top: 6px;
  color: var(--texto-suave);
}
.cita__medico .ico,
.cita__donde .ico { width: 18px; height: 18px; margin-top: 3px; }
.cita__donde { overflow-wrap: anywhere; }
.cita__donde > span,
.cita__medico > span { min-width: 0; }
/* La de aplicación de medicamentos no trae botones: esta línea dice por qué
   y a dónde ir, y es lo que el paciente tiene que leer antes de buscarlos. */
.cita__aviso {
  margin-top: 12px;
  padding: 10px 14px;
  border-left: 4px solid var(--info);
  border-radius: 12px;
  background: var(--info-tinte);
  color: var(--texto);
}
.cita__acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--borde);
}

/* ============================================================
   10. INICIO
   ============================================================ */
/* Lo que hay que hacer ahora, y nunca en blanco. */
.siguiente {
  --franja: var(--primario);
  margin: 0 0 8px;
  padding: 20px;
}
@media (min-width: 720px) {
  .siguiente { padding: 24px 28px; }
}
/* La franja de la próxima cita, con los mismos colores que su tarjeta en
   «Mis citas». DESPUÉS de `.siguiente`, que pone la de la marca: con el
   mismo peso gana la que va más abajo. */
.siguiente--confirmada { --franja: var(--exito); }
.siguiente--cerca { --franja: var(--aviso); }
.siguiente--whatsapp { --franja: var(--info); }
.siguiente__fila {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
}
.siguiente__rotulo {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: 700 0.875rem/1.3 var(--fuente);
  color: var(--primario-fuerte);
}
.siguiente__rotulo .ico { width: 18px; height: 18px; }
.siguiente__que {
  margin-top: 10px;
  font: 700 1.375rem/1.25 var(--fuente-titulo);
  color: var(--titulo);
}
@media (min-width: 720px) {
  .siguiente__que { font-size: 1.625rem; }
}
.siguiente__mas { margin-top: 6px; font: 600 1.125rem/1.4 var(--fuente); color: var(--texto); }
.siguiente .cita__donde { margin-top: 8px; }
/* Las acciones de la próxima cita son las de su tarjeta (`botonesDe`), en
   grande y sin la raya de separación: aquí son lo principal. */
.siguiente .cita__acciones { margin-top: 20px; padding-top: 0; border-top: 0; }
.siguiente .accion { min-height: 48px; padding: 12px 24px; }
/* SIN CITAS: en discontinuo y sin franja, como todo vacío; el texto es de
   calma, no de aviso. */
.siguiente--vacio {
  border-style: dashed;
  border-left-width: 1px;
  border-color: var(--borde-fuerte);
}
.siguiente--vacio .siguiente__que { margin-top: 0; font-size: 1.25rem; }
.siguiente--vacio .siguiente__mas { max-width: 60ch; font: 400 1rem/1.55 var(--fuente); color: var(--texto-suave); }
.siguiente--vacio .siguiente__mas + .siguiente__mas { margin-top: 4px; }
/* Consultando: la tarjeta sin franja, que todavía no hay estado que decir. */
.siguiente--lisa { border-left-width: 1px; padding: 4px 8px; }
.siguiente__ir {
  display: flex;
  align-items: center;
  width: max-content;
  min-height: 44px;
  margin-top: 8px;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Las puertas: la tarjeta entera es el enlace. */
.accesos {
  display: grid;
  gap: 12px;
  margin: 32px 0 0;
  padding: 0;
  list-style: none;
}
/* LOS CORTES VAN 256-280 PX MÁS TARDE QUE ANTES DE LA #48, que es lo que
   ocupa el panel lateral: lo que manda es el ancho que le queda a la página,
   no el de la ventana. Dos puertas por fila desde 960 (632 px de página, como
   los 672 de antes a 720) y cuatro desde 1.280 (936 px, como los 960 de antes
   a 1.024). */
@media (min-width: 720px) {
  .accesos { gap: 16px; }
}
@media (min-width: 960px) {
  .accesos { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1280px) {
  .accesos { grid-template-columns: repeat(4, 1fr); }
}
/* Icono, texto y flecha en fila; desde 1.280 px, con cuatro puertas en
   línea, el icono y la flecha arriba y el texto debajo a todo el ancho. */
.acceso {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  /* Sin esto, en una fila de tarjetas de igual alto la que tiene menos
     texto reparte el hueco entre sus filas y el título baja. */
  align-content: start;
  gap: 4px 14px;
  height: 100%;
  min-height: 64px;
  padding: 16px;
  border: 1px solid var(--borde);
  border-radius: 16px;
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
  color: var(--texto);
  text-decoration: none;
  transition: box-shadow 0.15s, border-color 0.15s;
}
.acceso:hover { border-color: var(--borde-fuerte); box-shadow: var(--sombra-tarjeta-hover); }
.acceso__icono {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--primario-tinte);
  color: var(--primario-fuerte);
}
.acceso__icono .ico { width: 22px; height: 22px; }
.acceso__texto { min-width: 0; }
.acceso__titulo { display: block; font: 600 1.125rem/1.3 var(--fuente-titulo); color: var(--titulo); }
.acceso__lede { display: block; margin-top: 4px; color: var(--texto-suave); }
/* La cuenta de lo que hay dentro, en píldora. Solo se ve con el dato. */
.acceso__cuenta {
  display: inline-block;
  margin-top: 8px;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--primario-tinte);
  color: var(--primario-fuerte);
  font: 600 0.875rem/1.3 var(--fuente);
}
.acceso__flecha { margin-top: 12px; color: var(--primario-fuerte); }
@media (min-width: 1280px) {
  .acceso { grid-template-columns: minmax(0, 1fr) auto; gap: 12px; padding: 20px; }
  .acceso__texto { grid-column: 1 / -1; grid-row: 2; }
  .acceso__flecha { grid-column: 2; grid-row: 1; }
}

/* ============================================================
   11. MIS CITAS
   ============================================================ */
/* Una columna en el móvil; desde 1.280 px, las citas y el calendario al
   lado. Hasta la #48 era desde 1.024, pero el panel lateral se lleva 280 px:
   a 1.024 la lista se quedaba en 272 px, más estrecha que en un teléfono, y
   a 1.280 le quedan 528 (a 1.024 sin panel eran 552). Las dos columnas se
   fijan por su nombre y no por el orden del documento, así que el móvil lee
   en el orden del HTML. */
.dentro__cuerpo { display: grid; gap: 28px; }
@media (min-width: 1280px) {
  .dentro__cuerpo {
    grid-template-columns: minmax(0, 1fr) 380px;
    align-items: start;
  }
  .dentro__principal { grid-column: 1; grid-row: 1; }
  .dentro__lado { grid-column: 2; grid-row: 1; }
}
.dentro__principal { display: grid; gap: 20px; align-content: start; min-width: 0; }

.citas__lista {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 720px) {
  .citas__lista { gap: 16px; }
}
.citas__vacio {
  padding: 20px;
  border: 1px dashed var(--borde-fuerte);
  border-radius: 16px;
  background: var(--superficie);
  color: var(--texto-suave);
}

/* ---------- Próximas y Pasadas ----------
   Un carril con dos pestañas. La elegida se distingue por el BORDE en
   --primario-fuerte (5,62:1 sobre el carril), no por el fondo blanco, que
   solo da 1,12:1, y además por el peso de la letra. */
.pestanas {
  display: flex;
  gap: 4px;
  max-width: 480px;
  padding: 4px;
  border-radius: 999px;
  background: var(--neutro-tinte);
}
.pestana {
  flex: 1 1 0;
  min-height: 44px;
  padding: 8px 12px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: none;
  color: var(--texto-suave);
  font: 600 1rem/1.2 var(--fuente);
}
.pestana:hover { color: var(--primario-fuerte); }
.pestana[aria-selected="true"] {
  border-color: var(--primario-fuerte);
  background: var(--superficie);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);
  color: var(--primario-fuerte);
  font-weight: 700;
}
.pestana__cuenta { font-variant-numeric: tabular-nums; }
.pestanas__panel { display: grid; gap: 16px; align-content: start; min-width: 0; }
.pestanas__panel > .cargando { margin: 0; }

/* El día elegido en el calendario, con su salida («Ver todas»). */
.filtro {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 12px;
}
.filtro__titulo { font: 600 1.125rem/1.3 var(--fuente-titulo); color: var(--titulo); }

/* ---------- El paginador ----------
   «Anteriores» y «Siguientes» en palabras: una flecha sola es un
   jeroglífico. Deshabilitado y no escondido en los extremos, para que el
   otro botón no salte de sitio. */
.pagina {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 12px;
  margin-top: 16px;
}
.pagina__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 44px;
  padding: 10px 18px;
  border: 1px solid var(--borde-fuerte);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--texto);
  font: 700 1rem/1.2 var(--fuente);
}
.pagina__btn:hover:not([disabled]) { border-color: var(--primario); color: var(--primario-fuerte); }
.pagina__btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.pagina__cuenta {
  flex: 1 1 auto;
  color: var(--texto-suave);
  font: 600 0.875rem/1.4 var(--fuente);
  text-align: center;
}
@media (max-width: 519px) {
  .pagina__cuenta { order: -1; flex-basis: 100%; }
  .pagina__btn { flex: 1; }
}

/* ============================================================
   12. EL CALENDARIO (Mis citas y Agendar)
   Un mes por pantalla. Solo son botones los días CON algo: el
   teclado no recorre 31 casillas muertas.
   ============================================================ */
.calendario {
  max-width: 440px;
  padding: 16px;
  border: 1px solid var(--borde);
  border-radius: 16px;
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
}
.calendario__barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
/* EL MES ARRIBA, EN SU LÍNEA, y debajo los dos pasos con icono Y texto
   («Mes anterior» / «Mes siguiente»): con el texto no caben los tres en una
   fila de 320 px. */
.calendario__mes {
  flex: 1 1 100%;
  order: -1;
  font: 600 1.125rem/1.3 var(--fuente-titulo);
  color: var(--titulo);
  text-align: center;
}
/* Si a 320 px no caben los dos pasos en una línea, «Mes siguiente» baja a la
   derecha en vez de pegarse al anterior. */
.calendario__paso--siguiente { margin-left: auto; }
.calendario__paso {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: none;
  min-width: 44px;
  min-height: 44px;
  padding: 8px 10px;
  border: 1px solid var(--borde-fuerte);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--texto);
  font: 600 0.875rem/1.2 var(--fuente);
  white-space: nowrap;
}
.calendario__paso svg { width: 18px; height: 18px; }
.calendario__paso:hover:not([disabled]) { border-color: var(--primario); color: var(--primario-fuerte); }
.calendario__paso[disabled] { opacity: 0.45; cursor: not-allowed; }

.calendario__dias,
.calendario__rejilla {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 4px;
  text-align: center;
}
.calendario__dias span { padding: 6px 0; color: var(--texto-suave); font: 700 0.875rem/1 var(--fuente); }

.dia {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 2px;
  border: 1px solid transparent;
  border-radius: 12px;
  background: none;
  color: var(--texto-suave);
  font: 600 1rem/1 var(--fuente);
}
.dia--vacio { visibility: hidden; }
/* Hoy se señala con un anillo, no con relleno: el relleno se confunde con
   el día elegido. */
.dia--hoy { box-shadow: inset 0 0 0 2px var(--borde-campo); }
/* El día pulsable lleva borde, no solo tinte: el tinte solo da 1,12:1. */
.dia--con {
  border-color: var(--primario);
  background: var(--primario-tinte);
  color: var(--primario-fuerte);
  font-weight: 700;
}
.dia--con:hover { box-shadow: inset 0 0 0 1px var(--primario-fuerte); }
/* Lo que ya pasó, en gris: se distingue de un vistazo lo que queda por hacer. */
.dia--pasado { border-color: var(--borde-campo); background: var(--neutro-tinte); color: var(--texto); }
.dia--elegido,
.dia--elegido:hover {
  border-color: var(--primario-fuerte);
  background: var(--primario-fuerte);
  color: #fff;
}
.dia__punto { width: 6px; height: 6px; margin-top: 4px; border-radius: 50%; background: currentColor; }
.dia__cuantos { margin-top: 3px; font: 700 0.875rem/1 var(--fuente); }
/* Fuera de lo consultado: no es «no hay», es «no se miró». */
.dia--fuera { opacity: 0.45; }

.calendario__pie { margin-top: 12px; color: var(--texto-suave); font: 600 0.875rem/1.4 var(--fuente); }

/* En el móvil se aprieta el marco, no las casillas: así cada día mide 44 px
   desde 360 px de ancho. */
@media (max-width: 519px) {
  .calendario { padding: 12px 4px; }
  .calendario__barra { padding: 0 4px; }
  .calendario__dias,
  .calendario__rejilla { gap: 1px; }
}

/* ============================================================
   13. LAS DOS VENTANAS (la cita y el calendario para agendar)
   Un <dialog> de verdad: el foco atrapado, el Escape y el fondo
   los pone el navegador. En el móvil es una hoja pegada abajo,
   donde llega el pulgar; en ancho, una ventana centrada.
   ============================================================ */
.modal {
  width: 100%;
  max-width: 100%;
  max-height: 88vh;
  max-height: 94dvh;
  margin: auto 0 0;
  padding: 16px 20px 24px;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 0;
  border-radius: 24px 24px 0 0;
  background: var(--superficie);
  color: var(--texto);
  box-shadow: var(--sombra-flotante);
}
.modal::backdrop { background: rgba(11, 16, 48, 0.75); }
@media (min-width: 720px) {
  .modal {
    width: 560px;
    width: min(560px, calc(100vw - 48px));
    max-height: calc(100vh - 48px);
    max-height: calc(100dvh - 48px);
    margin: auto;
    padding: 20px 24px 24px;
    border-radius: 24px;
  }
  /* DOS CLASES: con una sola, `.modal` —mismo peso y más arriba en la
     cascada de esta media— dejaba el calendario en 560 px. */
  .modal.modal--agenda {
    width: 920px;
    width: min(920px, calc(100vw - 48px));
  }
}
/* La animación mueve SOLO el <dialog>, que no tiene nada `fixed` dentro. */
@media (prefers-reduced-motion: no-preference) {
  .modal[open] { animation: subir 0.22s ease-out; }
  @keyframes subir {
    from { opacity: 0; transform: translateY(24px); }
    to { opacity: 1; transform: none; }
  }
}

.modal__cabeza {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--borde);
}
.modal__titulo { font: 600 1.25rem/1.3 var(--fuente-titulo); color: var(--titulo); }
.modal__cerrar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: none;
  min-width: 44px;
  min-height: 44px;
  padding: 8px 10px;
  border: 1px solid var(--borde-fuerte);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--texto);
  font: 600 1rem/1 var(--fuente);
}
.modal__cerrar:hover { border-color: var(--primario); color: var(--primario-fuerte); }
.modal__cerrar .ico { width: 20px; height: 20px; }
.modal__cerrar:has(> span) { padding: 8px 14px 8px 10px; }

/* ---------- La hoja en tres piezas (#49) ----------
   Cuando la ventana trae `.modal__cuerpo`, el <dialog> deja de desplazarse
   entero: la cabecera arriba, el cuerpo con su propio desplazamiento y el
   pie de acciones fijo abajo, donde llega el pulgar. Un navegador sin
   `:has()` se queda con la ventana de arriba, que se desplaza entera y
   funciona igual. */
.modal:has(> .modal__cuerpo) { padding: 0; overflow: hidden; }
.modal[open]:has(> .modal__cuerpo) { display: flex; flex-direction: column; }
.modal:has(> .modal__cuerpo) > .modal__cabeza {
  flex: none;
  margin: 0;
  padding: 12px 16px 12px 20px;
}
.modal__cuerpo {
  flex: 1 1 auto;
  min-height: 0;
  padding: 16px 20px 24px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.modal__cuerpo > :last-child { margin-bottom: 0; }
.modal__pie {
  flex: none;
  margin: 0;
  padding: 16px 20px;
  padding-bottom: 16px;
  padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--borde);
  background: var(--superficie);
  box-shadow: var(--sombra-barra);
}
/* Una cita ya pasada no trae acciones: sin pie vacío. */
.modal__pie:empty { display: none; }
.modal__pie > .panel__nota { margin: 0; }
/* El asa dice «esto se puede bajar» en el móvil; en ancho no hay hoja. */
.modal__asa {
  flex: none;
  width: 40px;
  height: 4px;
  margin: 10px auto 0;
  border-radius: 999px;
  background: var(--borde-fuerte);
}
@media (min-width: 720px) {
  .modal__asa { display: none; }
  .modal:has(> .modal__cuerpo) > .modal__cabeza { padding: 18px 20px 14px 24px; }
  .modal__cuerpo { padding: 20px 24px 24px; }
  .modal__pie { padding: 16px 24px; }
}

/* ============================================================
   14. LA AGENDA (elegir, revisar y qué quedó)
   ============================================================ */
.agenda__que { color: var(--texto-suave); font: 700 0.875rem/1.3 var(--fuente); }
.agenda__guia { max-width: 60ch; margin-bottom: 16px; }
.agenda__cuerpo { display: grid; gap: 20px; }
/* Dos columnas solo desde 960 px: a 720 el mes quedaba con días de 37 px. */
@media (min-width: 960px) {
  .agenda__cuerpo { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: start; }
}
.calendario--agenda { max-width: none; }
/* En la hoja del móvil se aprieta el margen del cuerpo, no las casillas:
   con 20 px a cada lado el día medía 43 px a 360 de ancho. */
@media (max-width: 519px) {
  .modal--agenda .modal__cuerpo { padding-left: 16px; padding-right: 16px; }
}
.calendario--agenda .dia { min-height: 52px; }

.agenda__leyenda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  margin-top: 10px;
  color: var(--texto-suave);
  font: 500 0.875rem/1.4 var(--fuente);
}
.agenda__muestra {
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-left: 8px;
  border: 1px solid var(--borde-fuerte);
  border-radius: 5px;
  background: var(--superficie);
  vertical-align: -2px;
}
.agenda__muestra:first-child { margin-left: 0; }
.agenda__muestra--con { border-color: var(--primario); background: var(--primario-tinte); }

.agenda__diaTitulo { margin-bottom: 6px; font: 600 1.125rem/1.3 var(--fuente-titulo); color: var(--titulo); }
.agenda__donde { margin-bottom: 12px; color: var(--texto-suave); }

.franja { margin-top: 18px; }
.franja__titulo { margin-bottom: 8px; font: 700 1rem/1.3 var(--fuente); color: var(--titulo); }
.franja__horas {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Una hora es un botón de su tamaño, no una barra de lado a lado. */
.hora {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 92px;
  min-height: 48px;
  padding: 10px 16px;
  border: 1px solid var(--borde-fuerte);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--primario-fuerte);
  font: 700 1rem/1 var(--fuente);
  font-variant-numeric: tabular-nums;
}
.hora:hover { border-color: var(--primario); background: var(--primario-tinte); }
.hora__donde {
  color: var(--texto-suave);
  font: 500 0.875rem/1.2 var(--fuente);
  text-align: center;
  overflow-wrap: anywhere;
}

/* Revisar y qué quedó: una columna de lectura, no el ancho de la ventana. */
.agenda__revisar,
.agenda__hecho { max-width: 560px; }
.agenda__revisar .agenda__diaTitulo { margin-bottom: 14px; }
.agenda__nota { margin: 14px 0 18px; color: var(--texto-suave); }
.agenda__hecho .hecho__que:empty { display: none; }

/* Por qué no hay horarios: el motivo que escribieron las reglas del equipo. */
.porque {
  display: grid;
  gap: 6px;
  max-width: 68ch;
  margin: 0 0 18px;
  padding: 0 0 0 20px;
}
.porque__una { color: var(--texto); }

/* ============================================================
   15. LA FICHA, CANCELAR Y QUÉ QUEDÓ
   ============================================================ */
/* La cita como lista de datos: rótulo a un lado y valor al otro. */
.ficha {
  display: grid;
  grid-template-columns: minmax(118px, max-content) minmax(0, 1fr);
  gap: 10px 20px;
  margin: 0 0 20px;
}
.ficha__que { padding-top: 1px; color: var(--texto-suave); font: 600 0.875rem/1.55 var(--fuente); }
.ficha__valor { margin: 0; color: var(--titulo); font: 600 1rem/1.5 var(--fuente); overflow-wrap: anywhere; }
@media (max-width: 359px) {
  .ficha { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .ficha__valor { margin-bottom: 10px; }
}
/* Suelta en una página (cancelar, la atención), la ficha va en tarjeta. */
.hub > .ficha {
  padding: 16px;
  border: 1px solid var(--borde);
  border-radius: 16px;
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
}
@media (min-width: 720px) {
  .hub > .ficha { padding: 20px; }
}

.ficha__acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 20px;
}
.ficha__notas { margin: 0 0 20px; padding-top: 16px; border-top: 1px solid var(--borde); }
.ficha__notasQue { margin-bottom: 6px; color: var(--texto-suave); }
.ficha__notasUna { margin: 0 0 4px; }

/* Lo que pasó y lo que sigue. */
.hecho {
  max-width: 640px;
  margin: 0 0 8px;
  padding: 24px;
  border: 1px solid var(--borde);
  border-radius: 16px;
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
}
.modal .hecho { padding: 4px 0 0; border: 0; box-shadow: none; }
.hecho__que { font: 600 1.125rem/1.45 var(--fuente); color: var(--titulo); }
.hecho__sigue { margin-top: 8px; color: var(--texto); }
.resultado__icono {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin-bottom: 12px;
  border-radius: 50%;
  background: var(--exito-tinte);
  color: var(--exito);
}
.resultado__icono .ico { width: 28px; height: 28px; }
/* NEUTRO en «Listo» de Mis citas: la misma pantalla cuenta una asistencia
   confirmada y una cita cancelada, y cancelar no es un éxito en verde. */
.resultado__icono--neutro { background: var(--primario-tinte); color: var(--primario-fuerte); }
.hecho > .panel__title { margin-bottom: 8px; }
.hecho > .ficha__acciones { margin-top: 24px; }

/* ANCHO COMPLETO SOLO EN EL MÓVIL, y solo en las filas de acciones y en los
   formularios: por debajo de 520 px un botón estrecho se falla con el pulgar. */
@media (max-width: 519px) {
  .ficha__acciones,
  .cita__acciones { flex-direction: column; align-items: stretch; }
  .ficha__acciones > .btn,
  .panel .btn,
  .clave__cuerpo .btn { width: 100%; }
  .ficha__acciones > .enlace { justify-content: center; }
}

/* ============================================================
   16. AGENDAR: LOS CONTROLES QUE LE CORRESPONDEN
   ============================================================ */
/* UNA COLUMNA DE LECTURA (720 px), como en la maqueta: una tarjeta de
   1.200 px deja el botón a un palmo del nombre del control. */
.tocan,
#tocanVacio,
.atenciones,
#historiaVacio,
#paginaHistoria,
#historiaPie { max-width: 720px; }
.tocan__lista {
  display: grid;
  gap: 12px;
  margin: 0 0 20px;
  padding: 0;
  list-style: none;
}
@media (min-width: 720px) {
  .tocan__lista,
  .atenciones { gap: 16px; }
}

/* LA TARJETA DE UN CONTROL Y LA DE UNA ATENCIÓN SON LA MISMA FORMA: el dibujo
   a la izquierda, lo que es a su lado y, debajo de una raya, la acción. Es
   una rejilla y no un flex porque la raya (`::before`) tiene que ocupar el
   ancho entero entre el texto y el botón, sin un elemento más en el HTML.
   Los avisos de la descarga van debajo, también a todo el ancho. */
.control,
.atencion {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  column-gap: 14px;
  align-items: start;
  padding: 16px;
}
@media (min-width: 720px) {
  .control,
  .atencion { padding: 20px; }
}
.control::before,
.atencion::before {
  content: "";
  grid-column: 1 / -1;
  grid-row: 2;
  margin-top: 16px;
  border-top: 1px solid var(--borde);
}
.control__icono,
.atencion__icono {
  grid-column: 1;
  grid-row: 1;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
}
.control__icono { background: var(--primario-tinte); color: var(--primario-fuerte); }
.atencion__icono { background: var(--neutro-tinte); color: var(--texto); }
.control__icono .ico,
.atencion__icono .ico { width: 22px; height: 22px; }
.control__info,
.atencion__info { grid-column: 2; grid-row: 1; min-width: 0; }
/* La acción, debajo de la raya y del ancho de su texto: ancho completo solo
   en el móvil (regla de los botones). */
.control > .accion,
.atencion__acciones {
  grid-column: 1 / -1;
  grid-row: 3;
  justify-self: start;
  margin-top: 16px;
}
@media (max-width: 519px) {
  .control > .accion,
  .atencion__acciones { justify-self: stretch; }
  .atencion__acciones .accion { width: 100%; }
}

.control__que { font: 600 1.125rem/1.3 var(--fuente-titulo); color: var(--titulo); overflow-wrap: anywhere; }
.control__porque { margin-top: 6px; color: var(--texto-suave); }
/* LA FRANJA DICE EN QUÉ ESTÁ CADA CONTROL, y sale solo del marcado que ya
   pinta `traerFrecuencias`: el que se puede pedir lleva «Ver horarios»
   (`.accion--principal`) y va en el azul de la marca; el que ya tiene cita o
   está por confirmar lleva «Ir a Mis citas» y va en gris. Un navegador sin
   `:has()` los deja todos con la franja neutra, y el texto sigue diciéndolo. */
.control:has(> .accion--principal) { --franja: var(--primario); }
.control:has(> .accion:not(.accion--principal)) { --franja: var(--borde-campo); }
/* LA QUE LE CORRESPONDE AHORA (22/09/2026): franja ámbar y el motivo en
   píldora. La distinción no es solo el color: también el peso y el botón
   primario. Sin ella, un paciente agendó fisioterapia y psicología mientras
   su reumatología —la principal— seguía pendiente. Va DESPUÉS de las de
   arriba, y con `:has()` para ganarles en peso. */
.control--suya,
.control--suya:has(> .accion--principal) { --franja: var(--aviso); }

/* «Ver horarios» con el calendario delante e «Ir a Mis citas» con la flecha
   detrás («esto lleva a otro sitio»). Por máscara, como los demás botones de
   tarjeta, para que el icono y el texto vayan siempre juntos. */
.control > .accion::before,
.control > .accion::after,
.atencion__acciones .accion::before {
  flex: none;
  width: 18px;
  height: 18px;
  background: currentColor;
}
.control > .accion--principal::before {
  content: "";
  -webkit-mask: var(--m-calendario) center / contain no-repeat;
  mask: var(--m-calendario) center / contain no-repeat;
}
.control > .accion:not(.accion--principal)::after {
  content: "";
  -webkit-mask: var(--m-flecha) center / contain no-repeat;
  mask: var(--m-flecha) center / contain no-repeat;
}
.control__porque--suya {
  display: inline-flex;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--aviso-tinte);
  color: var(--aviso);
  font-weight: 600;
}

/* ============================================================
   17. MI HISTORIA Y LA ATENCIÓN
   ============================================================ */
.atenciones {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Una atención no tiene estado que contar: sin franja de color (borde de
   1 px), como en la maqueta. La forma de la tarjeta está con la del control,
   en la sección 16. */
.atencion { --franja: var(--borde); border-left-width: 1px; }
.atencion__cabeza { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; }
.atencion__fecha { font: 600 1.0625rem/1.3 var(--fuente-titulo); color: var(--titulo); }
.atencion__hora { color: var(--texto-suave); font-variant-numeric: tabular-nums; }
/* El nombre de la plantilla puede ser largo: se parte, no se recorta, porque
   este renglón es el único sitio donde se lee entero. */
.atencion__que { margin-top: 4px; font: 600 1rem/1.4 var(--fuente); color: var(--texto); overflow-wrap: anywhere; }
.atencion__medico {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin-top: 6px;
  color: var(--texto-suave);
}
.atencion__medico .ico { flex: none; width: 18px; height: 18px; margin-top: 3px; }
.atencion__medico > span { min-width: 0; }
/* «Descargar PDF» con su flecha hacia abajo delante. */
.atencion__acciones .accion::before {
  content: "";
  -webkit-mask: var(--m-descarga) center / contain no-repeat;
  mask: var(--m-descarga) center / contain no-repeat;
}
/* Lo que pasa con la descarga de ESA atención, debajo de ella: es donde está
   mirando quien acaba de pulsar. */
.atencion__aviso { color: var(--texto); }
.atencion > .atencion__aviso { grid-column: 1 / -1; margin-top: 12px; }
.atencion__aviso--error { color: var(--aviso); font-weight: 600; }
.ficha__notasUna .atencion__aviso { margin-top: 4px; }

.atencion__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 20px;
}
.atencion__dato {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--texto);
  font: 500 0.875rem/1.4 var(--fuente);
}
.atencion__dato strong { color: var(--titulo); }

/* EL DIAGNÓSTICO, APARTE Y CON PESO: es lo que el paciente busca primero. */
.dx {
  max-width: 80ch;
  margin: 0 0 20px;
  padding: 16px 20px;
  border: 1px solid #d5dafa;
  border-radius: 16px;
  background: var(--primario-tinte);
}
.dx__que { display: block; color: var(--primario-fuerte); font: 700 0.875rem/1.4 var(--fuente); }
.dx__valor { margin-top: 4px; color: var(--titulo); font: 700 1.0625rem/1.75 var(--fuente); max-width: 72ch; }
.dx__otros { margin-top: 6px; color: var(--texto); line-height: 1.75; max-width: 72ch; }

/* LA NOTA ES UN DOCUMENTO. Las del ERP vienen EN MAYÚSCULAS y no se
   cambian —es la historia clínica—: se compensa con interlineado de 1,75 y
   72 caracteres por línea como máximo. Los saltos de línea del profesional
   se conservan (`pre-wrap`). */
.nota {
  max-width: 80ch;
  margin: 0 0 20px;
  overflow: hidden;
  border: 1px solid var(--borde);
  border-radius: 16px;
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
}
.nota__cabeza {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 12px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--borde);
}
.nota__titulo { font: 600 1.125rem/1.3 var(--fuente-titulo); color: var(--titulo); }
.nota__firma { color: var(--texto-suave); font-weight: 600; }
.nota__cuerpo { padding: 16px 20px 24px; }
@media (min-width: 720px) {
  .nota__cuerpo { padding: 20px 28px 28px; }
}
.nota__seccion { margin: 20px 0 8px; font: 700 1rem/1.4 var(--fuente-titulo); color: var(--titulo); }
.nota__seccion:first-child { margin-top: 0; }
.nota__campo { margin-top: 12px; }
.nota__que { display: block; color: var(--texto-suave); font: 600 0.875rem/1.4 var(--fuente); }
.nota__texto {
  max-width: 72ch;
  margin-top: 2px;
  color: var(--titulo);
  line-height: 1.75;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.nota__obs {
  max-width: 72ch;
  margin-top: 4px;
  color: var(--texto);
  line-height: 1.75;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.nota__vacia { max-width: 68ch; padding: 16px 20px; color: var(--texto-suave); }

/* ============================================================
   18. MI PERFIL: CAMBIAR LA CLAVE
   Siempre a la vista (German, 21/09/2026: nada plegado).
   ============================================================ */
.clave {
  max-width: 760px;
  margin-top: 8px;
  padding: 20px;
  border: 1px solid var(--borde);
  border-radius: 16px;
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
}
@media (min-width: 720px) {
  .clave { padding: 24px 28px; }
}
.clave__titulo { margin-bottom: 16px; font: 600 1.25rem/1.3 var(--fuente-titulo); color: var(--titulo); }
.clave__cuerpo { max-width: 460px; }
.clave__cuerpo .hub__ayuda { margin-top: 16px; }

/* ============================================================
   19. INGRESO
   El formulario en tarjeta y, a su lado en ancho, el panel de marca.
   ============================================================ */
.ingreso {
  display: grid;
  gap: 24px;
  align-items: start;
  padding-top: 24px;
}
@media (min-width: 960px) {
  .ingreso {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 40px;
    align-items: stretch;
    padding-top: 32px;
  }
  .brand { order: -1; }
}

.panel {
  padding: 24px 20px;
  border: 1px solid var(--borde);
  border-radius: 24px;
  background: var(--superficie);
  box-shadow: var(--sombra-tarjeta);
}
@media (min-width: 720px) {
  .panel { padding: 36px 40px; }
}
.panel__subtitle { max-width: 52ch; margin-bottom: 20px; color: var(--texto); }
.panel form { margin-top: 4px; }
.panel .alert { margin-top: 4px; }
.panel__help {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-top: 28px;
  color: var(--texto-suave);
}
.panel__help .ico { margin-top: 2px; color: var(--info); }

/* El panel de marca. En el móvil, debajo del formulario y reducido a su
   titular: lo primero es poder entrar. */
.brand {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px;
  overflow: hidden;
  padding: 20px;
  border-radius: 24px;
  background: var(--cabecera);
  background: linear-gradient(158deg, #0b1030 0%, #2c3260 46%, #3a4170 78%, #454f96 100%);
  color: #fff;
}
.brand > :not(.brand__rings) { position: relative; }
.brand__rings {
  position: absolute;
  right: -160px;
  bottom: -160px;
  width: 520px;
  height: 520px;
  pointer-events: none;
}
.brand__rings circle { fill: none; stroke: rgba(255, 255, 255, 0.08); stroke-width: 1.5; }
.brand__logo { align-self: flex-start; width: auto; height: 30px; }
.brand__headline {
  font: 700 1.5rem/1.15 var(--fuente-titulo);
  letter-spacing: -0.03em;
  color: #fff;
}
.brand__headline em { font-style: normal; color: #b9c2ff; }
.brand__lede { max-width: 46ch; margin-top: 14px; color: #e3e5ee; }
.brand__stats { display: flex; flex-wrap: wrap; gap: 16px 32px; margin: 24px 0 0; }
.brand__stats dt { font: 700 1.5rem/1.1 var(--fuente-titulo); }
.brand__stats dd { margin: 4px 0 0; color: #e3e5ee; font: 600 0.875rem/1.3 var(--fuente); }
.brand__foot { color: #e3e5ee; font-weight: 600; }
@media (max-width: 959px) {
  .brand__logo,
  .brand__stats,
  .brand__foot { display: none; }
}
@media (min-width: 720px) {
  .brand { padding: 40px; }
}
@media (min-width: 960px) {
  .brand__headline { font-size: 2.5rem; }
}

/* ============================================================
   20. PREFERENCIAS DE ACCESIBILIDAD
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

@media (prefers-contrast: more) {
  .input { border-color: var(--titulo); }
  .panel__subtitle,
  .panel__help,
  .hub__lede { color: var(--titulo); }
}
