/* V3 · Afiche serigrafía, DORADO (decisión de Jose, 2026-09-20: "probemos en la versión final que sea dorado, pero
   en una versión clara y otra oscura"). The palette lives here and nowhere else: site/js/theme.js reads these custom
   properties back for the brain shader, the cables, the tracts and every 2D canvas, so no colour is written twice.

   LIGHT is the default sheet. The Binance yellow (#F0B90B, read off bnbchain.org) is 1.6:1 on cream, so on this sheet
   it prints only as an AREA (--hot-fill: the flat mark, stamps, the buy button, the LIVE tag) with ink on top (10.5:1);
   anything that is TYPE or a LINE goes in brass. El 2026-09-20 el laton bajo un escalon (Jose: poco contraste en la
   clara): --hot pasa de #a67c00 (3,4:1) a #896900 (4,6:1) y --hot-text de #7a5c00 (5,5:1) a #6b5100 (6,6:1). Con eso
   el caliente se queda de MARCA — rotulos, filetes, sellos y tipo de display — y los DATOS (precios, cantidades, rho)
   se imprimen en tinta, que es lo que se lee en una placa. Same print, two papers: DARK below flips the sheet and
   lets the yellow itself carry type. Lo mide test/contrast_audit.py sobre el DOM real, elemento por elemento. */
:root {
  --paper: #f4f1ea;          /* the sheet */
  --ink: #111111;            /* the first screen: type, halftone, keylines */
  /* el laton pasa 4,5:1 POR SI SOLO y no sujeto a que nunca lleve tipo chico: #8a6a00 medía 4,494 y reprobaba el gate
     por seis milesimas donde el display cae bajo 24 px (la flecha de la cinta a 22 px y los dos .pin a 18 px en
     telefono). #896900 es un caracter de diferencia, invisible a ojo, y mide 4,56. */
  --hot: #896900;            /* the second screen as type and line: brass, 4,56:1 on cream */
  --hot-deep: #6b5100;       /* the same, stepped down where a block inverts */
  --hot-text: #6b5100;       /* hot carrying type under 24 px: 6,6:1 */
  --hot-fill: #f0b90b;       /* the Binance yellow, as an area only */
  --on-hot: #111111;         /* what prints on top of a hot fill */
  --grain: rgba(0,0,0,.045); /* riso grain: dark dots multiplied into the paper */
  --grain-blend: multiply;
  --display: 'League Gothic', Impact, 'Arial Narrow', sans-serif;
  --type: 'Special Elite', 'Courier Prime', monospace;
  --mono: 'Courier Prime', ui-monospace, monospace;
}

/* DARK: the sheet turns black and the first screen becomes bone; the yellow (10.9:1 on black) carries display type
   and areas, and small type steps down to --hot-deep (7.4:1). `gold` stays as an alias so the old links still work. */
[data-ink="dark"], [data-ink="gold"] {
  --paper: #0b0b0b;
  --ink: #f4f1ea;
  --hot: #f0b90b;
  --hot-deep: #c99700;
  --hot-text: #c99700;
  --hot-fill: #f0b90b;
  --on-hot: #0b0b0b;
  --grain: rgba(244,241,234,.05);   /* the grain inverts too: light dots screened over the black */
  --grain-blend: screen;
}
/* UN BLOQUE INVERTIDO IMPRIME AL REVES, en las dos hojas.
   En la CLARA el papel del bloque es la tinta: el laton que lleva tipo cae a 2,5:1 sobre negro, y ahi el unico que
   puede llevar tipo es el amarillo (10,5:1 sobre tinta), que fuera del bloque solo es area — o sea, dentro del bloque
   rige la regla de la hoja oscura. Los FILETES siguen en --hot: son linea, no tipo. */
.strip, #card, .token, .zoo-rules tr.on td { --hot-deep: var(--hot-fill); --hot-text: var(--hot-fill); }
/* an inverted block prints bone on the black page, so the loud gold has to step down inside it and its small type
   goes dark: gold on bone is 1.6:1, unreadable at any size */
[data-ink="dark"] .strip, [data-ink="dark"] #card, [data-ink="dark"] .token, [data-ink="dark"] .zoo-rules tr.on td,
[data-ink="gold"] .strip, [data-ink="gold"] #card, [data-ink="gold"] .token, [data-ink="gold"] .zoo-rules tr.on td { --hot: var(--hot-deep); --hot-text: var(--paper); }

/* ORANGE, the first poster (2026-09-19), kept for the record behind ?ink=orange. Not the product. */
[data-ink="orange"] {
  --paper: #f4f1ea; --ink: #111111; --hot: #ff4a1c; --hot-deep: #ff4a1c; --hot-text: #ff4a1c; --hot-fill: #ff4a1c; --on-hot: #111111;
  --grain: rgba(0,0,0,.045); --grain-blend: multiply;
}

/* the switch in the nav: mono, no box. It reprints the sheet (a reload), because every canvas read the palette once */
.nav .ink { background: none; border: 0; padding: 0; font: inherit; font-family: var(--mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink); cursor: pointer; opacity: .75; }
.nav .ink:hover { opacity: 1; text-decoration: underline; text-decoration-color: var(--hot); text-underline-offset: 3px; }

/* La banda de la nav es opaca desde que se le puso papel, asi que un ancla que aterriza en 0 queda debajo de ella.
   El valor es el alto real de la banda medido en Chrome (56 px; 68 con la marca en su propio renglon bajo 480 px)
   mas 2 px de aire, que es el grueso de su filete. */
html { scroll-padding-top: 58px; }
@media (max-width: 480px) { html { scroll-padding-top: 70px; } }
html, body { margin: 0; background: var(--paper); color: var(--ink); font-family: var(--mono); }
body::before { content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image: radial-gradient(var(--grain) 1px, transparent 1.2px); background-size: 3px 3px; mix-blend-mode: var(--grain-blend); }
/* El cabezal del afiche se imprime sobre su propio papel. Sin fondo la nav era transparente y lo de abajo se imprimia
   encima de ella: medido recorriendo la pagina de media en media pantalla, 24 de 29 paradas en movil tenian texto ajeno
   dentro de la caja de la nav (45 textos distintos) y 9 de 22 en escritorio, mas cinco canvas cruzandola.
   El grano se repite aqui porque la banda tapa la capa de grano de la pagina (z-index 5 contra 0) y el papel tiene que
   seguir siendo el mismo papel; la fase coincide porque las dos cajas arrancan en 0,0 con la misma celda de 3 px.
   La mezcla se va: multiply sobre el bloque negro del token borraria la banda entera. */
.nav { position: fixed; top: 0; left: 0; right: 0; z-index: 5; display: flex; justify-content: space-between; align-items: center; padding: 14px 22px;
  font-family: var(--type); font-size: 14px; letter-spacing: .04em; background-color: var(--paper);
  background-image: radial-gradient(var(--grain) 1px, transparent 1.2px); background-size: 3px 3px;
  border-bottom: 2px solid var(--ink); }
.nav a { color: var(--ink); text-decoration: none; border-bottom: 2px solid transparent; }
.nav a.on, .nav a:hover { border-color: var(--hot); }
.nav .brand { font-family: var(--display); font-size: 22px; letter-spacing: .06em; }

.hero { position: relative; z-index: 1; min-height: 100svh; display: grid; grid-template-columns: 1.05fr 1fr; align-items: stretch; }
.hero .stage { position: relative; min-height: 70svh; }
.hero canvas#brain { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
#labels { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
#labels span { position: absolute; transform: translate(-50%, -50%); font-family: var(--display); font-size: 21px; color: var(--hot-text); letter-spacing: .02em;
  text-shadow: 0 0 3px var(--paper), 0 0 3px var(--paper), 0 0 6px var(--paper); }
#labels span.hot { color: var(--paper); font-size: 22px; text-shadow: 0 0 3px var(--ink); }

.hero .copy { position: relative; padding: 11svh 5vw 6svh 2vw; display: flex; flex-direction: column; justify-content: center; }
.word { font-family: var(--display); font-weight: 400; font-size: clamp(88px, 15.5vw, 236px); line-height: .82; margin: 0 0 .06em -.02em; letter-spacing: -.005em; color: var(--ink);
  text-shadow: 3px 0 0 var(--hot); }
.tag { font-family: var(--display); font-size: clamp(34px, 4.6vw, 66px); line-height: .92; color: var(--hot); margin: .1em 0 .35em; letter-spacing: .01em; }
.sub { font-family: var(--type); font-size: clamp(14px, 1.15vw, 18px); max-width: 44ch; margin: 0 0 1.4em; }
.strip { display: inline-block; background: var(--ink); color: var(--paper); font-family: var(--display); font-size: clamp(26px, 3vw, 42px); padding: .18em .6em .1em;
  transform: rotate(-1.4deg); clip-path: polygon(0 6%, 3% 0, 98% 3%, 100% 94%, 96% 100%, 2% 97%); letter-spacing: .04em; align-self: flex-start; }
.strip span { border-bottom: 3px solid var(--hot); }
.live { font-family: var(--mono); font-size: 12px; margin-top: 2.2em; text-transform: uppercase; letter-spacing: .08em; }
.live b { font-weight: 400; color: var(--hot-text); }

.pulse { position: relative; z-index: 1; border-top: 4px solid var(--ink); padding: 5vh 4vw 8vh; }
.phead h2 { font-family: var(--display); font-size: clamp(64px, 10vw, 150px); line-height: .85; margin: 0; letter-spacing: .005em; text-shadow: 3px 0 0 var(--hot); }
.phead .sub { font-family: var(--type); font-size: clamp(15px, 1.2vw, 19px); max-width: 62ch; margin: .8em 0 2em; }
.pgrid { display: grid; grid-template-columns: 300px 1fr 300px; gap: 3vw; align-items: start; }
.ticket { border: 2px dashed var(--ink); padding: 14px 16px; background: var(--paper); font-family: var(--type); font-size: 13px; line-height: 1.5;
  position: relative; }
.ticket::before, .ticket::after { content: ''; position: absolute; top: -1px; bottom: -1px; width: 10px; background: radial-gradient(circle, var(--paper) 45%, transparent 47%) 0 0/10px 10px; }
.ticket::before { left: -6px; } .ticket::after { right: -6px; }
.ticket ol { list-style: none; margin: 0; padding: 0; }
.ticket li { padding: 8px 0; border-bottom: 1px dashed var(--ink); text-transform: uppercase; }
.ticket li:last-child { border: 0; }
.ticket li em { font-style: normal; color: var(--hot-text); }
.ticket li small { display: block; opacity: .6; }
/* LA PRIMERA COLUMNA DE BLOCK PULSE: el atlas chico golpeado por el bloque, y debajo el ticket. Se lee de arriba abajo
   bloque -> region encendida en el atlas -> la fila que se mueve en el raster. */
.pcol { display: grid; gap: 20px; align-content: start; }
.pulse-atlas canvas { display: block; width: 100%; height: 230px; }
.pulse-atlas b { display: block; font-family: var(--display); font-weight: 400; font-size: clamp(22px, 2.2vw, 32px); line-height: 1; letter-spacing: .02em; color: var(--ink);
  border-top: 2px solid var(--ink); padding-top: 8px; }
/* the block ticket: three rows of one height (2 lines of data + up to 2 of region name), reserved before the first block lands,
   so nothing below moves as blocks arrive. Six of them made the column twice as tall as the raster once the atlas went on top. */
#ticker { min-height: calc(3 * (6em + 16px) + 5px); }
#ticker li { min-height: 6em; box-sizing: content-box; }
.chart { position: relative; height: 420px; border: 2px solid var(--ink); background: var(--paper); }
.chart canvas { width: 100%; height: 100%; display: block; }
.chart .axis { position: absolute; left: 6px; top: 4px; bottom: 4px; display: flex; flex-direction: column; justify-content: space-between; font-size: 11px; font-family: var(--type); }
.meters .stamp { border: 3px solid var(--hot); color: var(--hot-text); padding: 8px 12px 10px; margin-bottom: 12px; transform: rotate(-1deg); font-family: var(--type); }
.meters .stamp small { display: block; font-size: 12px; letter-spacing: .1em; }
/* los dos sellos rho son DATO, en la portada y en el tablero de /pulse: el numero va en TINTA y el caliente se queda
   en el borde del sello y en su rotulo. Era --hot a 40 px: pasaba el 3:1 de texto grande y se leia lavado igual. */
.meters .stamp b { font-family: var(--display); font-size: 40px; font-weight: 400; line-height: 1; color: var(--ink); }
.meters .rule { font-family: var(--display); font-size: 22px; line-height: 1.05; margin-top: 18px; text-transform: uppercase; letter-spacing: .01em; }
.meters .rule span { color: var(--hot-text); }

#card { position: fixed; left: 22px; bottom: 22px; z-index: 6; background: var(--ink); color: var(--paper); font-family: var(--type); font-size: 13px; padding: 12px 14px; max-width: 320px; display: none; }
#card b { font-family: var(--display); font-size: 26px; font-weight: 400; color: var(--hot-text); display: block; letter-spacing: .02em; }
#boot { position: fixed; inset: 0; display: grid; place-items: center; font-family: var(--type); font-size: 13px; letter-spacing: .04em; text-transform: uppercase; }

/* sections below the fold: wood-type headline, typewriter body */
.wood { font-family: var(--display); font-weight: 400; font-size: clamp(56px, 9vw, 140px); line-height: .85; margin: 0 0 .3em; letter-spacing: .005em; text-shadow: 3px 0 0 var(--hot); }
.what, .experiments { position: relative; z-index: 1; border-top: 4px solid var(--ink); padding: 6vh 4vw 8vh; }

/* THE WIRES: plate on the left, cut-chart legend on the right */
.wires { position: relative; z-index: 1; border-top: 4px solid var(--ink); padding: 6vh 4vw 8vh; }
.wires .sub { font-family: var(--type); font-size: clamp(15px, 1.2vw, 19px); max-width: 62ch; margin: .8em 0 2em; }
.wgrid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 3vw; align-items: start; }
.wires .stage { position: relative; aspect-ratio: 1 / 1; border: 2px solid var(--ink); background: var(--paper); }
.wires .stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: pan-y; cursor: grab; }
.wires .stage canvas:active { cursor: grabbing; }
.wires .pin { position: absolute; left: 12px; bottom: 8px; margin: 0; font-family: var(--display); font-size: 26px; line-height: 1; color: var(--hot); letter-spacing: .02em; text-transform: uppercase; pointer-events: none; min-height: 1em; }
.legend { columns: 2; column-gap: 2vw; list-style: none; margin: 0; padding: 0; font-family: var(--type); font-size: 13px; line-height: 1.35; }
.legend li { padding: 4px 0; border-bottom: 1px dashed var(--ink); cursor: pointer; break-inside: avoid; }
.legend li.g { border: 0; cursor: default; padding: 0; break-after: avoid; }
.legend li code { font-family: var(--mono); font-size: 11px; letter-spacing: .04em; margin-right: 4px; opacity: .7; }
.legend li:hover, .legend li.on { color: var(--hot-text); }
.legend li.on { border-bottom-color: var(--hot); }
.legend li.on code { opacity: 1; }
.legend b { font-family: var(--display); font-weight: 400; font-size: 22px; display: block; margin-top: 10px; letter-spacing: .04em; }
.legend li.g:first-child b { margin-top: 0; }

/* THE SCANS: the film is pinned right after the hero and the scroll moves through the head, slice by slice. Back on
   2026-09-20 at Jose's request, on its own (ONE BRAIN, TEN BRAINS, PRIMATES and the cut chart stay out) and full
   bleed: the plate runs the whole height of the viewport and off its right edge, the type sits on the paper beside
   it. The four dangling declarations 6616dd2 left here are gone; the first one was eating the .exp rule. */
.scans { position: relative; z-index: 1; border-top: 4px solid var(--ink); }
.scrub { display: grid; grid-template-columns: minmax(24ch, 1fr) 1.45fr; grid-template-rows: 1fr auto; gap: 0 3vw; box-sizing: border-box; height: 100svh; padding: 0 0 0 4vw; overflow: hidden; }
.shead { grid-column: 1; grid-row: 1; align-self: center; }
.shead .wood { margin-bottom: .2em; }
.shead .sub { font-family: var(--type); font-size: clamp(15px, 1.2vw, 19px); max-width: 40ch; margin: 0; }
.film { position: relative; grid-column: 2; grid-row: 1 / span 2; height: 100svh; border-left: 2px solid var(--ink); background: var(--paper); box-sizing: border-box; }
.film canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* the slice number rides under the headline, never over the plate: the section sits in the middle of the film and any
   label inside the box lands on top of it */
.film-label { grid-column: 1; grid-row: 2; align-self: end; margin: 0 0 6svh; font-family: var(--display); font-size: clamp(30px, 3.6vw, 58px); line-height: 1; color: var(--hot); letter-spacing: .02em; }
.film input[type=range] { position: absolute; right: 20px; bottom: 20px; width: min(46%, 280px); margin: 0; appearance: none; -webkit-appearance: none; height: 3px; background: var(--ink); accent-color: var(--hot); outline-offset: 6px; }
.film input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; background: var(--hot); border: 2px solid var(--ink); border-radius: 0; cursor: pointer; }
.film input[type=range]::-moz-range-thumb { width: 12px; height: 12px; background: var(--hot); border: 2px solid var(--ink); border-radius: 0; cursor: pointer; }
.film input[type=range][hidden] { display: none; }
.wood.small { font-size: clamp(34px, 5vw, 64px); }

/* EXPERIMENTS es un LIBRO DE RESULTADOS: una fila por experimento, numero, nombre, la pregunta, el sello y el link.
   Eran seis tarjetas con un badge en la esquina, o sea la grilla de features de cualquier landing. */
.exp { list-style: none; margin: 24px 0 0; padding: 0; border-top: 1px solid var(--ink); }
.exp li { display: grid; grid-template-columns: 2.6em minmax(170px, 22%) 1fr auto 5em; gap: 2vw; align-items: baseline; padding: 14px 0 16px; border-bottom: 1px solid var(--ink); font-family: var(--type); font-size: 13px; line-height: 1.5; }
.exp .n { font-family: var(--display); font-size: 22px; color: var(--hot-text); }
.exp li h3 { font-family: var(--display); font-weight: 400; font-size: clamp(28px, 3vw, 44px); line-height: .9; margin: 0; letter-spacing: .02em; }
.exp li p { margin: 0; max-width: 60ch; }
.exp li a { color: var(--ink); text-decoration: none; border-bottom: 2px solid var(--hot); text-transform: uppercase; letter-spacing: .08em; font-size: 12px; justify-self: end; }
.exp .stamp { justify-self: end; border: 3px solid var(--hot); color: var(--hot-text); font-family: var(--display); font-size: 20px; line-height: 1; padding: 2px 8px; transform: rotate(-2deg); background: var(--paper); letter-spacing: .04em; white-space: nowrap; }
.exp .stamp.na { border-color: var(--ink); color: var(--ink); }

.token { position: relative; z-index: 1; background: var(--ink); color: var(--paper); padding: 8vh 4vw; }
.token .wood { text-shadow: 3px 0 0 var(--hot); }
.ca { display: flex; flex-wrap: wrap; align-items: center; gap: 18px 28px; margin: 0 0 32px; }
.ca code { font-family: var(--mono); font-size: clamp(16px, 2.2vw, 34px); letter-spacing: .01em; overflow-wrap: anywhere; }
.ca button { font-family: var(--display); font-size: 22px; letter-spacing: .06em; background: transparent; color: var(--paper); border: 3px solid var(--paper); padding: 4px 14px; cursor: pointer; }
.ca button:disabled { opacity: .35; cursor: default; }
.buy { background: var(--hot-fill); color: var(--on-hot); font-family: var(--display); font-size: 28px; padding: 6px 18px; text-decoration: none; letter-spacing: .04em; }
.buy[aria-disabled="true"] { opacity: .35; pointer-events: none; }
.tk { border-collapse: collapse; font-family: var(--type); font-size: 14px; width: min(100%, 720px); }
/* baseline, no top: el rotulo va a 12 px y el dato a 14 px de mono, asi que alineando las cajas por arriba la primera
   linea del dato caia 4 px mas abajo que la del rotulo en toda la tabla. */
.tk th, .tk td { text-align: left; padding: 8px 24px 8px 0; border-bottom: 1px dashed var(--paper); vertical-align: baseline; }
.tk th { font-weight: 400; text-transform: uppercase; letter-spacing: .08em; font-size: 12px; opacity: .7; white-space: nowrap; }
.tk td { font-family: var(--mono); }
.tk a { color: var(--hot-text); border-bottom: 2px solid var(--hot); text-decoration: none; }
.token .fine { font-family: var(--type); font-size: 13px; line-height: 1.5; opacity: .8; margin: 20px 0 0; max-width: 60ch; }


footer { position: relative; z-index: 1; border-top: 4px solid var(--ink); padding: 4vh 4vw 8vh; font-family: var(--type); font-size: 13px; line-height: 1.6; }
footer p { margin: 0 0 .8em; max-width: 110ch; }
/* what is not real, in one line: the section is gone (Jose, 2026-09-19) and this is the whole of it that stays */
footer .fine { font-size: 12px; line-height: 1.5; opacity: .8; }
footer a { color: var(--ink); border-bottom: 2px solid var(--hot); text-decoration: none; }

/* motion (spec section 6): a reveal is invisible only while the page can animate it (html.js is set by main.js once GSAP is
   here and motion is not reduced); without JS, without GSAP, in a crawler or a screenshot everything is simply printed */
.reveal { opacity: 1; }
html.js .reveal { opacity: 0; }

/* A SECOND SENSE: BINANCE */
/* la cabeza del mono al lado del titular de la seccion. Es lo unico de la pagina que es un modelo y no un dato,
   y el pie de la figura lo dice. */
.aperow { display: grid; grid-template-columns: .95fr 1.05fr; gap: 3vw; align-items: center; margin-bottom: 2vh; }   /* el animal entero pesa mas que la cabeza: media hoja */
.ape { margin: 0; }
/* EL RECINTO, COMPACTO: una VENTANA con su filete de 3 px en tinta en los cuatro lados, de la misma familia que la
   placa de abajo (`.placard`, tambien 3 px). Tenia una sola linea de piso de 1 px y la plancha se fundia con el
   papel ("el cuadro donde esta el mono me gustaria mas con un borde o algo porque choca mucho con el background",
   Jose 2026-09-21). El piso del animal ahora es el lado de abajo del marco. `box-sizing: border-box` mantiene el
   cuadrado y el lienzo y la plancha viven adentro del filete (`inset: 0` cae en la caja de relleno). En la hoja
   oscura --ink ya es hueso: el marco cambia de tinta solo. */
.ape-stage { position: relative; aspect-ratio: 1 / 1; border: 3px solid var(--ink); background: var(--paper); box-sizing: border-box; cursor: grab; }
.ape-stage .zoo-plate { position: absolute; inset: 0; }
/* EL PIE DEL ANIMAL, CON JERARQUIA Y AIRE. Las cuatro piezas eran cuatro renglones apretados uno contra otro y el
   nombre de la region colgaba del final del parrafo ("esos mensajes de animacion parecen comprimidos cuando podria
   verse mejor", Jose 2026-09-21): el acto es el titular, la firma el rotulo chico que lo fecha, la region su propio
   renglon y el parrafo el texto fijo. Mismo idioma del afiche: sin cajas, sin sombras, solo espacio. */
.ape figcaption .zoo-act { display: block; font-family: var(--display); font-weight: 400; font-size: clamp(30px, 3.2vw, 48px); line-height: .95; letter-spacing: .01em; margin: 14px 0 6px; }
/* la firma partia en dos renglones a .1em y quedaba apretada contra el acto y contra el parrafo: baja a .08em, se
   le da interlinea de rotulo (1.7) y el aire va debajo, separandola del bloque de texto */
.ape figcaption .zoo-why { display: block; font-family: var(--mono); font-size: 11px; letter-spacing: .08em; line-height: 1.7; text-transform: uppercase; margin: 0 0 12px; }
.ape figcaption .zoo-why b { font-weight: 400; color: var(--hot-text); }
/* el parrafo fijo: su propio bloque, para que el aire de abajo no dependa de la fila de sellos */
.ape figcaption p { margin: 0 0 14px; }
.ape-stage:active { cursor: grabbing; }
.ape-stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: pan-y; }
.ape figcaption { font-family: var(--type); font-size: 12px; line-height: 1.55; margin-top: 8px; max-width: 52ch; }
/* el unico link de la pagina que nunca tuvo regla y salia en el azul del navegador (viene asi de a65e4e7). Habla el
   idioma de los links de la casa, el del pie: tinta con el subrayado en caliente. Se arregla desde aca, sin tocar el
   markup del recinto. */
.ape figcaption a { color: var(--ink); border-bottom: 2px solid var(--hot); text-decoration: none; }
.senses { position: relative; z-index: 1; border-top: 4px solid var(--ink); padding: 6vh 4vw 8vh; }
.senses .sub { font-family: var(--type); font-size: clamp(15px, 1.2vw, 19px); max-width: 62ch; margin: .8em 0 1.6em; }
/* la cinta corre por el borde de arriba de la placa, en una ventana entre los dos tornillos de arriba: a sangre, el
   precio de turno caia justo encima de una cabeza de tornillo y la tapaba */
.tape { overflow: hidden; padding: 8px 0; margin: 0 34px; }
.tape-inner { display: flex; gap: 2.2em; white-space: nowrap; font-family: var(--display); font-size: clamp(22px, 2.6vw, 38px); line-height: 1; letter-spacing: .02em; animation: tape 28s linear infinite; will-change: transform; }
.tape-inner:empty::before { content: 'waiting for the first BNB / USDT trade'; font-family: var(--type); font-size: 14px; opacity: .6; }
/* EL DATO EN TINTA, EL CALIENTE SOLO MARCA: el precio y la cantidad se imprimen en tinta en los dos sentidos y lo
   unico que cambia de color es la flecha — ▲ en caliente, ▼ en tinta. Antes la mitad compradora de la cinta entera
   iba en laton a 3,4:1 y era la tira que mas se veia lavada del afiche. `.up` / `.dn` siguen en el span: son el dato
   del sentido, los lee senses.js y no solo el color. */
.tape-inner span { flex: none; color: var(--ink); }
.tape-inner .mark { font-style: normal; color: var(--ink); }
.tape-inner span.up .mark { color: var(--hot); }
.tape-inner small { font-family: var(--type); font-size: .45em; letter-spacing: 0; opacity: .75; }
/* La cinta viaja UNA copia exacta, no la mitad de la tira. Con 2n items (n repetidos dos veces) el ancho total es
   2S + (2n-1)g, asi que el 50 % cae medio hueco antes del comienzo de la segunda copia: el periodo verdadero es
   50 % + g/2. Antes la cinta imprimia 40 trades distintos y viajaba el 50 %, o sea que en el empalme la tira se
   reemplazaba entera. */
@keyframes tape { from { transform: translateX(0); } to { transform: translateX(calc(-50% - 1.1em)); } }
/* LA PLACA DEL RECINTO. Una sola chapa: filete grueso, cuatro cabezas de tornillo y la cinta de precios corriendo por
   su borde de arriba. Antes eran tres piezas de texto sueltas (la cinta, una fila de cuatro numeros que es la fila de
   KPI de cualquier plantilla, y dos tarjetas): el dato es el mismo, las piezas sueltas eran el molde. Los datos van en
   TINTA y el caliente solo rotula: en una placa de zoologico lo que se lee es el dato. */
.placard { position: relative; border: 3px solid var(--ink); background: var(--paper); margin: 0 0 3vh; padding: 0 0 34px; }
/* las cuatro cabezas de tornillo: dos en la banda de la cinta (sobre ella, como una chapa atornillada encima del
   tablero) y dos en el borde de abajo. Son los unicos circulos del afiche junto a los de FOOTPRINT. */
.placard::before, .placard::after, .pnotes::before, .pnotes::after { content: ''; position: absolute; width: 9px; height: 9px; border: 2px solid var(--ink); border-radius: 50%; }
.placard::before { top: 13px; left: 13px; } .placard::after { top: 13px; right: 13px; }
.pnotes::before { bottom: -22px; left: 13px; } .pnotes::after { bottom: -22px; right: 13px; }
.plate-head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding: 12px 40px 10px; border-top: 3px solid var(--ink); border-bottom: 3px solid var(--ink); }
.plate-head h3 { font-family: var(--display); font-weight: 400; font-size: clamp(26px, 2.6vw, 38px); line-height: 1; letter-spacing: .03em; margin: 0; }
.plate-head span { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--hot-text); white-space: nowrap; }
/* WP15b: el rotulo de los tres sentidos, bajo la cabecera de la chapa. Mismo cuerpo que los rotulos de las lineas
   (mono 11 px espaciado) pero en TINTA: es lo que nombra de donde sale cada renglon de abajo, no un dato. */
.plabel { margin: 0; padding: 8px 40px 0; font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink); }
/* las lineas de la placa: rotulo a la izquierda en caliente, dato a la derecha en tinta, un filete por renglon */
.plines { margin: 0; }
.plines > div { display: grid; grid-template-columns: minmax(150px, 24%) 1fr; gap: 2vw; align-items: baseline; padding: 9px 40px 10px; border-bottom: 1px solid var(--ink); }
.plines dt { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--hot-text); }
.plines dd { margin: 0; font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink); }
.plines dd b { font-family: var(--display); font-weight: 400; font-size: clamp(32px, 3.4vw, 50px); line-height: .9; color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: .01em; }
/* LAST SENSE no es una cifra, es una frase de aparato (L.INS · 88 · amp 0.62): entra en display pero un cuerpo abajo */
.plines .last dd b { font-size: clamp(22px, 2.2vw, 32px); }
.senses .live { font-family: var(--mono); font-size: 12px; text-transform: uppercase; letter-spacing: .08em; margin: 0; padding: 10px 40px 0; }
/* el estado del stream es tipo de 12 px: va en el caliente de tipo chico, no en el de display (--hot a 12 px medía 3,4:1) */
.senses .live b { font-weight: 400; color: var(--hot-text); }
/* el texto chico de la placa: las dos notas, en dos columnas */
.pnotes { position: relative; display: grid; grid-template-columns: 1fr 1fr; gap: 3vw; padding: 14px 40px 0; }
.pnotes h3 { font-family: var(--display); font-weight: 400; font-size: 24px; line-height: 1; letter-spacing: .02em; margin: 0 0 .4em; }
.pnotes .note { margin: 0 0 .7em; font-family: var(--type); font-size: 13px; line-height: 1.5; }
.pnotes a { font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--hot-text); text-decoration: none; border-bottom: 2px solid var(--hot); word-break: break-word; }
/* WHAT IT IS: un colofon (cosa viva | termino | definicion | referencia) con filetes. Eran tres tarjetas en fila; despues
   fue texto bien tipografiado, que sigue siendo una plantilla. Cada fila tiene ahora SU objeto a la izquierda: el atlas
   girando, dos osciladores del motor escribiendo y el ultimo bloque impreso como ticket. El objeto esta en el DOM
   despues del <dt> (un div dentro de un dl solo admite dt y dd) y la grilla lo manda a la primera columna. */
.colophon { margin: 0; border-top: 1px solid var(--ink); }
.colophon > div { display: grid; grid-template-columns: 200px minmax(170px, 22%) 1fr minmax(150px, 20%); gap: 2vw; align-items: baseline; padding: 18px 0 20px; border-bottom: 1px solid var(--ink); }
.colophon dt { grid-column: 2; font-family: var(--display); font-weight: 400; font-size: clamp(30px, 3.2vw, 48px); line-height: .9; letter-spacing: .02em; }
.colophon dd { margin: 0; font-family: var(--type); font-size: 14px; line-height: 1.5; max-width: 64ch; }
.colophon .def { grid-column: 3; }
.colophon .ref { grid-column: 4; font-family: var(--mono); font-size: 11px; text-align: right; }
.colophon .ref a { color: var(--hot-text); text-decoration: none; border-bottom: 2px solid var(--hot); word-break: break-word; }
.colophon .obj { grid-column: 1; grid-row: 1; align-self: start; max-width: none; }
.colophon .obj canvas { display: block; width: 200px; }
#what-atlas { height: 200px; }
#what-trace { height: 120px; border-bottom: 1px solid var(--ink); }
.obj-cap { display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--hot-text); text-align: right; width: 200px; padding-top: 4px; }
/* el ultimo bloque, impreso como el ticket de BLOCK PULSE y con la misma marca de llegada */
.obj-ticket { list-style: none; margin: 0; padding: 12px 12px 12px 10px; border: 2px dashed var(--ink); background: var(--paper); font-family: var(--type); font-size: 11px; line-height: 1.45; text-transform: uppercase; }
.obj-ticket:empty::before { content: 'waiting for the next block'; opacity: .6; }
.obj-ticket li { border-left: 3px solid transparent; padding-left: 8px; }
.obj-ticket li em { font-style: normal; color: var(--hot-text); }
.obj-ticket li small { display: block; opacity: .6; text-transform: none; }
.obj-ticket li.new { border-left-color: var(--hot); animation: fresh .5s linear 2; }
/* prendido / apagado duro, sin degradado entre medio: es un sello que llega, no un fundido */
@keyframes fresh { 0%, 49% { border-left-color: var(--hot); } 50%, 100% { border-left-color: transparent; } }

@media (prefers-reduced-motion: reduce) {
  .tape-inner { animation: none; }
  .reveal { opacity: 1 !important; transform: none !important; }
  .ticket li.new, .nav a { transition: none; }
  .obj-ticket li.new { animation: none; }
  html:focus-within { scroll-behavior: auto; }
}

/* error states (spec section 8): the still stands where the live brain would be, with its note; the quiet-feed lines reuse .live */
.stage img.still { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* main.js / pulse.js mark the stage `printed`: the still is contained, then scaled so the brain (62 % of the still's width) fills the
   stage the way the live fit does; the stage clips the transparent margins so nothing scrolls sideways. <noscript> keeps cover. */
.stage.printed { overflow: hidden; }
.stage.printed img.still { object-fit: contain; transform: scale(1.55); }
.stage .nogl { position: absolute; left: 22px; right: 22px; bottom: 16px; margin: 0; font-family: var(--type); font-size: 13px; letter-spacing: .04em; text-transform: uppercase; }
.stage .nogl::before { content: ''; display: inline-block; width: 10px; height: 10px; background: var(--hot); margin-right: 8px; vertical-align: 0; }
.board .stage .nogl { bottom: 44px; }

/* /pulse: the board (the live brain and the seal), the strip (ticket + aired chart), FOOTPRINT */
.nav a.brand { border: 0; }
.board { position: relative; z-index: 1; display: grid; grid-template-columns: 1.15fr 1fr; gap: 2vw; align-items: stretch; min-height: 100svh; padding: 0 4vw 0 0; box-sizing: border-box; }
.board .stage { position: relative; min-height: 72svh; }
.board .stage canvas#brain { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }
.board .stage .live { position: absolute; left: 22px; bottom: 16px; margin: 0; pointer-events: none; }
.board .meters { display: flex; flex-direction: column; justify-content: center; padding: 11svh 0 6svh; }
.board .meters .wood { font-size: clamp(56px, 7vw, 110px); margin-bottom: .15em; }
.board .meters .sub { font-family: var(--type); font-size: clamp(14px, 1.1vw, 17px); max-width: 48ch; margin: 0 0 1.6em; }
.stamp.big { display: inline-block; align-self: flex-start; border: 5px solid var(--hot); color: var(--hot); font-family: var(--display); font-size: clamp(64px, 7.5vw, 124px); line-height: .9;
  padding: .1em .35em .04em; letter-spacing: .04em; transform: rotate(-2deg); margin: 0 0 .35em; background: var(--paper); }
.stamp.big.passed { background: var(--hot-fill); color: var(--on-hot); border-color: var(--hot-fill); }
.stamp.big.failed { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.board .meters .rule { margin: 0 0 22px; max-width: 30ch; }
.board .pair { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; max-width: 460px; }
.board .pair .stamp { margin: 0; }
.board .meters .fine { font-family: var(--mono); font-size: 13px; letter-spacing: .04em; text-transform: uppercase; margin: 14px 0 0; }
.board .meters .fine span { color: var(--hot-text); }
.strip2 { position: relative; z-index: 1; border-top: 4px solid var(--ink); padding: 5vh 4vw 6vh; display: grid; grid-template-columns: 320px 1fr; gap: 3vw; align-items: stretch; }
.pulse-page #ticker { min-height: calc(12 * (4.35em + 15px)); font-size: 12px; }
.pulse-page #ticker li { min-height: 4.35em; padding: 7px 0; line-height: 1.45; }
.pulse-page #ticker li small { line-height: 1.3; }
.chart.tall { height: auto; min-height: 520px; }
.chart .note { position: absolute; right: 8px; bottom: 6px; font-family: var(--type); font-size: 11px; letter-spacing: .04em; text-transform: uppercase; background: var(--paper); padding: 1px 4px; }
.fp { position: relative; z-index: 1; border-top: 4px solid var(--ink); padding: 6vh 4vw 8vh; }
.fp .sub { font-family: var(--type); font-size: clamp(15px, 1.2vw, 19px); max-width: 62ch; margin: .8em 0 2em; }
.fpgrid { display: grid; grid-template-columns: minmax(0, 720px) 1fr; gap: 3vw; align-items: start; }
.fp canvas { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; border: 2px solid var(--ink); box-sizing: border-box; background: var(--paper); }
.fpside .fine { font-family: var(--type); font-size: 13px; line-height: 1.5; margin: 0 0 12px; max-width: 40ch; }
.fpside .fine span { color: var(--hot-text); }
.fp button { font-family: var(--display); font-size: 26px; letter-spacing: .06em; background: transparent; color: var(--ink); border: 3px solid var(--ink); padding: 6px 18px; cursor: pointer; margin-top: 8px; }
.fp button:hover, .fp button:focus-visible { color: var(--hot); border-color: var(--hot); outline: 0; }

/* /lab: the results board. One block per experiment: wood headline with its stamp, the rule as written, the file and date,
   then the figures (halftone heatmaps, stipple scatter, the null, two small brains on their data layers) and typewriter numbers */
.labhead { position: relative; z-index: 1; padding: 16svh 4vw 4vh; }
.labhead .wood { font-size: clamp(88px, 14vw, 220px); margin-bottom: .12em; }
.labhead .sub { font-family: var(--type); font-size: clamp(15px, 1.2vw, 19px); max-width: 62ch; margin: 0 0 1em; }
.labhead .fine, .lab .fine { font-family: var(--type); font-size: 13px; line-height: 1.5; margin: 0 0 10px; max-width: 70ch; }
.lab { position: relative; z-index: 1; border-top: 4px solid var(--ink); padding: 6vh 4vw 8vh; }
.lhead { display: grid; grid-template-columns: 1fr auto; gap: 2vw; align-items: end; margin-bottom: 3vh; }
.lhead .wood { margin-bottom: 0; }
.kicker { font-family: var(--type); font-size: 13px; letter-spacing: .12em; text-transform: uppercase; margin: 0 0 8px; }
.lab .stamp.big { font-size: clamp(40px, 5vw, 84px); margin: 0 0 .1em; }
.lab .stamp.big.mapped { border-color: var(--ink); color: var(--ink); background: var(--paper); }
.lab .rule { font-family: var(--display); font-size: clamp(20px, 2vw, 30px); line-height: 1.05; text-transform: uppercase; letter-spacing: .01em; margin: 0 0 12px; max-width: 70ch; }
.lab .rule span { color: var(--hot-text); }
.lab .file { font-family: var(--mono); font-size: 12px; letter-spacing: .04em; margin: 0 0 22px; max-width: 110ch; }
.lab .file span { color: var(--hot-text); }
.lab .sub { font-family: var(--type); font-size: clamp(14px, 1.1vw, 17px); max-width: 68ch; margin: 0 0 3vh; }
.lab .note { font-family: var(--type); font-size: clamp(17px, 1.6vw, 24px); line-height: 1.3; margin: 4vh 0 0; max-width: 46ch; padding-left: 18px; border-left: 6px solid var(--hot); }
.maps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2vw; margin: 0 0 4vh; }
.maps figure, .e2grid figure { margin: 0; }
.hm { position: relative; aspect-ratio: 1 / 1; border: 2px solid var(--ink); background: var(--paper); box-sizing: border-box; overflow: hidden; cursor: crosshair; }
.hm canvas, .plot canvas { display: block; width: 100%; height: 100%; }
/* the reading cursor of the three maps: two hot rules at --x / --y, printed over the plate, never on the canvas (redrawing
   244 x 244 dots on every pointer move is not free and the crosshair has to be crisp) */
.hair { position: absolute; inset: 0; pointer-events: none; opacity: 0; }
.hair.on { opacity: 1; }
.hair::before, .hair::after { content: ''; position: absolute; background: var(--hot); }
.hair::before { left: var(--x); top: 0; bottom: 0; width: 2px; margin-left: -1px; }
.hair::after { top: var(--y); left: 0; right: 0; height: 2px; margin-top: -1px; }
.hair.vert::after { display: none; }
.hair.held::before, .hair.held::after { background: var(--ink); }
.dot { position: absolute; width: 16px; height: 16px; margin: -8px 0 0 -8px; left: var(--x); top: var(--y); border: 2px solid var(--hot); border-radius: 50%;
  box-sizing: border-box; pointer-events: none; opacity: 0; }
.dot.on { opacity: 1; }
.probe { font-family: var(--mono); font-size: 13px; line-height: 1.5; margin: -2vh 0 4vh; border-top: 2px solid var(--ink); padding-top: 8px; min-height: 2.6em; }
.probe b { font-weight: 700; color: var(--hot-text); }
.probe em { font-style: normal; color: var(--hot-text); }
.probe span { opacity: .7; }
.probe.small { font-size: 12px; margin: 8px 0 0; min-height: 3.4em; }
.plot { cursor: crosshair; }
.lab figcaption { font-family: var(--type); font-size: 12px; line-height: 1.45; margin-top: 8px; }
.lab figcaption b { font-family: var(--display); font-weight: 400; font-size: 20px; letter-spacing: .04em; display: block; line-height: 1; margin-bottom: 2px; }
.e2grid { display: grid; grid-template-columns: 1.2fr 1fr; gap: 3vw; align-items: start; }
.plot { position: relative; border: 2px solid var(--ink); background: var(--paper); box-sizing: border-box; }
.e2grid .sc .plot { aspect-ratio: 4 / 3; }
.e2grid .null .plot { aspect-ratio: 3 / 1; }
.e2grid .null { margin-top: 22px; }
.num { border-collapse: collapse; font-family: var(--type); font-size: 13px; width: 100%; }
.num th, .num td { text-align: left; padding: 7px 14px 7px 0; border-bottom: 1px dashed var(--ink); vertical-align: top; }
.num th { font-weight: 400; text-transform: uppercase; letter-spacing: .08em; font-size: 11px; opacity: .7; }
.num td { font-family: var(--mono); }
.num thead th { padding-bottom: 4px; }
.num td b { font-family: var(--display); font-weight: 400; font-size: 20px; color: var(--hot-text); line-height: 1; }
.num td small { display: block; font-family: var(--type); opacity: .7; font-size: 11px; }
.num tr:last-child td { border-bottom: 0; }
.e3grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3vw; align-items: start; }
.e3grid .fig { margin: 0; }
.e3grid .stage { position: relative; aspect-ratio: 1 / 1; border: 2px solid var(--ink); background: var(--paper); box-sizing: border-box; }
.e3grid .stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: pan-y; cursor: grab; }
.e3grid .stage canvas:active { cursor: grabbing; }
.e3grid .pin { position: absolute; left: 12px; bottom: 8px; margin: 0; font-family: var(--display); font-size: clamp(18px, 1.8vw, 26px); line-height: 1; color: var(--hot); letter-spacing: .02em; text-transform: uppercase; pointer-events: none; min-height: 1em; max-width: calc(100% - 24px); }
.e3grid .side .wood.small { font-size: clamp(30px, 3.6vw, 48px); margin-bottom: .3em; }
.e3grid .side .num { margin-bottom: 16px; }
.e3grid .side .fine { max-width: none; }

@media (max-width: 900px) {
  /* la placa en el telefono: las cuatro lineas en 2 x 2 (rotulo arriba del dato) y las dos notas apiladas */
  .plines { display: grid; grid-template-columns: 1fr 1fr; }
  .plines > div { grid-template-columns: 1fr; gap: 2px; padding: 9px 22px 10px; }
  /* el rotulo reserva DOS renglones: `DIET · BNB / USDT` parte en dos en media celda y los otros tres no, asi que
     sin la reserva el dato de esa celda cae un renglon mas abajo que el de al lado */
  .plines dt { min-height: calc(2 * 1.2em); }
  .plines > div:nth-child(odd) { border-right: 1px solid var(--ink); }
  .plate-head { padding: 12px 22px 10px; flex-wrap: wrap; gap: 4px 16px; }
  .plabel { padding: 8px 22px 0; }
  .tape { margin: 0 30px; }   /* la ventana de la cinta arranca despues del tornillo (que termina en 26 px) */
  .senses .live { padding: 10px 22px 0; }
  .pnotes { grid-template-columns: 1fr; gap: 18px; padding: 14px 22px 0; }
  /* el objeto de cada fila del colofon pasa arriba, a 140 px de alto, y el resto se apila debajo */
  .colophon > div { grid-template-columns: 1fr; gap: 8px; }
  /* cada uno por su nombre: `.colophon .obj` y `.colophon .def` pesan mas que un `> div > *` y se quedaban en sus
     columnas de escritorio, abriendo columnas implicitas a la derecha del unico 1fr */
  .colophon dt, .colophon .obj, .colophon .def, .colophon .ref { grid-column: 1; grid-row: auto; }
  .colophon .obj { order: -1; }
  .colophon .obj canvas, #what-atlas, #what-trace { width: 100%; height: 140px; }
  .obj-cap { width: auto; }
  .colophon .ref { text-align: left; }
  .exp li { grid-template-columns: 2.6em 1fr auto; row-gap: 8px; }
  .exp li p { grid-column: 2 / -1; }
  .exp .stamp { grid-column: 2; justify-self: start; }
  .exp li a { grid-column: 3; grid-row: 3; }
  .exp .void { display: none; }
  .aperow { grid-template-columns: 1fr; gap: 18px; }
  .hero { grid-template-columns: 1fr; }
  .hero .stage { min-height: 52svh; }
  .hero .copy { padding: 2svh 6vw 8svh; }
  .word { font-size: clamp(76px, 24vw, 150px); }
  .pgrid { grid-template-columns: 1fr; }
  .chart { height: 300px; }
  .nav { gap: 10px; }
  .nav a { white-space: nowrap; }
  .exp { grid-template-columns: 1fr; gap: 26px; }
  .wgrid { grid-template-columns: 1fr; gap: 24px; }
  .wires .stage { aspect-ratio: 1 / 1; }
  .legend { font-size: 12px; column-gap: 14px; }
  .legend b { font-size: 20px; }
  .wires .pin { font-size: 20px; }
  .scrub { grid-template-columns: 1fr; grid-template-rows: auto 1fr auto; gap: 14px 0; padding: 7svh 0 0; }
  .shead { padding: 0 6vw; }
  .film { grid-column: 1; grid-row: 2; height: auto; min-height: 0; border-left: 0; border-top: 2px solid var(--ink); border-bottom: 2px solid var(--ink); }
  .film-label { grid-column: 1; grid-row: 3; align-self: start; margin: 0 0 3svh; padding-left: 6vw; font-size: 30px; }
  .film input[type=range] { left: 12px; right: 12px; bottom: 36px; width: auto; }
  .ca { flex-direction: column; align-items: flex-start; }
  .tk th { padding-right: 14px; }
}

@media (max-width: 480px) {
  /* the poster head on a phone: one row cuts the last link at 419 px, so the brand takes its own line and the four sections spread on the next */
  .nav { flex-wrap: wrap; row-gap: 2px; padding: 12px 16px 10px; }
  .nav .brand { flex-basis: 100%; }
  /* las cuatro lineas de la placa reservan dos renglones: LAST SENSE es la unica que parte en dos y hacia crecer su
     fila 34 px, y como cambia cada segundo la placa entera se movia debajo del dedo mientras se lee. */
  .plines dd b { font-size: 28px; }
  .plines dd { min-height: calc(2 * .9em); }
  .plines .last dd b { font-size: 19px; }
  /* el acto ocupaba dos renglones de 44 px en un telefono y empujaba todo el pie: en la hoja chica el titular baja
     a la medida del ancho (8vw) y el resto del bloque se queda igual */
  .ape figcaption .zoo-act { font-size: clamp(26px, 8vw, 34px); }
}

/* Los 45 tractos en dos columnas de 175 px parten TODOS los renglones en dos o tres: a 560 px la leyenda pasa a una
   sola columna y cada tracto vuelve a ser una linea. */
@media (max-width: 560px) { .legend { columns: 1; } }

@media (max-width: 900px) {
  .board { grid-template-columns: 1fr; padding: 0 0 6svh; min-height: 0; }
  .board .stage { min-height: 56svh; }
  .board .stage .live { left: 6vw; bottom: 10px; }
  .board .stage .nogl { left: 6vw; right: 6vw; bottom: 36px; }
  .hero .stage .nogl { left: 6vw; right: 6vw; }
  .board .meters { padding: 2svh 6vw 0; }
  .board .meters .wood { font-size: clamp(48px, 15vw, 90px); }
  .stamp.big { font-size: clamp(56px, 18vw, 96px); }
  .board .pair { max-width: none; }
  .strip2 { grid-template-columns: 1fr; gap: 22px; padding: 5vh 6vw 6vh; }
  .strip2 .chart.tall { order: -1; min-height: 0; height: 320px; }
  .pulse-page #ticker { min-height: 0; }
  .fp { padding: 6vh 6vw 8vh; }
  .fpgrid { grid-template-columns: 1fr; gap: 18px; }
  .labhead { padding: 14svh 6vw 3vh; }
  .lab { padding: 6vh 6vw 8vh; }
  .lhead { grid-template-columns: 1fr; align-items: start; gap: 14px; }
  .lab .stamp.big { justify-self: start; font-size: clamp(44px, 14vw, 76px); }
  .maps, .e2grid, .e3grid { grid-template-columns: 1fr; gap: 22px; }
  .e2grid .null { margin-top: 0; }
  .lab .note { max-width: none; }
}

/* ── THE PRESS ─────────────────────────────────────────────────────────────────────────────────────
   Entry sequence behind ?press=on (brief: docs/design/2026-09-20-press-brief.md). The sheet is the page
   background already, so the press only adds ink on top of it and never paints its own paper: that is
   what makes the handoff seamless — there is nothing to fade out underneath.
   Two screens, not three: this poster prints in ink and hot, so the misregistration has two impressions
   and no soft grey ghost (a drop shadow is banned by the palette and would read as one). */
#press {
  position: fixed; inset: 0; z-index: 90;
  background: var(--paper);
  display: grid; grid-template-rows: auto 1fr auto auto;
  padding: 3vh 4vw; gap: 2vh;
  opacity: 1; transition: opacity .4s linear;
}
#press.lift { opacity: 0; pointer-events: none; }

/* registration marks: real press furniture, one per corner */
.press-reg { position: absolute; width: 26px; height: 26px; opacity: .85; }
.press-reg::before, .press-reg::after { content: ''; position: absolute; background: var(--ink); }
.press-reg::before { left: 50%; top: 0; width: 1px; height: 100%; }
.press-reg::after { top: 50%; left: 0; height: 1px; width: 100%; }
.press-reg.tl { left: 2vw; top: 2vh; } .press-reg.tr { right: 2vw; top: 2vh; }
.press-reg.bl { left: 2vw; bottom: 2vh; } .press-reg.br { right: 2vw; bottom: 2vh; }

.press-head, .press-foot {
  font-family: var(--mono); font-size: 11px; letter-spacing: .18em; text-transform: uppercase; color: var(--ink);
}
.press-head { display: flex; justify-content: space-between; }
.press-foot { text-align: center; color: var(--hot-text); }

/* the stage mirrors the hero's own split (1.05fr plate / 1fr type) so both pieces can travel onto their
   live counterparts at the end instead of dissolving into an unrelated layout */
.press-stage { display: grid; grid-template-columns: 1.05fr 1fr; align-items: center; gap: 2vw; min-height: 0; }
.press-plate { display: grid; place-items: center; min-height: 0; }
#press-dots {
  width: min(62vh, 46vw); height: min(62vh, 46vw); max-width: 100%; display: block;
  transform-origin: 50% 50%;
  transition: transform .78s cubic-bezier(.76,0,.24,1);   /* press.js writes the transform inline */
}

/* the wordmark: two impressions of one poster, out of register until the bytes land.
   --ox/--oy/--rot are driven by real download progress; --tx/--ty/--k by the handoff. */
.press-word {
  justify-self: start; display: grid; place-items: start;
  --ox: 29px; --oy: 11px; --rot: .9deg;                   /* misregistration, driven by real progress */
  transform-origin: 50% 50%;
  transition: transform .78s cubic-bezier(.76,0,.24,1);   /* the travel transform is written inline */
}
.press-word .imp {
  grid-area: 1 / 1;
  font-family: var(--display); font-weight: 400;
  font-size: clamp(46px, 9.2vw, 150px); line-height: .82; letter-spacing: -.005em;
  transition: transform .5s cubic-bezier(.33,1,.68,1);
}
.press-word .hot { color: var(--hot); transform: translate(var(--ox), calc(var(--oy) * -1)) rotate(var(--rot)); }
.press-word .ink { color: var(--ink); }

/* the plate log: eight real files, their real byte counts */
.press-plates {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px 3vw;
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
}
.press-plates li { display: flex; align-items: baseline; gap: 6px; color: var(--ink); opacity: .32; transition: opacity .3s linear; }
.press-plates li.set { opacity: 1; }
.press-plates li.failed { opacity: 1; color: var(--hot-text); }
.press-plates .dots { flex: 1; border-bottom: 1px dotted currentColor; transform: translateY(-3px); }
.press-plates b { font-weight: 400; }
.press-plates i { font-style: normal; }

/* the handoff: the furniture goes first, then the two pieces travel onto the live hero */
#press.handoff .press-head,
#press.handoff .press-foot,
#press.handoff .press-plates,
#press.handoff .press-reg { opacity: 0; transition: opacity .3s linear; }

@media (max-width: 860px) {
  .press-stage { grid-template-columns: 1fr; grid-template-rows: 1fr auto; }
  .press-word { justify-self: center; }
  #press-dots { width: min(38vh, 70vw); height: min(38vh, 70vw); }
  .press-plates { grid-template-columns: repeat(2, 1fr); }
  .press-word .imp { font-size: clamp(38px, 15vw, 92px); }
}

/* reduced motion never mounts the press (main.js checks), but if anything ever renders it, no travel */
@media (prefers-reduced-motion: reduce) {
  .press-word, .press-word .imp, #press-dots { transition: none; }
}

/* ── E3 · THE INSTRUMENT ───────────────────────────────────────────────────────────────────────────
   The lesion was always there; it looked like a figure next to a table and nothing said it could be
   touched. Now the brain takes the width, the numbers sit in a rail, and the affordance is printed. */
.e3op { display: grid; grid-template-columns: 1.45fr 1fr; gap: 3vw; align-items: start; }
.e3op .fig { margin: 0; }
.e3op .stage { position: relative; aspect-ratio: 1 / 1; border: 2px solid var(--ink); background: var(--paper); box-sizing: border-box; }
.e3op .stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: pan-y; cursor: crosshair; }
.e3op .stage canvas:active { cursor: grabbing; }
.e3op .pin { position: absolute; left: 12px; bottom: 8px; margin: 0; font-family: var(--display); font-size: clamp(18px, 1.8vw, 26px); line-height: 1; color: var(--hot); letter-spacing: .02em; text-transform: uppercase; pointer-events: none; min-height: 1em; max-width: calc(100% - 24px); }

/* the cue: the page says what it used to whisper. It steps back once a region is off. */
.e3op .cue { position: absolute; left: 12px; top: 10px; margin: 0; pointer-events: none;
  font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink); }
.e3op .cue b { display: block; font-weight: 400; color: var(--hot-text); }
/* el renglon de abajo del cartel pisa el semitono del cerebro: es tipo de 11 px, asi que la opacidad que lo hacia
   secundario (.55 = 4,0:1, y .45 = 3,0:1 una vez apagada una region) sube hasta pasar el 4,5:1. Sigue un escalon
   por debajo de la tinta plena, que es todo lo que tenia que decir. */
.e3op .cue span { display: block; opacity: .65; margin-top: 3px; }
.e3op .stage.cut .cue b { color: var(--ink); opacity: .65; }

.e3op .restore { position: absolute; right: 12px; top: 10px; cursor: pointer;
  font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  background: var(--ink); color: var(--paper); border: 0; padding: 7px 12px; }
.e3op .restore:hover { background: var(--hot-fill); color: var(--on-hot); }

/* the readout: two independent measures side by side, which is the honest part */
.e3op .readout { border: 2px solid var(--ink); padding: 14px 16px 16px; margin-bottom: 22px; }
.e3op .ro-head { margin: 0 0 10px; font-family: var(--display); font-size: clamp(26px, 2.8vw, 38px); line-height: 1; letter-spacing: .02em; }
.e3op .readout[data-state="cut"] .ro-head { color: var(--hot-text); }
.e3op .ro-nums { margin: 0; display: grid; gap: 5px; }
.e3op .ro-nums > div { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; border-bottom: 1px dotted var(--ink); }
.e3op .ro-nums dt { font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; opacity: .7; }
.e3op .ro-nums dd { margin: 0; font-family: var(--mono); font-size: 13px; font-variant-numeric: tabular-nums; }
.e3op .side .wood.small { font-size: clamp(30px, 3.6vw, 48px); margin-bottom: .3em; }
.e3op .side .num { margin-bottom: 16px; }
.e3op .side .fine { max-width: none; }

/* the table is a control surface too: a row lights its region, a click switches it off */
.num.pickable tbody tr { cursor: pointer; }
.num.pickable tbody tr:hover td { background: var(--hot-fill); color: var(--on-hot); }
.num.pickable tbody tr:hover td small { color: var(--on-hot); opacity: .8; }
.num.pickable tbody tr[aria-pressed="true"] td { outline: 2px solid var(--hot); outline-offset: -2px; }

@media (max-width: 900px) {
  .e3op { grid-template-columns: 1fr; }
}

/* ── E2 · THE CURTAIN ──────────────────────────────────────────────────────────────────────────────
   One plate, two runs. The scramble is printed on top and clipped from the left edge of the handle, so
   dragging swaps which run you are looking at without either map moving. The overlay takes no pointer
   events: the map underneath keeps the reading crosshair that links all the figures, and nothing gets
   two listeners on one box. */
.maps { grid-template-columns: 1fr 1.6fr; }
.curtain { position: relative; aspect-ratio: 1 / 1; }
.curtain .hm { position: absolute; inset: 0; }
.curtain .hm.over { clip-path: inset(0 0 0 var(--cut)); pointer-events: none; }
.curtain .tag { position: absolute; top: 8px; font-family: var(--mono); font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; background: var(--paper); color: var(--ink); padding: 2px 6px; pointer-events: none; z-index: 3; }
.curtain .tag.left { left: 8px; } .curtain .tag.right { right: 8px; }
.curtain .bar { position: absolute; top: 0; bottom: 0; left: var(--cut); width: 2px; background: var(--hot);
  cursor: col-resize; z-index: 4; touch-action: none; }
/* el tirador es un AREA con tinta encima, no tipo en caliente: por la regla de la hoja va en --hot-fill (10,5:1),
   como el sello que pasa, el boton de compra y el rotulo LIVE. En --hot quedaba en 3,7:1 con el laton nuevo. */
.curtain .bar b { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  background: var(--hot-fill); color: var(--on-hot); font-family: var(--mono); font-weight: 400; font-size: 10px;
  letter-spacing: .12em; padding: 6px 8px; white-space: nowrap; }
.curtain .bar:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

@media (max-width: 900px) { .maps { grid-template-columns: 1fr; } }

/* ── THE ENCLOSURE · WHAT YOU CAN GIVE HIM ────────────────────────────────────────────────────────
   Los cinco botones que hay bajo el animal en las dos hojas (la plancha de /lab y el pie de la figura
   de la portada). No son una interfaz: son la misma tipografia chica y a caja alta de los rotulos del
   afiche, con el filete de un sello y NADA redondeado, ninguna sombra y ningun degrade. Apretado, el
   sello se invierte (tinta llena, papel por letra), que es lo unico que hace una prensa.
   `.zoo-cap` no recibe el dedo (el lienzo esta debajo y hay que poder arrastrar al animal a traves del
   pie): esta fila si. */
.zoo-give { display: flex; flex-wrap: wrap; gap: 10px 8px; margin-top: 16px; pointer-events: auto; position: relative; z-index: 2; }
.zoo-give[hidden] { display: none; }   /* sin WebGL no hay animal que responda: la fila no se imprime */
.zoo-give button { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  border: 1px solid var(--ink); background: var(--paper); color: var(--ink); padding: 7px 10px; border-radius: 0;
  cursor: pointer; white-space: nowrap; max-width: 100%; }
.zoo-give button:hover, .zoo-give button:focus-visible, .zoo-give button:active { background: var(--ink); color: var(--paper); }
.zoo-give button:focus-visible { outline: 2px solid var(--hot); outline-offset: 2px; }
/* EL RENGLON DE LA REGION. El nombre real de la region que el estimulo enciende colgaba del final del parrafo
   detras de un `·` suelto ("… reaches the market. · precentral gyrus, intermediate part") y se leia como una
   coletilla del texto fijo. Ahora es un renglon propio debajo de la firma, que es donde el pie ya imprime su
   codigo (`L.PRG.I 30`): el rotulo fijo va en tinta y el nombre en caliente, o sea el dato es lo que cambia de
   color. Vacio — que es casi siempre, hasta que el lector le da algo — no ocupa renglon. */
.zoo-region { display: block; font-family: var(--mono); font-size: 11px; letter-spacing: .12em; line-height: 1.7;
  text-transform: uppercase; color: var(--hot-text); margin: 0 0 12px; }
.zoo-region:empty { display: none; }
.zoo-region::before { content: 'lit on the atlas · '; color: var(--ink); }

/* ── /log · THE KEEPER'S LOG ──────────────────────────────────────────────────────────────────────
   WP15b. El cuaderno de un cuidador: una entrada por hora, la de la hora en curso arriba. Nada nuevo de
   paleta ni de tipo, y ni una caja redondeada: la fecha en mono sobre un filete (que es como se abre una
   anotacion de turno) y el texto en la maquina de escribir, a la medida de lectura. La entrada viva se
   distingue por su sello, no por un color propio. */
.logbook { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--ink); max-width: 86ch; }
.logent { padding: 18px 0 20px; border-bottom: 1px solid var(--ink); }
/* la entrada en curso se marca `now` y NO `live`: `.live` ya es una regla del afiche (mono, caja alta, 2.2em de
   aire) y aplicada al <li> le pasaba la caja alta al texto entero de la entrada. */
.logent.now { border-left: 6px solid var(--hot); padding-left: 16px; }
.loghead { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; margin-bottom: 8px; }
.loghead b { font-family: var(--mono); font-weight: 700; font-size: 12px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink); }
.logtag { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--hot-text); }
.logtag.now { border: 1px solid var(--hot); padding: 2px 7px; }
.logtext { margin: 0; font-family: var(--type); font-size: clamp(15px, 1.2vw, 18px); line-height: 1.6; max-width: 76ch; }
@media (max-width: 900px) {
  .logent.now { padding-left: 12px; border-left-width: 4px; }
  .logtext { font-size: 15px; line-height: 1.55; }
}
