/* ===========================================================================
   SICEAC · Carátula de ingreso

   Autoría:
   Jesús Moreno Cruz y Corro;
   jesus.moreno@imssbienestar.gob.mx
   jesusmcyc@gmail.com
   WhatsApp: 56 1877 6840

   Hoja propia, y solo la carga esta pantalla. El resto de la aplicación sigue
   con `siceac.css` sin enterarse: el ingreso es la única vista que no hereda
   `base.html` y la única con este lenguaje visual, así que no tiene por qué
   cobrarle su peso a nadie más.

   DOS SISTEMAS, Y EL ORDEN IMPORTA
   --------------------------------
   CAPA 0 · Identidad institucional. Manda en tipografía y color de marca.
     Patria display, Noto Sans cuerpo, paleta de la leyenda oficial 2024-2030.
     Los logos no se recolorean nunca.

   CAPA 2 · Glassmorphism. Manda en materialidad y movimiento. Mesh
     atmosférico, vidrio con jerarquía, borde cónico rotatorio reservado al
     elemento ceremonial, curva cubic-bezier(.22,1,.36,1) sin rebote.

   El teal neón entra SOLO como luz —halos, borde cónico, anillo de foco—.
   Nunca como color de marca ni de texto: eso sería pisar la Capa 0.

   DOS ACENTOS CON PAPELES DISTINTOS
   ---------------------------------
   ORO  = identidad y certificación. El nombre del sistema, el sello.
   TEAL = interacción. Foco, botón, dot de operación, borde ceremonial.
   El oro no toca un control; el teal no toca la marca.

   NOTA SOBRE `url()` Y `collectstatic`
   ------------------------------------
   `CompressedManifestStaticFilesStorage` reescribe cada `url()` de este
   archivo al nombre con hash, y FALLA si el archivo referenciado no existe.
   Toda ruta de aquí tiene que resolver contra `static/`.
   =========================================================================== */

/* --- Fuentes institucionales, subconjuntadas a latín --------------------- */
@font-face { font-family: "Patria"; font-weight: 300; font-style: normal;
  src: url("../fonts/Patria-Light.1f6dd3bc13d1.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Patria"; font-weight: 400; font-style: normal;
  src: url("../fonts/Patria-Regular.37dd12c70d17.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Patria"; font-weight: 700; font-style: normal;
  src: url("../fonts/Patria-Bold.2f132a16368e.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Noto Sans"; font-weight: 400; font-style: normal;
  src: url("../fonts/NotoSans-Regular.e5b9307518b5.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Noto Sans"; font-weight: 500; font-style: normal;
  src: url("../fonts/NotoSans-Medium.e6f101b648e0.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Noto Sans"; font-weight: 600; font-style: normal;
  src: url("../fonts/NotoSans-SemiBold.f2c152fd1b15.woff2") format("woff2"); font-display: swap; }
@font-face { font-family: "Noto Sans"; font-weight: 700; font-style: normal;
  src: url("../fonts/NotoSans-Bold.c76cc012d2e2.woff2") format("woff2"); font-display: swap; }

:root {
  --font-display: "Patria", "Noto Sans", Georgia, serif;
  --font-cuerpo:  "Noto Sans", system-ui, -apple-system, sans-serif;

  --vid-base:   #050810;
  --vid-mesh-1: rgba(0, 229, 196, 0.11);
  --vid-mesh-2: rgba(0, 200, 255, 0.05);
  --vid-mesh-3: rgba(188, 149, 92, 0.07);

  --vid-glass-soft:   rgba(255, 255, 255, 0.035);
  --vid-glass-medium: rgba(255, 255, 255, 0.055);

  --vid-borde-sutil: rgba(255, 255, 255, 0.07);
  --vid-borde:       rgba(255, 255, 255, 0.13);

  --vid-tinta:   rgba(255, 255, 255, 0.96);
  --vid-tinta-2: rgba(255, 255, 255, 0.62);
  --vid-tinta-3: rgba(255, 255, 255, 0.40);

  --vid-oro-neon:    #f0cb85;
  --vid-guinda-neon: #ff4d78;
  --vid-neon:        #00e5c4;

  --vid-sombra: 0 28px 70px -30px rgba(0, 0, 0, 0.85);
  --curva: cubic-bezier(0.22, 1, 0.36, 1);
}

@property --neon-angulo  { syntax: '<angle>'; initial-value: 0deg; inherits: false; }
@property --brillo-angulo{ syntax: '<angle>'; initial-value: 0deg; inherits: false; }

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0; min-height: 100dvh; display: flex; flex-direction: column;
  background-color: var(--vid-base); color: var(--vid-tinta);
  font-family: var(--font-cuerpo); overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

:focus-visible { outline: 2px solid var(--vid-neon); outline-offset: 3px; border-radius: 3px; }

.salto-contenido {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--vid-neon); color: #04211d; padding: 11px 20px;
  font-weight: 700; text-decoration: none;
}
.salto-contenido:focus { left: 0; }

.caja { width: 100%; padding-inline: clamp(16px, 3vw, 32px); }

.icono {
  width: 17px; height: 17px; flex-shrink: 0; display: inline-block;
  vertical-align: -0.18em; fill: none; stroke: currentColor;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
}

/* --- Mesh atmosférico. Estático a propósito: un fondo que se mueve compite. */
.mesh {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    radial-gradient(46% 52% at 12% 14%, var(--vid-mesh-1) 0%, transparent 62%),
    radial-gradient(50% 58% at 88% 84%, var(--vid-mesh-2) 0%, transparent 66%),
    radial-gradient(42% 46% at 78% 12%, var(--vid-mesh-3) 0%, transparent 60%),
    radial-gradient(ellipse at 50% 50%, #0b1220 0%, #050810 62%, #010208 100%);
}

/* --- Filigrana guilloché ---------------------------------------------------
   El entramado de un título de crédito. UNA rueda cuyo color recorre de verde
   a oro a lo largo del propio grabado, y ese recorrido viaja al girar el
   ángulo. No es luz sobre color plano: el color mismo cambia.

   Se pinta con `mask` y no con `<img>` porque `currentColor` no cruza la
   frontera de un `<img>`: dentro, el SVG se resuelve contra su propio
   documento y sale negro.                                                   */
.filigrana {
  position: fixed; z-index: 0; pointer-events: none;
  inline-size: min(126vh, 1220px); aspect-ratio: 1;
  inset-block-start: 50%; inset-inline-start: 26%;
  translate: -50% -50%;
  opacity: 0.10;
  background-image: conic-gradient(from var(--brillo-angulo),
    #00e5c4  0deg, #00e5c4  62deg, #3fe3a8 118deg, #9adf8e 168deg,
    #d8d383 214deg, #f0cb85 262deg, #ffe9b8 300deg, #ffffff 318deg,
    #ffe9b8 336deg, #6fe0b6 354deg, #00e5c4 360deg);
  -webkit-mask-image: url("../guilloche/roseta-sello.db70af56c77f.svg");
          mask-image: url("../guilloche/roseta-sello.db70af56c77f.svg");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: contain;     mask-size: contain;
  animation: girar 150s linear infinite, brillar 30s linear infinite;
  transition: opacity 900ms var(--curva), filter 700ms var(--curva);
}

/* EL CENTINELA. Segunda rueda en guinda, casi apagada: la brasa que espera.
   Cuando el sistema cierra la puerta, se enciende y toma la pantalla. */
.filigrana--centinela {
  inline-size: min(64vh, 600px);
  inset-inline-start: 84%; inset-block-start: 24%;
  opacity: 0.028;
  background-image: conic-gradient(from var(--brillo-angulo),
    rgba(255, 77, 120, 0.35) 0deg, rgba(255, 77, 120, 0.35) 200deg,
    rgba(255, 77, 120, 1) 292deg, rgba(255, 214, 226, 1) 318deg,
    rgba(255, 77, 120, 1) 344deg, rgba(255, 77, 120, 0.35) 360deg);
  animation: girar 190s linear infinite reverse, brillar 22s linear infinite reverse;
}

@keyframes girar   { to { rotate: 360deg; } }
@keyframes brillar { to { --brillo-angulo: 360deg; } }

/* La clase la pone `movimiento.js` leyendo `document.activeElement`. Con CSS
   puro no se puede: `:focus` deja de coincidir cuando la ventana pierde el
   foco del sistema, y `:has()` con pseudoclases dinámicas adentro no invalida
   de forma fiable. Comprobado en el navegador. */
body.hay-foco .filigrana            { opacity: 0.115; }
body.hay-foco .filigrana--centinela { opacity: 0.045; }

/* --- Franja de convivencia — Capa 0, cumplimiento -------------------------
   Gobierno de México a la izquierda, horizontal, con Escudo. IMSS-BIENESTAR
   a la derecha.

   LA FRANJA SE QUEDA CLARA aunque el tema sea oscuro. No es una concesión
   estética: el bundle de identidad NO trae versión blanca del logotipo de
   Gobierno de México —sus cuatro variantes están marcadas `fondo: claro`— y
   recolorear un logosímbolo que contiene el Escudo Nacional está prohibido.
   Sin ese asset, la única forma de cumplir sobre fondo negro es darle a los
   logos el fondo claro que piden.

   Si la Coordinación de Calidad e Información Estratégica entrega la versión
   oficial en blanco, esta franja puede volverse oscura cambiando dos rutas. */
.franja {
  position: relative; z-index: 3;
  background: linear-gradient(180deg, #fbfaf7 0%, #f4f1ea 100%);
  border-block-end: 1px solid rgba(188, 149, 92, 0.55);
  box-shadow: 0 10px 40px -12px rgba(0, 0, 0, 0.85);
}
.franja__interior {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; min-height: 78px; padding-block: 12px;
}
.franja__gob { display: block; height: 40px; width: auto; }
.franja__imb { display: block; height: 40px; width: auto; }

/* --- Composición ---------------------------------------------------------- */
.escena {
  position: relative; z-index: 2; flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(380px, 470px);
  align-items: center; gap: clamp(30px, 6vw, 110px);
  width: 100%; max-width: 1560px; margin-inline: auto;
  padding: clamp(34px, 6vh, 90px) clamp(20px, 4vw, 72px);
}

.marca__eyebrow {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--vid-tinta-3); margin: 0 0 26px;
}
.dot {
  inline-size: 6px; block-size: 6px; border-radius: 999px;
  background: var(--vid-neon); box-shadow: 0 0 10px rgba(0, 229, 196, 0.85);
  animation: latir 2.6s var(--curva) infinite;
}
@keyframes latir {
  0%, 100% { opacity: 1;   box-shadow: 0 0 10px rgba(0,229,196,0.85); }
  50%      { opacity: 0.5; box-shadow: 0 0 3px  rgba(0,229,196,0.30); }
}

.marca__sigla {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(60px, 9.4vw, 138px); line-height: 0.82;
  letter-spacing: -0.048em; margin: 0; color: var(--vid-tinta);
}

/* La frase mide 53 caracteres y su único corte equilibrado es 26 / 26:
       Sistema de Comprobación de
       Enfermedades de Alto Costo
   Con 28ch cabe el renglón más largo y `text-wrap: balance` reparte. No se usa
   <br> porque en móvil debe poder pasar a tres renglones sola. */
.marca__glosa {
  font-family: var(--font-display); font-weight: 300;
  font-size: clamp(19px, 2.3vw, 31px); line-height: 1.26;
  color: var(--vid-oro-neon); margin: 26px 0 0;
  max-width: 28ch; text-wrap: balance;
  text-shadow: 0 0 28px rgba(240, 203, 133, 0.28),
               0 0 6px  rgba(240, 203, 133, 0.16);
}
.marca__fondo {
  margin: 28px 0 0; max-width: 46ch;
  font-size: 13.5px; line-height: 1.62; color: var(--vid-tinta-2);
}

.marca__cifras {
  display: flex; flex-wrap: wrap; margin-top: 30px;
  border-block-start: 1px solid var(--vid-borde-sutil); padding-block-start: 20px;
}
.marca__cifras > div { padding-inline: 24px; }
.marca__cifras > div:first-child { padding-inline-start: 0; }
.marca__cifras > div + div { border-inline-start: 1px solid var(--vid-borde-sutil); }
.cifra__rotulo {
  display: block; font-size: 9.5px; font-weight: 600; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--vid-tinta-3); margin-bottom: 6px;
}
.cifra__valor {
  font-family: var(--font-display); font-weight: 700; font-size: 27px;
  line-height: 1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
  color: var(--vid-tinta);
}
.cifra__valor small {
  font-family: var(--font-cuerpo); font-weight: 500; font-size: 11.5px;
  letter-spacing: 0; color: var(--vid-tinta-3); margin-left: 6px;
}

/* --- La tarjeta ceremonial -----------------------------------------------
   Único borde cónico rotatorio de toda la aplicación. Puesto en cada tarjeta,
   deja de significar nada.                                                 */
.portal { position: relative; padding: 2px; border-radius: 20px; isolation: isolate; }
.portal::before {
  content: ""; position: absolute; inset: 0; border-radius: 20px; padding: 1.5px;
  background: conic-gradient(from var(--neon-angulo),
    transparent 0deg, transparent 258deg, rgba(0, 143, 128, 0.85) 296deg,
    var(--vid-neon) 330deg, #ffffff 345deg, var(--vid-neon) 355deg,
    transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  animation: neon-girar 5.5s linear infinite; pointer-events: none;
}
.portal::after {
  content: ""; position: absolute; inset: -3px; border-radius: 22px; z-index: -1;
  background: conic-gradient(from var(--neon-angulo),
    transparent 258deg, rgba(0, 229, 196, 0.22) 330deg,
    rgba(255, 255, 255, 0.16) 345deg, transparent 360deg);
  filter: blur(11px); animation: neon-girar 5.5s linear infinite;
  pointer-events: none;
}
@keyframes neon-girar { to { --neon-angulo: 360deg; } }

.portal__vidrio {
  position: relative; border-radius: 18px; overflow: hidden;
  background: var(--vid-glass-medium); border: 1px solid var(--vid-borde);
  box-shadow: var(--vid-sombra);
  padding: clamp(28px, 2.6vw, 36px) clamp(28px, 3.2vw, 42px);
}
/* Las dos propiedades en `@supports` SEPARADOS. Los minificadores modernos
   colapsan la pareja y dejan solo la versión webkit, y el blur desaparece en
   los navegadores que piden la estándar. */
@supports (-webkit-backdrop-filter: blur(1px)) {
  .portal__vidrio { -webkit-backdrop-filter: blur(26px) saturate(160%); }
}
@supports (backdrop-filter: blur(1px)) {
  .portal__vidrio { backdrop-filter: blur(26px) saturate(160%); }
}

/* Sello en seco: la roseta grabada en la esquina, como en un certificado. */
.portal__vidrio::after {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  inline-size: 250px; aspect-ratio: 1;
  inset-block-end: -78px; inset-inline-end: -66px;
  background-color: var(--vid-oro-neon); opacity: 0.11;
  -webkit-mask-image: url("../guilloche/roseta-sello.db70af56c77f.svg");
          mask-image: url("../guilloche/roseta-sello.db70af56c77f.svg");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: contain;     mask-size: contain;
}
/* Filete de seguridad en el canto superior, como la banda de un documento. */
.portal__vidrio::before {
  content: ""; position: absolute; z-index: 1; pointer-events: none;
  inset-block-start: 0; inset-inline: 0; block-size: 1px;
  background: linear-gradient(90deg, transparent 0%,
    rgba(240, 203, 133, 0.55) 18%, rgba(0, 229, 196, 0.75) 50%,
    rgba(240, 203, 133, 0.55) 82%, transparent 100%);
}
.portal__vidrio > * { position: relative; z-index: 2; }

.portal__titulo {
  font-family: var(--font-display); font-weight: 700; font-size: 25px;
  letter-spacing: -0.015em; margin: 0 0 4px; color: var(--vid-tinta);
}
.portal__glosa { font-size: 12.5px; color: var(--vid-tinta-3); margin: 0 0 6px; }
.portal__regla {
  block-size: 1px; margin: 14px 0 24px;
  background: linear-gradient(90deg, rgba(255,255,255,0.16) 0%,
    rgba(255,255,255,0.03) 60%, transparent 100%);
}

/* --- Campos de vidrio ----------------------------------------------------- */
.campo { display: block; margin-bottom: 26px; }
.campo__rotulo {
  display: block; font-size: 9.5px; font-weight: 600; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--vid-tinta-3); margin-bottom: 11px;
  transition: color 260ms var(--curva);
}
/* `display: block` no es cosmético: la caja es un <span> dentro de un <label>,
   y un elemento inline NO toma el alto de su hijo. Sin esto colapsa a 22px y
   el campo se ve como una barra delgada por más que se le suba la altura. */
.campo__caja {
  display: block; position: relative; border-radius: 12px;
  background: var(--vid-glass-soft); border: 1px solid var(--vid-borde-sutil);
  transition: border-color 260ms var(--curva), background-color 260ms var(--curva),
              box-shadow 260ms var(--curva);
}
.campo__control {
  width: 100%; height: 58px; padding: 0 17px; background: transparent;
  border: 0; outline: none; border-radius: 12px; color: var(--vid-tinta);
  font-family: var(--font-cuerpo); font-size: 16px; letter-spacing: 0.02em;
}
.campo__control::placeholder { color: rgba(255, 255, 255, 0.22); }
.campo__caja:focus-within {
  background: var(--vid-glass-medium); border-color: rgba(0, 229, 196, 0.55);
  box-shadow: 0 0 0 3px rgba(0, 229, 196, 0.14), 0 0 26px -6px rgba(0, 229, 196, 0.42);
}
.campo:focus-within .campo__rotulo { color: var(--vid-neon); }

/* Autorrelleno del navegador: sin esto Chrome pinta un fondo azul opaco que
   destruye el vidrio. La sombra interior enorme lo tapa sin tocar el texto. */
.campo__control:-webkit-autofill,
.campo__control:-webkit-autofill:hover,
.campo__control:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--vid-tinta);
  -webkit-box-shadow: 0 0 0 1000px rgba(10, 22, 32, 0.96) inset;
  caret-color: var(--vid-tinta);
  transition: background-color 9999s ease-out;
}

/* --- Botón ---------------------------------------------------------------- */
.boton {
  position: relative; width: 100%; height: 58px; margin-top: 8px;
  border: 1px solid rgba(0, 229, 196, 0.45); border-radius: 12px;
  background: linear-gradient(180deg, rgba(0, 229, 196, 0.22), rgba(0, 143, 128, 0.16));
  color: var(--vid-tinta); cursor: pointer; overflow: hidden;
  font-family: var(--font-cuerpo); font-size: 12px; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  transition: border-color 260ms var(--curva), box-shadow 260ms var(--curva),
              transform 110ms var(--curva);
}
.boton:hover {
  border-color: rgba(0, 229, 196, 0.85);
  box-shadow: 0 0 32px -6px rgba(0, 229, 196, 0.55);
}
.boton:active { transform: scale(0.988); }
/* Barrido de luz: el vidrio reacciona a la mano. */
.boton::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%,
              rgba(255, 255, 255, 0.24) 50%, transparent 62%);
  translate: -110% 0; transition: translate 720ms var(--curva);
}
.boton:hover::after { translate: 110% 0; }

.portal__pie {
  margin-top: 28px; padding-top: 18px;
  border-top: 1px solid var(--vid-borde-sutil);
  font-size: 12px; color: var(--vid-tinta-3); line-height: 1.62;
}
.portal__pie strong { color: var(--vid-tinta-2); font-weight: 600; }

/* --- Avisos -----------------------------------------------------------------
   SIN FILETE DE COLOR EN EL CANTO IZQUIERDO. La barrita vertical a la
   izquierda de una caja de alerta es la marca de agua del diseño generado
   automáticamente: aparece en todos, no significa nada y aquí sobraba, porque
   el tono ya está dicho tres veces —en el anillo, en el icono y en la
   negrita—. Quitarla no le resta información al aviso; le quita un tic.

   Lo que queda son tres capas de luz, todas del mismo `--tono`: un anillo
   exterior de 1 px, un halo hacia afuera y un halo hacia ADENTRO, que hace
   que el aviso parezca iluminado desde su propio borde en vez de tener un
   fondo de color. La variante de espera solo cambia la variable.

   El relleno también se emparejó: era un degradado de izquierda a derecha
   que existía para sentar el filete, y sin él quedaba como una mancha
   pegada a un costado.                                                     */
.aviso {
  --tono: var(--vid-guinda-neon);
  display: flex; gap: 12px; align-items: flex-start;
  padding: 15px 17px; margin-bottom: 24px; border-radius: 12px;
  font-size: 13px; line-height: 1.55; color: var(--vid-tinta);
  background: color-mix(in srgb, var(--tono) 9%, transparent);
  border: 1px solid color-mix(in srgb, var(--tono) 40%, transparent);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--tono) 22%, transparent),
    0 0 34px -8px color-mix(in srgb, var(--tono) 75%, transparent),
    inset 0 0 26px -14px color-mix(in srgb, var(--tono) 90%, transparent);
}
.aviso .icono {
  color: var(--tono); margin-top: 1px;
  filter: drop-shadow(0 0 7px color-mix(in srgb, var(--tono) 70%, transparent));
}
.aviso strong {
  font-weight: 700; color: var(--tono);
  text-shadow: 0 0 16px color-mix(in srgb, var(--tono) 55%, transparent);
}
.aviso--espera { --tono: var(--vid-oro-neon); }
.aviso p { margin: 0 0 5px; }
.aviso p:last-child { margin-bottom: 0; }

/* --- El centinela encendido -------------------------------------------------
   Cuando el sistema cierra la puerta, la pantalla ENTERA lo acusa: la rueda
   guinda toma el lado derecho, la verde-oro se apaga y se dessatura, y el
   borde cónico de la tarjeta pasa de teal a guinda. Un solo estado, tres
   elementos que ya existían.                                               */
body.centinela .filigrana            { opacity: 0.035; filter: saturate(0.25); }
body.centinela .filigrana--centinela { opacity: 0.16; filter: none; }
body.centinela .portal::before {
  background: conic-gradient(from var(--neon-angulo),
    transparent 0deg, transparent 258deg, rgba(155, 34, 71, 0.9) 296deg,
    var(--vid-guinda-neon) 330deg, #ffffff 345deg,
    var(--vid-guinda-neon) 355deg, transparent 360deg);
}
body.centinela .portal::after {
  background: conic-gradient(from var(--neon-angulo),
    transparent 258deg, rgba(255, 77, 120, 0.30) 330deg,
    rgba(255, 255, 255, 0.18) 345deg, transparent 360deg);
}
body.centinela .portal__vidrio {
  border-color: color-mix(in srgb, var(--vid-guinda-neon) 30%, transparent);
}
.portal::before, .portal::after, .portal__vidrio {
  transition: background 700ms var(--curva), border-color 700ms var(--curva);
}

/* --- Errores por campo ----------------------------------------------------
   `AuthenticationForm` devuelve el error a nivel de formulario, no de campo,
   pero `PasswordChangeForm` y compañía sí los devuelven por campo: la clase
   existe para cuando esta hoja se reutilice.                               */
.campo__error {
  display: block; margin-top: 8px; font-size: 12px; font-weight: 500;
  color: var(--vid-guinda-neon);
}
.campo--erroneo .campo__caja { border-color: color-mix(in srgb, var(--vid-guinda-neon) 55%, transparent); }

.visualmente-oculto {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* --- Responsive ----------------------------------------------------------- */
@media (max-width: 1000px) {
  .escena { grid-template-columns: 1fr; gap: 40px; padding-block: 44px; }
  .marca__glosa { font-size: clamp(19px, 5.2vw, 26px); max-width: 30ch; }
  .filigrana { inset-inline-start: 50%; opacity: 0.04; }
  .filigrana--centinela { display: none; }
}
@media (max-width: 560px) {
  .franja__gob, .franja__imb { height: 30px; }
  .franja__interior { min-height: 62px; }
  .marca__cifras > div { padding-inline: 16px; }
}

/* --- Menos movimiento ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .filigrana, .dot, .portal::before, .portal::after { animation: none !important; }
  .boton::after { display: none; }
  /* El borde cónico se detiene en su punto MÁS LUMINOSO en vez de
     desaparecer: la tarjeta sigue siendo la ceremonial, solo que quieta. */
  .portal::before, .portal::after { --neon-angulo: 336deg; }
  .filigrana { --brillo-angulo: 318deg; }
  .filigrana--centinela { --brillo-angulo: 318deg; }
}
