/* Revva — flujo de análisis. Complementa styles.css (tokens/typo/botones/nav/scanwin). */

body.an{background:var(--bone)}
/* sin JS el flujo entero no arranca (la medición corre en el navegador) */
.nojs{padding:14px 22px;background:var(--ink);color:var(--bone);font-size:.9rem;text-align:center}
body.an main{max-width:720px;padding-top:112px;padding-bottom:90px;min-height:100svh}
body.an section.step{padding:14px 0 40px;content-visibility:visible;contain-intrinsic-size:none}
body.an h1{font-size:clamp(2.7rem,10.5vw,4.6rem)}
body.an h2{margin-top:.2em}
.navtag{font-size:.6rem;color:var(--cap);padding-right:10px}

/* pasos */
.steps{display:flex;gap:18px;list-style:none;margin:26px 0 34px;font-size:.62rem;
  letter-spacing:.16em;text-transform:uppercase;color:var(--cap)}
.steps li{display:flex;align-items:center;gap:7px;padding-bottom:6px;border-bottom:1px solid transparent}
.steps .sn{color:var(--brass-text)}
.steps li.on{color:var(--ink);border-color:var(--brass)}
.steps li.done{color:var(--cap)}

.step h1,.step h2{margin-bottom:.35em}
.step .lead{margin-bottom:26px}

/* privacidad */
.privacy{border:1px solid rgba(82,100,106,.4);border-radius:14px;padding:16px 18px;margin:22px 0;
  background:linear-gradient(180deg,rgba(130,153,165,.10),rgba(130,153,165,0))}
.privacy .ptag{display:block;font-size:.58rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--brass-text);margin-bottom:6px}
.privacy p{font-size:.95rem;color:var(--body-2);line-height:1.55}

/* ---- GUÍA DE ENCUADRE (js/guia-encuadre.js) ----
   Sustituye a `.guidegrid` y a las cuatro fotos beige de assets/guia/. Vive dentro del panel
   de tinta, que es donde el latón sí funciona: #CDB06A sobre #172024 mide 7,9:1 (sobre hueso
   se quedaría en 1,9:1 — la regla de `--dot`). */
.ge{display:flex;flex-direction:column;gap:18px;width:100%}
/* Esqueleto de reserva (ver el comentario en scan.html/analisis.html). Hereda TODO el
   dimensionado de `.ge`, así que el hueco es exacto por construcción y no por un número:
   en móvil `.ge` es fila y la altura la manda el SVG por su relación de aspecto — medido en
   360/390/430/600/879 px, el esqueleto cae dentro de 0,3 px de la guía real.
   En escritorio `.ge` apila SVG y texto, y ahí el SVG solo no basta: el bloque de texto medía
   109 px a 880 y 87 px a 1440 (medido). Se reservan 110 px, el mayor de los dos: pasarse no
   produce desplazamiento —la caja ya es lo bastante alta y el contenido real solo la rellena—
   mientras que quedarse corto sí. Los 23 px de sobra a 1440 caen en una columna que mide
   876 px, así que no le quitan sitio a nada.
   2026-08-10: al retirarse la regla numérica el bloque de texto encogió, así que estos 110 px
   son ahora un techo aún más holgado — que es el lado seguro. El CLS de /scan sigue medido en
   **0,0000 en las 8 corridas** de `_qa_cls_scan.py` después del cambio. */
@media(min-width:880px){ .ge-esqueleto .ge-info{min-height:110px} }
/* `#guia` es un flex item de `.intro-vis`, así que por defecto se encoge a su contenido. Con
   la guía montada el texto lo estiraba al ancho completo; el esqueleto, que no lleva texto,
   se quedaba en 176 px y reservaba 88 px de alto en vez de 150 — o sea, reservaba mal y en
   silencio. Con `flex:1` el ancho ya no depende de lo que haya dentro, que es la condición
   para que el hueco valga antes y después de montar. */
.intro-vis>#guia{flex:1 1 auto;min-width:0}
.ge-vis{width:100%;max-width:275px;margin:0 auto}
.ge-svg{width:100%;height:auto;display:block;overflow:visible}
/* TODO trazo va con `non-scaling-stroke`: el ancho se declara en px de PANTALLA, no en
   unidades del viewBox. Sin esto, el componente se pinta a ~275 px de ancho sobre un lienzo
   de 1000, así que un trazo de 2 u salía a 0,55 px y el antialias se comía el latón — el
   instrumento se veía gris. Es el mismo criterio que la malla del hero. */
.ge-svg path,.ge-svg rect{vector-effect:non-scaling-stroke}
.ge-borde{stroke:rgba(243,239,231,.16);stroke-width:1;fill:rgba(243,239,231,.03)}
.ge-esq{stroke:var(--brass);stroke-width:1.6;fill:none}
.ge-oval{stroke:var(--halo);stroke-width:1.7;fill:none;stroke-linejoin:round}
.ge-rasgo{stroke:rgba(243,239,231,.5);stroke-width:1.2;fill:none;stroke-linejoin:round}
.ge-iris{stroke:none;fill:rgba(243,239,231,.42)}
.ge-cara{transform-box:view-box;transform-origin:0 0;
  transition:transform .5s cubic-bezier(.2,.7,.2,1),opacity .35s ease}
.ge-marcas{transition:opacity .3s ease}
.ge-eje-ref{stroke:rgba(243,239,231,.34);stroke-width:1;stroke-dasharray:4 6;fill:none}
.ge-eje{stroke:var(--brass);stroke-width:1.3;fill:none}
.ge-tick,.ge-corchete{stroke:var(--brass);stroke-width:1.5;fill:none}
/* poca luz: el dibujo se apaga, que es exactamente lo que le pasa a la foto */
.ge[data-estado="oscura"] .ge-cara{opacity:.3}

.ge-info{display:flex;flex-direction:column;gap:14px}
.ge-msg{font-size:.92rem;line-height:1.5;color:var(--bone-dim);min-height:3.1em}
.ge-msg .ge-t{display:block;font-weight:600;color:var(--bone);margin-bottom:2px}
.ge-mal .ge-msg .ge-t{color:var(--err)}

/* (La regla numérica —banda de GATE + marcador con el valor medido— se retiró el 2026-08-10;
   ver el comentario en js/guia-encuadre.js. Sus reglas de CSS se van con ella.) */

/* ---- zona de subida (plan 004): la zona ES la pantalla ----
   Un <label> del input de archivo: TODA la superficie abre el selector y recibe el
   arrastre, con el botón dentro como afordancia. Sin decisión previa — elegir foto
   arranca la medición y el consentimiento viaja en la acción (línea legal debajo). */
.upzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:16px;
  min-height:clamp(190px,30vh,320px);margin:18px 0 0;padding:26px 22px;cursor:pointer;
  border:1.5px dashed rgba(82,100,106,.55);border-radius:16px;
  text-align:center;transition:border-color .2s ease,background-color .2s ease,
    transform var(--press-dur) ease-out;background:var(--paper)}
.upzone.drag{border-color:var(--brass);background:#F7F4EC}
.upzone .btn{margin:0;width:auto;display:inline-flex}
.upzone .mono{margin:0;font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;color:var(--cap)}
/* la zona entera es el control: pulsación de superficie grande (--press-lg, no se inventa
   otro token) y el botón interior no dobla la señal */
.upzone:active{transform:scale(var(--press-lg))}
.upzone:active .btn{transform:none}
@media(hover:hover){
  .upzone:hover{border-color:rgba(82,100,106,.85)}
  body.an.intro-active .upzone:hover{border-color:rgba(243,239,231,.55)}
}
/* el input .vh queda clipado a 1px: el anillo de foco lo enseña la zona entera */
.upzone:has(.vh:focus-visible){outline:2px solid var(--focus);outline-offset:2px}

/* línea legal (plan 004): sustituye a la casilla de edad — el consentimiento va en la
   acción de subir. Vive sobre el panel de tinta: --bone-dim mide 12,4:1 y el enlace en
   hueso pleno 14,4:1 (la variante clara de abajo es por si algún día sale del panel). */
.legalline{margin:14px 0 0;font-size:var(--t-fine);line-height:1.55;color:var(--cap)}
.legalline a{text-decoration:underline;text-underline-offset:2px;color:var(--brass-text)}

/* sexo — desde el plan 004 no hay chips en la entrada: la pregunta pasa a la espera de la
   medición (plan 005), que reutiliza estas piezas. Se conservan a propósito. */
.sexo{border:0;margin:26px 0 6px}
.sexo legend{font-size:.62rem;letter-spacing:.18em;text-transform:uppercase;color:var(--cap);margin-bottom:12px}
.sexchips{display:flex;gap:10px}
.chipbtn{font-family:var(--sans);font-size:.92rem;padding:.7em 1.5em;border-radius:999px;
  border:1px solid var(--line);background:transparent;color:var(--ink);cursor:pointer;
  transition:background-color .2s ease,border-color .2s ease,color .2s ease,
    transform var(--press-dur) ease-out}
.chipbtn[aria-pressed="true"]{background:var(--ink);color:var(--bone);border-color:var(--ink)}

body.an .check{color:var(--body-2);margin:18px 0}
body.an .check a{color:var(--brass-text)}
body.an .cta{margin-top:10px}
.btn[aria-disabled="true"]{opacity:.42;pointer-events:none}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.trustline{margin-top:16px;font-size:.6rem;letter-spacing:.14em;text-transform:uppercase;color:var(--cap)}

/* error del gate */
.gate-error{margin-top:26px;border:1px solid #b4542e;border-radius:14px;padding:16px 18px;background:#faf1ea}
.gate-error .getag{font-size:.58rem;letter-spacing:.2em;text-transform:uppercase;color:#9a4525;margin-bottom:6px}
.gate-error p{color:var(--body-2);font-size:.95rem}
.gate-error .gehint{margin-top:6px;color:var(--cap);font-size:.85rem}

/* aviso de pose en el RESULTADO (plan 004). No es el gate rojo: aquí la medición existe y
   es válida — la pose se corrigió antes de medir y lo que no aguantaba ya se calló solo.
   Por eso va en latón (señal), no en terracota (error), y no lleva el borde de alarma.
   El latón NUNCA como texto sobre claro: aquí manda --brass-text (#77622E, AA sobre hueso),
   que es la regla 3 de brand/revva/CLAUDE.md. */
.aviso{margin:0 0 26px;border:1px solid var(--line);border-left:3px solid var(--brass-text);
  border-radius:12px;padding:14px 16px;background:var(--paper)}
.aviso .avisoT{font-size:.58rem;letter-spacing:.2em;text-transform:uppercase;
  color:var(--brass-text);margin-bottom:6px}
.aviso p+p{color:var(--body-2);font-size:.92rem}
.aviso .linkbtn{margin-top:8px;font-size:.85rem}

/* reanudar */
.resume{margin-top:30px;border:1px solid var(--line);border-radius:14px;padding:18px;background:var(--paper)}
.resume>.mono{font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;color:var(--cap);margin-bottom:12px}
.resume .cta{display:flex;gap:10px;flex-wrap:wrap}

/* ============ PANTALLA DE ENTRADA sobre el campo (2026-08-05) ============
   Misma pieza que la puerta de email —panel de TINTA OPACO sobre el campo mineral—, que es
   el material ya validado: el contraste se mide contra el panel, no contra el fondo, así que
   no depende de por dónde caiga el degradado. Retícula en tres áreas para que el orden de
   lectura en móvil sea instrucción → acción y no al revés. */
body.an.intro-active main{max-width:1080px;padding:104px 24px 56px;position:relative;z-index:1;
  min-height:100svh}
.scanpage.intro-active main{padding-top:34px}
/* Nada de texto DESNUDO sobre el campo. Lo midió el QA y son los tres sitios donde caí:
   los pasos (latón #CDB06A a 2,9:1 — exactamente la regla que ya estaba escrita desde el
   01-08), el pie (hueso atenuado a 2,1:1 abajo, donde el campo aclara) y la etiqueta de la
   nav sobre el vidrio (3,5:1). Los tres pasan a superficie opaca, que es lo que ya hacen los
   chips de la landing sobre el retrato: sobre tinta el hueso mide 14,4:1 y no depende de por
   dónde caiga el degradado. */
body.an.intro-active .steps{color:var(--bone-dim);background:var(--ink);border-radius:999px;
  padding:.7em 1.15em;gap:16px;align-self:flex-start;width:max-content;max-width:100%;
  border:1px solid rgba(243,239,231,.14)}
body.an.intro-active .steps li{padding-bottom:0;border-bottom:0}
body.an.intro-active .steps .sn{color:var(--halo)}
body.an.intro-active .steps li.on{color:var(--bone)}
body.an.intro-active .steps li.on .sn{color:var(--brass)}
body.an.intro-active .steps li.done{color:var(--bone-dim)}
/* la pastilla de la nav deja de ser vidrio aquí: sobre el campo su composición cambiaba con
   el degradado y la etiqueta se quedaba en 3,5:1 */
body.an.intro-active nav .pill{background:var(--bone)}  /* opaca como la del resto del flujo */
body.an.intro-active .navtag{color:var(--body-2)}
body.an.intro-active .scbrand .wordmark{color:var(--bone);--dot:var(--brass)}
body.an.intro-active>footer{border-top:0;position:relative;z-index:1;background:var(--ink)}
body.an.intro-active>footer .fl,body.an.intro-active>footer .fl a{color:var(--bone-dim)}
/* el wordmark del pie es tinta por defecto (styles.css:122): sobre el campo se pierde, y su
   punto de latón tiene que volver al latón claro — sobre oscuro, `--brass-text` no vale */
body.an.intro-active>footer .wordmark{color:var(--bone);--dot:var(--brass)}

.intro-card{display:grid;border:1px solid rgba(243,239,231,.16);border-radius:22px;
  overflow:hidden;background:var(--ink);box-shadow:0 30px 80px rgba(23,32,36,.28)}
.intro-head{padding:clamp(26px,4vw,44px) clamp(22px,4vw,44px) 0}
.intro-vis{padding:clamp(24px,4vw,38px) clamp(22px,4vw,44px);display:flex;align-items:center}
.intro-act{padding:6px clamp(22px,4vw,44px) clamp(26px,4vw,40px)}
@media(min-width:880px){
  .intro-card{grid-template-columns:1.04fr .96fr;grid-template-rows:auto 1fr;
    grid-template-areas:"head vis" "act vis"}
  .intro-head{grid-area:head}.intro-vis{grid-area:vis}.intro-act{grid-area:act}
  .intro-vis{border-left:1px solid rgba(243,239,231,.14);justify-content:center}
  .ge-vis{max-width:252px}
  /* la zona de subida debe ser el ELEMENTO MAYOR también aquí (plan 004): más área que el
     bloque entero de la guía en la vista estándar de 1000px de alto (medido: la guía ocupa
     ~166k px²; a 40vh la zona da ~179k) */
  .upzone{min-height:clamp(260px,40vh,420px)}
}
/* ---- todo en un viewport (plan 004, criterio de Jorge): a 390×844 la entrada enseña
   h1 + guía + zona de subida + línea legal SIN scroll, medido con captura. En estrecho la
   guía pasa a fila (dibujo + lectura al lado) y los aires se comprimen; el orden sigue
   siendo instrucción → acción (la retícula de .intro-card no cambia). */
@media(max-width:879px){
  body.an.intro-active main{padding-top:88px;padding-bottom:28px}
  body.an.scanpage.intro-active main{padding-top:26px}
  body.an.intro-active .steps{margin:12px 0 16px}
  .intro-head{padding:20px 20px 0}
  .intro-vis{padding:16px 20px}
  .intro-act{padding:2px 20px 22px}
  .ge{flex-direction:row;align-items:center;gap:16px}
  .ge-vis{flex:0 0 40%;max-width:160px;margin:0}
  .ge-info{flex:1 1 auto;min-width:0;gap:10px}
  .ge-msg{min-height:0;font-size:.85rem}
  .upzone{min-height:clamp(210px,26svh,280px)}
  .trustline{margin-top:12px}
}

/* tipografía y controles del panel: todo sobre tinta (14,4:1 el hueso, 12,3:1 --bone-dim) */
body.an.intro-active h1{color:var(--bone);font-size:clamp(2.2rem,5vw,3.4rem);line-height:1}
body.an.intro-active h1 .muted{color:var(--bone-dim)}
body.an.intro-active .eyebrow{color:var(--halo);margin-bottom:14px}
body.an.intro-active .lead{color:var(--bone-dim);margin-bottom:0}
body.an.intro-active .upzone{border-color:rgba(243,239,231,.3);background:rgba(243,239,231,.04)}
body.an.intro-active .upzone.drag{border-color:var(--brass);background:rgba(205,176,106,.12)}
body.an.intro-active .upzone .mono{color:var(--halo)}
body.an.intro-active .btn-solid{background:var(--bone);color:var(--ink);border-color:var(--bone)}
body.an.intro-active .btn-solid:hover{background:#fff}
body.an.intro-active .btn-ghost{color:var(--bone);border-color:rgba(243,239,231,.34)}
body.an.intro-active .btn-ghost:hover{border-color:var(--bone)}
body.an.intro-active .resume{border-color:rgba(243,239,231,.16);
  background:rgba(243,239,231,.04)}
body.an.intro-active .resume>.mono{color:var(--halo)}
body.an.intro-active .legalline{color:var(--bone-dim)}
body.an.intro-active .legalline a{color:var(--bone)}
body.an.intro-active .linkbtn{color:var(--halo)}
body.an.intro-active .linkbtn:hover{color:var(--bone)}
body.an.intro-active .trustline{color:var(--halo)}
/* el gate rojo era una tarjeta clara: sobre tinta se queda en su propio material */
body.an.intro-active .gate-error{background:rgba(154,69,37,.14);border-color:#b4542e}
body.an.intro-active .gate-error .getag{color:var(--err)}
body.an.intro-active .gate-error p{color:var(--bone)}
body.an.intro-active .gate-error .gehint{color:var(--bone-dim)}
body.an.intro-active .scpillars{border-top-color:rgba(243,239,231,.14)}
body.an.intro-active .scpillars .pi b{color:var(--bone)}
body.an.intro-active .scpillars .pi span{color:var(--bone-dim)}
@media(min-width:600px){
  body.an.intro-active .scpillars .pi{border-left-color:rgba(243,239,231,.14)}
}

/* ---- medición (plan 005): foto + malla + la pregunta, en UN viewport ----
   La ventana se ajusta a la foto con tope de altura (46svh): una foto 9:16 a 360 px de
   ancho mediría 640 px y echaría la pregunta fuera de un móvil de 844. El canvas y la capa
   de rótulos comparten caja con la imagen, que conserva su proporción SIEMPRE (la escala
   del overlay es uniforme: cv.width / photo.width). */
#s-medir h2{font-size:clamp(1.9rem,7vw,3rem)}
#s-medir .scanwin{margin:22px auto 14px;width:fit-content;max-width:min(78vw,360px)}
#s-medir .scanwin img{width:auto;max-width:min(78vw,360px);max-height:46svh;display:block}
/* rótulos de medición sobre la foto: SIEMPRE chip de tinta (regla 4 de brand/revva/CLAUDE.md
   — un rótulo desnudo midió 1,0:1 sobre el pelo del sujeto del hero). Sobre tinta el hueso
   mide 14,4:1 y el latón 7,9:1, caiga donde caiga el chip. Solo opacity/transform. */
#mlabels{position:absolute;inset:0;pointer-events:none}
.mchip{position:absolute;white-space:nowrap;background:var(--ink);color:var(--bone);
  border:1px solid rgba(243,239,231,.18);font-family:var(--mono);font-size:.56rem;
  letter-spacing:.12em;text-transform:uppercase;padding:.4em .7em;border-radius:999px;
  opacity:0;transform:translateY(5px);transition:opacity .4s ease,transform .4s ease}
.mchip b{font-weight:500;color:var(--brass)}
.mchip.in{opacity:1;transform:none}
body.motion-static .mchip{transition:none}
/* una sola línea de estado (aria-live): lo visual es la malla, no una lista de frases */
.scanline{max-width:360px;margin:0 auto;font-size:.62rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--cap);min-height:1.6em}
/* la única pregunta del flujo, dentro de la espera: dos opciones grandes */
#s-medir .sexo{margin:14px auto 0;max-width:360px;text-align:center}
#s-medir .sexo legend{margin:0 auto 10px}
#s-medir .sexchips{justify-content:center}
#s-medir .chipbtn{font-size:1rem;padding:.8em 2em}
#s-medir .chipbtn:active{transform:scale(var(--press))}
/* elegido y calculado: la elección queda fijada — cambiarla exigiría re-medir */
#s-medir .sexo.resuelto .chipbtn{pointer-events:none}
#s-medir .sexo.resuelto .chipbtn[aria-pressed="false"]{opacity:.4}

/* email — puerta de desbloqueo, con campo mineral vivo y movimiento casi imperceptible */
/* ---- pantallas de MOMENTO: campo mineral (2026-08-05) ----
   La entrada (`intro-active`) y la puerta de email (`email-active`) comparten material con
   el hero. Antes la entrada caía a hueso plano —el primer clic desde la home cambiaba de
   piel— y la puerta usaba OTRO mineral: `--min-m` liso con dos halos de 70 px de desenfoque
   animados en bucle. Ahora las dos usan `--campo`, el degradado ya medido del hero.
   Los halos se retiran con dos motivos: el fondo bajo un panel translúcido dejaba de ser
   determinista (fue lo que obligó a quitarle el vidrio a la tarjeta de email el 04-08) y
   eran la capa más cara de pintar en un móvil.
   El campo va en pseudoelementos FIJOS, no en el `background` del body: si la página crece
   más que el viewport, un degradado sobre la caja del body se estira y el velo de tinta del
   20 % superior deja de caer donde se midió. */
body.an.intro-active,body.an.email-active{overflow-x:hidden;background:var(--min-d);
  color:var(--bone);isolation:isolate}
body.an.intro-active::before,body.an.email-active::before{content:"";position:fixed;inset:0;
  z-index:0;pointer-events:none;background:var(--campo-v)}
body.an.intro-active::after,body.an.email-active::after{content:"";position:fixed;inset:0;
  z-index:0;pointer-events:none;opacity:.1;mix-blend-mode:overlay;background-size:170px 170px;
  background-image:var(--campo-grano)}
@media(min-width:1240px){
  body.an.intro-active::before,body.an.email-active::before{background:var(--campo)}
}
body.an.email-active main{max-width:1040px;display:grid;align-items:center;padding:90px 24px;position:relative;z-index:1}
body.an.email-active .steps,body.an.email-active>nav,body.an.email-active>header,body.an.email-active>footer,
body.an.email-active>.scbrand{display:none}
#s-email.email-stage{width:100%;padding:0}
/* Panel de TINTA OPACO, sin vidrio. Tres razones y ninguna estética:
   (1) el `backdrop-filter:blur(18px)` sobre un fondo que se mueve hacía que el contraste no
       fuera determinista — la línea "Sin spam · Puedes borrar tus datos" medía 3,59:1 en
       móvil y 4,13:1 en desktop, variando según dónde estuviera el blob;
   (2) un backdrop-filter encima de dos capas de 70 px de desenfoque animadas en bucle es de
       lo más caro que se puede poner en un móvil, y el coste de render en gama baja sigue
       sin medirse;
   (3) es el mismo material que .paywall, que ya es tinta opaca: las dos superficies donde
       se paga dejan de hablar distinto. */
.email-card{display:grid;min-height:480px;border:1px solid rgba(243,239,231,.16);border-radius:22px;overflow:hidden;
  background:var(--ink);box-shadow:0 30px 80px rgba(23,32,36,.28)}
.email-intro,.email-panel{padding:clamp(28px,5vw,52px)}
.email-intro{display:flex;flex-direction:column;justify-content:space-between;border-right:1px solid rgba(243,239,231,.14)}
.email-intro .wordmark{color:var(--bone);align-self:flex-start}
.email-intro .eyebrow,.email-social{color:var(--halo)}
.email-intro h2{color:var(--bone);font-size:clamp(2.5rem,6vw,4.2rem);line-height:.94}
.email-intro .muted{color:rgba(243,239,231,.62)}
.email-intro .lead{color:rgba(243,239,231,.76);max-width:31rem;margin:0}
#s-email form.email-panel{max-width:none;margin:0;display:flex;flex-direction:column;justify-content:center}
.email-social{font-size:.58rem;letter-spacing:.14em;text-transform:uppercase;margin-bottom:38px}
.email-fields{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.35fr);gap:12px}
#s-email .field label{display:block;color:rgba(243,239,231,.7);font-size:.62rem;letter-spacing:.12em;
  text-transform:uppercase;margin:0 0 8px}
#s-email .field label span{opacity:.7}
#s-email input[type=email],#s-email input[type=text]{width:100%;background:rgba(243,239,231,.08);
  border:1px solid rgba(243,239,231,.22);color:var(--bone);font-family:var(--sans);font-size:1rem;
  padding:1em 1.1em;border-radius:10px}
#s-email input[type=email]:focus,#s-email input[type=text]:focus{outline:2px solid var(--brass);outline-offset:2px;border-color:transparent}
body.an.email-active #s-email .check{color:rgba(243,239,231,.76);font-size:.84rem;margin:18px 0 0}
body.an.email-active #s-email .check+.check{margin-top:10px}
body.an.email-active #s-email .check a{color:var(--bone)}
.hp{position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden}
/* error POR CAMPO y pegado a su campo: antes un único #emailErr servía para el email y
   para la casilla de consentimiento, y aparecía encima del botón, lejos del que fallaba.
   El color sale del token: #9A4525 sobre la tarjeta de tinta medía 2,6:1. */
.ferr{color:var(--err);font-size:.7rem;letter-spacing:.08em;margin:8px 0 0}
#s-email .field .ferr{margin-bottom:0}
#s-email input[aria-invalid="true"]{border-color:var(--err)}
#s-email .btn{margin-top:14px}
body.an form .btn-solid{background:var(--ink);color:var(--bone);border-color:var(--ink)}
body.an form .btn-solid:hover{background:#000}
body.an.email-active form .btn-solid{background:var(--bone);color:var(--ink);border-color:var(--bone);width:100%;justify-content:space-between}
body.an.email-active #s-email .linkbtn{color:rgba(243,239,231,.72);align-self:flex-start}
body.an.email-active #s-email .trustline{color:var(--halo)}
.arrow-action{display:inline-flex;align-items:center;gap:18px;overflow:hidden}
.arrow-swap{position:relative;display:block;width:20px;height:20px;overflow:hidden;flex:0 0 20px}
.arrow-swap i{position:absolute;inset:0;font-style:normal;display:grid;place-items:center;
  transition:transform .24s cubic-bezier(.2,.7,.2,1)}
.arrow-swap i+ i{transform:translateX(-150%)}
/* el relevo por hover solo con puntero real: en táctil el tap dejaba la flecha cambiada */
@media (hover:hover) and (pointer:fine){
  .arrow-action:hover .arrow-swap i:first-child{transform:translateX(150%)}
  .arrow-action:hover .arrow-swap i+ i{transform:translateX(0)}
}
.arrow-action:focus-visible .arrow-swap i:first-child{transform:translateX(150%)}
.arrow-action:focus-visible .arrow-swap i+ i{transform:translateX(0)}

/* ---- resultado: el primer viewport vende (plan 006) ----
   Orden: aviso → foto medida + forma + frase → CTA con su precio. A 390×844 el CTA entra
   sin scroll, también con el aviso de pose activo (_qa_resultado_viewport.py lo mide). */
.rhero{display:grid;grid-template-columns:minmax(96px,132px) 1fr;gap:12px 16px;
  align-items:center;margin:14px 0 16px}
/* segunda mitad del titular en mineral medio: 4,22:1 sobre hueso, por encima del 3:1 que pide
   el texto grande. Ver la nota del `<h2>` en analisis.html. */
#s-result h2 .h2b{color:var(--min-m)}
.rh-tag{font-size:var(--t-mono);letter-spacing:.2em;text-transform:uppercase;color:var(--brass-text);
  margin-bottom:4px}
.rh-forma{font-family:var(--sans);font-weight:600;font-size:var(--t-card);
  letter-spacing:-.01em;line-height:1.18;margin:0 0 8px}
.rh-frase{font-size:var(--t-body);color:var(--body-2);line-height:1.5}
.paydeck{margin:0 0 38px}
.paydeck .paywall{margin-top:0}
/* la captura de email, ya como vía secundaria: una línea discreta bajo el bloque de pago */
.email-alt{margin-top:14px;font-size:var(--t-fine);color:var(--cap)}
.email-alt .linkbtn{font-family:var(--sans);font-size:var(--t-fine);letter-spacing:0;
  text-transform:none;padding:0;color:var(--brass-text)}
.email-alt .linkbtn:hover{color:var(--ink)}

/* lo demás baja (plan 006 §2) */
.rmeta{display:flex;flex-wrap:wrap;align-items:center;gap:12px 20px;margin:0 0 18px}
.rmeta .btn{width:auto}
.badges{display:flex;flex-wrap:wrap;gap:8px 18px;margin:0;font-size:var(--t-mono);
  letter-spacing:.14em;text-transform:uppercase;color:var(--brass-text)}
.fichawrap{border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 14px 38px rgba(23,32,36,.10);background:#fff}
.fichawrap canvas{width:100%;height:auto;display:block}
.freecards{display:grid;gap:14px;align-content:start;margin-bottom:34px}
.fcard{background:var(--paper);border:1px solid var(--line);border-radius:14px;padding:20px 22px}
.fcard .ft{font-family:var(--sans);font-weight:600;font-size:var(--t-card);letter-spacing:-.01em;line-height:1.2;margin-bottom:8px}
.fcard p{font-size:var(--t-body);color:var(--body-2)}
.fcard .mono{display:block;font-size:var(--t-mono);letter-spacing:.2em;text-transform:uppercase;
  color:var(--brass-text);margin-bottom:8px}

/* zona bloqueada — las tarjetas van DEBAJO del CTA desde el plan 006 y se compactan */
.lockzone{border-top:1px solid var(--line);padding-top:30px}
.lockzone h3{font-size:var(--t-h3);margin-bottom:.3em}
#lockCards{display:grid;gap:12px;margin:22px 0}
.lcard{position:relative;background:var(--paper);border:1px solid var(--line);border-radius:14px;
  padding:14px 18px;overflow:hidden}
.lcard .lt{font-family:var(--sans);font-weight:600;font-size:var(--t-card);letter-spacing:-.01em;margin-bottom:5px;display:flex;gap:10px;align-items:center}
.lcard .teaser{font-size:var(--t-fine);color:var(--cap)}
/* el blur de la línea siguiente es CERRADURA, no material: no se toca (regla en
   SISTEMA-DISENO §3, brand/revva/CLAUDE.md y aquí; _qa_prefs.py la verifica) */
.lcard .lockrows{margin-top:14px;filter:blur(5px);user-select:none;pointer-events:none}
.lcard .lockrows span{display:block;height:7px;border-radius:5px;background:#DFD9CC;margin:7px 0}
.lcard .lockrows span:nth-child(2){width:82%}
.lcard .lockrows span:nth-child(3){width:64%}
.lcard .lock{position:absolute;top:18px;right:18px;font-size:var(--t-mono);letter-spacing:.18em;
  text-transform:uppercase;color:var(--brass-text);border:1px solid var(--brass);
  border-radius:999px;padding:.45em .9em;background:rgba(243,239,231,.9)}
.lcard.open .lockrows,.lcard.open .lock{display:none}
.lcard.open p{font-size:var(--t-body);color:var(--body-2);margin:10px 0 0}

/* paywall */
.paywall{background:var(--ink);color:var(--bone);border-radius:18px;padding:30px 26px;margin-top:26px}
.paywall .pwlead{font-family:var(--sans);font-weight:500;font-size:var(--t-lead);letter-spacing:-.01em;line-height:1.3;margin-bottom:18px}
.paywall .btn-solid{background:var(--bone);color:var(--ink);border-color:var(--bone);width:100%;justify-content:center}
.paywall .btn-solid:hover{background:#fff}
.paywall .trustline{color:#8DA0AA}
.paywall .upsell{margin-top:16px;font-size:var(--t-fine);color:var(--bone-dim);line-height:1.55}
.paywall .demo{margin-top:12px;font-size:var(--t-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--halo)}
/* Precio, motivo y ancla (ADR 2026-08-05). Tres elementos prominentes, porque en móvil la
   mirada rebota entre lo destacado en vez de leer en orden (patrón pinball, NN/g). */
.paywall .pwmotivo{color:var(--halo);font-size:var(--t-mono);letter-spacing:.16em;text-transform:uppercase;
  margin-bottom:10px}
.paywall .pwprice{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;margin-bottom:14px}
.paywall .pwprice b{font-family:var(--serif);font-weight:500;font-size:clamp(2.6rem,11vw,3.6rem);
  line-height:.9;letter-spacing:-.01em;color:var(--bone)}
.paywall .pwafter{font-family:var(--mono);font-size:var(--t-fine);letter-spacing:.1em;text-transform:uppercase;
  color:var(--bone-dim)}
/* El ancla es de categoría, no de un competidor con nombre: ver config.js. */
.paywall .pwancla{margin:18px 0 22px;border-top:1px solid rgba(243,239,231,.14)}
.paywall .pwancla>div{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  flex-wrap:wrap;padding:12px 0;border-bottom:1px solid rgba(243,239,231,.14)}
.paywall .pwancla dt{font-family:var(--mono);font-size:var(--t-body);color:var(--bone-dim);flex:0 0 auto}
.paywall .pwancla dd{font-size:var(--t-fine);line-height:1.45;color:var(--bone-dim);text-align:right;
  flex:1 1 12rem}
.paywall .pwancla-yo dt{color:var(--brass);font-weight:500}
.paywall .pwancla-yo dd{color:var(--bone)}

/* Estados del desbloqueo (ADR 2026-08-04). Los cuatro comparten .paywall y ninguno fija
   `display`: si lo hicieran, el atributo `hidden` perdería y se verían a la vez. */
.paywall+.paywall{margin-top:0}
.paywall .pwterms{margin-top:16px;font-size:var(--t-fine);line-height:1.6;color:var(--bone-dim)}
.paywall .pwterms b{font-weight:600;color:var(--bone)}
.paywall .pwnote{margin-top:10px;font-size:var(--t-body);line-height:1.6;color:var(--bone-dim)}
.paywall .pwnote a{color:var(--halo)}
/* Una nota seguida de un botón necesita su aire, y `*{margin:0}` no lo da (2026-08-12, lo vio
   Jorge en su iPhone). En `#paywall` el hueco lo aportaba `.pwancla` con su margen inferior;
   `#pwSoon` no tiene ancla, así que el botón nacía **pegado a 0 px** al texto. Se iguala al
   mismo ritmo que la otra cara del panel —22 px aquí, 14 en móvil— para que abrir la venta no
   mueva nada de sitio. Regla general y no un `#pwSoon`: cualquier panel futuro con este orden
   la hereda. */
.paywall .pwnote + .btn{margin-top:22px}
.paywall .pwrecover{margin-top:18px;padding-top:16px;border-top:1px solid rgba(243,239,231,.14);
  font-size:var(--t-fine);color:var(--bone-dim)}
/* El .linkbtn genérico es tinta sobre claro: aquí abajo es 1,3:1 y desaparece. */
.paywall .linkbtn{color:var(--halo);font-size:var(--t-fine);letter-spacing:0;text-transform:none;
  text-decoration:underline;text-underline-offset:3px}
.paywall .linkbtn:hover{color:var(--bone)}

/* Insignias propias (plan 006 §4, ADR 2026-08-06): fila de claims VERIFICABLES bajo el
   botón. Sobre el panel de tinta: hueso atenuado 12,4:1 y el latón del icono 7,9:1 —
   la regla de siempre (el latón solo sobre oscuro). */
.sellos{display:flex;flex-wrap:wrap;gap:8px 18px;list-style:none;margin:16px 0 0;
  padding:14px 0 0;border-top:1px solid rgba(243,239,231,.14)}
.sellos li{display:flex;align-items:center;gap:8px;font-size:var(--t-fine);color:var(--bone-dim)}
.sellos img{display:block;width:18px;height:18px;flex:0 0 18px}
/* Métodos de pago: fila vacía alimentada por datos — cero logos hasta que la cuenta LIVE
   exista y la lista esté verificada contra Stripe (ADR 2026-08-06). */
.paylogos{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.paylogo{font-size:var(--t-mono);letter-spacing:.14em;text-transform:uppercase;color:var(--bone-dim);
  border:1px solid rgba(243,239,231,.22);border-radius:6px;padding:.4em .7em}

/* Recuperar el acceso: superficie clara, porque vive fuera del panel de tinta. */
.recover{margin-top:20px;border:1px solid var(--line);border-radius:16px;background:var(--paper);
  padding:24px 22px}
.recover .rcv-lead{font-size:var(--t-body);line-height:1.6;color:var(--body-2);margin-bottom:16px}
.recover .field label{display:block;font-family:var(--mono);font-size:var(--t-mono);letter-spacing:.12em;
  text-transform:uppercase;color:var(--cap);margin:0 0 8px}
.recover input[type=email]{width:100%;background:#fff;border:1px solid var(--line);color:var(--ink);
  font-family:var(--sans);font-size:1rem;padding:.9em 1.05em;border-radius:10px}
.recover input[aria-invalid="true"]{border-color:var(--err)}
.recover .rcv-actions:not([hidden]){display:flex;gap:16px;align-items:center;flex-wrap:wrap;margin-top:16px}
.recover .rcv-msg{margin-top:14px;font-size:var(--t-body);line-height:1.55;color:var(--cap)}

/* vuelta del pago — estado, no celebración */
.payreturn{border:1px solid var(--brass);border-radius:14px;padding:16px 18px;margin-bottom:28px;
  background:var(--paper)}
.payreturn .prlead{font-family:var(--sans);font-weight:500;font-size:var(--t-lead);color:var(--ink)}
.payreturn .prhint{margin-top:5px;font-size:var(--t-fine);color:var(--cap);line-height:1.55}
/* el botón de reintentar es .btn (display:inline-flex), que gana al display:none del
   atributo `hidden` — ver la nota del atributo `hidden` en styles.css */
.payreturn .btn[hidden]{display:none}
.payreturn .btn{margin-top:14px}
.payreturn.stuck{border-color:#b4542e;background:#faf1ea}

/* confirmación en dos pasos de las dos acciones destructivas del resultado */
.confirmnote{flex-basis:100%;margin:2px 0 0;font-size:var(--t-fine);line-height:1.5;color:var(--err)}
.btn-ghost.armed{border-color:var(--err);color:var(--err)}
.linkbtn.armed{color:var(--err)}

/* ---- carrusel de reseñas (plan 006 §5): construido y APAGADO ----
   Pista continua por TRANSFORM (nunca left: el comparador ya costó ese arreglo), contenido
   duplicado para el bucle (-50% exacto: los dos grupos son idénticos y el hueco va como
   padding DENTRO de cada grupo), desvanecido en los bordes con mask-image. Pausa al pasar
   el puntero y al enfocar con teclado (el viewport es tabbable). */
.resenas{margin:40px 0 8px;border-top:1px solid var(--line);padding-top:30px}
.resenas h3{font-size:var(--t-h3);margin-bottom:18px}
.rsn-viewport{overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.rsn-viewport:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.rsn-pista{display:flex;width:max-content;animation:rsn-scroll 42s linear infinite}
.rsn-viewport:hover .rsn-pista,.rsn-viewport:focus-within .rsn-pista{animation-play-state:paused}
.rsn-grupo{display:flex;gap:14px;padding-right:14px}
.rsn{flex:0 0 260px;background:var(--paper);border:1px solid var(--line);border-radius:14px;
  padding:16px 18px;margin:0}
.rsn-foto{border-radius:50%;display:block;margin-bottom:10px}
.rsn blockquote{font-size:var(--t-body);color:var(--body-2);line-height:1.5;margin:0 0 10px}
.rsn figcaption{font-size:var(--t-mono);letter-spacing:.16em;text-transform:uppercase;color:var(--cap)}
@keyframes rsn-scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* `?static=1` iguala a reduced-motion (regla del plan 005): mismas reglas que en el bloque
   de preferencias de abajo — rejilla estática, sin copia del bucle */
body.motion-static .rsn-pista{animation:none;width:auto;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px}
body.motion-static .rsn-grupo{display:contents}
body.motion-static .rsn-grupo.rsn-copia{display:none}
body.motion-static .rsn-viewport{-webkit-mask-image:none;mask-image:none}

.rfoot{display:flex;gap:14px;flex-wrap:wrap;align-items:center;margin-top:36px}
.linkbtn{background:none;border:0;cursor:pointer;font-family:var(--mono);font-size:var(--t-mono);
  letter-spacing:.14em;text-transform:uppercase;color:var(--cap);text-decoration:underline;padding:8px 0}
.linkbtn:hover{color:var(--ink)}

footer a{text-decoration:underline}

/* ---- /scan (entrada de ads, hero-v6-brief.md TAREA 2): sin nav, sin fugas ----
   Marca mínima no clicable arriba; una frase, el botón y los tres pilares. */
.scanpage .scbrand{display:flex;justify-content:center;padding:26px 0 0}
.scanpage .scbrand .wordmark{font-size:.9rem;opacity:.92}
.scanpage main{padding-top:40px}
.scanpage h1{font-size:clamp(2.3rem,8.6vw,3.6rem)}
.scpillars{display:grid;gap:12px;margin-top:30px;padding-top:20px;border-top:1px solid var(--line)}
.scpillars .pi b{display:block;font-weight:600;font-size:.9rem;color:var(--ink)}
.scpillars .pi span{display:block;margin-top:2px;font-size:.8rem;color:var(--cap);line-height:1.5}
@media(min-width:600px){
  .scpillars{grid-template-columns:repeat(3,1fr);gap:0}
  .scpillars .pi{padding:0 18px;border-left:1px solid var(--line)}
  .scpillars .pi:first-child{padding-left:0;border-left:0}
}
#s-email .linkbtn{display:block;margin-top:4px}

@media(min-width:761px){
  body.an main{max-width:760px}
  /* 200px de columna de foto: con 280 el CTA caía a 1084 en un viewport de 1000 (medido).
     La foto 4:5 + banda mide 1,374× su ancho: la columna decide la altura del hero. */
  .rhero{grid-template-columns:200px 1fr;gap:14px 26px;margin:14px 0 16px}
  /* con el aviso de pose delante, mismo trato que en móvil: el primer viewport recupera
     su hueco y el CTA no se sale (criterio 3 del plan 006, medido) */
  #s-result .aviso{padding:10px 16px}
  #s-result .aviso .linkbtn{margin-top:2px;padding:2px 0}
  #aviso:not([hidden])~.eyebrow{display:none}
  #aviso:not([hidden])~h2{font-size:var(--t-h3)}
  #aviso:not([hidden])~.rhero{grid-template-columns:148px 1fr;margin:12px 0 14px}
  .rh-forma{margin-bottom:10px}
  .freecards{grid-template-columns:1fr 1fr}
  #s-medir .scanwin{margin-left:0}
  .scanline{margin-left:0}
  #s-medir .sexo{margin-left:0;text-align:left}
  #s-medir .sexo legend{margin-left:0}
  #s-medir .sexchips{justify-content:flex-start}
  .paywall{padding:36px 34px}
  .paywall .btn-solid{width:auto}
}
@media(min-width:760px){.email-card{grid-template-columns:1fr 1.12fr}}
@media(max-width:759px){
  body.an.email-active main{padding:24px 16px;align-items:start}
  .email-card{min-height:0}.email-intro{gap:54px;border-right:0;border-bottom:1px solid rgba(243,239,231,.14)}
  .email-fields{grid-template-columns:1fr}.email-social{margin-bottom:24px}
}
/* ---- primer viewport a 390×844 (plan 006 §6, criterio de Jorge con captura) ----
   Sin tocar la pantalla de entrada (plan 004) ni la de medición (plan 005): solo el
   resultado se compacta para que foto+forma+frase+CTA con su precio entren sin scroll,
   también con el aviso de pose delante. */
@media(max-width:760px){
  /* la entrada (intro-active) y /scan tienen sus propios paddings, más específicos */
  body.an main{padding-top:96px}
  body.an .steps{margin:16px 0 20px}
  body.an section.step#s-result{padding-top:8px}
  #s-result .eyebrow{margin-bottom:2px}
  #s-result h2{font-size:var(--t-h2);margin-bottom:.2em}
  #s-result .aviso{margin-bottom:12px;padding:10px 14px}
  #s-result .aviso p+p{font-size:.88rem}
  #s-result .aviso .linkbtn{margin-top:2px;padding:2px 0}
  .rhero{margin:10px 0 12px}
  /* con el aviso de pose delante, el primer viewport recupera su hueco: la foto baja un
     paso y el eyebrow —redundante con el h2— se retira. El CTA no puede salirse (criterio
     3 del plan 006, medido por _qa_resultado_viewport.py). */
  #aviso:not([hidden])~.eyebrow{display:none}
  #aviso:not([hidden])~h2{font-size:var(--t-h3)}
  #aviso:not([hidden])~.rhero{grid-template-columns:minmax(80px,102px) 1fr}
  .paydeck .paywall{padding:20px 18px}
  .paywall .pwmotivo{margin-bottom:8px}
  .paywall .pwprice{margin-bottom:8px}
  .paywall .pwprice b{font-size:clamp(2.3rem,9.6vw,3rem)}
  .paywall .pwlead{font-size:1rem;margin-bottom:10px}
  .paywall .pwancla{margin:10px 0 14px}
  .paywall .pwnote + .btn{margin-top:14px}   /* mismo hueco que da `.pwancla` en movil */
  .paywall .pwancla>div{padding:8px 0}
  .paywall .pwancla dt{font-size:.92rem}
  .paywall .pwancla dd{font-size:.8rem}
}

@media(prefers-reduced-motion:reduce){
  .arrow-swap i,.mchip{transition:none}
  /* el campo ya no tiene halos animados que apagar (2026-08-05); la guía además dejó de
     ciclar (plan 004): solo se mueve si el cartel de error la conduce a un fallo */
  .ge-cara,.ge-marcas{transition:none}
  /* pulsación de la zona de subida: se retira la compresión, como en el resto del sistema */
  .upzone:active{transform:none}
  /* el carrusel de reseñas no se queda parado a medias: pasa a rejilla estática y la copia
     del bucle desaparece (plan 006 §5) */
  .rsn-pista{animation:none;width:auto;display:grid;
    grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px}
  .rsn-grupo{display:contents}
  .rsn-grupo.rsn-copia{display:none}
  .rsn-viewport{-webkit-mask-image:none;mask-image:none}
}

/* ============ TRANSPARENCIA REDUCIDA ============
   Los dos discos de 72vmax con blur(70px) que el plan 002 venía a retirar ya NO existen:
   los quitó el paso al campo mineral (ADR 2026-08-05-entrada-campo-mineral). El campo y su
   grano (::before/::after fijos) no entran: son el propio fondo, no un material sobre
   contenido. Queda lo que de verdad deja ver algo a través:
   NO se toca `.lcard .lockrows{filter:blur(5px)}`: ese desenfoque NO es un material, es la
   cerradura del contenido de pago. Quitarlo enseñaría gratis lo que cuesta 9,90 €. */
@media (prefers-reduced-transparency: reduce){
  /* la pastilla de la nav sobre el campo era hueso al .95: pasa a pleno */
  body.an.intro-active nav .pill{background:var(--bone)}
  /* el sello CONTENIDO DE PAGO flota sobre las filas difuminadas del candado */
  .lcard .lock{background:var(--bone)}
}

/* ============ CONTRASTE ALTO ============
   El texto atenuado por alfa sobre los paneles de tinta sube a hueso pleno. Equivalencias
   medidas sobre tinta: .62 -> 6,30:1 · .70 -> 7,69:1 · .76 -> 8,80:1; con hueso pleno,
   14,44:1. Y las hairlines de .14-.3 pasan a línea vista. Incluye la pantalla de entrada
   y la guía de encuadre, posteriores al plan (2026-08-05). */
@media (prefers-contrast: more){
  .email-intro .muted{color:#CFDCE3}
  .email-intro .lead{color:var(--bone)}
  #s-email .field label{color:var(--bone)}
  #s-email .field label span{opacity:1}
  body.an.email-active #s-email .check{color:var(--bone)}
  body.an.email-active #s-email .linkbtn{color:var(--bone)}
  #s-email input[type=email],#s-email input[type=text]{border-color:var(--bone)}
  .email-card,.email-intro,.paywall .pwancla,.paywall .pwancla>div,
  .paywall .pwrecover{border-color:rgba(243,239,231,.5)}
  .privacy{border-color:var(--cap)}
  .upzone{border-color:var(--cap)}
  /* el estado deshabilitado del botón: .42 de opacidad deja la etiqueta en 2,53:1 — fue el
     fallo medido el 2026-08-04. Con contraste alto se marca con borde, no atenuando. */
  .btn[aria-disabled="true"]{opacity:.75}
  /* pantalla de entrada sobre el campo: panel y controles sobre tinta */
  .intro-card{border-color:rgba(243,239,231,.5)}
  .intro-vis{border-left-color:rgba(243,239,231,.45)}
  body.an.intro-active .steps{border-color:rgba(243,239,231,.5)}
  body.an.intro-active .upzone{border-color:var(--bone)}
  body.an.intro-active .btn-ghost{border-color:var(--bone)}
  body.an.intro-active .resume{border-color:rgba(243,239,231,.5)}
  /* guía de encuadre: los trazos estructurales suben (no-texto: ≥3:1 sobre tinta).
     Los de latón y halo ya cumplen (7,9:1 y 10,1:1) y no se tocan. */
  .ge-borde{stroke:rgba(243,239,231,.45)}
  .ge-rasgo{stroke:rgba(243,239,231,.8)}
  .ge-eje-ref{stroke:rgba(243,239,231,.6)}
  .ge-iris{fill:rgba(243,239,231,.7)}
}
