/* ==================================================================
   EISHIKI v3 · Djoaniel Hernandez
   Reconciled 1:1 against reference/design-export/tokens/*.css
   ("Djoaniel Style" — extracted verbatim from the .fig)

   THREE families, three voices. Revised 2026-07-26.

     Instrument Serif — THE ARGUMENT. Every headline, claim and quote.
                        Sentence case, always. Never uppercase.
     Radio Canada     — THE STRUCTURE. Wordmark, body prose, UI.
     IBM Plex Mono    — THE MACHINE. Labels, readouts, eyebrows, data.

   Removed: Instrument Sans (the type lock retired it) and Anybody 900
   (it existed to set four eyebrow words per page; the eyebrow is a
   machine label, so it belongs to the mono).

   THE CASE RULE — the one thing that fixes the headline hierarchy:
     uppercase belongs to Radio Canada (the wordmark) and to the mono
     (labels). The serif is never uppercase. All-caps strips a serif of
     its voice, and the negative tracking that made caps survivable was
     crushing the counters at display size.
   ================================================================== */

/* ---------------- TOKENS (verbatim) ---------------- */
:root{
  /* base palette */
  --ink-900:rgb(9,9,9);
  --ink-700:rgb(62,62,58);
  --ink-650:rgb(61,61,57);
  --ink-600:rgb(102,102,96);
  --ink-500:rgb(116,115,101);
  --ink-400:rgb(150,149,143);
  --ink-300:rgb(51,51,51);
  --line:rgb(214,213,208);
  --paper:rgb(247,246,242);
  --white:rgb(255,255,255);
  --black:rgb(0,0,0);
  --accent-blue:rgb(11,63,255);
  --data-red:rgb(169,46,38);
  --ochre:oklch(0.74 0.115 74);
  --sage:oklch(0.56 0.05 155);

  /* semantic aliases */
  --surface-page:var(--paper);
  --surface-card-16:rgba(255,255,255,0.16);
  --surface-card-25:rgba(255,255,255,0.25);
  --surface-card-28:rgba(255,255,255,0.28);
  --surface-card-30:rgba(255,255,255,0.30);
  --surface-inverse:var(--ink-900);
  --text-primary:var(--ink-900);
  --text-body:var(--ink-700);
  --text-muted:var(--ink-600);
  --text-faint:var(--ink-400);
  --text-inverse:var(--white);
  --border-default:var(--line);
  --border-strong:var(--ink-900);
  --accent:var(--accent-blue);
  --data-null:var(--data-red);      /* ambiguous / unknown */
  --accent-warm:var(--ochre);       /* annotation, in-progress */
  --data-ok:var(--sage);            /* resolved — the "after" side of a fix */

  /* families */
  --font-display:"Instrument Serif",ui-serif,Georgia,"Times New Roman",serif;
  --font-sans:"Radio Canada",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,Consolas,monospace;
  /* the wordmark is Radio Canada 700 — J and I are tailed and barred */
  --font-wordmark:var(--font-sans);

  /* type shorthands */
  --text-hero:88px/84.48px var(--font-display);
  --text-display-lg:46px/52px var(--font-display);
  --text-display-md:40px/45.6px var(--font-display);
  --text-wordmark:188px/146.64px var(--font-wordmark);
  --text-body-lg:17px/29.75px var(--font-sans);

  /* ------------------------------------------------------------------
     MONO SCALE — four roles, replacing six ad-hoc sizes that bottomed
     out at 9px.

     Why the old scale was illegible: monospace is ALREADY letterspaced
     by construction. Every glyph sits in an identical advance, so the
     narrow ones (i l t f j) ship with generous built-in side bearings.
     Adding .10–.13em on top spaces the string a second time. Stack that
     on uppercase (which removes the word-shape cue you actually read by)
     and an 11px body (IBM Plex Mono's x-height ratio is ~0.516, so 11px
     leaves a 5.7px x-height) and you are paying three legibility taxes
     on one string. Hence: bigger, tighter, heavier.

     THE THREE RULES, enforced site-wide:
       1. Uppercase mono never below 12.5px.
       2. Mono tracking never above .05em. Ever. It is pre-tracked.
       3. Uppercase mono is 500, never 400 — uppercase optically thins
          the stems at small sizes and 400 disappears into the paper.
     Tabular / data mono is the exception to 1 and 3: it stays sentence
     case at 400, and takes ZERO tracking, because a monospace column is
     already a grid and letterspacing fights the alignment.
     ------------------------------------------------------------------ */
  --mono-label:500 13px/1.25 var(--font-mono);      /* eyebrows, nav, chips — UPPERCASE */
  --mono-caption:400 12.5px/1.35 var(--font-mono);  /* captions, helper, empty states */
  --mono-data:400 13px/1.5 var(--font-mono);        /* tables, readouts, ISINs, code */
  --mono-key:600 15px/1.2 var(--font-mono);         /* numbered keys, tokens, step numbers */
  --track-label:.04em;
  --track-caption:.02em;
  --track-data:0;

  /* legacy aliases — every existing `font:var(--text-eyebrow)` call site
     keeps working and is silently routed onto the new scale. */
  --text-nav:var(--mono-label);
  --text-eyebrow:var(--mono-label);
  --text-label:var(--mono-label);
  --text-caption:var(--mono-caption);
  --text-micro:var(--mono-caption);
  --text-data-value:var(--mono-data);

  /* space */
  --space-3xs:4px;  --space-2xs:8px;  --space-xs:12px;  --space-sm:14px;
  --space-md:18px;  --space-lg:24px;  --space-xl:34px;  --space-2xl:38px;
  --space-3xl:52px; --space-4xl:56px; --space-5xl:86px; --space-6xl:120px;

  --radius-none:0px; /* system uses zero corner radius throughout */
  --border-hair:0.667px solid var(--border-default);
  --border-solid:1px solid var(--border-default);
  --border-dashed:0.667px dashed var(--border-default);

  /* motion */
  --ease-linear:linear;
  --ease-out:cubic-bezier(0.22,1,0.36,1);
  --ease-snap:cubic-bezier(0.2,0.9,0.1,1);
  --dur-fast:120ms; --dur-med:220ms; --dur-spark:560ms;
  --dur-vt:420ms;   /* cross-document title morph — tuned in the sandbox */

  /* measure */
  --outer:1376px;
  --inner:1060px;
  --prose:714px;
  --gut:52px;

  /* case-study rail + band.
     The rail lives in the left margin now; it is no longer paid for out of
     the content width. Body band = outer - 2*gut - rail - railgap = 1000px,
     which is the width every specimen, demo and data grid gets by default.
     Prose stays at --prose inside that band, so the measure token finally
     binds instead of being silently overridden by a narrower column. */
  --rail:220px;
  --railgap:var(--space-3xl);
  --csmax:var(--outer);  /* case-study container; drops to --inner once the rail is gone */
}
@keyframes ds-spark{0%{opacity:1;transform:translate(0,0) scale(1)}70%{opacity:.9}
  100%{opacity:0;transform:translate(var(--tx),var(--ty)) scale(.35)}}

*{box-sizing:border-box}
/* overflow-x:clip, not hidden — clip does not create a scroll container, so
   the sticky topbar and sticky .snav keep working. Guards .bleed against the
   classic-scrollbar gap on Windows, where 100vw > the visible viewport. */
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;overflow-x:clip}
body{margin:0;background:var(--surface-page);color:var(--text-body);
  font:var(--text-body-lg);text-rendering:optimizeLegibility}

/* ==================================================================
   DISPLAY — Instrument Serif. One weight (400) + italic, no axes.
   Hairline survival = size floor + no synthetic bold + full-stroke
   rendering. Never set below 24px.
   ================================================================== */
.disp,.d-hero,.d-lg,.d-md,.stat .v,.pq q{
  font-family:var(--font-display);font-weight:400;
  font-synthesis-weight:none;font-synthesis-style:none;
  -webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;
  color:var(--text-primary);text-wrap:pretty;
}
/* THE LADDER — four rungs, each differentiated by role, not just size.
   Tracking is near-zero: a sentence-case serif at display size already
   has the sidebearings it wants, and negative tracking closes counters
   the hairlines can't afford to lose. */

/* 01 · page title — one per page */
.d-hero{font-size:clamp(44px,6.1vw,76px);line-height:1.0;letter-spacing:-.018em;
  margin:0 0 var(--space-lg)}

/* 02 · section headline and brief claim — the same rung, so the same style.
   A clear step down from the title rather than a near-match of it. */
.d-lg,.claim{font-family:var(--font-display);font-weight:400;
  font-synthesis-weight:none;font-synthesis-style:none;
  -webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:auto;
  color:var(--text-primary);text-wrap:pretty;
  font-size:clamp(30px,3.3vw,41px);line-height:1.14;letter-spacing:-.012em;
  margin:0 0 var(--space-lg);max-width:22ch}

/* 03 · the posed question / aside — italic is the differentiator, not size.
   It's the one thing this face does better than any sans, and it stops
   this rung from reading as a second, smaller headline. */
.d-md{font-size:clamp(26px,2.5vw,31px);line-height:1.2;letter-spacing:-.006em;
  font-style:italic;color:var(--text-body);margin:0 0 var(--space-md);max-width:34ch}
/* inside an italic line, emphasis reverses to roman */
.d-md em{font-style:normal}
.pq em,.d-lg em,.claim em{font-style:italic}

/* ==================================================================
   PROSE — Radio Canada, 714px measure
   ================================================================== */
.prose{max-width:var(--prose);margin:0 0 var(--space-md);font:var(--text-body-lg);
  color:var(--text-body);text-wrap:pretty}
.prose:last-child{margin-bottom:0}
.prose.lead{font-size:19px;line-height:33.25px;color:var(--text-primary)}
.prose b,.prose strong{font-weight:600;color:var(--text-primary)}

/* mono "//" aside — the NDA/meta device */
.mono-note{display:flex;gap:var(--space-2xs);max-width:var(--prose);
  font:var(--text-data-value);color:var(--text-muted);margin-top:var(--space-md)}
.mono-note::before{content:'//';color:var(--text-faint);flex-shrink:0}

/* ==================================================================
   SECTION RULE — mono eyebrow + 1px ink rule + blue square.
   The system's one recurring ornament.
   ================================================================== */
.srule{display:flex;flex-direction:row;gap:var(--space-sm);align-items:center;
  width:100%;margin-bottom:var(--space-lg)}
.srule .eb{font:var(--text-eyebrow);font-weight:500;letter-spacing:0.04em;
  color:var(--text-muted);text-transform:uppercase;white-space:nowrap}
.srule .ln{height:1px;background:var(--text-primary);flex-grow:1}
.srule .sq{display:block;width:9px;height:9px;background:var(--accent);flex-shrink:0}

/* ==================================================================
   THE THREE UNDERLINES — never ambiguous
   ================================================================== */
a{color:var(--text-primary);text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:3px;text-decoration-color:var(--border-default);
  transition:color var(--dur-fast) linear}
a:hover{color:var(--accent);text-decoration-color:var(--accent)}
a.plain,a.arrow{text-decoration:none}

/* term = dotted, carries a definition */
.term{font:inherit;color:inherit;background:none;border:0;padding:0;margin:0;
  text-decoration:underline;text-decoration-style:dotted;text-decoration-thickness:1px;
  text-decoration-color:var(--text-faint);text-underline-offset:4px;cursor:help;
  transition:text-decoration-color var(--dur-fast) linear,background var(--dur-fast) linear}
.term:hover,.term[aria-expanded="true"]{text-decoration-color:var(--accent);
  background:rgba(11,63,255,.06)}
.term:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.term::after{content:'';display:inline-block;width:3px;height:3px;background:var(--accent);
  vertical-align:super;margin-left:2px;opacity:.6}

/* mark = marker stroke under display type, un-clickable */
.mark{background-image:linear-gradient(var(--accent),var(--accent));
  background-repeat:no-repeat;background-size:100% .07em;background-position:0 93%}

/* ==================================================================
   TOOLTIP
   ================================================================== */
.tip{position:absolute;z-index:80;max-width:290px;background:var(--surface-inverse);
  color:var(--text-inverse);font-family:var(--font-sans);font-size:13px;line-height:1.55;
  padding:10px 13px;opacity:0;transform:translateY(4px);pointer-events:none;
  transition:opacity var(--dur-fast) linear,transform var(--dur-fast) var(--ease-out)}
.tip.on{opacity:1;transform:translateY(0)}
.tip i{display:block;font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--ink-400);font-style:normal;margin-bottom:5px}
.tip::before{content:'';position:absolute;top:-5px;left:var(--tx,18px);width:0;height:0;
  border-left:5px solid transparent;border-right:5px solid transparent;
  border-bottom:5px solid var(--ink-900)}
.tip.flip::before{top:auto;bottom:-5px;border-bottom:0;border-top:5px solid var(--ink-900)}

/* ==================================================================
   LAYOUT
   ================================================================== */
.wide{max-width:var(--outer);margin:0 auto;padding:0 var(--gut)}
.inner{max-width:var(--inner);margin:0 auto;padding:0 var(--gut)}
.sec{padding:var(--space-5xl) 0}

/* case-study masthead: same container as .cs-grid, so the H1's left edge and
   the rail's left edge sit on one line. Tracks --csmax through breakpoints. */
.cs-head{max-width:var(--csmax);margin:0 auto;padding:0 var(--gut)}

/* case-study body: sticky index rail + content band.
   Container is --outer, matching .top .in and the case-study hero, so the
   rail's left edge sits on the same optical line as the logo and the H1.
   minmax(0,1fr) not 1fr: stops wide children (tables, code, overflow
   scrollers) from blowing the track out past the container. */
.cs-grid{display:grid;grid-template-columns:var(--rail) minmax(0,1fr);
  gap:var(--railgap);
  max-width:var(--csmax);margin:0 auto;padding:0 var(--gut)}

/* Everything in the band is full-band by default; only prose is measured.
   That inversion is the whole point — a paragraph wants 714px, a four-up
   product grid does not, and the old layout gave them both 684px. */
.cs-grid > :not(.snav){min-width:0}

/* ---- escape hatch: right-bleed to the viewport edge ----
   Bleeds right only. The sticky rail occupies the left margin, so a
   symmetric full-bleed would slide under it; bleeding right reads as the
   specimen running off the page, which is the gesture we want anyway.
   max() clamps to 0 below --outer, where it degrades to eating the gutter. */
.bleed{margin-right:calc(-1 * (var(--gut) + max(0px,(100vw - var(--csmax))/2)))}
.bleed-fade{-webkit-mask-image:linear-gradient(to right,#000 88%,transparent);
  mask-image:linear-gradient(to right,#000 88%,transparent)}

/* ---- sticky numbered section nav ---- */
.snav{position:sticky;top:var(--space-xl);display:flex;flex-direction:column;gap:2px;
  align-self:start;height:max-content}
.snav a{display:flex;gap:11px;align-items:baseline;padding:7px 0;
  border-top:0.667px solid var(--border-default);font:var(--text-caption);
  letter-spacing:.04em;text-transform:uppercase;color:var(--text-faint);
  text-decoration:none;transition:color var(--dur-fast) linear}
.snav a:hover{color:var(--accent);text-decoration:none}
.snav a .n{color:inherit}
.snav a.on{color:var(--text-primary)}
.snav a.on .n{color:var(--accent)}

/* ---- top bar ---- */
.top{border-bottom:var(--border-hair);position:sticky;top:0;z-index:40;
  background:var(--paper)}
.top .in{max-width:var(--outer);margin:0 auto;padding:var(--space-md) var(--gut);
  display:flex;align-items:center;justify-content:space-between}
.logo{display:flex;align-items:center;gap:10px;text-decoration:none}
.logo .wm{font-family:var(--font-wordmark);font-weight:600;font-size:17px;
  letter-spacing:-.045em;text-transform:uppercase;color:var(--text-primary)}
.logo .sq{width:9px;height:9px;background:var(--accent);display:block}
.top nav{display:flex;gap:var(--space-xl)}
.top nav a{font:var(--text-nav);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);text-decoration:none}
.top nav a:hover{color:var(--accent)}
.top nav a[aria-current]{color:var(--text-primary)}

/* ---- arrow link ---- */
.arrow{display:inline-flex;align-items:center;gap:9px;font:var(--text-data-value);
  letter-spacing:0.04em;text-transform:uppercase;color:var(--text-primary)}
.arrow:hover{color:var(--accent)}
.arrow .g{transition:transform var(--dur-fast) var(--ease-snap)}
.arrow:hover .g{transform:translateX(3px)}
.arrow.lg{font-size:15px}

/* ==================================================================
   IMAGE SLOT — flat frame, no radius, mono label. Zero real bitmaps
   in the source, so these stay honest placeholders until art exists.
   ================================================================== */
.slot{position:relative;border:var(--border-hair);background:var(--surface-card-16);
  display:grid;place-items:center;overflow:hidden}
.slot::after{content:'';position:absolute;inset:0;
  background:repeating-linear-gradient(-45deg,transparent 0 11px,rgba(9,9,9,.026) 11px 22px);
  pointer-events:none}
.slot .lbl{font:var(--text-caption);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-faint);z-index:1;text-align:center;padding:0 20px}
.slot .idx{position:absolute;top:11px;left:13px;font:var(--text-caption);
  color:var(--text-faint);z-index:1}
.slot[data-ratio="16/9"]{aspect-ratio:16/9}
.slot[data-ratio="4/3"]{aspect-ratio:4/3}

/* ==================================================================
   DATA FIELD — the case study's core artifact
   tones: default · null (red) · ok (sage) · dash (muted)
   variant: dashed = deliberately empty
   ================================================================== */
.df{position:relative;background:var(--surface-card-30);border:var(--border-hair);
  display:flex;flex-direction:column;padding:13px 15px;
  transition:border-color var(--dur-med) linear,background var(--dur-med) linear}
.df .lbl{font:var(--text-label);color:var(--text-muted);text-transform:uppercase;
  letter-spacing:0.04em}
.df .val{padding:7px 0 0;font-family:var(--font-sans);font-weight:600;font-size:16px;
  line-height:23.2px;color:var(--text-primary);transition:color var(--dur-med) linear}
.df.is-null .val{color:var(--data-null)}
.df.is-ok   .val{color:var(--data-ok)}
.df.is-dash .val{color:var(--text-faint)}
.df.dashed{background:transparent;border:var(--border-dashed)}

/* the rule that fired — appears on the "after" side */
.df .fired{font:var(--text-caption);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-faint);margin-top:9px;padding-top:8px;
  border-top:0.667px dashed var(--border-default);
  opacity:0;max-height:0;overflow:hidden;
  transition:opacity var(--dur-med) linear,max-height var(--dur-med) var(--ease-out)}
.df.show-rule .fired{opacity:1;max-height:44px}
.df .fired b{color:var(--accent);font-weight:400}

/* signifier legend */
.legend{display:flex;flex-wrap:wrap;gap:var(--space-lg);margin-top:var(--space-md);
  padding-top:var(--space-sm);border-top:var(--border-hair)}
.legend .k{display:flex;align-items:center;gap:8px;font:var(--text-caption);
  letter-spacing:0.04em;text-transform:uppercase;color:var(--text-muted)}
.legend .k i{width:9px;height:9px;flex-shrink:0;display:block}
.legend .k.null i{background:var(--data-null)}
.legend .k.dash i{background:var(--text-faint)}
.legend .k.ok   i{background:var(--data-ok)}
.legend .k.warm i{background:var(--accent-warm)}

/* ==================================================================
   DEMO SHELL (before / after)
   ================================================================== */
.demo{border:var(--border-hair);background:var(--surface-card-30)}
.demo .bar{display:flex;justify-content:space-between;align-items:center;
  padding:14px 18px;border-bottom:var(--border-hair);gap:var(--space-md);flex-wrap:wrap}
.demo .bar .t{font:var(--text-micro);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-primary)}
.demo .grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px 18px;padding:18px}
.toggle{display:flex;border:var(--border-hair)}
.toggle button{font:var(--text-caption);letter-spacing:0.04em;text-transform:uppercase;
  padding:9px 14px;border:0;cursor:pointer;background:transparent;color:var(--text-muted);
  transition:background var(--dur-fast) linear,color var(--dur-fast) linear}
.toggle button.active{background:var(--surface-inverse);color:var(--text-inverse)}

/* ==================================================================
   FOUR STATES — interactive
   ================================================================== */
.states{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-2xs)}
.state{text-align:left;border:var(--border-hair);background:var(--surface-card-30);
  padding:16px 15px;cursor:pointer;font:inherit;
  transition:border-color var(--dur-fast) linear,background var(--dur-fast) linear}
.state:hover,.state.on{border-color:var(--accent);background:var(--white)}
.state .n{font-family:var(--font-mono);font-weight:600;font-size:15px;line-height:19px;
  letter-spacing:-.025em;color:var(--text-primary)}
.state.on .n{color:var(--accent)}
.state .t{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);margin:13px 0 7px}
.state .d{font-family:var(--font-sans);font-size:13px;line-height:1.55;color:var(--text-body)}
.state-out{margin-top:var(--space-xs);border:var(--border-hair);
  background:var(--surface-card-25);padding:var(--space-md);
  display:grid;grid-template-columns:1fr auto;gap:var(--space-md);align-items:center}
.state-out .txt{font-family:var(--font-sans);font-size:15px;line-height:1.6;color:var(--text-body)}
.state-out .tok{font-family:var(--font-mono);font-size:24px;font-weight:600;
  color:var(--text-primary);white-space:nowrap}

/* ==================================================================
   RULE TABLE
   ================================================================== */
.rules{border:var(--border-hair);background:var(--surface-card-30)}
.rule{display:grid;grid-template-columns:170px 1fr 84px;gap:var(--space-md);
  align-items:center;padding:16px 18px;border-bottom:var(--border-hair)}
.rule:last-child{border-bottom:0}
.rule.blanket{border-left:2px solid var(--text-primary);background:var(--white)}
.rule .cond{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);line-height:1.6}
.rule .out{font-family:var(--font-sans);font-size:15px;line-height:1.6;
  color:var(--text-body);margin:0}
.rule .out b{font-weight:600;color:var(--text-primary)}
.rule .tok{font-family:var(--font-mono);font-size:22px;font-weight:600;
  color:var(--text-primary);text-align:right;white-space:nowrap}

/* ==================================================================
   ROLE CHIPS + INFLUENCE MAP
   ================================================================== */
.coi{display:grid;grid-template-columns:250px 1fr;gap:var(--space-lg);
  background:var(--surface-card-25);border:var(--border-hair);padding:var(--space-lg)}
.coi .list{display:flex;flex-direction:column;gap:6px}
.chip{width:100%;text-align:left;border:0.667px solid var(--border-default);
  background:transparent;display:flex;flex-direction:column;justify-content:center;
  padding:11px 13px;cursor:pointer;font:inherit;
  transition:border-color var(--dur-fast) linear,background var(--dur-fast) linear}
.chip:hover,.chip.active{border-color:var(--accent);background:var(--surface-card-25)}
.chip b{font-family:var(--font-sans);font-weight:700;font-size:15px;line-height:18.85px;
  color:var(--text-primary)}
.chip small{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);margin-top:3px}
.stage2{position:relative;min-height:420px;border:var(--border-hair);
  background:var(--surface-card-16)}
.stage2 svg.edges{position:absolute;inset:0;width:100%;height:100%}
.edge{fill:none;stroke:var(--border-default);stroke-width:1;
  transition:stroke var(--dur-fast) linear,stroke-width var(--dur-fast) linear}
.edge.lit{stroke:var(--accent);stroke-width:1.6}
.sat{position:absolute;width:9px;height:9px;background:var(--text-faint);
  transform:translate(-50%,-50%);transition:all var(--dur-fast) linear}
.sat.lit{background:var(--accent);width:12px;height:12px}
.hub{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  background:var(--accent);color:var(--text-inverse);font:var(--text-data-value);
  font-weight:600;letter-spacing:0.02em;padding:12px 15px;text-align:center;z-index:2}
.hub small{display:block;font-size:12.5px;font-weight:500;opacity:.9;letter-spacing:.04em;margin-top:3px}
.desc{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);
  background:var(--surface-inverse);color:var(--text-inverse);font-family:var(--font-sans);
  font-size:13px;line-height:1.5;padding:10px 14px;max-width:80%;text-align:center;
  opacity:0;transition:opacity var(--dur-med) linear}
.desc.show{opacity:1}

/* ==================================================================
   STAT BLOCK · PULL QUOTE
   ================================================================== */
.stats{display:flex;flex-wrap:wrap;gap:var(--space-3xl)}
.stat{display:flex;flex-direction:column;gap:10px;min-width:180px}
.stat .v{font-size:46px;line-height:52px;letter-spacing:-.03em}
.stat .r{height:1px;background:var(--text-primary)}
.stat .l{font:var(--text-label);text-transform:uppercase;color:var(--text-muted);
  letter-spacing:0.04em}
.stat .n{font:var(--text-caption);color:var(--text-faint)}

.pq{margin:0;max-width:880px}
.pq q{quotes:none;display:block;font-size:clamp(28px,3.4vw,40px);line-height:1.14;
  letter-spacing:-.03em}
.pq .by{margin-top:var(--space-md);display:flex;align-items:center;gap:var(--space-xs)}
.pq .by .r{width:34px;height:1px;background:var(--text-primary);flex-shrink:0}
.pq .by span{font:var(--text-caption);text-transform:uppercase;color:var(--text-muted);
  letter-spacing:0.04em}

/* ==================================================================
   BUTTON — offset slab + spark burst. Primary actions only.
   ================================================================== */
.btn{position:relative;display:inline-block}
.btn .slab{position:absolute;inset:0;transform:translate(4px,4px);
  background:var(--accent);pointer-events:none}
.btn button,.btn a{position:relative;display:inline-flex;text-decoration:none;align-items:center;gap:10px;
  padding:12px 20px;font:var(--text-caption);font-weight:500;letter-spacing:0.04em;
  text-transform:uppercase;background:var(--surface-inverse);color:var(--text-inverse);
  border:0.667px solid var(--surface-inverse);cursor:pointer;white-space:nowrap;
  transition:transform var(--dur-fast) var(--ease-snap)}
.btn button:hover,.btn a:hover{transform:translate(1px,1px)}
.btn button:active,.btn a:active{transform:translate(4px,4px)}
.spark{position:absolute;background:var(--accent);pointer-events:none;
  animation:ds-spark var(--dur-spark) var(--ease-out) forwards}

/* ==================================================================
   PREV / NEXT · FOOTER
   ================================================================== */
.prevnext{display:grid;grid-template-columns:1fr 1fr;border:var(--border-hair);
  background:var(--surface-card-30);margin-top:var(--space-5xl)}
.pn{padding:var(--space-md) var(--space-md);text-decoration:none;
  border-right:var(--border-hair);transition:background var(--dur-fast) linear}
.pn:hover{background:var(--white);text-decoration:none}
.pn.next{border-right:0;text-align:right}
.pn .k{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);margin-bottom:10px}
.pn .t{font-family:var(--font-display);font-weight:400;font-size:28px;line-height:1.1;
  letter-spacing:-.03em;text-transform:uppercase;color:var(--text-primary)}

.foot{border-top:var(--border-hair);margin-top:var(--space-5xl)}
.foot .in{max-width:var(--outer);margin:0 auto;padding:var(--space-lg) var(--gut);
  display:flex;align-items:center;justify-content:space-between;gap:var(--space-lg)}
.foot .z{font:var(--text-caption);letter-spacing:0.02em;color:var(--text-muted)}
/* 意識 — Instrument Serif has no CJK. Pinned to a Mincho stack. */
.foot .mk{font-family:'Hiragino Mincho ProN','Yu Mincho','Noto Serif JP',serif;
  font-size:20px;letter-spacing:.2em;color:var(--text-primary)} /* CJK — .2em is correct here and exempt from the mono tracking rule; Mincho is not monospace */

/* ==================================================================
   MOTION — the system is still. No scroll-fade.
   ================================================================== */
@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important;scroll-behavior:auto}
}

/* ==================================================================
   SITEWIDE COMPONENTS — added when v3 rolled off the case study
   and became the whole site's system.
   ================================================================== */

/* ---- HOME HERO ---- */
.hhero{padding:var(--space-6xl) 0 var(--space-5xl)}
.hhero .kick{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);margin:0 0 var(--space-lg)}
.hhero .d-hero{max-width:16ch}
.hhero .prose.lead{margin-top:var(--space-lg)}
.actions{display:flex;flex-wrap:wrap;gap:var(--space-lg);align-items:center;
  margin-top:var(--space-2xl)}

/* ---- FACT STRIP — mono meta, hairline dividers ---- */
.facts{display:grid;grid-template-columns:repeat(4,1fr);border:var(--border-hair);
  background:var(--surface-card-30)}
.facts .f{padding:var(--space-md) var(--space-md);border-right:var(--border-hair)}
.facts .f:last-child{border-right:0}
.facts .k{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);margin-bottom:9px}
.facts .v{font-family:var(--font-sans);font-weight:600;font-size:15px;line-height:1.35;
  color:var(--text-primary)}
.facts .v small{display:block;font-weight:400;font-size:13px;color:var(--text-muted);
  margin-top:4px}

/* ---- WORK INDEX — the homepage's main event ---- */
.widx{border-top:1px solid var(--text-primary)}
.wrow{display:grid;grid-template-columns:64px 1fr 300px 36px;gap:var(--space-lg);
  align-items:start;padding:var(--space-xl) 0;border-bottom:var(--border-hair);
  text-decoration:none;transition:background var(--dur-fast) linear}
.wrow:hover{background:var(--white);text-decoration:none}
.wrow .n{font-family:var(--font-mono);font-weight:600;font-size:15px;line-height:1;
  letter-spacing:-.025em;color:var(--text-faint);padding-top:6px}
.wrow:hover .n{color:var(--accent)}
.wrow .t{font-family:var(--font-display);font-weight:400;
  font-size:clamp(26px,3vw,34px);line-height:1.08;letter-spacing:-.03em;
  text-transform:uppercase;color:var(--text-primary);margin:0}
.wrow .tags{display:flex;flex-wrap:wrap;gap:var(--space-xs);margin-top:11px}
.wrow .tags span{font:var(--text-caption);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted)}
.wrow .d{font-family:var(--font-sans);font-size:15px;line-height:1.6;
  color:var(--text-body);margin:0;padding-top:4px}
.wrow .g{font:var(--text-data-value);color:var(--text-faint);text-align:right;
  padding-top:6px;transition:transform var(--dur-fast) var(--ease-snap),color var(--dur-fast) linear}
.wrow:hover .g{color:var(--accent);transform:translateX(4px)}
.wrow.locked{cursor:default}
.wrow.locked:hover{background:transparent}
.wrow.locked:hover .n{color:var(--text-faint)}
.wrow.locked .g{opacity:.45}

/* ---- CLIENT MARKS ---- */
.marks{display:flex;flex-wrap:wrap;gap:var(--space-xl) var(--space-3xl);
  padding:var(--space-lg) 0;border-top:var(--border-hair);border-bottom:var(--border-hair)}
.marks span{font:var(--text-micro);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted)}

/* ---- CARD ROW — barriers, frictions, any 3-up ---- */
.cards3{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-xs)}
.cardx{border:var(--border-hair);background:var(--surface-card-30);padding:var(--space-md)}
.cardx .n{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--accent);margin-bottom:11px}
.cardx .t{font-family:var(--font-sans);font-weight:700;font-size:15px;line-height:1.3;
  color:var(--text-primary);margin-bottom:7px}
.cardx .d{font-family:var(--font-sans);font-size:13.5px;line-height:1.55;
  color:var(--text-body)}

/* ---- NUMBERED PRINCIPLE ROWS ---- */
.plist{border:var(--border-hair);background:var(--surface-card-30)}
.prow{display:grid;grid-template-columns:64px 1fr;gap:var(--space-md);
  padding:var(--space-md) var(--space-md);border-bottom:var(--border-hair)}
.prow:last-child{border-bottom:0}
.prow .n{font-family:var(--font-mono);font-weight:600;font-size:15px;line-height:1.2;
  letter-spacing:-.025em;color:var(--text-faint)}
.prow .t{font-family:var(--font-sans);font-weight:700;font-size:16px;
  color:var(--text-primary);margin-bottom:6px}
.prow .d{font-family:var(--font-sans);font-size:15px;line-height:1.6;color:var(--text-body)}
.prow .d b{font-weight:600;color:var(--text-primary)}

/* ---- STEP FLOW ---- */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-xs)}
.step{border:var(--border-hair);background:var(--surface-card-30);padding:var(--space-md);
  border-top:2px solid var(--text-primary)}
.step .n{font-family:var(--font-mono);font-weight:600;font-size:15px;line-height:1;
  color:var(--accent);margin-bottom:13px}
.step .t{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-primary);margin-bottom:9px}
.step .d{font-family:var(--font-sans);font-size:13.5px;line-height:1.55;color:var(--text-body)}

/* ---- CHAT — conversation design artifact ---- */
.chat{max-width:520px;border:var(--border-hair);background:var(--surface-card-30);
  padding:var(--space-md)}
.chat .hdr{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);margin-bottom:var(--space-md);padding-bottom:var(--space-2xs);
  border-bottom:var(--border-hair)}
.bub{max-width:84%;padding:11px 14px;font-family:var(--font-sans);font-size:14px;
  line-height:1.5;margin-bottom:9px}
.bub.bot{background:var(--white);border:var(--border-hair);color:var(--text-primary)}
.bub.user{background:var(--surface-inverse);color:var(--text-inverse);margin-left:auto}

/* ---- BEFORE/AFTER COPY PAIRS ---- */
.vpairs{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-xs)}
.vpair{border:var(--border-hair);background:var(--surface-card-30);padding:var(--space-md)}
.vpair .tag{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);margin-bottom:11px}
.vpair .before{font-family:var(--font-mono);font-size:12.5px;line-height:1.5;
  color:var(--data-null);padding-bottom:10px;margin-bottom:10px;
  border-bottom:0.667px dashed var(--border-default);text-decoration:line-through;
  text-decoration-color:rgba(169,46,38,.4)}
.vpair .after{font-family:var(--font-sans);font-size:14px;line-height:1.55;
  color:var(--text-primary)}

/* ---- SWATCH COLLECTIONS ---- */
.cols2{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-xs)}
.colcard{border:var(--border-hair);background:var(--surface-card-30);padding:var(--space-md)}
.colcard .h{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-primary);margin-bottom:9px}
.colcard .s{font-family:var(--font-sans);font-size:13.5px;line-height:1.55;
  color:var(--text-body);margin-bottom:var(--space-md)}
.swatches{display:flex;flex-wrap:wrap;gap:7px}
.swatches i{display:block;width:34px;height:34px;border:0.667px solid rgba(9,9,9,.12)}

/* ---- ABOUT / SPEAKING ---- */
.two{display:grid;grid-template-columns:1fr 340px;gap:var(--space-3xl);align-items:start}
.dl{border-top:var(--border-hair)}
.dl .r{display:grid;grid-template-columns:96px 1fr;gap:var(--space-md);
  padding:12px 0;border-bottom:var(--border-hair)}
.dl .k{font:var(--text-label);letter-spacing:0.04em;text-transform:uppercase;
  color:var(--text-muted);padding-top:3px}
.dl .v{font-family:var(--font-sans);font-size:14px;line-height:1.5;color:var(--text-primary)}
.dl .v small{display:block;color:var(--text-muted);font-size:12.5px;margin-top:3px}

/* ==================================================================
   RESPONSIVE
   ================================================================== */
@media(max-width:1100px){
  .wrow{grid-template-columns:52px 1fr 30px}
  .wrow .d{grid-column:2/4;padding-top:0}
  .two{grid-template-columns:1fr;gap:var(--space-2xl)}
}
@media(max-width:860px){
  .facts{grid-template-columns:repeat(2,1fr)}
  .facts .f:nth-child(2){border-right:0}
  .facts .f:nth-child(-n+2){border-bottom:var(--border-hair)}
  .cards3{grid-template-columns:1fr}
  .steps{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:600px){
  .hhero{padding:var(--space-3xl) 0}
  .steps,.vpairs,.cols2{grid-template-columns:1fr}
  .prow{grid-template-columns:1fr;gap:9px}
}

@media(max-width:1100px){
  /* rail gone: reclaim its width, but clamp the railless body to --inner so
     the single column doesn't sprawl to full-viewport on a large tablet */
  :root{--csmax:var(--inner)}
  .cs-grid{grid-template-columns:minmax(0,1fr);gap:0}
  .snav{display:none}
  .demo .grid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:860px){
  :root{--gut:24px}
  .states{grid-template-columns:repeat(2,1fr)}
  .coi{grid-template-columns:1fr}
  .stage2{min-height:340px}
}
@media(max-width:600px){
  :root{--gut:18px}
  .sec{padding:var(--space-3xl) 0}
  .demo .grid{grid-template-columns:1fr}
  .rule{grid-template-columns:1fr;gap:9px}
  .rule .tok{text-align:left}
  .states{grid-template-columns:1fr}
  .state-out{grid-template-columns:1fr}
  .prevnext{grid-template-columns:1fr}
  .pn{border-right:0;border-bottom:var(--border-hair);text-align:left!important}
  .srule .eb{font-size:14px;white-space:normal}
  .top nav{gap:var(--space-md)}
}

/* ==================================================================
   DESTINATION ICONS — Phosphor (regular).
   The rule: an icon means the control LEAVES this page context.
     ph-envelope-simple   hands off to the visitor's mail client
     ph-arrow-square-out  leaves this site, in a new tab
   Internal navigation keeps the bare -> <- arrows and takes NO icon,
   so the presence of an icon is never ambiguous.
   Every icon is aria-hidden and paired with a .sr-only phrase, so the
   signal reaches screen readers as words rather than as decoration.
   ================================================================== */
.ph{flex:none;line-height:1;font-size:1.4em;
  transition:transform var(--dur-fast) var(--ease-snap)}
/* ACTION-LEVEL icons run 2x the label so the destination reads before
   the words do. The label is 10-13px mono caps; a 1em icon disappears
   against it, which is exactly the failure this pass exists to fix. */
.arrow .ph{font-size:26px}
.btn .ph{font-size:20px}
a:hover .ph-arrow-square-out{transform:translate(2px,-2px)}
a:hover .ph-envelope-simple{transform:translateY(-2px)}
/* TEXT-LEVEL icons sit inside a running line (nav, footer credit) and are
   capped so they cannot blow out the line box. Signal, not shout. */
.ph.inl{margin-right:.42em;vertical-align:-.14em;font-size:1.35em}

/* Screen-reader-only destination text. Must never be display:none —
   that would strip it from the accessibility tree, which is the whole
   point of having it. */
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}


/* ======================================================================
   VIEW TRANSITIONS — the incoming half.
   Both documents must opt in, so this lives in the shared stylesheet
   that every case study loads. The card title on the homepage and the
   .d-hero here share a view-transition-name, so the title travels
   between documents instead of the page cutting.
   Browsers without support navigate instantly and lose nothing.
   ====================================================================== */
@view-transition{navigation:auto}
::view-transition-group(*){
  animation-duration:var(--dur-vt,420ms);
  animation-timing-function:var(--ease-snap);
}
::view-transition-old(root),::view-transition-new(root){
  animation-duration:var(--dur-vt,420ms);
}
@media (prefers-reduced-motion:reduce){
  ::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){
    animation-duration:0.001ms !important;
  }
}
