/* ============================================================================
   econ — "TWO HALVES, ONE SPARK"
   Direction derived from the user's own mark: a disc cut by a horizontal seam
   with a four-pointed concave spark carved out of it as NEGATIVE space.
   Architecture note: the page is light paper; the world is a single fixed
   WebGL canvas that renders ONLY inside each card's stage rect (scissor), so
   every dark moment on this page is a real aperture cut through the paper.
   ========================================================================= */

@font-face{font-family:Satoshi;src:url(/vendor/fonts/Satoshi.woff2)format("woff2");font-weight:300 900;font-display:swap}
@font-face{font-family:Archivo;src:url(/vendor/fonts/Archivo.woff2)format("woff2");font-weight:100 900;font-display:swap}
@font-face{font-family:Archivo;src:url(/vendor/fonts/Archivo-italic.woff2)format("woff2");font-weight:100 900;font-style:italic;font-display:swap}
@font-face{font-family:"Space Grotesk";src:url(/vendor/fonts/SpaceGrotesk.woff2)format("woff2");font-weight:300 700;font-display:swap}

:root{
  /* triples are SPACE-separated so `rgb(var(--tok) / a)` is legal CSS.
     a comma-separated token inside rgb()/slash is silently dropped — #19 */
  --ink: 16 16 45;            /* the mark's own navy */
  --ground: 242 243 249;      /* paper */
  --paper: 255 255 255;       /* card plate */
  --stage: 8 9 20;            /* inside the aperture */
  /* THE GROUND IS BLACK AND ALIVE. The feed's gaps now show a moving field
     rendered by the world canvas underneath, so this colour is only what sits
     behind it before the first frame and wherever the canvas cannot reach. */
  --page: 5 6 13;

  /* ROUND 14 — the chapter accent ramp, locked on its own law. The gate row is
     "lock perceived lightness: oklch(L C h) with fixed L/C, rotate hue only",
     and this ramp was only half obeying it: measured oklch L 0.6406 / 0.5799 /
     0.6532, a 0.073 drift, and relative luminance 118.5 / 54.3 / 132.2 — a
     78-point spread on markers that are supposed to read as one series. It
     showed up as a 27.3 same-rank spread on the ticker, where the lit word is a
     member of this ramp sitting inside a rank of navy micro-caps.
     Every hue is now stated at the BRAND BLUE's own L, so #008CFF is unchanged
     to the byte and the two derived accents move to meet it. Chroma is each
     hue's sRGB CEILING at that L, not a locked number, and that is a stated
     limit rather than a miss: at L 0.6406 an amber (H 70) cannot exceed C
     0.1388 in this gamut while a violet reaches 0.2489, so a single C would
     mean muting the brand blue to a hue no chapter uses. L is locked exactly;
     C is capped and reported. Y spread 77.9 -> 15.1. */
  --e-blue:#008CFF; --e-violet:#B450FF; --e-amber:#C17B00;
  /* White on #008CFF measures 3.39:1 and fails AA at pill size. The accent
     stays the brand blue everywhere it is a line, a ring or a glow; a FILLED
     button gets the darkened variant so its label is actually readable.
     Measured: blue 6.05:1, violet 6.99:1, amber 5.70:1. */
  /* the same lock on the light-plate ramp, anchored on #0A5BD0's L 0.5029.
     Here L was already constant to 0.005 and CHROMA was doing all the damage:
     the violet at C 0.2608 rendered Y 44.8 against the blue's 82.2, so the one
     chapter set in violet showed a visibly heavier lit word than the seven set
     in blue. Violet drops to the blue's own chroma; the amber sits at its
     ceiling (0.1071). Y spread 48.9 -> 11.2, contrast on the white plate
     6.14 / 6.54 / 6.04 against a 4.5 floor. */
  --e-blue-solid:#0A5BD0; --e-violet-solid:#8039BA; --e-amber-solid:#885900;
  --ax: var(--e-violet); --ax-solid: var(--e-violet-solid);

  --ink-display: rgb(var(--ink) / .94);
  --ink-body:    rgb(var(--ink) / .72);
  /* The kicker sits DARKER than body on purpose. Letterspaced micro-caps at
     .66rem lose their flanks to antialiasing, so equal intrinsic ink renders
     LIGHTER than body at the same alpha — measured 99.4 against a <=85 band
     while body passed at 84.4. Weight is already 600 (the first lever), so the
     second lever is the hex: .75 renders ~77 and reads as the same rank. */
  --ink-kicker:  rgb(var(--ink) / .75);
  /* The same rank one size DOWN. The FIRST value here (.88) was solved against
     a DPR-1 reading, and AA erosion is a rasterisation property that vanishes
     at DPR>=2 — which is every Retina Mac and every phone. Measured at DPR 3,
     where band40 converges on the arithmetic composite, .88 put this label at
     45.8 on light: darker than the body it serves (81.5) and darker than the
     eyebrow one size UP (74.6), i.e. a navigation label outranking its own
     sentence. .77 composites to ~70 — still a step under the eyebrow, 15 inside
     the <=85 ceiling, and no longer louder than the paragraph. */
  --ink-kicker-sm: rgb(var(--ink) / .77);
  --ink-rule:    rgb(var(--ink) / .14);

  --geo: .32;                  /* ONE geometry window, page-wide */
  --ease: cubic-bezier(.16,1,.3,1);
  --r-card: 26px;
  --r-stage: 20px;
}

*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scrollbar-gutter:stable;scroll-behavior:auto}
body{
  font-family:Archivo,system-ui,sans-serif;
  background:rgb(var(--page));
  color:var(--ink-body);
  overflow-x:clip;
  overflow-y:auto;
  min-height:100svh;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
a{color:inherit}
:focus-visible{outline:2px solid var(--ax);outline-offset:3px;border-radius:4px}
.skip{position:fixed;left:14px;top:-70px;z-index:99;background:rgb(var(--ink));color:rgb(var(--ground));
  padding:11px 18px;border-radius:10px;font:600 .78rem/1 "Space Grotesk",monospace;transition:top .2s}
.skip:focus{top:14px}

/* ── the world ─────────────────────────────────────────────────────────── */
#world{position:fixed;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;display:block}
/* Film grain sits ABOVE the world and BELOW all content (taxonomy #2): a grade
   that multiplies glyphs dims their flanks site-wide. */
.grain{position:fixed;inset:0;z-index:1;pointer-events:none;opacity:.05;mix-blend-mode:soft-light;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter><rect width='160' height='160' filter='url(%23n)' opacity='.5'/></svg>");
  animation:grainShift 7s steps(6) infinite}
@keyframes grainShift{0%{transform:translate(0,0)}20%{transform:translate(-4px,3px)}40%{transform:translate(3px,-5px)}
  60%{transform:translate(-6px,-2px)}80%{transform:translate(5px,4px)}100%{transform:translate(0,0)}}

/* ── header ────────────────────────────────────────────────────────────── */
.hd{position:fixed;top:0;left:0;right:0;z-index:20;display:flex;align-items:center;gap:20px;
  padding:clamp(16px,1.8vw,26px) clamp(18px,3vw,42px);pointer-events:none}
/* The reference keeps navigation over the composition, never in a bar. Ink
   still changes with the active card; the header itself remains transparent. */
.hd::before{content:none}
.hd>*{pointer-events:auto}
.hd-brand{display:flex;align-items:center;gap:10px;text-decoration:none;margin-right:auto}
/* The header ink no longer inherits the card's tone. With a black page the
   header sits over the GROUND, not over a card, on every desktop frame — dark
   ink there is simply invisible. It is white always, and the scrim below turns
   black for the one case that can still fail: one column, where the card runs
   up under it. */
/* ROUND 9 — that stopped being true for the HERO. It is now a pale takeover
   (clear glass and a spectrum cannot read on black), so white ink there is the
   invisible case the note above was written to avoid — in reverse. The ink is
   a token, and main.js flips it while a light-luminance card covers the
   header. Everywhere else it is still white, always. */
.hd{--hd-ink:255 255 255}
.hd[data-ink="dark"]{--hd-ink:16 16 45}
.hd-mark{width:26px;height:26px;fill:rgb(var(--hd-ink) / .92);transition:fill .5s}
.hd-word{font:600 1.08rem/1 Satoshi,sans-serif;letter-spacing:-.02em;color:rgb(var(--hd-ink) / .96);
  transition:color .5s}
.hd-count{font:600 .68rem/1 "Space Grotesk",monospace;letter-spacing:.14em;color:rgb(var(--hd-ink) / .8);
  transition:color .5s;
  display:flex;gap:6px;align-items:baseline;font-variant-numeric:tabular-nums}
.hd-count i{opacity:.4;font-style:normal}
.hd-count span{opacity:.55}
/* ROUND 14, user directive: "tambien quita la barra de progreso". The blue
   scroll rule under the header is gone — element, style and the per-frame write
   in main.js. The header keeps "NN / 09", which says the same thing in words. */

/* ── pills ─────────────────────────────────────────────────────────────── */
.pill{display:inline-flex;align-items:center;gap:9px;padding:12px 21px;border-radius:999px;
  font:600 .72rem/1 "Space Grotesk",monospace;letter-spacing:.1em;text-transform:uppercase;
  text-decoration:none;border:1px solid rgb(var(--ink) / .22);color:var(--ink-display);
  white-space:nowrap;
  transition:transform .35s var(--ease),background .3s,border-color .3s,color .3s;will-change:transform}
.pill::after{content:"";width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.55}
.pill:hover{background:rgb(var(--ink) / .06);border-color:rgb(var(--ink) / .4)}
.pill:active{transform:translateY(1px) scale(.985)}
.pill-solid{background:var(--ax-solid);border-color:transparent;color:#fff;
  box-shadow:0 8px 26px color-mix(in srgb,var(--ax) 40%,transparent)}
.pill-solid:hover{filter:brightness(1.14);
  box-shadow:0 12px 34px color-mix(in srgb,var(--ax) 58%,transparent)}
.hd-cta{padding:11px 18px}
@media (max-width:720px){.hd-cta{display:none}}

/* ── native scroll feed ────────────────────────────────────────────────── */
.wrap{position:relative;z-index:2}
.feed{display:flex;flex-direction:column;align-items:center;
  gap:clamp(34px,6.5vh,86px);padding:11vh 0 13vh}
/* The opening field starts at the viewport edge so the transparent navigation
   sits over the composition itself, as in the reference — never over page
   ground masquerading as a header bar. */
#top{margin-top:-11vh}

/* ── THE CARD ──────────────────────────────────────────────────────────── */
/* ENTRY LAW: a card never begins as a card. Every plate, border and shadow
   alpha is driven from `--g * --g` starting at ZERO, so what enters the frame
   is the subject, and the card materialises around it afterwards. */
.card{
  --p:0; --g:0;
  /* --c (copy), --f (fine strip) and --rl (rail fill) are written by JS every
     frame. They used to carry literal CSS fallbacks here too, which meant the
     repo stated two different ordering laws and the one in main.js was the
     real one. Defaults only, so nothing is mid-state before the first frame. */
  --c:0; --f:0; --rl:0;
  --gg: calc(var(--g) * var(--g));
  --card-h: min(716px, 78svh);
  --st:.065; --sr:.245; --sb:.165; --sl:.37;
  --plate: var(--paper);

  --card-w: min(1240px, 93vw);
  --rail-plate: var(--paper);        /* constant across tones, see .c-rail */
  position:relative;width:var(--card-w);height:var(--card-h);flex:none;
  border-radius:calc(var(--r-card) + 16px - 16px * var(--g));
  padding:clamp(24px,3vw,46px);
  display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-rows:1fr auto;
  gap:clamp(14px,2vh,26px);
  /* NO background of its own: `.c-cut` below paints the plate outward from
     the stage rect, so the plate IS the cut-out. A background here would
     cover the aperture and the world would never be visible through it. */
  background:none;
  border:1px solid rgb(var(--ink) / calc(var(--gg) * .13));
  box-shadow:0 calc(30px * var(--gg)) calc(74px * var(--gg)) rgb(var(--ink) / calc(var(--gg) * .1));
  transform:scale(calc(.72 + .28 * var(--g)));
  overflow:hidden;
  isolation:isolate;
}
.card{--copy-top:calc(.08 * var(--card-h) - clamp(24px,3vw,46px) + 6px)}
.card[data-tone="dark"]{--copy-top:calc(.03 * var(--card-h) - clamp(24px,3vw,46px) + 30px)}
.card[data-tone="takeover"]{--copy-top:0px}
.card[data-tone="takeover"] .c-copy{align-self:center}
/* Four apertures were introduced without the type following them, so the
   gutter between the copy's last ink and the window ran 47px (frame c) to
   140px (frame b) — spread 93px, a 2.98x ratio — and pinning the copy to a
   CONSTANT top left 213-294px of dead plate below it, a mean 44% of the card.
   Both are the same error: a constant asserted against a variable rectangle.
   The measure is now cut by the same fraction of the card that the aperture
   takes, the display size answers the column it has to live in, and the block
   is centred on the APERTURE'S own vertical span rather than on the card:
   with `align-self:center` a margin shifts the box by half itself, so
   (--st - --sb) * --card-h places the copy's centre exactly on the window's
   centre, and the +40px absorbs the fine strip's row below. */
.card[data-tone="light"] .c-copy{
  align-self:center;padding-top:0;
  margin-top:calc((var(--st) - var(--sb)) * var(--card-h) + 40px);
  max-width:min(46ch, calc(var(--sl) * var(--card-w) - clamp(24px,3vw,46px) - 46px))}
.card[data-tone="light"] .c-head{
  font-size:calc(clamp(26px, calc((var(--sl) * var(--card-w) - 100px) * .125), 45px) * var(--hs,1));
  letter-spacing:-.028em}
/* The light override set body one rank SMALLER (14.688px vs 16.128px) than the
   same rank on the dark cards, which did two things at once: it broke same-rank
   size parity 9.8%, and at that size AA erosion put the measured glyph core
   16-24 points BELOW what the declared alpha predicts, so light body measured
   98-106 against a <=90 gate while the dark cards at the same nominal alpha sat
   mid-band. Size was the mechanism, not colour: computed rgba is byte-identical
   on all nine cards. The light copy column is 320-419px, so one size gives
   40-52ch here, still inside the comfort band. */
.card[data-tone="light"] .c-body{max-width:100%}
/* There were exactly three stage rects site-wide and no per-card override, so
   every light card was the identical composition with a swapped subject. Four
   frames, assigned in index.html, so the window changes size, aspect and
   vertical position as the feed advances. */
/* The four frames vary the aperture's SIZE, WIDTH and left edge — but they now
   share one vertical centre (.455 of the card). They did not: the centre drifted
   .385 -> .530, i.e. 84px card to card on a 580px card, and in a feed that
   settles one card per viewport that reads as the window slipping rather than as
   rhythm. Height is preserved per frame (.76 / .73 / .72 / .69); only the pair
   is re-balanced around the common centre. */
/* Aperture HEIGHT is quantised to two values, tall .78 and short .71, both on
   the common .455 centre. It was a +/-19px wobble across four frames with no
   ordering, and it was anti-correlated with need: quant, the only two-register
   device on the page, held the shortest window. The assignment is by MEASURED
   subject aspect, not by intuition: quant's two registers make its subject
   nearly square (AR 1.04), so it takes the SHORT window whose aspect matches;
   giving it the tall one dropped its vertical coverage from 85% to 76%.
   pieces (0.73) and build (0.84) take the tall one.
   The left-edge march (frames a->d) is the rhythm and is untouched; the height
   wobble was noise. */
/* SUPERSEDED, and the note above is left standing because it records the wrong
   turn. Tying each window to its own subject made five windows: left edge
   drifting 83px, right edge 68px, five distinct widths. With the copy pinned at
   x=120 those two verticals are the only other structural edges in the frame,
   so nothing in the right two-thirds of the page sat on a shared axis. The
   aperture — not the subject — is what a reader tracks from chapter to chapter,
   and that constancy is worth more than the coverage points it cost.
   ONE window, set at the MAXIMUM of the five so no subject shrinks: the widest
   (.33/.22, from the old frame c) and the tallest (h .77, from the base), with
   st/sb solved to hold the common vertical centre .455. Variation now lives
   INSIDE the window as per-card fit, where it costs the page nothing. */
.card[data-frame]{--st:.07; --sr:.22; --sb:.16; --sl:.33}
/* --ax is the LINE/RING/GLOW token and is right as a stroke. Used as a text
   FILL on the light plate it measured 2.66:1 (amber) to 3.78:1 (violet) against
   a 4.5:1 floor — 14/14 accent micro-type instances on the five light cards
   below AA, while the same elements pass at 4.85-5.20:1 on dark. axe reports
   these INCOMPLETE rather than FAIL because it cannot resolve a WebGL ground,
   so a11y 1.00 was never counter-evidence. The darkened variants this file
   already ships for filled buttons are exactly the fix; they were simply never
   wired to type. Strokes keep --ax: the ring, the spine, the rail line. */
.card[data-tone="light"] .c-idx,
.card[data-tone="light"] .c-rail li.lit i,
.card[data-tone="light"] .c-rail li[data-me] i,
.card[data-tone="light"] .c-fine b[data-on]{color:var(--ax-solid)}
.card[data-ax="violet"]{--ax:var(--e-violet);--ax-solid:var(--e-violet-solid)}
.card[data-ax="amber"]{--ax:var(--e-amber);--ax-solid:var(--e-amber-solid)}

/* .78, not .82. The body rank was authored against an OPAQUE plate, where the
   only thing between the ink and the ground was the ink: white at .82 over
   rgb(16,18,36) composites to ~213 against a 215 ceiling, i.e. two points of
   headroom. That was fine while the copy sat on a plate. It is not fine now
   that the copy sits on live art with a thin scrim over it — any lit pixel
   behind the paragraph spends the whole margin, which is why markets and
   contact kept landing on 215.0-215.7 depending on the animation frame. The
   honest fix is headroom at the source, not a thicker scrim: .78 composites to
   ~203, mid-band, and the rank reads FURTHER from the display above it. */
/* dark cards: the aperture takes nearly the whole plate and copy rides over it */
.card[data-tone="dark"]{
  --ink:255 255 255; --plate:16 18 36; --ground:8 9 20; --rail-plate:11 12 26;
  --ink-display:rgb(255 255 255 / .98); --ink-body:rgb(255 255 255 / .80);
  --ink-kicker:rgb(255 255 255 / .7); --ink-kicker-sm:rgb(255 255 255 / .74); --ink-rule:rgb(255 255 255 / .16);
  --st:.03; --sr:.026; --sb:.09; --sl:.026;
}
.card[data-tone="dark"] .pill{border-color:rgb(255 255 255 / .3)}
.card[data-tone="dark"] .pill:hover{background:rgb(255 255 255 / .1);border-color:rgb(255 255 255 / .55)}

/* takeover: the frame dissolves, the world fills the viewport, type sits on it */
.card[data-tone="takeover"]{
  --ink:255 255 255; --plate:8 9 20; --rail-plate:11 12 26;
  --ink-display:rgb(255 255 255 / .98); --ink-body:rgb(255 255 255 / .80);
  --ink-kicker:rgb(255 255 255 / .7); --ink-kicker-sm:rgb(255 255 255 / .74); --ink-rule:rgb(255 255 255 / .18);
  --st:0; --sr:0; --sb:0; --sl:0;
  width:100vw;height:100svh;border-radius:0;
  padding:clamp(26px,4vw,72px) clamp(22px,5vw,86px) clamp(60px,8vh,96px);
  background:none;border-color:transparent;box-shadow:none;
  transform:scale(calc(.9 + .1 * var(--g)));
}

/* ── the aperture ──────────────────────────────────────────────────────── */
/* `.c-cut` paints the card plate OUTWARD from the stage rect with a huge
   spread shadow, clipped by the card. The plate literally IS the cut-out, so
   the entry law and the aperture opening are one animation, not two. */
.c-stage{position:absolute;top:calc(var(--st) * 100%);right:calc(var(--sr) * 100%);
  bottom:calc(var(--sb) * 100%);left:calc(var(--sl) * 100%);
  z-index:1;border-radius:var(--r-stage);
  transform:scale(calc(.34 + .66 * var(--g)));
  transform-origin:50% 50%}
.c-cut{position:absolute;inset:0;border-radius:var(--r-stage);
  box-shadow:0 0 0 2400px rgb(var(--plate) / calc(var(--gg) * .96)),
             inset 0 0 0 1px rgb(var(--ink) / calc(var(--gg) * .12)),
             inset 0 0 60px rgb(0 0 0 / calc(var(--gg) * .5))}
/* the takeover has no plate, but while its aperture is still opening the page
   ground has to close around it — at g=1 the stage covers the viewport and the
   spread lands outside it, so one rule serves both ends */
.card[data-tone="takeover"] .c-cut{
  box-shadow:0 0 0 2400px rgb(var(--page)),
             inset 0 0 0 1px rgb(255 255 255 / calc((1 - var(--g)) * .18))}
.c-ov{position:absolute;inset:0;width:100%;height:100%;border-radius:var(--r-stage);pointer-events:none}

/* ROUND 15d, user directive: "cuando scrolleo hay una barra iluminada en azul
   morado etc en el costado izquierdo del card que estoy viendo, eso no es
   necesario, quita esa barra". That was C10, the axis spine: a 2px bar on the
   card's left edge in the chapter's accent, filling with `--rl` and carrying a
   16px glow of its own colour. It is gone from the CSS, from the markup and
   from the takeover override. `--rl` is still written every frame — it is the
   card's entry progress and the entry law reads it — it simply no longer has a
   decoration attached to it. */
/* ROUND 9 — A LIGHT TAKEOVER, and the reason it exists.
   The hero's subject is clear refractive glass with spectral dispersion. That
   material cannot be rendered on black: a translucent body on a black ground is
   a glowing solid, and a spectrum has nothing to disperse against. So the hero
   carries the pale ground the material needs. It does NOT invent a palette —
   every token below is the value the five light cards already measure 63/63 on,
   and the whole switch is `data-lum="light"` on #top, so it is one attribute to
   put back. */
.card[data-tone="takeover"][data-lum="light"]{
  --ink:16 16 45; --plate:236 234 230;
  --ink-display:rgb(var(--ink) / .94);
  --ink-body:rgb(var(--ink) / .72);
  --ink-kicker:rgb(var(--ink) / .75);
  --ink-kicker-sm:rgb(var(--ink) / .77);
  --ink-rule:rgb(var(--ink) / .16);
}
/* the opening ring is a hairline against the page, so it flips with the ground */
.card[data-tone="takeover"][data-lum="light"] .c-cut{
  box-shadow:0 0 0 2400px rgb(233 231 226),
             inset 0 0 0 1px rgb(16 16 45 / calc((1 - var(--g)) * .14))}
/* The chapter panel and the ticker were plates cut for a black stage. They now
   take the SAME plate every light card uses — not a tinted one. Ink composites
   against its own ground, so a panel one shade off makes the identical declared
   colour render differently on this card than on the other five: measured 11.2
   of rendered40 spread on the rail rank and 104.4 on the ticker against a gate
   of 4.0. Matching the plate makes the rank one design again. */
.card[data-tone="takeover"][data-lum="light"]{--rail-plate:var(--paper)}
.card[data-tone="takeover"][data-lum="light"] .c-fine{
  background:rgb(var(--paper));box-shadow:none}
/* the copy sits ON the wall, the way the reference does — the underlay is a
   soft lift that keeps the display legible over moving light, not a card */
/* no underlay at all, exactly as the light cards do it. Blurred or not, it is
   a RECTANGLE, and over the glass disc its straight edge was plainly visible
   crossing the object. The wall behind the copy is calm enough to carry navy
   type on its own — the type gates are re-measured for this tone. */
/* ROUND 11 — re-keyed from [data-lum="light"] to the hero ITSELF. The rule was
   written for the pale hero, so dropping that attribute to go back to black
   silently switched the underlay on again — an elliptical dark plate sitting
   exactly over the left half, which is where the spectrum lives. Measured: the
   rainbow was clipped to the first ~70px of the frame. Card 09 is a takeover
   too and still needs its underlay, so this is scoped to #top, and to the wide
   layout only: on one column the hero takes the same bottom scrim as every
   other card, because there the copy covers the mark rather than sitting
   beside it. */
/* ROUND 14, user directive: "quitar la opacidad ... degradado desde la orilla
   de la pantalla y mas sutil en la mitad de longitud". The blurred ellipse is
   gone from every card (see below); the two TAKEOVERS are the only cards whose
   copy sits over live art on the wide layout — every other card's stage starts
   at --sl:.37, so its copy is on the plate — and they take the same idiom the
   phone layout already uses: a scrim anchored to an EDGE, falling continuously,
   with its stops in ABSOLUTE px.
   The edge is the LEFT one here because the copy is a left column, and the
   stops are solved against measured ink: the hero's body runs 73-350px and its
   clincher 73-352px from the card edge, and the glass mark's left silhouette
   starts at 576px. A ramp that reaches zero by 620px therefore covers all of
   the type and none of the subject.
   Measured cause: with no scrim the hero's body ink sat on a ground running 10
   to 74 (the beam's incoming wash crosses the copy at y 531-707), against
   contact's flat 10.7 — taxonomy #5, and the 4.3 same-rank spread this round
   was opened to close. The colour is `--page`, the void the takeover already
   opens onto, so the scrim DARKENS toward the page ground instead of laying a
   navy plate back over the art. */
@media (min-width:861px){
  .card[data-tone="takeover"] .c-stage::after{content:"";position:absolute;inset:0;
    z-index:2;pointer-events:none;border-radius:inherit;opacity:var(--gg);
    background:linear-gradient(to right,
      rgb(var(--page) / .90) 0,
      rgb(var(--page) / .86) 120px,
      rgb(var(--page) / .78) 260px,
      rgb(var(--page) / .60) 380px,
      rgb(var(--page) / .38) 470px,
      rgb(var(--page) / .14) 545px,
      rgb(var(--page) / 0) 620px)}
  /* The hero keeps the identical edge-scrim structure in light mode, but it
     lifts toward its paper field instead of reintroducing a dark veil. */
  .card[data-tone="takeover"][data-lum="light"] .c-stage::after{
    background:linear-gradient(to right,
      rgb(233 231 226 / .94) 0,
      rgb(233 231 226 / .90) 120px,
      rgb(233 231 226 / .80) 260px,
      rgb(233 231 226 / .57) 380px,
      rgb(233 231 226 / .30) 470px,
      rgb(233 231 226 / .10) 545px,
      rgb(233 231 226 / 0) 620px)}
}
.card[data-tone="takeover"] .c-copy{max-width:min(34ch,46vw)}
/* A display line's measure has to be counted in the DISPLAY font. `.c-copy`
   caps at 46ch of the BODY font — about 400px — and at 78px that is barely one
   word, which is why the hero set one word per line. Each tone now states its
   own measure in its own ch. */
/* The measure is what fixes the line COUNT, and the count is what fixes the
   rag: at 777px the hero could not fit "The operating system" on one line, so
   the breaker was solving an exactly-3-line problem whose own minimum is 37%
   ragged. The breaker is not the defect — the box it was handed is. */
.card[data-tone="takeover"] .c-head{font-size:calc(clamp(36px,5.4vw,78px) * var(--hs,1));max-width:18ch}
.card[data-tone="takeover"] .c-copy{max-width:min(66vw,960px)}
.card[data-tone="takeover"] .c-body{max-width:34ch}
.card[data-tone="dark"] .c-head{max-width:min(20ch,663px)}
/* the other half of the same fix. `.c-head` may declare 16ch of Satoshi (663px)
   but it is clamped by `.c-copy`'s min(46ch,100%), counted in ARCHIVO — 406px —
   so card 03 broke to three lines at 67% ragged-right with "stays" orphaned on
   a 125px line. The breaker cannot beat that: it is an exact minimiser over a
   line count the measure has already forced. */
.card[data-tone="dark"] .c-copy{max-width:min(663px,58%)}

/* ── Z1..Z3 copy ───────────────────────────────────────────────────────── */
/* The copy column must END where the aperture begins. Its grid track is the
   whole card minus the rail, so without this the headline runs under the
   stage — the track is wider than the space the composition actually leaves. */
/* The aperture is pinned at y=130 on 7/7 light cards, the rail plate at 203,
   the fine strip at 613 — and the copy block's first ink measured
   219/258/260/238/248/239/247: a 41px spread on the one thing the reader's eye
   enters by. `align-self:center` on a variable-height block against three
   fixed rectangles. It now starts on the aperture's own top line. */
.c-copy{grid-column:1;grid-row:1;align-self:start;justify-self:start;z-index:3;
  padding-top:var(--copy-top,0px);
  max-width:min(46ch,100%);position:relative;
  opacity:var(--c);transform:translateY(calc(16px * (1 - var(--c))))}
/* taxonomy #5 — an opaque underlay behind every block of type that sits over
   live art, so the label plane is uniform card to card */
/* This was a radial colour ramp. Two measurements killed it: a hard band edge
   at x=538 crossing BOTH materials on desktop (8-bit quantisation stepping in
   the colour ramp itself), and on mobile a ground spread of 137 across a
   single paragraph — its 78% stop landed INSIDE the measure, so white body
   type fell to 2.67:1. A blurred SOLID has no colour ramp to quantise: the
   core is one flat value under the whole text and only the alpha falls off. */
/* A blurred RECTANGLE still has a rectangular footprint: on card 09 the plate
   read as a visible dark box behind the headline once the door's light column
   sat behind it. The blur softens the edge, it does not remove the shape. An
   elliptical alpha mask does — and because the fill stays one FLAT colour, the
   thing that killed the original radial version (8-bit banding in a colour
   ramp) cannot come back: only alpha varies, and only out in the -26/-36px
   margin where there is no ink to sit on. */
/* ROUND 14, user directive: "entendiste lo de quitar la opacidad". The blurred
   elliptical plate behind the copy is DELETED, not zeroed — it was the layer
   the user was pointing at. What replaced it is the edge-anchored ramp above
   (wide layout, takeovers) and the one in the phone block (all cards): the same
   idiom at both breakpoints, so there is one answer to "what carries type over
   art" instead of two. The seven non-takeover cards need neither on the wide
   layout: their stage starts at --sl:.37, so no art is ever behind their copy —
   measured body core 81.44 flat on 5 of 5 light cards, 208.1 on both dark. */

/* ROUND 14, user directive: "quitar el chapter number y chapter name de cada
   card". Round 13 hid this on the phone only; the directive carries no width,
   so it is hidden at EVERY width now. The chapter number is not lost — the
   header still carries "04 / 09" and the rail still names the chapter on the
   wide layout. Hidden, not deleted: one line puts it back. */
.c-eye{display:none}
.c-eye--was{display:flex;align-items:center;gap:13px;margin-bottom:clamp(14px,2vh,22px)}
/* C6 — the index is struck like a coin edge: disc + ring + milled bezel */
.c-idx{position:relative;flex:none;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  font:600 .64rem/1 "Space Grotesk",monospace;letter-spacing:.02em;font-style:normal;
  color:var(--ax);background:color-mix(in srgb,var(--ax) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--ax) 42%,transparent)}
.c-idx::before{content:"";position:absolute;inset:-4px;border-radius:50%;
  background:repeating-conic-gradient(from 0deg,color-mix(in srgb,var(--ax) 50%,transparent) 0deg 2deg,transparent 2deg 30deg);
  -webkit-mask:radial-gradient(circle,transparent 0 calc(50% - 2px),#000 calc(50% - 2px) 50%,transparent 50%);
          mask:radial-gradient(circle,transparent 0 calc(50% - 2px),#000 calc(50% - 2px) 50%,transparent 50%);
  opacity:.8}
.c-eye-t{font:600 .655rem/1.3 "Space Grotesk",monospace;letter-spacing:.19em;text-transform:uppercase;
  color:var(--ink-kicker)}

/* --hs: the display answers its own LENGTH. A six-word statement and a
   twelve-word one cannot be set at the same size in the same box — the long
   one either runs off the card or turns into a column of single words. JS
   measures the string once and states the ratio here. */
/* the scroll-velocity skew. It was being written to --sk every frame on all
   nine cards and `grep -c "var(--sk)"` returned 0 in this file and 0 in the
   markup — the whole feature was inert, and nine inline-style writes per frame
   were dirtying each card's style for no output. It goes on the TYPE, never on
   the wrap: a skew on the wrap makes every stage's axis-aligned scissor rect
   wrong, because the AABB of a skewed quad is larger than the quad, and the
   world bleeds outside its own aperture during a fast scroll. */
.c-head,.c-body,.c-punch{transform:skewY(var(--sk,0deg));will-change:transform}
@media (prefers-reduced-motion:reduce){.c-head,.c-body,.c-punch{transform:none}}
.c-head{font:500 clamp(30px,4.15vw,60px)/1.03 Satoshi,sans-serif;letter-spacing:-.032em;
  font-size:calc(clamp(30px,4.15vw,60px) * var(--hs,1));
  color:var(--ink-display);text-wrap:balance;margin-bottom:clamp(14px,2vh,20px)}
/* C8 — word boxes are nowrap so the per-letter split can never break inside a
   word; the letters animate inside a box that itself wraps normally */
.c-head .w{display:inline-block;white-space:nowrap}
.c-head .ln{display:block;width:max-content;max-width:100%;white-space:nowrap}
.c-head .l{display:inline-block;transform:translateY(118%) rotate(9deg);opacity:0}
.c-head.on .l{animation:letterIn .95s var(--ease) forwards}
@keyframes letterIn{60%{transform:translateY(-3.5%) rotate(-.4deg);opacity:1}
  100%{transform:none;opacity:1}}

/* text-wrap:pretty is what removes the one-word last lines measured here:
   "agree." 32px against a 316px measure, "telling." 35px against 235px.
   balance is for the display, pretty is for the paragraph. */
/* the punchline: the copy's own closing beat, set as a statement rather than
   as more body — one rank up in weight, one rank down in size, and a rule
   above it so it reads as a conclusion and not as a second paragraph */
/* text-wrap:balance, not pretty: the punch is DISPLAY rank, so a 10px second
   line carrying "it." is a broken headline rather than a widow. Measured before:
   336px/10px = 97.0% ragged-right on card 08, 77.0% on 05, 71.1% on 06. The
   least-squares breaker in main.js only ever runs on `.c-head`, and balance is
   what the browser can do for a block of ordinary inline text. */
.c-punch{margin-top:clamp(14px,2vh,22px);padding-top:clamp(12px,1.6vh,18px);
  border-top:1px solid var(--ink-rule);
  font:600 clamp(12.5px,.95vw,14.5px)/1.45 Satoshi,sans-serif;letter-spacing:-.012em;
  color:var(--ink-display);max-width:34ch;text-wrap:balance}
/* The brief names two lines load-bearing — the promise on 01, the thesis on 09
   — and both inherited the generic punch rule, so they rendered 2-3px SMALLER
   than the paragraph directly above them, in the same slot and the same weight
   as the seven ordinary section clinchers. On 09 that put a category cliche at
   56px and the sentence the brand is built on at 13px under a hairline: the
   page's own hierarchy was telling the reader the cliche was the point. Colour
   was already display rank; the missing lever was size. The rule goes too — a
   hairline above a statement makes it an annotation to the paragraph, and
   these two are not annotations to anything. */
#top .c-punch{border-top:0;padding-top:0;
  font:600 clamp(19px,1.5vw,26px)/1.32 Satoshi,sans-serif;
  letter-spacing:-.021em;max-width:26ch}
.c-ops{margin-top:clamp(12px,1.8vh,18px)}
.c-body{font:400 clamp(14.5px,1.12vw,17.5px)/1.62 Archivo,sans-serif;color:var(--ink-body);
  max-width:44ch;text-wrap:pretty}
/* the action row is allowed to be wider than the copy measure: a 40ch text
   column is narrower than two pills, and wrapping them reads as a mistake */
.c-acts{display:flex;flex-wrap:wrap;gap:12px;margin-top:clamp(20px,3vh,30px);
  width:max-content;max-width:min(52ch,46vw)}
.c-links{list-style:none;display:flex;flex-wrap:wrap;gap:10px 26px;margin-top:22px}
/* footer links inherit the BODY rank — an affordance must not outrank the text
   it sits in; the underline carries the affordance, not extra brightness */
.c-links a{color:var(--ink-body);text-decoration:none;font:400 clamp(14.5px,1.12vw,17.5px)/1.6 Archivo,sans-serif;
  border-bottom:1px solid color-mix(in srgb,var(--ax) 60%,transparent);padding-bottom:2px;
  transition:border-color .3s,transform .3s var(--ease);display:inline-block}
.c-links a:hover{border-color:var(--ax);transform:translateX(4px)}

/* C16 — a written roster: greppable and screen-readable, not pixels only */
.c-roster{list-style:none;display:flex;flex-wrap:wrap;gap:5px 7px;margin-top:20px;max-width:44ch}
.c-roster li{font:600 .58rem/1 "Space Grotesk",monospace;letter-spacing:.15em;text-transform:uppercase;
  color:rgb(255 255 255 / .62);border:1px solid rgb(255 255 255 / .17);border-radius:5px;padding:5px 7px}
.card[data-tone="light"] .c-roster li{color:rgb(var(--ink) / .62);border-color:rgb(var(--ink) / .16)}

/* ── AIPump / source-ranked models ───────────────────────────────────── */
/* The model panel is deliberately a reading surface, not a trading ticket:
   rank is AIPump's order, each trace is its published OOS walk-forward path,
   and the status badge reports the source's own investability gate verbatim. */
.model-board{position:absolute;z-index:4;left:calc(33% + 18px);right:calc(22% + 18px);
  top:calc(7% + 14px);bottom:calc(16% + 12px);display:flex;flex-direction:column;
  gap:10px;color:rgb(16 16 45);opacity:var(--c);transform:translateY(calc(14px * (1 - var(--c))));
  transition:opacity .35s,transform .35s var(--ease)}
.model-board-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;min-height:38px}
.model-kicker{display:flex;align-items:center;gap:7px;font:600 .55rem/1 "Space Grotesk",monospace;
  letter-spacing:.15em;color:rgb(16 16 45 / .62)}
.model-kicker i{width:6px;height:6px;border-radius:50%;background:var(--e-violet-solid);
  box-shadow:0 0 0 4px rgb(128 57 186 / .12)}
.model-board[data-state="live"] .model-kicker i{background:#15966f;box-shadow:0 0 0 4px rgb(21 150 111 / .12)}
.model-board h3{margin-top:6px;font:600 clamp(16px,1.25vw,20px)/1 Satoshi,sans-serif;letter-spacing:-.025em;color:rgb(16 16 45 / .94)}
.model-sync{padding-top:2px;font:600 .53rem/1.35 "Space Grotesk",monospace;letter-spacing:.10em;text-align:right;
  text-transform:uppercase;color:rgb(16 16 45 / .58);white-space:nowrap}
.model-list{list-style:none;display:flex;flex:1;flex-direction:column;gap:6px;min-height:0}
.model-card{display:grid;grid-template-columns:23px minmax(92px,1fr) minmax(94px,1.15fr) auto;
  align-items:center;gap:10px;min-height:0;flex:1;padding:7px 9px;border:1px solid rgb(16 16 45 / .12);
  border-radius:9px;background:rgb(255 255 255 / .94);box-shadow:0 5px 16px rgb(16 16 45 / .05);
  transition:transform .35s var(--ease),border-color .35s,box-shadow .35s}
.model-card:hover{transform:translateX(3px);border-color:rgb(128 57 186 / .38);box-shadow:0 9px 20px rgb(16 16 45 / .09)}
.model-rank{font:600 .57rem/1 "Space Grotesk",monospace;letter-spacing:.04em;color:var(--e-violet-solid)}
.model-id{font:600 .69rem/1.1 "Space Grotesk",monospace;letter-spacing:.06em;color:rgb(16 16 45 / .90)}
.model-thesis{overflow:hidden;margin-top:4px;font:500 .58rem/1.25 Archivo,sans-serif;color:rgb(16 16 45 / .56);
  white-space:nowrap;text-overflow:ellipsis}
.model-walk{align-self:stretch;min-width:0;display:grid;grid-template-columns:1fr auto;align-items:center;gap:7px}
.model-walk svg{width:100%;height:32px;overflow:visible}
.model-walk-base{stroke:rgb(16 16 45 / .16);stroke-width:1;vector-effect:non-scaling-stroke}
.model-walk-path{fill:none;stroke:var(--e-violet-solid);stroke-width:1.65;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke}
.model-walk-dot{fill:var(--e-violet-solid)}
.model-walk-label{font:600 .49rem/1 "Space Grotesk",monospace;letter-spacing:.06em;text-transform:uppercase;color:rgb(16 16 45 / .45)}
.model-tags{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:4px;max-width:115px}
.model-tag{padding:4px 5px;border:1px solid rgb(16 16 45 / .12);border-radius:4px;
  font:600 .47rem/1 "Space Grotesk",monospace;letter-spacing:.07em;text-transform:uppercase;color:rgb(16 16 45 / .54);white-space:nowrap}
.model-tag.good{color:#0b7251;border-color:rgb(11 114 81 / .26);background:rgb(21 150 111 / .06)}
.model-tag.warn{color:#7d4b00;border-color:rgb(193 123 0 / .28);background:rgb(193 123 0 / .06)}
.model-disclaimer{font:500 .52rem/1.35 "Space Grotesk",monospace;letter-spacing:.05em;color:rgb(16 16 45 / .52)}
.model-skeleton{flex:1;min-height:54px;border-radius:9px;border:1px solid rgb(16 16 45 / .08);
  background:linear-gradient(100deg,rgb(16 16 45 / .045) 15%,rgb(255 255 255 / .88) 45%,rgb(16 16 45 / .045) 75%);
  background-size:220% 100%;animation:modelShimmer 1.7s ease-in-out infinite}
@keyframes modelShimmer{to{background-position:-220% 0}}
.model-board[data-state="delayed"] .model-kicker i{background:var(--e-amber-solid);box-shadow:0 0 0 4px rgb(136 89 0 / .11)}
.model-board[data-state="error"] .model-list{justify-content:center;border:1px dashed rgb(16 16 45 / .16);border-radius:9px;padding:16px}
.model-error{font:500 .68rem/1.45 Archivo,sans-serif;color:rgb(16 16 45 / .62)}

/* ── Z5 the rail ───────────────────────────────────────────────────────── */
/* on its OWN opaque plate — a .9-alpha white panel on a white card is
   invisible, so the plate is a real tint plus a border and a shadow */
.c-rail{grid-column:2;grid-row:1;align-self:center;z-index:3;position:relative;
  width:clamp(186px,15vw,232px);padding:17px 17px 19px;border-radius:15px;
  /* the plate under the rail must be OPAQUE. It sits over the aperture, and
     a translucent panel there lets the live art through the numbers, which is
     exactly the non-uniform label plane taxonomy #5 exists to prevent.
     It must also be the SAME opaque value on every card. Borrowing --plate
     made it follow the tone: the dark cards' plate is 16,18,36 and the
     takeovers' is 8,9,20, so the identical rail measured 161 on one and 157
     on the other — a 4.0 spread on the one element that is literally the same
     object nine times over. */
  background:rgb(var(--rail-plate));
  box-shadow:inset 0 0 0 100vmax rgb(var(--ink) / .05);
  border:1px solid rgb(var(--ink) / .15);
  filter:drop-shadow(0 12px 30px rgb(var(--ink) / .16));
  opacity:calc(var(--gg) * .999);transform:translateX(calc(18px * (1 - var(--g))))}
.c-rail-label{font:600 .58rem/1 "Space Grotesk",monospace;letter-spacing:.15em;text-transform:uppercase;
  color:var(--ink-kicker-sm);margin-bottom:13px}
.c-rail ol{list-style:none;display:flex;flex-direction:column;gap:1px}
.c-rail li{display:flex;gap:9px;align-items:baseline;position:relative;padding:3.5px 0 3.5px 9px;
  font:400 .715rem/1.35 Archivo,sans-serif;color:rgb(var(--ink) / .34);transition:color .45s}
.c-rail li i{font:600 .6rem/1.35 "Space Grotesk",monospace;font-style:normal;font-variant-numeric:tabular-nums;
  color:rgb(var(--ink) / .3);transition:color .45s}
/* C7 — the lit step gets a 1px leading rule that draws in from the left */
.c-rail li::before{content:"";position:absolute;left:0;top:6px;bottom:6px;width:1px;background:var(--ax);
  transform:scaleY(0);transform-origin:50% 0;transition:transform .5s var(--ease)}
/* Measured: rail-current 106.5-111.9 against body 121.6-123.4 — a nav label
   was the second-darkest mark on every light card, mean 14.2 ahead of the
   paragraph it exists to serve, and five declared levels collapsed into a
   21.6-wide window. Small bold ink cores DEEPER than regular ink at equal
   alpha — the same asymmetry this file already documents for the kicker — so
   the current step needs a lower alpha than body to measure at body's rank.
   Its state is carried by weight, by the axis rule and by the number. */
.c-rail li.lit{color:rgb(var(--ink) / .5)}
.c-rail li.lit i{color:var(--ax)}
.c-rail li.lit::before{transform:scaleY(1)}
.c-rail li[data-me]{color:rgb(var(--ink) / .58);font-weight:600}
.c-rail li[data-me] i{color:var(--ax)}
/* ROUND 14, user directive: "tambien quita la barra de progreso". Two elements
   answered to that name and both are gone: the blue scroll rule under the
   header (above) and this fill under the chapter list. Neither carried
   information the page does not still state in words — the header counts
   "NN / 09" and the rail still lights the chapter you are in. The `--rl` var
   they read is still written every frame; it drives the entry law, so nothing
   downstream changes. (Round 15d removed the spine it also drove.) */

/* ── Z6 the fine strip ─────────────────────────────────────────────────── */
/* .55rem, not .585rem: at 9.36px this aria-hidden ticker measured 0.08px
   LARGER than the .c-rail-label it sits under (9.28px). Weight, tracking and
   ink all rank the label first; size ranked the ticker first, on the one axis
   the label's own note called primary. 8.8px puts size in agreement with the
   other three and costs a decorative strip nothing. */
.c-fine{grid-column:1/-1;grid-row:2;z-index:3;justify-self:start;
  display:flex;gap:7px;align-items:center;flex-wrap:wrap;
  padding:8px 13px;border-radius:9px;
  background:rgb(var(--plate));
  box-shadow:inset 0 0 0 100vmax rgb(var(--ink) / .05);
  border:1px solid rgb(var(--ink) / .12);
  /* The rail label and this strip were the SAME typographic object at two
     opacities: 9.28 vs 9.36px, both 600, both Space Grotesk, both .15em, both
     uppercase — separated on colour alone, i.e. one axis of three. A navigation
     label and a decorative ticker should not be one object. This one gives up
     weight and tracking; it keeps the caps, because micro-caps ARE the machine
     voice and dropping them would cost the system more than it buys. */
  font:500 .55rem/1.5 "Space Grotesk",monospace;letter-spacing:.09em;text-transform:uppercase;
  /* .6 is the LIGHT-PLATE alpha, and it is one number for all six light-plate
     tickers on purpose. Navy at .5 over the white plate measures 3.49:1 against
     a 4.5 floor; .6 measures 5.2:1. axe only ever reported the hero's four
     words because it cannot resolve a WebGL ground and files the other five
     cards as INCOMPLETE — but they are the same ink on the same plate, so
     fixing only the card the tool could see would have split one rank into two
     declared values and traded an a11y failure for a spread failure. */
  color:rgb(var(--ink) / .6);opacity:var(--f);transform:translateY(calc(8px * (1 - var(--f))))}
.card[data-tone="dark"] .c-fine,.card[data-tone="takeover"] .c-fine{color:rgb(255 255 255 / .55)}
/* ROUND 9 — and NOT on the pale hero, where that rule put white ink on a white
   plate: measured 0.1% glyph coverage, i.e. the ticker was rendering nothing at
   all. It takes the light cards' own ink and their own lit-chip colour. */
/* .6, not the .5 every other tone uses. Round 9 moved this strip onto a white
   plate and kept the alpha that was written for a dark one: measured 3.49:1
   against a 4.5 floor on all four unlit words, i.e. four axe serious
   color-contrast violations sitting on the hero, on BOTH viewports. .6
   measures 5.2:1 and still sits well below the .77 the rail label above it
   carries, so the rank order the ticker is gated on is unchanged. */
.card[data-tone="takeover"][data-lum="light"] .c-fine{color:rgb(var(--ink) / .6)}
.card[data-tone="takeover"][data-lum="light"] .c-fine b[data-on]{color:var(--ax-solid)}
.card[data-tone="takeover"][data-lum="light"] .c-idx,
.card[data-tone="takeover"][data-lum="light"] .c-rail li.lit i,
.card[data-tone="takeover"][data-lum="light"] .c-rail li[data-me] i{color:var(--ax-solid)}
/* C9 — the three product axes run as a ticker, the current one lit */
.c-fine b{font-weight:600;position:relative;padding-right:7px}
.c-fine b+b::before{content:"·";position:absolute;left:-7px;opacity:.45}
.c-fine b[data-on]{color:var(--ax)}

/* ── preloader ─────────────────────────────────────────────────────────── */
.pre{position:fixed;inset:0;z-index:60;background:#fff;color:#111;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:0;padding:32px 20px;text-align:center;transition:opacity .55s var(--ease),visibility .55s;overflow:hidden}
.pre.done{opacity:0;visibility:hidden;pointer-events:none}
.pre-emblem{position:relative;width:104px;height:104px;margin-bottom:30px;isolation:isolate}
.pre-emblem::before{content:"";position:absolute;inset:-30px;border-radius:50%;background:radial-gradient(circle,rgb(0 140 255 / .16),transparent 65%);animation:preAura 2.6s ease-in-out infinite;z-index:-1}
.pre-mark{display:block;width:100%;height:100%;border-radius:16px;box-shadow:0 14px 34px rgb(0 0 0 / .13)}
.pre-glint{position:absolute;inset:0;border-radius:16px;overflow:hidden;pointer-events:none}
.pre-glint::after{content:"";position:absolute;inset:-50%;background:linear-gradient(110deg,transparent 35%,rgb(0 140 255 / .12) 43%,rgb(255 255 255 / .65) 50%,rgb(0 140 255 / .18) 56%,transparent 65%);transform:translateX(-75%);animation:preGlint 2.6s ease-in-out infinite}
.pre-brand{font:500 11px/1.4 Archivo,sans-serif;letter-spacing:.15em;margin:0 0 16px;color:#606060}
.pre-title{font:500 clamp(30px,5vw,48px)/1.1 Satoshi,sans-serif;letter-spacing:-.04em;margin:0 0 18px}
.pre-value{font:400 clamp(13px,2.4vw,16px)/1.6 Archivo,sans-serif;color:#616161;margin:0}
.pre-signals{display:flex;align-items:center;gap:14px;margin-top:28px;font:500 11px/1.4 Archivo,sans-serif;color:#555}
.pre-signals span{animation:preSignal 2.6s ease-in-out infinite}
.pre-signals span:nth-of-type(2){animation-delay:.3s}.pre-signals span:nth-of-type(3){animation-delay:.6s}
.pre-signals i{width:3px;height:3px;border-radius:50%;background:#008CFF}
.pre.done *,.pre.done *::before,.pre.done *::after{animation-play-state:paused}
@keyframes preAura{0%,100%{opacity:.35;transform:scale(.9)}50%{opacity:1;transform:scale(1.1)}}
@keyframes preGlint{0%,12%{transform:translateX(-75%)}70%,100%{transform:translateX(75%)}}
@keyframes preSignal{0%,100%{color:#555}35%{color:#0A5BD0}}
@media(prefers-reduced-motion:reduce){.pre *,.pre *::before,.pre *::after{animation:none !important}}
@media(max-height:540px){.pre{padding:20px}.pre-emblem{width:68px;height:68px;margin-bottom:16px}.pre-title{font-size:30px}.pre-signals{margin-top:18px}}
body[data-graphics="recovering"] #world,body[data-graphics="unavailable"] #world{visibility:hidden}
:root.booting .pre:not(.done){display:flex}

/* ── cursor ────────────────────────────────────────────────────────────── */
.cur{position:fixed;left:0;top:0;z-index:50;pointer-events:none;opacity:0;
  mix-blend-mode:difference;transition:opacity .3s}
.cur.on{opacity:1}
.cur i{position:absolute;border-radius:50%;transform:translate(-50%,-50%)}
.cur-d{width:5px;height:5px;background:#fff}
.cur-r{width:30px;height:30px;border:1px solid rgb(255 255 255 / .55);
  transition:width .3s var(--ease),height .3s var(--ease)}
.cur.hot .cur-r{width:52px;height:52px}
@media (pointer:coarse){.cur{display:none}}

/* ── responsive ────────────────────────────────────────────────────────── */
@media (max-width:1060px){
  .card{--sl:.32;--sr:.27}
  .c-rail{width:172px}
}
@media (max-width:860px){
  .card{width:94vw;height:auto;min-height:78svh;
    grid-template-columns:minmax(0,1fr);grid-template-rows:1fr auto;
    --st:0; --sr:0; --sb:0; --sl:0;
    padding:clamp(20px,5vw,30px)}
  /* The SAME specificity failure this round already fixed for the dark tone's
     `.c-copy`, missed on the takeover tone's own box. `.card[data-tone=
     "takeover"]` is (0,2,0) and the mobile `.card` reset is (0,1,0), so
     `height:100svh` survived into the single-column layout where stage + copy
     + rail + fine stack to 1102px (card 01) and 1145px (card 09) against an
     842px box with `overflow:hidden`. Measured loss: 260px and 303px —
     card 09's ENTIRE nine-item chapter rail and the site's only copyright line
     rendered to nothing. `width:100vw` survived too, so the two takeovers were
     390px/351px wide against every other card's 264px. */
  .card[data-tone="takeover"]{width:94vw;height:auto;min-height:78svh;
    padding:clamp(22px,6vw,34px) clamp(20px,6vw,30px) 68px}
  /* The live model library is a compact instrument above the section's copy.
     Giving this one chapter more vertical runway preserves both the five OOS
     traces and the action without turning either into a scrollable mini-app. */
  #models{min-height:max(850px,102svh)}
  #models .model-board{left:20px;right:20px;top:24px;bottom:auto;height:390px;gap:8px}
  #models .model-board-head{min-height:34px}
  #models .model-board h3{font-size:17px}
  #models .model-card{grid-template-columns:20px minmax(76px,1fr) minmax(88px,1.2fr);gap:7px;padding:6px 7px}
  #models .model-tags{display:none}
  #models .model-thesis{font-size:.54rem}
  #models .model-walk svg{height:27px}
  #models .model-disclaimer{font-size:.48rem}
  /* r10, user directive: "los card animados deben estar atras del texto".
     Until now one column stacked TWO blocks — a 330px art band, then the copy
     under it — and read as two unrelated rectangles. The stage now covers the
     whole card and sits BEHIND the type (stage z-index 1, copy 3), so a phone
     card is one composition: art edge to edge, words floating on it. The
     scissor rect the renderer uses IS this element's box, so every device
     reframes to the card's own aspect (390x844: 367x658, AR 0.56) — `minW`
     dollies the camera back and `fit` contains each subject, exactly as it
     already does for the narrow desktop apertures. */
  .c-stage{position:absolute;grid-row:auto;grid-column:auto;
    top:0;right:0;bottom:0;left:0;height:auto;margin:0}
  /* the outer spread is what PAINTS the card plate; dropping it here left
     every mobile card sitting directly on the page ground with no plate */
  /* and the takeover rule below it, at higher specificity, was still painting
     the light PAGE ground — under ink that stays white at every width. On one
     column a takeover is not full-bleed, so it needs its own dark plate like
     any other dark card. Measured before: spread rgb(242,243,249) with
     headColor rgba(255,255,255,.98). */
  .card[data-tone="takeover"] .c-cut{
    box-shadow:0 0 0 2400px rgb(var(--plate) / calc(var(--gg) * .96)),
               inset 0 0 0 1px rgb(255 255 255 / calc(var(--gg) * .12)),
               inset 0 0 44px rgb(0 0 0 / calc(var(--gg) * .5))}
  /* both insets above were authored for a DARK plate: a white hairline and a
     44px black inner glow. On the pale hero they read as a dirty vignette
     inside a light card. */
  .card[data-tone="takeover"][data-lum="light"] .c-cut{
    box-shadow:0 0 0 2400px rgb(var(--plate) / calc(var(--gg) * .96)),
               inset 0 0 0 1px rgb(16 16 45 / calc(var(--gg) * .10)),
               inset 0 0 40px rgb(120 116 108 / calc(var(--gg) * .16))}
  /* r10 — one column, ONE ground. The aperture now IS the card, and an
     aperture clears STAGE_HEX: there is no pale plate left under a light
     card's navy ink. The alternative to this flip is laying a plate back over
     the art, which is precisely the box the user asked to remove. So on a
     phone the five light cards take the dark tone's ink set and all nine read
     as one thing — art edge to edge, type floating on it. The hero is NOT in
     this set: its aperture clears pale (data-lum="light") and its glass is
     authored for a pale ground, so it is already art-behind-type. */
  .card[data-tone="light"]{
    --ink:255 255 255; --plate:16 18 36; --rail-plate:11 12 26;
    --ink-display:rgb(255 255 255 / .98); --ink-body:rgb(255 255 255 / .80);
    --ink-kicker:rgb(255 255 255 / .7); --ink-kicker-sm:rgb(255 255 255 / .74);
    --ink-rule:rgb(255 255 255 / .16)}
  /* Quant's eight chapter instruments deliberately stay on the light field at
     every viewport. The earlier mobile rule made any light card go dark so
     white type could sit on art; that is the opposite of the product direction
     here. A pale edge-gradient preserves the glass under the copy while navy
     text remains legible without turning the animation back into a dark scene. */
  .card[data-tone="light"][data-lum="light"]{
    --ink:16 16 45; --plate:255 255 255; --rail-plate:255 255 255;
    --ink-display:rgb(16 16 45 / .94); --ink-body:rgb(16 16 45 / .72);
    --ink-kicker:rgb(16 16 45 / .75); --ink-kicker-sm:rgb(16 16 45 / .77);
    --ink-rule:rgb(16 16 45 / .14)}
  .card[data-tone="light"][data-lum="light"] .c-cut{
    box-shadow:0 0 0 2400px rgb(var(--plate) / calc(var(--gg) * .96)),
               inset 0 0 0 1px rgb(16 16 45 / calc(var(--gg) * .10)),
               inset 0 0 40px rgb(120 116 108 / calc(var(--gg) * .16))}
  /* --ax-solid is the accent DARKENED for a light plate — it exists because the
     stroke token measured 2.66:1 on paper. On the dark ground the stroke token
     is the one that measures 4.85-5.20:1, so the darkened variant goes back. */
  .card[data-tone="light"] .c-idx,
  .card[data-tone="light"] .c-fine b[data-on]{color:var(--ax)}
  /* ROUND 13, user directive: "eso puede ser degradado desde la orilla de la
     pantalla y mas sutil en la mitad de longitud."

     Two things change. The scrim moves OFF the copy and onto the stage, and it
     stops being a slab.

     Anchoring: `.c-stage` is inset:0 of the card on one column, so it IS the
     screen edge the directive names — while `.c-copy` is a box whose height
     runs 206px (markets) to 402px (contact). A ramp anchored to the copy is a
     different ramp on every card by construction; anchored to the card it is
     one ramp, and its stops can be stated in the same absolute pixels the
     content was measured in.

     Shape: round 10's version held a flat .84 plateau across the whole copy and
     put its entire fall into a 132px band, which is a plate with a soft top
     edge, not a gradient. This falls continuously from the bottom edge, so by
     mid-card it is already thin and the art reads through the headline.

     Stops are solved against the measured content, not chosen: the body — the
     one rank that binds, being 16px at .82 over live art — sits 133-289px above
     the card bottom on the seven ordinary cards, and 373-492px on the hero and
     contact, which carry buttons and contact links below it. */
  /* ROUND 14b, user directive: "te falto arreglar las opacidades ... en la vista
     mobile". The shape was already a continuous fall; the COLOUR was the defect,
     and it is the same mistake the wide layout made until this round — a scrim
     the colour of the PLATE.
     Measured, scrim off, type hidden, per ink block: the phone stage is already
     dark (median ground 9.6 under every rank on 9/9 cards). What crosses the
     type is not a bright field, it is a handful of bright STROKES — the order
     book's bars read p90 184.7 and max 242.8 straight through card 04's
     paragraph. A navy plate at .94 answers that by flattening BOTH: a 245 bar
     lands on 32 and the 9.6 ground is LIFTED to 18.3, so the bars turn into
     grey slabs and the card's blacks go milky. That milk is the "opacidad" the
     user is pointing at.
     Black at the same alpha is a multiply, not a fill: every channel scales, so
     the bar keeps its hue and the ground goes DOWN instead of up. Same numbers,
     both measured over a 245 bar on a 9.6 ground at a=.74 — navy gives 66 on
     16.5, black gives 52 on 2.5: identical 49.5 of contrast, but black keeps
     the black black and the blue blue. It is also the safer number for the
     type: white .80 over the navy-composited bar reads 217.2, one point PAST
     the 215 ceiling, where over the black-composited bar it reads 214.4.
     The fall is steeper too, because the ranks it must protect were measured:
     ink stops 376px above the card bottom on the seven ordinary cards, so the
     ramp is done by 540 there instead of 660. The two takeovers carry copy to
     587 and get their own longer tail below. */
  .c-stage::after{content:"";position:absolute;inset:0;z-index:2;
    pointer-events:none;border-radius:inherit;opacity:var(--gg);
    background:linear-gradient(to top,
      rgb(0 0 0 / .90) 0,
      rgb(0 0 0 / .89) 130px,
      rgb(0 0 0 / .86) 215px,
      rgb(0 0 0 / .72) 295px,
      rgb(0 0 0 / .46) 372px,
      rgb(0 0 0 / .21) 452px,
      rgb(0 0 0 / 0) 540px)}
  /* the hero's headline top sits 575px above the card bottom and contact's 587,
     against 293-376 on the other seven — a single ramp cannot serve both, and
     anchoring it to the copy instead of the card is the mistake round 13 already
     measured (the copy box runs 206-402px, so it is a different ramp per card). */
  /* ROUND 14c, user directive: "me parece que en el hero page en mobile sigue la
     opacidad." Correct, and the fix is to take it away entirely rather than
     thin it: the HERO NEEDS NO SCRIM ON THE PHONE, and the measurement says so
     in the direction I did not expect. Ground under its copy, scrim off:
     display p90 13.3, body p90 10.2 — the mark reads as a silhouette against
     the void, not as a lit field, so there is nothing there to knock down. Read
     four times, and swept across five scroll offsets so the beam's own travel
     is included: 36/36 PASS, `takeover body` spread 0.4-0.9 (it was 1.9 WITH
     the scrim — the veil was pushing the hero's ground to near-black while
     contact's stayed at 19, which made the two cards differ), punch 0.7,
     display 0.1-0.2.
     Contact is the opposite case and keeps its ramp: its traces are not a
     silhouette but a dense field, p50 13-20 with peaks at 142 under EVERY rank
     including the email links. Rendered without it, the card reads as clutter. */
  #top .c-stage::after{content:none}
  /* ROUND 15c. The wall term added in 15b lights every device's body, and on
     card 08 the rack of slabs sits DIRECTLY behind the body block on the
     stacked layout: measured band40 210.6 against 204.1-206.1 for the other
     six dark cards — a 6.5 spread on a 4.0 gate, and the only card out of
     line. The scrim is the lever taxonomy #5 names for exactly this, so the
     one card that needs a deeper one gets a deeper one. */
  #app .c-stage::after{
    background:linear-gradient(to top,
      rgb(0 0 0 / .93) 0,
      rgb(0 0 0 / .92) 130px,
      rgb(0 0 0 / .90) 215px,
      rgb(0 0 0 / .84) 295px,
      rgb(0 0 0 / .70) 372px,
      rgb(0 0 0 / .46) 452px,
      rgb(0 0 0 / .18) 540px,
      rgb(0 0 0 / 0) 620px)}
  #access .c-stage::after{
    background:linear-gradient(to top,
      rgb(0 0 0 / .86) 0,
      rgb(0 0 0 / .84) 150px,
      rgb(0 0 0 / .78) 280px,
      rgb(0 0 0 / .66) 400px,
      rgb(0 0 0 / .48) 510px,
      rgb(0 0 0 / .26) 610px,
      rgb(0 0 0 / 0) 700px)}
  .card[data-lum="light"] .c-stage::after,
  #app.card[data-lum="light"] .c-stage::after,
  #access.card[data-lum="light"] .c-stage::after{
    background:linear-gradient(to top,
      rgb(245 244 248 / .97) 0,
      rgb(245 244 248 / .95) 150px,
      rgb(245 244 248 / .89) 280px,
      rgb(245 244 248 / .72) 410px,
      rgb(245 244 248 / .43) 550px,
      rgb(245 244 248 / .14) 680px,
      rgb(245 244 248 / 0) 800px)}
  /* the ticker's two alphas were one rank on two GROUNDS — .5 on paper, .55 on
     a plate — and the flip above puts both on the same plate. Measured as one
     group they read 143.4 and 154.3: same rank, two designs. */
  .card[data-tone="light"] .c-fine{color:rgb(255 255 255 / .55)}
  .card[data-tone="light"][data-lum="light"] .c-fine{color:rgb(var(--ink) / .55)}
  /* The kicker is what BINDS the scrim, and it binds for a reason no amount of
     scrim tuning removes: 9px caps at .19em are nearly all AA skirt, so the
     ground is most of what the instrument measures, and a live ground moves
     with the animation frame. Measured: at plateau .88 the same file read 3.0,
     5.0, 6.6 and 6.8 on four runs of one gate. Rather than buy uniformity by
     making the scrim opaque — which would put the art back BEHIND a wall, the
     thing this round exists to undo — the fragile rank gets its own ground.
     `.c-fine` is already exactly this object at the other end of the card:
     micro-caps on an opaque plate with a hairline. Making the two micro-cap
     rows one idiom is what lets the scrim drop to where the art reads. */
  /* ROUND 13, user directive: "elimina el titulo del card que parece indice que
     marca el numero y nombre del card ... solo el contenido del card." The
     eyebrow IS that title — the struck numeral plus "04 - PRODUCT - MARKETS" —
     and round 12 had just given it a plate of its own, which is exactly what
     made it read as an index chip rather than as a label. The chapter number is
     not lost: the header still carries "04 / 09" at every width. Hidden, not
     deleted, for the same reason the rail is. */
  .card[data-frame]{--st:0;--sr:0;--sb:0;--sl:0}
  .c-cut{box-shadow:0 0 0 2400px rgb(var(--plate) / calc(var(--gg) * .96)),
                    inset 0 0 0 1px rgb(var(--ink) / calc(var(--gg) * .14)),
                    inset 0 0 44px rgb(0 0 0 / calc(var(--gg) * .5))}
  /* the light-card copy is clamped to 30vw so it stops at the aperture; on one
     column there is no aperture beside it and 30vw is 117px of text */
  .card[data-tone="light"] .c-copy{max-width:100%;margin-top:0;align-self:end}
  .card[data-tone="light"] .c-body{max-width:100%}
  .card[data-tone="takeover"] .c-copy{max-width:100%}
  /* the dark tone's display measure is a DESKTOP rule: `min(663px,58%)` of a
     390px column is 226px, which set card 07's headline as an eight-line
     one-word ladder. Its specificity (0,2,1) outranks the generic `.c-copy`
     reset below, so the reset has to be stated for this tone too. */
  .card[data-tone="dark"] .c-copy{max-width:100%}
  .card[data-tone="dark"] .c-head{max-width:100%}
  .card[data-tone="light"] .c-stage{background:rgb(var(--stage) / calc(var(--gg) * .04))}
  .c-copy{grid-column:1;grid-row:1;max-width:100%;align-self:end}
  /* r10, user directive: the 1-9 chapter index is gone on one column. It was a
     <nav> with no links that cost ~200px of every card and duplicated the
     numeral already struck into `.c-idx`. It stays in the DOM rather than the
     markup: the card loop writes `lit`/`data-me` into these <li>s every frame,
     and keepOut() already returns null when the rail rect and the stage rect
     do not overlap (a display:none rail measures 0x0). */
  .c-rail{display:none}
  .c-fine{grid-row:2;margin-top:14px;position:relative;z-index:3}
  .c-head,.card[data-tone="light"] .c-head{font-size:clamp(27px,7.4vw,40px)}
  .feed{gap:34px;padding:9vh 0 11vh}
  #top{margin-top:-9vh}
}
@media (max-width:520px){
  .c-rail ol{grid-template-columns:1fr 1fr;gap:0 10px}
  .c-rail li{font-size:.66rem;padding:3px 0 3px 8px}
  .c-roster li{font-size:.54rem}
}

/* ── reduced motion: the card is fully READ, nothing is withheld ───────── */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important}
  .card{--p:1;--g:1;transform:none}
  .c-stage{transform:none}
  .c-head .l{transform:none;opacity:1;animation:none}
  .grain{animation:none}
  .cur{display:none}
}

/* Readable by default. The module adds animated surfaces to a native feed;
   missing scripts leave the content readable with the same native scroll. */
:root:not(.enhanced) body{overflow:auto}
:root:not(.enhanced) .hd{--hd-ink:255 255 255;background:rgb(var(--page))}
:root:not(.enhanced) .wrap{position:relative;inset:auto;transform:none !important;will-change:auto}
:root:not(.enhanced) .feed{padding:90px 0 40px}
:root:not(.enhanced) #top{margin-top:0}
:root:not(.enhanced) .card{
  --p:1 !important;--g:1 !important;--c:1 !important;--f:1 !important;--rl:1 !important;
  --plate:var(--paper);--ink-display:rgb(16 16 45 / .94);--ink-body:rgb(16 16 45 / .72);
  height:auto;min-height:0;grid-template-columns:minmax(0,1fr);grid-template-rows:auto;
  background:rgb(var(--paper));transform:none !important}
:root:not(.enhanced) .c-copy{max-width:none !important;margin:0 !important;padding-top:0 !important}
:root:not(.enhanced) .c-head,:root:not(.enhanced) .c-body,:root:not(.enhanced) .c-punch{
  transform:none !important;opacity:1 !important;will-change:auto}
:root:not(.enhanced) .c-head .l{transform:none;opacity:1;animation:none}
:root:not(.enhanced) .c-fine{color:rgb(16 16 45 / .6);opacity:1;transform:none}
:root:not(.enhanced) .model-board{position:static;width:auto;inset:auto;transform:none;height:auto}
:root:not(.enhanced) #world,:root:not(.enhanced) .pre,:root:not(.enhanced) .cur,
:root:not(.enhanced) .grain,:root:not(.enhanced) .c-stage,:root:not(.enhanced) .c-rail,
:root:not(.enhanced) .hd-count{display:none}
