/* ═══════════════════════════════════════════════════════════════════════════
   c-aviso.css  ·  EL MENSAJERO DE CADA ÉPOCA
   Contrato: design-system/08-contrato-segunda-tirada.md §2 (marcado) · §3 (reglas)
   Doctrina: 07-contrato-vida-y-armazon.md §0 (MATERIA)

   MARCADO CONGELADO (no se toca, no se añade ARIA — el role ya viene del HTML):

     <div class="c-aviso c-aviso--exito" role="status">
       <strong class="c-aviso__titulo">Guardado.</strong>
       <p class="c-aviso__texto">Tus cambios están a salvo.</p>
     </div>

   Variantes: --exito · --error · --info   (sin variante = aviso neutro)
   Estado:    .is-nueva                    (ver §0.3)

   ── LA IDEA ────────────────────────────────────────────────────────────────
   El aviso no es una caja de color: **es un mensaje que ACABA DE LLEGAR**.
   Cada época tiene su forma de recibir noticias, y esa forma ES el componente:

     1 · Cueva   → LA SEÑAL     · marca de pigmento fresca en la pared, con halo.
                                  El error es tierra quemada.
     2 · Piedra  → EL EDICTO    · cartela tallada y asentada en el muro.
                                  El error es la fisura que la cruza.
     3 · Papel   → LA ESQUELA   · media cuartilla crema sobre la mesa del taller,
                                  sello de rúbrica en el canto. Éxito = el visto
                                  del maestro impresor. Error = tachadura.
     4 · Hierro  → EL TELEGRAMA · tira de papel de máquina con perforaciones de
                                  arrastre. `.is-nueva` lo saca de la ranura a
                                  tirones y le pasa la luz de impresión por
                                  encima. Error = la campana: vibra UNA vez.
     5 · Cabina  → LA LUZ       · filo lateral semántico con núcleo, sobre
                                  cristal. Entrada seca de 130 ms.

   ── 0.1 · REGLA DE ORO ─────────────────────────────────────────────────────
   El HTML es UNO. Todo lo de arriba vive en `::before` (LA MARCA), en `::after`
   (LA MATERIA que llega: halo, fisura, tachadura, pasada de luz, filo de luz) y
   en fondos, bordes y sombras. Ni un nodo nuevo.

   ── 0.2 · LOS DOS PSEUDOS (política de este fichero) ───────────────────────
   `::before` = LA MARCA. Es un ítem de la rejilla (columna izquierda). Lleva su
                silueta (fondo/anillo) y el glifo como `content`.
   `::after`  = LA MATERIA. `position:absolute; inset:0; z-index:-1`. Cae encima
                del fondo del aviso y DEBAJO del texto (el `isolation:isolate`
                de la raíz garantiza que el -1 no se hunda hasta la página).

   ── 0.3 · `.is-nueva` — LA ENTRADA, DOCUMENTADA ────────────────────────────
   `.is-nueva` es **entrada única**: se pone en el HTML del aviso que acaba de
   aparecer y se olvida. NO hay que quitarla: todas las animaciones de este
   fichero corren SIN `animation-fill-mode`, así que al terminar el elemento
   vuelve a su estilo estático — que ES el estado final. Un aviso con
   `.is-nueva` en reposo y un aviso sin ella son el mismo píxel.

     · Sin `.is-nueva`  → el aviso ya estaba ahí. Cero movimiento.
     · Con `.is-nueva`  → el mensaje llega, una sola vez, con el fenómeno de su
                          época. Nada se repite, nada queda latiendo.
     · `prefers-reduced-motion` → no llega: ya está. Estado final, quieto (§7).

   Corolario del punto 5 de la doctrina («una sola cosa encendida»): el aviso
   NO tiene hover. No es un control, es una noticia; calentarse al pasar la mano
   sería prometer una interacción que no existe.

   ── 0.4 · DISTINCIÓN SIN COLOR (obligatoria: hay daltónicos) ───────────────
   Error e info NO se distinguen por color. Se distinguen por DOS canales de
   forma, idénticos en las cinco épocas:

     variante   silueta de la marca        glifo
     ─────────  ─────────────────────────  ─────
     --exito    disco MACIZO               ✓
     --error    CUADRADO (esquina viva)    ×      ← silueta y glifo distintos
     --info     ANILLO (hueco)             i
     (ninguna)  anillo tenue               •

   Y un tercer canal, gratis, por época: el error siempre trae además su
   accidente material (tierra quemada · fisura · tachadura · campana · doble
   filo). En blanco y negro los tres avisos siguen siendo tres cosas distintas.

   ── 0.5 · CONTRASTE ────────────────────────────────────────────────────────
   El título va SIEMPRE en la tinta principal, nunca en el color semántico: así
   ningún estado del componente depende de un color medido al límite. El color
   semántico solo pinta marca, filo y accidente — piezas NO textuales (umbral
   3:1), aunque todas las de aquí superan 4.5:1 igualmente. Medidas en §8.

   ── 0.6 · AUTOCONTENIDO ────────────────────────────────────────────────────
   Este fichero no lee un solo token `--eN-*` de las hojas de época: los suyos
   los declara él, con prefijo `--av-`. Motivo práctico: la época 3 se está
   rehaciendo (contrato 08 §1, taller oscuro + hojas crema) y `--e-tinta` va a
   pasar de tinta negra a crema. Un aviso que dependiera de `--e-tinta` para la
   tinta de la esquela se volvería crema sobre crema el día del cambio. Aquí la
   hoja trae su propia tinta y la esquela se lee igual antes y después.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ───────────────────────────────────────────────────────────────────────────
   1 · ESTRUCTURA — solo `var(--e-*)`. Ni un color ni una duración a mano.
   ─────────────────────────────────────────────────────────────────────────── */

.c-aviso{
  /* — contrato interno: lo que cada época redefine (§2..§6) — */
  --av-sup:      var(--e-sup);        /* la superficie del mensaje            */
  --av-tinta:    var(--e-tinta);      /* la tinta del título                  */
  --av-tinta-2:  var(--e-tinta-2);    /* la del cuerpo                        */
  --av-linea:    var(--e-linea);      /* su filo                              */
  --av-radio:    var(--e-radio);

  /* LAS DOS SILUETAS DE LA MARCA (§0.4). Van en tokens, NO en `border-radius`
     de cada época: una época que escribiera `border-radius` en `::before`
     tendría más peso que la regla de la variante y aplastaría la distinción
     redondo/anguloso — que es un canal de accesibilidad, no un adorno.
     Regla de propiedad de este fichero: las épocas tocan estos dos tokens y
     nunca el `border-radius` de la marca. */
  --av-radio-marca:      50%;         /* redondo: éxito e info                */
  --av-radio-marca-viva: 3px;         /* esquina viva: error                  */

  --av-ok:       var(--e-ok);         /* semánticos: parten de los del sistema */
  --av-info:     var(--e-acento);
  --av-error:    var(--e-acento);     /* suelo — cada época pone el suyo (§0.5) */
  --av-neutro:   var(--e-tinta-2);

  --av-color:    var(--av-neutro);    /* el color de ESTA variante            */
  --av-contra:   var(--av-sup);       /* lo que se lee ENCIMA de --av-color   */
  --av-glifo:    "•";
  --av-marca:    26px;                /* lado de la marca                     */

  position: relative;
  isolation: isolate;                 /* el ::after z-index:-1 no se hunde    */

  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "marca titulo"
    "marca texto";
  column-gap: calc(var(--e-gap) * .68);
  row-gap:    calc(var(--e-gap) * .2);
  align-items: start;

  /* El padding vertical va amortiguado a .92: es lo que mantiene el alto
     dentro del ±20% entre la cueva (aire 12) y la cabina (aire 40). Medido
     en §8.3. */
  padding: calc(var(--e-pad-caja) * .92) var(--e-pad-caja);
  min-width: 0;

  border: var(--e-grosor) solid var(--av-linea);
  border-radius: var(--av-radio);
  background: var(--av-sup);
  color: var(--av-tinta);
}

/* — LA MARCA — silueta + glifo. Ítem de rejilla, no capa absoluta. */
.c-aviso::before{
  content: var(--av-glifo);
  grid-area: marca;

  display: grid;
  place-items: center;
  width:  var(--av-marca);
  height: var(--av-marca);
  flex: none;
  margin-top: 1px;                    /* alineación óptica con la altura de X */

  border-radius: var(--av-radio-marca);
  background: var(--av-color);
  color: var(--av-contra);

  /* Pila propia: el glifo tiene que existir aunque la display de la época no
     traiga el carácter (Anton, Cinzel y Garamond no llevan «✓»; el navegador
     cae por glifo, no por elemento, y la caja no se mueve). */
  font-family: var(--e-cuerpo), 'DejaVu Sans', 'Segoe UI Symbol', sans-serif;
  font-weight: 700;
  font-size: calc(var(--av-marca) * .58);
  line-height: 1;
  letter-spacing: 0;
  font-style: normal;
  text-transform: none;
}

/* — LA MATERIA — capa de época; en la base no pinta nada. */
.c-aviso::after{
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
}

/* — TEXTO — */
.c-aviso__titulo{
  grid-area: titulo;
  display: block;
  margin: 0;
  font-family: var(--e-cuerpo);
  font-weight: 600;
  font-size: 15px;
  line-height: 1.3;
  letter-spacing: var(--e-tracking);
  color: var(--av-tinta);
}
.c-aviso__texto{
  grid-area: texto;
  margin: 0;                          /* el <p> trae margen del UA: fuera */
  font-family: var(--e-cuerpo);
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--av-tinta-2);
}
/* FIX 2026-08-13 (bug probado dos veces esta noche): `grid-area: texto` es UNA
   celda. Con dos `__texto` hermanos, los dos caen en la MISMA celda (fila 2,
   columna 2) y se pintan superpuestos — la regla `+` de abajo quedaba inerte
   porque nunca hay overlap-margin entre cajas que ocupan el mismo sitio.
   Arreglo mínimo: solo el PRIMER `__texto` usa el área nombrada (fila fija).
   Cualquier hermano siguiente SUELTA esa fila (`grid-row: auto`) y conserva
   solo la columna (`grid-column: 2`, la misma que ocupaba `texto`): el
   algoritmo de auto-colocación de grid busca, en esa columna, la primera fila
   libre — fila 1 y 2 ya están ocupadas (título y primer texto), así que cae
   en una fila nueva, implícita, debajo. La marca (columna 1) no necesita
   cubrir esas filas extra: solo se alinea `start` con el título, así que un
   aviso con 3+ filas de texto no le cambia el aspecto. Cero cambio para el
   caso de UN texto (sigue siendo la única celda de la fila 2) ni para el caso
   de un `__texto` con varios `<p>` DENTRO (sigue siendo un solo ítem de grid,
   el flujo normal del bloque apila los `<p>` internos sin tocar la rejilla).
   Verificado en `…/scratchpad/c-aviso-fix/`: (a) y (c) 0px de diff contra el
   CSS anterior; (b) pasa de superpuesto a apilado, con el `margin-top` de la
   regla `+` de abajo ahora sí visible entre los dos. */
.c-aviso__texto ~ .c-aviso__texto{
  grid-row: auto;
  grid-column: 2;
}
.c-aviso__texto + .c-aviso__texto{ margin-top: calc(var(--e-gap) * .34); }
.c-aviso__texto a{
  color: var(--av-tinta);
  text-decoration: underline;
  text-underline-offset: .18em;
  text-decoration-thickness: from-font;
}

/* — LAS TRES VARIANTES — color + silueta + glifo (§0.4) — */
.c-aviso--exito{ --av-color: var(--av-ok);    --av-glifo: "✓"; }  /* disco macizo */
.c-aviso--error{ --av-color: var(--av-error); --av-glifo: "×"; }  /* cuadrado    */
.c-aviso--info { --av-color: var(--av-info);  --av-glifo: "i"; }  /* anillo      */

/* la esquina viva del error — misma especificidad que la marca base, después
   en el orden: gana sin `!important` y sin que ninguna época la pueda pisar
   por accidente (las épocas solo mueven los tokens). */
.c-aviso--error::before{ border-radius: var(--av-radio-marca-viva); }
/* info y neutro son ANILLO: hueco, no macizo. */
.c-aviso--info::before,
.c-aviso:not(.c-aviso--exito):not(.c-aviso--error):not(.c-aviso--info)::before{
  background: none;
  color: var(--av-color);
  box-shadow: inset 0 0 0 2px var(--av-color);
}

/* ≤390px: el texto no se estrangula contra la marca. La marca no se encoge
   (es el canal de forma: si se pierde, se pierde la accesibilidad). */
@media (max-width: 420px){
  .c-aviso{ column-gap: calc(var(--e-gap) * .5); }
  .c-aviso__titulo{ font-size: 14.5px; }
  .c-aviso__texto{ font-size: 14px; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   2 · ÉPOCA 1 · LA SEÑAL
   Alguien acaba de mojar el dedo en ocre y ha dejado una marca en la pared.
   El pigmento está FRESCO: por eso mancha un halo alrededor. Nada más.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="1"] .c-aviso{
  --av-sup:     #1A120C;                        /* el fragmento de pared      */
  --av-linea:   rgba(201,122,61,.46);
  --av-error:   #EE7C52;                        /* tierra quemada, aclarada
                                                   hasta ser legible (6,9:1)  */
  --av-neutro:  #C9A184;
  --av-contra:  #170902;                        /* la tinta que va SOBRE el
                                                   pigmento encendido         */
  --av-radio:   16px 7px 13px 6px / 8px 15px 7px 12px;   /* ni una igual */
  /* aquí no hay compás ni escuadra: el pegote redondo es un pegote, y el
     anguloso está mal cortado — pero siguen siendo redondo y anguloso. */
  --av-radio-marca:      12px 6px 11px 5px / 6px 11px 5px 10px;
  --av-radio-marca-viva: 4px 2px 3px 2px / 2px 4px 2px 3px;

  /* mota de ocre — la textura ES la prueba del material (doctrina §4);
     alfa acotada dentro del propio SVG para no levantar los oscuros */
  --av1-moteado: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='170' height='170'%3E%3Cfilter id='a' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.84' numOctaves='4' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 .788 0 0 0 0 .478 0 0 0 0 .239 .15 0 0 0 0'/%3E%3C/filter%3E%3Crect width='170' height='170' filter='url(%23a)'/%3E%3C/svg%3E");

  background-color: var(--av-sup);
  background-image:
    var(--av1-moteado),
    linear-gradient(168deg, #1F160E 0%, #150E09 100%);
  background-size: 170px 170px, auto;
  border-width: var(--e-grosor);
  box-shadow: 0 14px 34px -22px rgba(0,0,0,.9);
  transform: rotate(-.45deg);                   /* la mano no traza recto */
}
html[data-epoca="1"] .c-aviso__titulo{
  font-family: var(--e-display);
  font-weight: var(--e-peso-display, 400);
  font-size: 17px;
  letter-spacing: .045em;
  text-transform: uppercase;
}

/* EL HALO del pigmento fresco: la mancha que deja el dedo alrededor de la
   marca. Centrado sobre la marca, no sobre la caja. */
html[data-epoca="1"] .c-aviso::after{
  background:
    radial-gradient(46px 40px at calc(var(--e-pad-caja) + 13px)
                                calc(var(--e-pad-caja) * .92 + 14px),
      color-mix(in oklab, var(--av-color) 30%, transparent) 0%,
      color-mix(in oklab, var(--av-color) 9%,  transparent) 46%,
      transparent 74%);
}

/* la marca: un pegote de pigmento, hecho con el dedo */
html[data-epoca="1"] .c-aviso::before{
  background-image: var(--av1-moteado);
  background-size: 90px 90px;
  transform: rotate(-2.2deg);
  box-shadow: 0 0 16px -4px color-mix(in oklab, var(--av-color) 60%, transparent);
}
html[data-epoca="1"] .c-aviso--info::before,
html[data-epoca="1"] .c-aviso:not(.c-aviso--exito):not(.c-aviso--error):not(.c-aviso--info)::before{
  background-image: none;
  box-shadow: inset 0 0 0 3px var(--av-color);   /* trazo gordo de la cueva */
}

/* EL ERROR ES TIERRA QUEMADA. La quemadura se queda PEGADA AL CANTO IZQUIERDO,
   detrás de la marca, y se ha apagado del todo antes de donde empieza el texto
   (≈49px; el título arranca en 62px). No es delicadeza: la primera versión
   ponía el chamuscado a lo ancho y el peor píxel bajo el cuerpo daba 4,15:1 —
   por debajo del 4.5. Con la quemadura confinada, el texto se lee sobre pared
   limpia (5,7:1) y la marca, que sí está encima del chamuscado, mide 4,7:1. */
html[data-epoca="1"] .c-aviso--error{
  --av-sup: #1E110A;
  border-color: rgba(140,59,34,.85);
  background-image:
    var(--av1-moteado),
    radial-gradient(70px 130% at 0% 50%, rgba(140,59,34,.5) 0%, transparent 70%),
    linear-gradient(168deg, #241108 0%, #180C06 100%);
  background-size: 170px 170px, auto, auto;
}

/* ENTRADA · el pigmento aún está mojado y se asienta (720 ms, orgánico) */
html[data-epoca="1"] .c-aviso.is-nueva{
  animation: av1-senal var(--e-vel) var(--e-curva, cubic-bezier(.34,.02,.24,1));
}
html[data-epoca="1"] .c-aviso.is-nueva::before{
  animation: av1-dedo var(--e-vel) var(--e-curva, cubic-bezier(.34,.02,.24,1));
}
html[data-epoca="1"] .c-aviso.is-nueva::after{
  animation: av1-halo calc(var(--e-vel) * 1.15) var(--e-curva, cubic-bezier(.34,.02,.24,1));
}
@keyframes av1-senal{
  from{ opacity: 0; transform: rotate(-1.9deg) scale(.985); }
  60% { opacity: 1; }
  to  { opacity: 1; transform: rotate(-.45deg) scale(1); }
}
@keyframes av1-dedo{                 /* el dedo aprieta y levanta */
  from{ transform: rotate(-9deg) scale(.5); }
  55% { transform: rotate(1.5deg) scale(1.09); }
  to  { transform: rotate(-2.2deg) scale(1); }
}
@keyframes av1-halo{                 /* la mancha se abre y se seca */
  from{ opacity: 0; transform: scale(.72); }
  45% { opacity: 1.0; transform: scale(1.12); }
  to  { opacity: 1;  transform: scale(1); }
}


/* ═══════════════════════════════════════════════════════════════════════════
   3 · ÉPOCA 2 · EL EDICTO
   Una cartela con arco, tallada en el muro, con su doble filete grabado.
   No aparece: SE ASIENTA. El error es la fisura que la cruza de lado a lado.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="2"] .c-aviso{
  --av-sup:     #1C1914;
  --av-linea:   rgba(207,199,184,.22);
  --av-error:   #E0764B;                        /* la grieta (5,9:1)          */
  --av-neutro:  #BDB4A2;
  --av-contra:  #0E0C0A;
  --av-radio:   20px 20px 3px 3px / 13px 13px 3px 3px;   /* arco arriba */
  --av-radio-marca:      50%;                   /* medallón de bronce         */
  --av-radio-marca-viva: 2px;                   /* sillar cortado a escuadra  */

  /* El degradado ARRANCA en `--av-sup` a propósito: el anillo de 7px del
     filete grabado (más abajo) se pinta con ese mismo token, y si el fondo no
     partiera de él se vería un marco de otro color rodeando la cartela. */
  background:
    linear-gradient(180deg, rgba(207,199,184,.055) 0%, transparent 26%),
    linear-gradient(180deg, var(--av-sup) 0%,
                            color-mix(in oklab, var(--av-sup) 84%, #000000) 100%);

  /* el doble filete grabado, entero con box-shadow de la raíz: relleno →
     surco oscuro → canto claro. Así el ::after queda libre para la fisura. */
  box-shadow:
    inset 0 1px 0 rgba(207,199,184,.15),
    inset 0 0 0 7px var(--av-sup),
    inset 0 0 0 8px rgba(0,0,0,.55),
    inset 0 0 0 9px rgba(207,199,184,.09),
    inset 0 -2px 0 rgba(0,0,0,.85),
    0 3px 0 rgba(0,0,0,.9),
    0 20px 40px -30px rgba(0,0,0,.95);
}
html[data-epoca="2"] .c-aviso__titulo{
  font-family: var(--e-display);
  font-weight: var(--e-peso-display, 700);
  font-size: 14.5px;
  letter-spacing: var(--e-tracking);
  text-transform: uppercase;
  text-shadow: 0 -1px 0 rgba(232,226,213,.18), 0 1px 0 rgba(0,0,0,.85);
}
html[data-epoca="2"] .c-aviso::before{
  box-shadow:
    inset 0 1px 0 rgba(232,226,213,.28),
    inset 0 -1px 0 rgba(0,0,0,.45),
    0 1px 0 rgba(0,0,0,.8);
  text-shadow: 0 1px 0 rgba(0,0,0,.35);
}
html[data-epoca="2"] .c-aviso--info::before,
html[data-epoca="2"] .c-aviso:not(.c-aviso--exito):not(.c-aviso--error):not(.c-aviso--info)::before{
  box-shadow:
    inset 0 0 0 2px var(--av-color),
    inset 0 1px 0 rgba(232,226,213,.2),
    0 1px 0 rgba(0,0,0,.8);
  text-shadow: 0 1px 0 rgba(0,0,0,.6);
}

/* LA FISURA — solo en el error. Cruza la cartela entera, filetes incluidos:
   trazo negro (el hueco) + canto claro 1,4px por encima (la luz que entra).
   Ruta deliberada por el TERCIO BAJO: una grieta recta por mitad del título lo
   volvía ilegible de leer (aunque el contraste aguantara: la grieta solo
   oscurece, y el canto claro medido sobre el texto sigue dando 9,2:1). Entra
   por la izquierda a media altura, baja al pie y sale por arriba a la derecha:
   cruza entera y deja los renglones respirar. */
html[data-epoca="2"] .c-aviso--error{
  --av-sup: #1F1813;
  border-color: rgba(224,118,75,.4);
}
html[data-epoca="2"] .c-aviso--error::after{
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='90' viewBox='0 0 400 90' preserveAspectRatio='none'%3E%3Cg fill='none' stroke-linejoin='miter'%3E%3Cpath d='M-4 52 L38 66 L26 76 L96 70 L86 86 L166 74 L206 88 L252 68 L232 60 L306 50 L286 40 L344 32 L404 8' stroke='%23000000' stroke-opacity='.82' stroke-width='2.2'/%3E%3Cpath d='M-4 50.6 L38 64.6 L26 74.6 L96 68.6 L86 84.6 L166 72.6 L206 86.6 L252 66.6 L232 58.6 L306 48.6 L286 38.6 L344 30.6 L404 6.6' stroke='%23CFC7B8' stroke-opacity='.16' stroke-width='.9'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

/* ENTRADA · el bloque baja y se asienta (560 ms, casi quieto) */
html[data-epoca="2"] .c-aviso.is-nueva{
  animation: av2-asienta var(--e-vel) var(--e-curva, cubic-bezier(.33,.02,.28,1));
}
html[data-epoca="2"] .c-aviso.is-nueva::before{
  animation: av2-talla calc(var(--e-vel) * .8) var(--e-curva, cubic-bezier(.33,.02,.28,1));
}
/* la fisura no baja con el bloque: SE ABRE cuando el bloque toca el muro */
html[data-epoca="2"] .c-aviso--error.is-nueva::after{
  animation: av2-fisura calc(var(--e-vel) * .5) calc(var(--e-vel) * .62) both;
}
@keyframes av2-asienta{
  from{ opacity: 0; transform: translateY(-5px); }
  70% { opacity: 1; transform: translateY(.5px); }
  to  { opacity: 1; transform: translateY(0); }
}
@keyframes av2-talla{
  from{ opacity: 0; transform: translateY(-3px); }
  to  { opacity: 1; transform: translateY(0); }
}
@keyframes av2-fisura{
  from{ opacity: 0; }
  to  { opacity: 1; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   4 · ÉPOCA 3 · LA ESQUELA SOBRE LA MESA
   Construida contra el contrato 08 §1 (taller de noche): el MUNDO es oscuro y
   el papel vive en las SUPERFICIES. Esto es media cuartilla crema dejada sobre
   la mesa, con su sombra, su margen de copista y el sello de rúbrica en el
   canto. La tinta de dentro se mide contra el crema, nunca contra el taller.
   Por eso las tintas van declaradas aquí (§0.6) y no salen de `--e-tinta`.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="3"] .c-aviso{
  --av-sup:     #F2EAD9;                        /* la hoja                    */
  --av-tinta:   #1A1714;                        /* negro de humo   (15,1:1)   */
  --av-tinta-2: #4A423A;                        /* segunda pasada   (8,3:1)   */
  --av-linea:   rgba(26,23,20,.24);
  --av-ok:      #1B5334;                        /* verde del corrector (7,5:1)*/
  --av-error:   #A8321E;                        /* rojo de rúbrica   (5,6:1)  */
  --av-info:    #1A1714;                        /* la nota al margen va en
                                                   tinta: el naranja contenido
                                                   se queda en 3,8:1 sobre el
                                                   crema y no llega (§8.2)    */
  --av-neutro:  #4A423A;
  --av-contra:  #F5EEE0;
  --av-radio:   0;                              /* la hoja no tiene esquinas
                                                   redondeadas                */
  --av-radio-marca:      50%;                   /* sello redondo              */
  --av-radio-marca-viva: 2px;                   /* lo tachado se encuadra     */

  /* ── EL PROTOCOLO DE CONTEXTO DE LA ÉPOCA 3 ─────────────────────────────
     La esquela ES una superficie de hoja, así que tiene el mismo deber que las
     cuatro superficies de papel de `epoca-3.css`: REDECLARAR el contexto. Sin
     esto, mis textos se veían bien (uso tinta propia, §0.6) pero cualquier
     pieza del kernel COMPUESTA dentro heredaba la voz del taller y quedaba
     crema sobre crema. Reproducido antes de arreglarlo, en pantalla:
       `c-boton--fantasma`   dentro de la esquela → **1,03:1** · invisible
       `c-distintivo--acento` dentro de la esquela → **2,23:1**
     Con el bloque: 14,91:1 y 5,59:1. El defecto es el mismo que ya se corrigió
     en `c-precio`, y sigo su plantilla al pie de la letra.

     Se leen del token de época con MI literal de respaldo: si esos tokens
     cambiaran de nombre, la esquela se sigue vistiendo sola.

     `--e3-foco` entra porque esta superficie PUEDE contener piezas enfocables
     (un enlace en el texto, un botón compuesto) y el anillo se dibuja FUERA de
     la caja (`outline-offset: 3px`), o sea sobre la hoja: sobre papel, el
     anillo es de tinta.                                                      */
  --e3-texto:       var(--e3-tinta-hoja,   #1A1714);
  --e3-texto-2:     var(--e3-tinta-hoja-2, #4A423A);
  --e3-filete:      var(--e3-linea-hoja,   rgba(26, 23, 20, .20));
  --e3-rojo:        var(--e3-rubrica,      #A8321E);
  --e3-rojo-hondo:  var(--e3-tinta-honda,  #8E2A18);
  --e3-verde:       var(--e3-ok-hoja,      #1B5334);
  --e3-regla:       var(--e3-tinta-hoja,   #1A1714);
  --e3-papel-local: var(--e3-hoja,         #F2EAD9);
  --e3-foco:        var(--e3-tinta-hoja,   #1A1714);

  --av3-fibra: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='f' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='4' seed='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 .40 0 0 0 0 .33 0 0 0 0 .24 .07 0 0 0 0'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23f)'/%3E%3C/svg%3E");

  /* el sello pequeño de rúbrica del canto: círculo mordido, sin texto (a este
     tamaño una leyenda sería una mancha), inclinado como se estampa a mano */
  --av3-sello: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'%3E%3Cdefs%3E%3Cfilter id='m' x='-30%25' y='-30%25' width='160%25' height='160%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.09' numOctaves='3' seed='9' result='t'/%3E%3CfeDisplacementMap in='SourceGraphic' in2='t' scale='4.4' xChannelSelector='R' yChannelSelector='G'/%3E%3C/filter%3E%3C/defs%3E%3Cg transform='rotate(-13 30 30)' filter='url(%23m)' fill='none' stroke='%23A8321E' stroke-opacity='.62'%3E%3Ccircle cx='30' cy='30' r='20' stroke-width='3.4'/%3E%3Ccircle cx='30' cy='30' r='13.5' stroke-width='1.2'/%3E%3Cpath d='M22 30 h16 M30 22 v16' stroke-width='1.6'/%3E%3C/g%3E%3C/svg%3E");

  /* la tachadura del corrector: dos trazos de mano sobre la marca */
  --av3-tacha: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34' height='34' viewBox='0 0 34 34'%3E%3Cg fill='none' stroke='%23A8321E' stroke-linecap='round'%3E%3Cpath d='M2 27 C10 19 18 12 32 5' stroke-width='2.6' stroke-opacity='.9'/%3E%3Cpath d='M3 8 C12 15 21 22 31 28' stroke-width='1.7' stroke-opacity='.7'/%3E%3C/g%3E%3C/svg%3E");

  border-color: rgba(26,23,20,.28);
  border-width: 1px;
  background-color: var(--av-sup);
  background-image:
    var(--av3-fibra),
    /* el margen del copista: filete de rúbrica vertical, a la izquierda */
    linear-gradient(90deg, transparent 0, transparent calc(var(--e-pad-caja) + 34px),
                    rgba(168,50,30,.34) calc(var(--e-pad-caja) + 34px),
                    rgba(168,50,30,.34) calc(var(--e-pad-caja) + 35px),
                    transparent calc(var(--e-pad-caja) + 35px)),
    linear-gradient(178deg, #F6EFE1 0%, #EDE3CF 100%);
  background-size: 260px 260px, auto, auto;

  /* la hoja está APOYADA en la mesa del taller, no pegada al fondo */
  box-shadow:
    0 1px 0 rgba(0,0,0,.34),
    0 12px 26px -16px rgba(0,0,0,.85);
  transform: rotate(-.5deg);
}
html[data-epoca="3"] .c-aviso__titulo{
  font-family: var(--e-display);
  font-weight: var(--e-peso-fuerte, 600);
  font-size: 17px;
  letter-spacing: .012em;
}
html[data-epoca="3"] .c-aviso__texto{ font-size: 15.5px; line-height: 1.45; }
html[data-epoca="3"] .c-aviso__texto a{ color: #A8321E; }

/* el sello del canto, en la capa de materia: pequeño, arriba a la derecha */
html[data-epoca="3"] .c-aviso::after{
  background-image: var(--av3-sello);
  background-repeat: no-repeat;
  background-position: right calc(var(--e-pad-caja) * .5) top calc(var(--e-pad-caja) * .45);
  background-size: 34px 34px;
}

/* la marca es un SELLO estampado: el canto se come un poco de tinta */
html[data-epoca="3"] .c-aviso::before{
  --mordido: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cfilter id='k' x='-25%25' y='-25%25' width='150%25' height='150%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.12' numOctaves='3' seed='6' result='t'/%3E%3CfeDisplacementMap in='SourceGraphic' in2='t' scale='3.2' xChannelSelector='R' yChannelSelector='G'/%3E%3C/filter%3E%3Ccircle cx='20' cy='20' r='18' fill='%23fff' filter='url(%23k)'/%3E%3C/svg%3E");
  -webkit-mask-image: var(--mordido);
          mask-image: var(--mordido);
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  transform: rotate(-4deg);
  font-size: calc(var(--av-marca) * .62);
}

/* ÉXITO = EL VISTO DEL MAESTRO IMPRESOR: verde de corrector, mano inclinada */
html[data-epoca="3"] .c-aviso--exito::before{ transform: rotate(-7deg); }

/* ERROR = TACHADURA: la marca queda anulada. Cuadrado hueco + los dos trazos
   del corrector encima. Sin una gota de color: dos rayas cruzadas ya lo dicen. */
html[data-epoca="3"] .c-aviso--error::before{
  -webkit-mask-image: none;
          mask-image: none;
  background: none;
  background-image: var(--av3-tacha);
  background-size: 100% 100%;
  background-repeat: no-repeat;
  color: var(--av-error);
  box-shadow: inset 0 0 0 1.5px rgba(168,50,30,.55);
  transform: rotate(-1.5deg);
}
html[data-epoca="3"] .c-aviso--info::before,
html[data-epoca="3"] .c-aviso:not(.c-aviso--exito):not(.c-aviso--error):not(.c-aviso--info)::before{
  -webkit-mask-image: none;
          mask-image: none;
  box-shadow: inset 0 0 0 1.5px var(--av-color);
}

/* ENTRADA · la esquela se POSA en la mesa (400 ms, «página que pasa») */
html[data-epoca="3"] .c-aviso.is-nueva{
  animation: av3-posa var(--e-vel) var(--e-curva, cubic-bezier(.22,.61,.36,1));
}
html[data-epoca="3"] .c-aviso.is-nueva::before{
  animation: av3-estampa calc(var(--e-vel) * .6) calc(var(--e-vel) * .55) both;
}
@keyframes av3-posa{
  from{ opacity: 0; transform: translateY(-11px) rotate(1.7deg); }
  to  { opacity: 1; transform: translateY(0)     rotate(-.5deg); }
}
@keyframes av3-estampa{           /* el sello baja, aprieta y levanta */
  from{ opacity: 0; transform: rotate(-4deg) scale(1.5); }
  62% { opacity: 1; transform: rotate(-4deg) scale(.94); }
  to  { opacity: 1; transform: rotate(-4deg) scale(1); }
}
html[data-epoca="3"] .c-aviso--exito.is-nueva::before{ animation-name: av3-visto; }
@keyframes av3-visto{
  from{ opacity: 0; transform: rotate(-24deg) scale(1.45); }
  62% { opacity: 1; transform: rotate(-7deg)  scale(.94); }
  to  { opacity: 1; transform: rotate(-7deg)  scale(1); }
}
html[data-epoca="3"] .c-aviso--error.is-nueva::before{ animation-name: av3-tachar; }
@keyframes av3-tachar{            /* el corrector pasa la pluma dos veces */
  from{ opacity: 0; background-size: 0% 100%; }
  40% { opacity: 1; background-size: 100% 100%; }
  to  { opacity: 1; background-size: 100% 100%; transform: rotate(-1.5deg); }
}


/* ═══════════════════════════════════════════════════════════════════════════
   5 · ÉPOCA 4 · EL TELEGRAMA
   Tira de papel de máquina: perforaciones de arrastre a los dos lados, su línea
   de troquel, tipografía condensada en caja alta y tinta de máquina. En un
   mundo de hierro y hollín, la noticia es LO ÚNICO claro de la pantalla — que
   es exactamente lo que era un telegrama.

   Cuatro decisiones técnicas, todas medidas:
   · Las perforaciones van en el FONDO DE LA RAÍZ (5 capas fijas), no en el
     ::after. Así el ::after queda con UNA sola capa y la pasada de luz se puede
     animar por `background-position` sin repetir cinco posiciones por keyframe.
   · El `padding-inline` reserva la banda del troquel: el texto nunca pisa un
     agujero, tampoco a 390px.
   · La superficie es CLARA, así que los semánticos son las versiones HONDAS de
     los mismos colores (§8.2): el filamento y el cardenillo de la época en
     claro se quedan en 1,6:1 sobre manila y no pueden pintar la marca.
   · La salida por la ranura va con `steps()`: una máquina no interpola.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="4"] .c-aviso{
  --av-sup:     #D8CCB2;                        /* manila de máquina          */
  --av-tinta:   #14110E;                        /* tinta de tipo   (11,9:1)   */
  --av-tinta-2: #4A4238;                        /* la segunda copia (6,2:1)   */
  --av-linea:   rgba(20,17,14,.34);
  --av-ok:      #2C4A2E;                        /* cardenillo hondo  (5,6:1)  */
  --av-error:   #7E2D10;                        /* óxido hondo       (5,1:1)  */
  --av-info:    #63441B;                        /* latón hondo       (5,1:1)  */
  --av-neutro:  #4A4238;
  --av-contra:  #D8CCB2;
  --av-radio:   0;                              /* cortada, no redondeada     */
  --av-radio-marca:      50%;                   /* troquel redondo            */
  --av-radio-marca-viva: 2px;                   /* bloque de tipos            */

  --av4-hueco: #17130F;                         /* lo que se ve por el agujero*/
  --av-condensada: 'Oswald', 'Archivo Narrow', 'Arial Narrow', 'Helvetica Neue',
                   system-ui, sans-serif;

  /* la banda de arrastre ocupa 0→22px por lado; el texto empieza después */
  padding-inline: calc(var(--e-pad-caja) + 20px);

  border: 0;                                    /* una tira no tiene marco    */
  background-color: var(--av-sup);
  background-image:
    radial-gradient(circle 3.2px at 6px 6px, var(--av4-hueco) 0 3.2px, transparent 3.5px),
    radial-gradient(circle 3.2px at 6px 6px, var(--av4-hueco) 0 3.2px, transparent 3.5px),
    repeating-linear-gradient(180deg, rgba(23,19,15,.36) 0 5px, transparent 5px 10px),
    repeating-linear-gradient(180deg, rgba(23,19,15,.36) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, rgba(255,255,255,.42) 0%, rgba(255,255,255,0) 34%,
                            rgba(23,19,15,.05) 100%);
  background-position:
    left 4px top 6px, right 4px top 6px,
    left 18px top 0, right 18px top 0,
    0 0;
  background-size: 12px 22px, 12px 22px, 1px 100%, 1px 100%, auto;
  background-repeat: repeat-y, repeat-y, no-repeat, no-repeat, no-repeat;

  /* apoyada sobre la chapa, con su sombra dura de papel fino */
  box-shadow:
    0 1px 0 rgba(0,0,0,.5),
    0 18px 32px -20px rgba(6,5,4,.95);
}
html[data-epoca="4"] .c-aviso__titulo{
  font-family: var(--av-condensada);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: .1em;
  text-transform: uppercase;
}
html[data-epoca="4"] .c-aviso__texto{ font-size: 14px; }
html[data-epoca="4"] .c-aviso::before{
  font-family: var(--av-condensada), 'DejaVu Sans', sans-serif;
  font-weight: 600;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.28);
}
html[data-epoca="4"] .c-aviso--info::before,
html[data-epoca="4"] .c-aviso:not(.c-aviso--exito):not(.c-aviso--error):not(.c-aviso--info)::before{
  box-shadow: inset 0 0 0 2px var(--av-color);
}

/* la capa de materia = LA PASADA del cabezal. En reposo está aparcada fuera de
   la tira: cero píxeles encendidos hasta que llega un mensaje.

   Va por `transform` y no por `background-position`, que fue el primer intento:
   con `background-size:260%` la banda solo cruza la tira en una ventana de ~30
   puntos de la posición, y la curva de entrada se los comía en los primeros 70
   ms — el barrido existía y no se veía nunca. Con una capa estrecha que se
   traslada y `overflow:hidden` en la tira, el recorrido es el que se ve.

   Y la banda NO es un destello blanco: sobre manila, blanco sobre casi-blanco
   no es nada. Es un cabezal FÍSICO — núcleo claro con dos sombras a los lados,
   que es lo que se ve pasar sobre el papel. */
html[data-epoca="4"] .c-aviso{ overflow: hidden; }
html[data-epoca="4"] .c-aviso::after{
  inset: 0 auto 0 0;
  width: 46%;
  border-radius: 0;
  background: linear-gradient(100deg,
    transparent 0%,
    rgba(23,19,15,.15) 33%,
    rgba(255,255,255,.85) 50%,
    rgba(23,19,15,.11) 67%,
    transparent 100%);
  transform: translateX(-110%);
}

/* ENTRADA · SALE DE LA RANURA. La tira se imprime de arriba abajo a tirones
   (steps: una máquina no interpola) y solo después le pasa la luz. */
html[data-epoca="4"] .c-aviso.is-nueva{
  animation: av4-ranura calc(var(--e-vel) * 2.6) steps(9, end);
}
/* `linear` a propósito: un cabezal de impresión va a velocidad constante. Con
   una curva de aceleración la banda se plantaba en el tercio final en 70 ms y
   el resto de la animación era una tira quieta. */
html[data-epoca="4"] .c-aviso.is-nueva::after{
  animation: av4-pasada calc(var(--e-vel) * 1.9) calc(var(--e-vel) * 2.6) linear;
}
@keyframes av4-ranura{
  from{ clip-path: inset(0 0 100% 0); transform: translateY(-7px); }
  to  { clip-path: inset(0 0 0 0);    transform: translateY(0); }
}
@keyframes av4-pasada{
  from{ transform: translateX(-110%); }
  to  { transform: translateX(320%); }
}

/* EL ERROR ES LA CAMPANA. El telegrafista tocaba la campanilla en los urgentes.
   Vibra UNA vez, DOS oscilaciones, y se acabó: arranca cuando la tira ya ha
   terminado de salir, así que el `transform` no se pelea con el de la ranura
   (y sin `fill-mode`, ninguna de las dos deja residuo). */
html[data-epoca="4"] .c-aviso--error{
  --av-sup: #D5C6AA;
  background-color: var(--av-sup);
}
html[data-epoca="4"] .c-aviso--error.is-nueva{
  animation:
    av4-ranura  calc(var(--e-vel) * 2.6) steps(9, end),
    av4-campana calc(var(--e-vel) * .58) calc(var(--e-vel) * 2.6) 2 ease-in-out;
}
@keyframes av4-campana{
  0%,  100%{ transform: translateX(0); }
  25%      { transform: translateX(2.5px); }
  75%      { transform: translateX(-2.5px); }
}


/* ═══════════════════════════════════════════════════════════════════════════
   6 · ÉPOCA 5 · LA NOTIFICACIÓN DE LUZ
   Cristal, filo lateral del color semántico con su núcleo sangrando hacia
   dentro, y una entrada seca de 130 ms. Ni materia ni ornamento: luz + dato.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-epoca="5"] .c-aviso{
  --av-sup:     transparent;                    /* el cristal no es una pintura */
  --av-linea:   rgba(238,241,246,.14);
  --av-error:   #FF6B6B;                        /* rojo frío: separado del
                                                   naranja de marca (6,7:1)   */
  --av-neutro:  #A9B2C0;
  --av-contra:  #06070A;
  --av-radio:   var(--e-radio);
  --av-radio-marca:      50%;                   /* nodo de luz                */
  --av-radio-marca-viva: 3px;

  background:
    linear-gradient(180deg, rgba(255,255,255,.048) 0%,
                            rgba(255,255,255,.014) 46%,
                            rgba(255,255,255,.022) 100%);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);

  /* EL FILO: 3px del color semántico pegados al canto izquierdo, con un núcleo
     más claro dentro — una luz real es más clara en el centro. */
  box-shadow:
    inset 3px 0 0 var(--av-color),
    inset 4px 0 0 -1px color-mix(in oklab, var(--av-color) 55%, #FFFFFF),
    inset 0 1px 0 rgba(255,255,255,.07),
    0 1px 2px rgba(0,0,0,.5);
  padding-left: calc(var(--e-pad-caja) + 6px);
}
html[data-epoca="5"] .c-aviso__titulo{
  font-size: 15px;
  font-weight: 600;
  letter-spacing: var(--e-tracking);
}
/* el núcleo del filo sangra hacia dentro: la luz ilumina a sus vecinos */
html[data-epoca="5"] .c-aviso::after{
  background: linear-gradient(90deg,
    color-mix(in oklab, var(--av-color) 20%, transparent) 0%,
    transparent 32%);
}
/* la marca es un nodo de luz, no una pastilla de color */
html[data-epoca="5"] .c-aviso::before{
  box-shadow: 0 0 14px -3px color-mix(in oklab, var(--av-color) 75%, transparent);
}
html[data-epoca="5"] .c-aviso--info::before,
html[data-epoca="5"] .c-aviso:not(.c-aviso--exito):not(.c-aviso--error):not(.c-aviso--info)::before{
  box-shadow:
    inset 0 0 0 2px var(--av-color),
    0 0 12px -4px color-mix(in oklab, var(--av-color) 60%, transparent);
}
/* el error, además del cuadrado y la ×, lleva DOBLE filo: en una sala de mando
   lo grave se ve antes de leerlo, y se ve también sin color. */
html[data-epoca="5"] .c-aviso--error{
  box-shadow:
    inset 3px 0 0 var(--av-color),
    inset 7px 0 0 -1px color-mix(in oklab, var(--av-color) 55%, #FFFFFF),
    inset 9px 0 0 -1px var(--av-color),
    inset 0 1px 0 rgba(255,255,255,.07),
    0 1px 2px rgba(0,0,0,.5);
  padding-left: calc(var(--e-pad-caja) + 11px);
}

/* ENTRADA · seca: 130 ms. La luz sube antes que la caja acabe de colocarse. */
html[data-epoca="5"] .c-aviso.is-nueva{
  animation: av5-entra var(--e-vel) var(--e-curva, cubic-bezier(.22,.61,.36,1));
}
html[data-epoca="5"] .c-aviso.is-nueva::after{
  animation: av5-luz calc(var(--e-vel) * 1.6) var(--e-curva, cubic-bezier(.22,.61,.36,1));
}
@keyframes av5-entra{
  from{ opacity: 0; transform: translateY(-4px); }
  to  { opacity: 1; transform: translateY(0); }
}
@keyframes av5-luz{                  /* el tubo se enciende de golpe y se abre */
  from{ opacity: 0; transform: scaleY(.14); }
  40% { opacity: 1; transform: scaleY(.14); }
  to  { opacity: 1; transform: scaleY(1); }
}


/* ═══════════════════════════════════════════════════════════════════════════
   7 · REDUCED-MOTION — estado final, quieto. Siempre (doctrina §6).
   base.css ya neutraliza duraciones globalmente; esto lo hace explícito y sin
   depender del orden de carga: aquí no queda ni un fotograma que ejecutar.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce){
  .c-aviso,
  .c-aviso::before,
  .c-aviso::after,
  .c-aviso.is-nueva,
  .c-aviso.is-nueva::before,
  .c-aviso.is-nueva::after{
    animation: none !important;
    transition: none !important;
  }
}


/* ═══════════════════════════════════════════════════════════════════════════
   8 · LO MEDIDO (no declarado: calculado sobre el píxel que se pinta)

   MÉTODO: no se mide el token, se mide **el peor píxel que se llega a pintar**.
   Para cada época se compone a mano la pila real de capas (color de fondo →
   degradado → textura con su alfa acotada → sangrados y quemaduras) y se toma
   el extremo que menos contraste deja bajo cada trozo de texto. Tres cifras de
   la primera pasada se cayeron al hacerlo así, y las tres están arregladas
   abajo. Alto y desbordes van medidos en navegador a 390px.

   8.1 · CONTRASTE DE TEXTO — sobre el PEOR píxel de cada superficie
     época       peor píxel bajo el texto     título        cuerpo
     1 · Cueva   #382515 (veta de ocre)       #F2E3D2 11,6  #B99C82  5,6
     2 · Piedra  #26231D (canto iluminado)    #E8E2D5 12,2  #A29985  5,5
     3 · Papel   #E3D9C4 (fibra de trapo)     #1A1714 12,9  #4A423A  7,1
     4 · Hierro  #CEC3AA (pie de la tira)     #14110E 10,8  #4A4238  5,7
     5 · Cabina  #35201 9 (sangrado del filo) #EEF1F6 13,7  #A9B2C0  7,2
   Ningún texto toma nunca el color semántico (§0.5): el peor caso de lectura no
   depende de la variante, y por eso esta tabla vale para las cuatro.

   8.2 · CONTRASTE DE LA MARCA (no es texto → umbral 3:1; todas pasan 4,5:1)
     época      exito              error              info
     1 · Cueva  #DFAC4E  7,0       #EE7C52  4,7 *     #FF6A1F  6,7
     2 · Piedra #A9BE9B  8,0       #E0764B  5,2       #FF8A3D  6,7
     3 · Papel  #1B5334  6,4       #A8321E  4,8       #1A1714 12,9
     4 · Hierro #2C4A2E  5,6       #7E2D10  5,1       #63441B  5,1
     5 · Cabina #FFC08A  8,5       #FF6B6B  5,5       #FF6A1F  5,4
   * la marca del error de la Cueva es la única que se apoya sobre la tierra
     quemada; medida ENCIMA de la quemadura, no al lado (ver §2).
   El glifo invertido sobre la marca maciza no depende del fondo: es la misma
   pareja de colores del revés, y va de 7,1:1 (Cueva) para arriba.

   Tres desvíos, los tres por medición y no por gusto:
     · Papel: `info` NO usa el naranja contenido (#C4551A sobre crema = 3,8:1);
       usa la tinta. La nota al margen del impresor iba en tinta, de todos modos.
     · Hierro: la tira es CLARA, así que los semánticos son las versiones hondas
       de los mismos colores. El filamento #FFB070 sobre manila da 1,6:1 — como
       marca sería un adorno ilegible. Óxido y latón se bajaron además un punto
       (#8E3413→#7E2D10, #6B4A1E→#63441B): sobre el pie del degradado de la tira
       se quedaban en 4,35 y 4,60, demasiado al filo.
     · Cueva: la quemadura del error se confinó al canto (§2) porque a lo ancho
       dejaba el cuerpo en 4,15:1.

   8.3 · CAJA — medida en navegador (390px, título + una línea)
     1 · Cueva 86,1 · 2 · Piedra 82,2 · 3 · Papel 90,1 · 4 · Hierro 84,1 ·
     5 · Cabina 83,9   →  extremos 82,2 ↔ 90,1 = **+9,6 %** (tope del contrato:
     ±20 %). Las subpáginas no se mueven al cambiar de era.

   8.4 · 390px: `document.scrollWidth` = `clientWidth` = 390 en las cinco épocas.
   La rejilla es `auto minmax(0,1fr)`: la columna de texto puede llegar a 0 sin
   desbordar, y la marca nunca encoge (es un canal de accesibilidad, no un
   adorno). La tira del Hierro es la más apretada — 40px de bandas de arrastre,
   `padding-inline` medido 42,3px — y aún deja 264px de columna de texto.

   8.5 · `.is-nueva` NO DEJA RESIDUO — comprobado, no supuesto. En las cinco
   épocas se comparó la huella del aviso (caja, `transform`, `opacity`,
   `clip-path`, y los mismos cuatro del `::before` y del `::after`) en reposo,
   contra la del mismo aviso con `.is-nueva` puesta y sus animaciones llevadas a
   `finish()`. Resultado: **IDÉNTICO en las 5**. Es lo que sostiene la promesa de
   §0.3 — la clase se pone y se olvida, no hay que quitarla.

   8.6 · REDUCED-MOTION: forzando la media query de §7, en las cinco épocas
   quedan **0 animaciones vivas** (`getAnimations({subtree:true}).length === 0`)
   y `animation-name: none` en raíz, `::before` y `::after`. Estado final, quieto.

   8.7 · LA CAMPANA del Hierro, resuelta por el navegador:
     `av4-ranura 0.624s delay 0s` + `av4-campana 0.1392s delay 0.624s ×2`,
     `fill-mode: none` en las dos. Es decir: suena DESPUÉS de que la tira acabe
     de salir (por eso el `transform` de una no se pelea con el de la otra), da
     exactamente dos oscilaciones y se calla. Ni una más, y sin residuo.

   8.8 · Prohibiciones del contrato §3: cero JS · cero recursos remotos (los
   cuatro SVG son `data:` inline; los `url(%23…)` de dentro son referencias a
   filtros del propio SVG) · cero fuentes prohibidas · cero `!important` fuera
   del bloque de reduced-motion · cero selectores que no cuelguen de `.c-aviso`
   · los 15 `@keyframes` van con prefijo `av1-`…`av5-` y no chocan con ningún
   otro del sistema (comprobado contra base, las 5 épocas y las 8 hojas de vida)
   · este fichero no toca base.css, epoca-*.css, vida/*.css ni el muestrario.

   8.9-bis · EL CONTEXTO DE PAPEL (§4) — antes / después, medido en pantalla con
   un `c-boton--fantasma` y un `c-distintivo--acento` compuestos DENTRO del
   aviso, y las mismas dos piezas sueltas sobre la mesa como control:

     pieza                              antes    después   control (mesa)
     c-boton--fantasma dentro            1,03  →  14,91        14,68
     c-distintivo--acento dentro         2,23  →   5,59         6,78
   Sobre el peor píxel del interior de la hoja (#EDE3CF, pie del degradado):
   14,01 y 5,25 — los dos por encima del 4.5. Los controles de la mesa no se
   mueven ni un punto: el contexto se queda dentro de la esquela, que es
   justamente lo que tiene que hacer.

   BYTE-CHECK del arreglo: se compararon las 1.573 propiedades computadas de
   raíz + `::before` + `::after` + caja, en las 3 variantes y el neutro × 5
   épocas (20 avisos), con el bloque puesto y con las 9 declaraciones quitadas
   por CSSOM sobre la misma página. Lo ÚNICO que cambia son esos 9 tokens; **ni
   una sola propiedad de pintado ni una caja se mueven**. Épocas 1, 2, 4 y 5,
   idénticas hasta el último valor. Sale limpio porque los literales de la hoja
   que ya usaba (#F2EAD9 · #1A1714 · #4A423A · #A8321E · #1B5334) son los mismos
   que publica `epoca-3.css`; el bloque no repinta nada, solo da voz de hoja a
   lo que se componga dentro.

   8.9 · DEPENDENCIA CONOCIDA — la época 3 está construida contra el contrato 08
   §1 (taller de noche), que aún no ha aterrizado en `epoca-3.css`. Verificada de
   las dos maneras: sobre el mundo claro de hoy la esquela se sostiene (la sombra
   y el filete la separan del fondo, y su tinta es propia, así que se lee), y
   sobre el taller oscuro simulado es lo que tiene que ser — una cuartilla crema
   encima de la mesa. Cuando el rework entre, este fichero no necesita tocarse:
   por eso las tintas de la hoja son suyas y no de `--e-tinta` (§0.6).

   8.10 · FIX N-TEXTOS (2026-08-13) — el arreglo de §1 (`.c-aviso__texto ~
   .c-aviso__texto{ grid-row:auto; grid-column:2 }`) verificado en banco propio
   (scratchpad, Chrome headless, 608×520, 5 épocas × 4 variantes):
     · (a) título+1 texto y (a) sin título: **0 px de diff** contra el CSS
       anterior en 4/5 épocas (é2,é3,é4,é5); é1 muestra un diff de ≤5/255 por
       canal que es RUIDO DE RENDER del `feTurbulence` de `--av1-moteado` —
       reproducido idéntico comparando el propio fichero ORIGINAL contra sí
       mismo en dos procesos de Chrome distintos (26.860 px, máxΔ=4, mismo
       bbox), o sea: no lo causa este cambio.
     · (c) un `__texto` con 2 `<p>` dentro (la mitigación de esta noche,
       patrón real de `comprar-curso.ejs`/`academia-top.ejs`): **0 px de
       diff** en las 5 épocas — sigue siendo un solo ítem de grid, ajeno al
       selector `~` nuevo.
     · (b) dos `__texto` hermanos: pasa de superpuesto (solapado, ilegible) a
       apilado en las 5 épocas × 4 variantes (20/20). Confirmado con capturas
       visuales de las 5 (scratchpad `shots/single/*/FIXED/*/b.png`) y con el
       `grid` completo de é3 y é5 MIRADO a ojo: título + 2 líneas de
       cuerpo, marca alineada arriba, sello/filo/perforaciones/fisura de cada
       época se estiran solos a la caja más alta (son `%` o `inset`, no un
       alto fijo) sin ningún ajuste en este fichero.
     · Contraste de la fila 3 (nueva): el fix no toca un solo token de color
       — pinta con el mismo `--av-tinta-2` sobre el mismo fondo de la raíz
       que ya mide §8.1. Muestreo de control (texto retirado, protocolo R4,
       columna central de la tarjeta, mediana de la banda para no puntuar un
       trazo decorativo de 1-2 px como la fisura de é2 o el moteado de é1):
       é1 6,6:1 · é2 6,2:1 · é3 7,5:1 · é4 5,7:1 · é5 8,8:1 — todas ≥4,5:1 y a
       menos de una décima de los valores de cuerpo ya documentados en §8.1.
     · 390px: `document.documentElement.scrollWidth === clientWidth === 390`
       en las 5 épocas con el caso (b) apilado dentro.
     · Sintaxis: 123 `{` de apertura fuera de comentarios/strings en el
       fuente = 123 reglas totales por CSSOM (`sheet.cssRules` recursivo,
       incl. `@media`/`@keyframes`) — cuadra, cero reglas perdidas (error 16).
   No se tocó ningún otro fichero del sistema ni el espejo `public/css/epoca/`
   (lo sincroniza la sesión principal al verificar, contrato 13 §0.8).
   ═══════════════════════════════════════════════════════════════════════════ */
