/* Hive Architect — the site.
   A sticky navigation rail from 1024 up; below that a top bar carrying the logo and
   a burger, and nothing pinned to the bottom of the viewport. Everything between the
   two comps is interpolated, not snapped — the layout has four states and the type
   ramp has none.

   The topbar, the rail and the footer are generated into every page from one table
   in `tools/chrome.py`. Edit the table, run it; do not hand-edit the markup between
   the CHROME markers. The §03 drawings are generated the same way by `tools/draw.js`. */

/* ══ base ═══════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--paper);
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--size-body);
  line-height: var(--line-body);
  font-weight: var(--weight-regular);
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
button { font: inherit; color: inherit; }
hr { border: 0; height: var(--stroke-hair); background: var(--grid); margin: 0; }
::selection { background: var(--ink); color: var(--paper); }

:focus-visible {
  outline: var(--focus-width) solid var(--focus-ring);
  outline-offset: var(--focus-offset);
}

a {
  color: var(--water);
  text-decoration: none;
  transition: color var(--motion-1) var(--ease-standard);
}
a:hover { color: var(--ink); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 99;
  background: var(--ink); color: var(--paper);
  padding: var(--space-3) var(--space-6);
  font-family: var(--font-mono); font-size: var(--size-label);
  letter-spacing: var(--track-label); text-transform: uppercase;
}
.skip:focus { left: 0; color: var(--paper); }

/* ══ type roles ═════════════════════════════════════════════════════════════ */
.kicker, .label-t {
  font-family: var(--font-mono);
  font-weight: var(--weight-medium);
  font-size: var(--size-label);
  line-height: var(--line-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.caption {
  font-family: var(--font-mono);
  font-weight: var(--weight-regular);
  font-size: var(--size-caption);
  line-height: var(--line-caption);
  letter-spacing: var(--track-caption);
  text-transform: uppercase;
}
.data {
  font-family: var(--font-mono);
  font-weight: var(--weight-regular);
  font-size: var(--size-data);
  line-height: var(--line-data);
}
.lead {
  font-size: var(--size-lead);
  line-height: var(--line-lead);
  font-weight: var(--weight-medium);   /* §1.3 Lead is Saira 500, not 400 */
  max-width: var(--measure-lead);
}
.body { max-width: var(--measure-body); }
.small { font-size: var(--size-small); line-height: var(--line-small); }

/* §1.3 weights: Display 800, H1 700, H2 700, H3 600. The shared rule carries H3's. */
h1, h2, h3 { margin: 0; font-weight: var(--weight-semibold); }
h1 {
  font-size: var(--size-display); line-height: var(--line-display);
  letter-spacing: var(--track-display); font-weight: var(--weight-extrabold);
  max-width: 20ch;
}
h2 {
  font-size: var(--size-h2); line-height: var(--line-h2);
  letter-spacing: var(--track-h2); font-weight: var(--weight-bold);
}
h3 {
  font-size: var(--size-h3); line-height: var(--line-h3);
  letter-spacing: var(--track-h3);
}
/* The sub-pages' headline. The landing's h1 is H1 (56/34) via `.hero-h`; left on the
   global rule, "Blog" was set at Display and shouted a role louder than the headline of
   the site. Same role as the landing, so the whole site has one top of hierarchy.
   The global `h1` rule stays as it is — the campaign landing pages depend on it. */
.page-h {
  font-size: var(--size-h1); line-height: var(--line-h1);
  letter-spacing: var(--track-h1); font-weight: var(--weight-bold);
}
p { margin: 0; }
ul.ticks { margin: var(--space-4) 0 0; padding-left: 1.15em; }
ul.ticks li { font-size: var(--size-small); line-height: var(--line-small); }
ul.ticks li + li { margin-top: var(--space-1); }
ul.ticks::marker { color: var(--ink); }

/* ══ shell ══════════════════════════════════════════════════════════════════
   The cap used to sit on the page, which left the content ending short of the right
   edge while still sitting one gutter from the rail — a visibly fatter right margin
   at every width above about 1400.
   Centring the whole shell instead only moves the problem: the rail then floats off
   the screen edge with paper to its left, which reads as a mistake rather than as a
   margin. So the rail stays pinned to the edge, and the page is capped and centred
   inside whatever the rail leaves. Both gutters are then the same auto margin plus
   the same padding — equal by construction at every width. */
.shell { display: flex; align-items: flex-start; min-height: 100vh; }

.page {
  flex: 1 1 auto;
  min-width: 0;
  max-width: calc(var(--content-max) + 2 * var(--page-x));
  margin-inline: auto;
  padding: 0 var(--page-x) var(--space-32);
}

.sec { scroll-margin-top: 40px; padding-top: var(--section-gap); }
.sec:first-child { padding-top: clamp(2rem, 0.8857rem + 4.5714vw, 5rem); }  /* 32 → 80 */
.sec-no { display: block; margin-bottom: var(--space-4); }

/* ── §01 the hero ─────────────────────────────────────────────────────────
   The reading order this section is built to produce, in this order and no other:

     1  the headline      — what we do
     2  the primary CTA   — what to do about it
     3  the chart         — why you should believe it
     4  the paragraph     — who it is for

   That is an order of *attention*, not of sequence: the paragraph still sits second
   down the page, immediately under the headline, because it is the headline's own
   qualifying clause. It is simply not what the eye is meant to spend its first second
   on, so it is set quiet and short.

   The previous pass got the sizes right and the hierarchy wrong. Dropping the headline
   from Display to H1, the deck to Body and the button from lg to base narrowed the range
   the ramp had to work with, and the leftover spacing — 40px above the paragraph, 40px
   below it — grouped nothing. Four objects arrived at once. This pass does not put the
   size back. It makes the *steps* legible instead, with the levers that cost no size:

     space      24px above the paragraph, 48px above the CTA. A 1:2 ratio, so the
                paragraph belongs to the headline and the plate stands alone.
     colour     the paragraph, the arrow link and the chart's tag drop to --quiet. The
                plate keeps ink on red. Two levels of type colour where there was one.
     area       the chart lost 46% of its footprint at 1440 (475x376 -> 418x229) and its
                own axis-name row. See the chart block below.
     red        exactly one Command Red object in the composition — the plate. §3.4,
                and override 02 in working/site-rebuild/brand-overrides.md. The chart's
                "după" line was the second one and is now ink.

   The hero as a whole is 462px tall at 1440 where it was 625. Nothing shrank to get
   there except the chart; the rest is the spacing being spent where it does work.

   The split waits for 1200 rather than following the rail at 1024: the rail has
   already taken 224px there, and half of what is left is a 310px box, which is
   four characters per line at a 60px display size.

   Row gap is 0 and the vertical rhythm is set by margins on the three parts, because a
   single grid `gap` can only say one number and the whole point here is that the two
   gaps are different. */
.hero { display: grid; gap: 0 clamp(32px, 1rem + 2.5vw, 64px); }
/* §1.3 H1, not Display. Display is 1.8x the H2s that carry the seven sections below it
   and a weight step above them as well; at that ratio the headline stopped being the top
   of a hierarchy and became a poster with a document underneath. H1 is one role step
   above H2 — 56/40, the same 1.4 step the ramp uses between every other adjacent pair —
   so the headline still leads and the page reads as one thing.
   It decides the mobile case too: at Display the headline ran four lines and pushed the
   chart off a 390x810 screen, so the claim arrived without its evidence. At H1 it is two
   lines and the whole argument — claim, way in, proof — lands in one screen.
   Every other page's h1 is `.page-h`, the same H1 role at the same four metrics — size,
   weight, line-height and tracking — so the site has one top of hierarchy throughout.
   Which leaves Display rendering on nothing this build owns. The global `h1` rule in the
   type roles above is the only thing still carrying it, and is kept for the reason
   given there: the campaign landing pages set their h1 with it. */
/* §1.3 Display — 72/800 at 1440, 44 on mobile. It went to H1 for one round because the
   headline looked isolated, but the isolation was never the headline's fault: Lead was
   set at Body's size and 400 weight, and Body at 1.6 instead of 1.67, so the two roles
   under the headline had collapsed into each other and there was no cascade for it to
   sit on top of. With the ramp corrected against the manual, Display is the top of a
   real 72 → 22 → 18 sequence, which is what it is for. A hero set at the same role as
   every sub-page heading is not a hero. */
/* `balance` is load-bearing, not a nicety. Greedy wrapping set this headline as
   "De la vânzări sporadice la" / "venituri previzibile." — a 731px line over a 564px
   one. That 167px step is the ragged right edge the composition kept catching on: the
   second line stopped 19px short of the chart column at 1440 and 100px short of it at
   1920, so the headline's edge and the chart's edge missed each other by a different
   amount at every width and never read as either an alignment or a gap.
   Balanced, the two lines come out at 664 and 631 — a 33px rag — and the headline is a
   near-flush block whose right edge is stable across the whole range. The line count
   cannot change: the string is ~1320px at Display and the widest this column ever gets
   is 1176, so it is two lines from 1200 up no matter what. */
.hero-h {
  grid-column: 1 / -1;
  font-size: var(--size-display); line-height: var(--line-display);
  letter-spacing: var(--track-display); font-weight: var(--weight-extrabold);
  text-wrap: balance;
}
/* The paragraph under the headline is support, not a deck: the line above it is already
   the claim, and setting this at Lead put two competing voices in the same column. It is
   Body — the same paragraph the rest of the page is written in.
   Fourth in the order, so it is the one thing here that gives ground. It gives it in
   colour and in position, not in size: `--quiet` rather than ink (4.91:1 on paper,
   5.55:1 on ink — measured after killing transitions, not read off the token comment),
   and 24px under the headline, which is half the gap below it. That 1:2 is what makes it
   read as part of the headline rather than as its own announcement.
   The measure is the third lever and it did the least. Taking it right down — 400px was
   tried and looked at — turns three lines into four, which is more vertical grey between
   the headline and the plate, the opposite of what this paragraph is for, and it breaks
   "10.000 și / 250.000 €" over two lines, splitting the one number a qualifying reader
   came to check. So it stays at the ~470px it was reading at, which is 45 characters:
   short enough to scan, long enough to keep the range whole.
   45ch, written out, rather than `var(--measure-body)`. `ch` resolves against the element
   that uses it, so the 53ch token is 554px down here at 18px, not the 475px it is at the
   root's 16px — wider than this column, i.e. no cap at all. The paragraph was only ever
   475 wide because the old 1fr column was 475 wide. This one binds. */
.hero-copy .lead {
  font-size: var(--size-lead);
  line-height: var(--line-lead);
  font-weight: var(--weight-medium);
  max-width: 42ch;
  margin-top: var(--space-8);
}
/* 48px of air above the plate — double the gap above the paragraph. The plate is second
   in the order and it earns that by standing alone, not by growing: it is the same
   `.btn` at the same Button role the last pass settled on. */
.hero-cta {
  margin-top: var(--space-12);
  display: flex; align-items: center; gap: var(--space-8); flex-wrap: wrap;
}
/* The arrow link was Body ink, the same size and weight as the label on the plate beside
   it, so a filled red rectangle and a piece of running text read as two equal choices.
   They are not equal. Small and quiet — still AA, still a 44px row to hit, visibly the
   other option rather than the other half of a pair. */
.hero-cta .go {
  font-size: var(--size-small); line-height: var(--line-small);
  color: var(--quiet);
}
/* The hero's plate stays Command Red like every other CTA on the page.
   An earlier pass made it Ink so that §3.4's one-red-per-screen rule could be kept
   with the chart's "după" line — but Darius asked for both: the after line red, and
   every CTA the same button. A black hero CTA beside four red ones is the exact
   inconsistency he asked to remove, so the rule gives way to the instruction.
   Logged in brand-overrides.md. */

.hero .chart { margin: var(--space-12) 0 0; max-width: 560px; }
/* A hero has to own the screen. At 449px in a 900px viewport the section ended with
   §02's heading already visible beside it, so the eye read one continuous document and
   the top of it was just the first heading. Height is what says "this is the entry",
   and it costs no type size: the section takes the viewport, its content sits optically
   centred in it, and the next section starts below the fold where it belongs.
   `svh` rather than `vh` so a phone's collapsing toolbar cannot make it taller than the
   screen; `vh` first for anything that does not know `svh`. */
@media (min-width: 1024px) {
  .sec.hero {
    min-height: calc(100vh - var(--space-8));
    min-height: calc(100svh - var(--space-8));
    padding-top: var(--space-16);
    padding-bottom: var(--space-20);
    align-content: center;
  }
}

@media (min-width: 1200px) {
  /* `center`, and it was measured rather than argued. Baseline alignment put the chart's
     tag baseline on the paragraph's first baseline, which sounds like the two columns
     open on one line and is not what it does: the paragraph carries 32px of margin above
     its first line, so aligning to its baseline pushed the whole chart column 44px down
     the page. At 1440 the copy block ran 366→586 and the chart 410→639 — optical centres
     71px apart, and the tag's hairline landing across the middle of the paragraph at no
     particular height. Two objects that are meant to read as one row, one of them
     sitting visibly lower than the other: that is the "still looks weird".
     Centred, the two centres are 502 and 502,5 and the row reads as a row. The tag's
     hairline no longer cuts anything, because it is no longer near the copy's lines.
     Two other arrangements were built and looked at before this one:
     · The chart moved into the right column across both rows, beside the headline, to
       fill the empty top right. It fills it and costs more than it buys: the headline
       loses the width for its two-line break and comes out at 3 or 4 lines with a rag
       worse than the one being fixed, the chart column drops under 380px and the "DUPĂ ·
       40.000 €" label loses its figure, and the chart ends up floating mid-column with
       symmetric holes above and below it, related to nothing.
     · The same, top-aligned to the headline rather than centred, which moves that hole
       to the bottom right and puts it next to the CTA, where it is more visible.
     The empty top right is not a fault to be filled. It is what a headline shorter than
     its column leaves, and with the rag balanced it is a clean rectangle of paper with
     the headline's own edge on one side of it.
     The columns stay 1.12/0.88. Equal halves gave the chart the same width as the
     argument it is evidence for and cost the paragraph a fourth line; a fifth narrower
     says which one is which. At 1440 the chart's left edge lands 48px inside the
     headline's balanced right edge, so the two blocks interlock rather than butt. */
  .hero { grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr); align-items: center; }
  .hero .chart { margin: 0; max-width: none; }
  /* One figure, not a vw curve. The chart column runs 357 (1280) to 489 (1920, where the
     page hits --content-max), so 184px holds the plot between 1.9:1 and 2.7:1 across the
     whole range — one shape, and short enough that the chart never out-masses the copy
     block beside it. */
  .hero .chart-plot { height: 184px; }
}

/* the tag that names the chart — §1.3 Label, and nothing else: no source, no caveat.
   Quiet, not ink: it sits on the same line as the paragraph and at full ink it was the
   darkest thing at that height, which put a third dark mass in the frame. It names the
   chart; the chart's own line is what carries weight. It absorbed the unit (`în €`) when
   the VENIT · € / TIMP · LUNI row was dropped — same one line, one mark fewer. */
.chart-tag {
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: var(--stroke-hair) solid var(--grid);
  color: var(--quiet);
}

/* ── the rail (≥1024) ───────────────────────────────────────────────────── */
.rail {
  position: sticky; top: 0;
  flex: 0 0 var(--rail-w); width: var(--rail-w);
  height: 100vh; height: 100dvh;
  padding: var(--space-10) var(--space-6);
  border-right: var(--stroke-hair) solid var(--grid);
  display: flex; flex-direction: column; gap: var(--space-6);
}
.rail-bar {
  position: absolute; top: 0; right: -1px;
  width: 3px; height: 0; background: var(--red);
  will-change: height;
}
/* The chrome's wordmark is the lockup now. `.wordmark` is kept because the campaign
   landing pages (pachet-*.html, css/lp.css — not part of this build) still set type
   with it, and removing it would break their headers. */
.wordmark {
  font-weight: var(--weight-bold); font-size: 0.875rem; line-height: 1.43;
  letter-spacing: var(--track-lockup); text-transform: uppercase;
  color: var(--ink);
}

/* The width is explicit, not a max: the lockup inside is `width: 100%`, so against a
   `flex: none` parent with auto basis the two resolve to nothing and the logo vanishes. */
.brand { display: block; flex: none; color: var(--ink); }
.brand:hover { color: var(--red); }
.rail .brand { width: 172px; max-width: 100%; }
.topbar .brand { width: 124px; }

.rail-nav { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-4); }
/* §1.3 Nav — 16, +0.02em, one size at every width. It used to borrow `--size-small`,
   which was a flat 16 and so happened to be right; now that Body small ramps 15 → 16 the
   nav needs its own token or it would shrink under the role below 1440.
   The role's 16/24 is not taken: every link here is one line, so the extra 2px per line
   buys nothing but 30px of rail, which is enough to put the index into its own scrollbar
   at 1280x800 and 1024x768 where it fits today. 1.375 is the rail's, and it stays. */
.rail-nav a {
  border-left: var(--stroke-med) solid transparent;
  padding-left: var(--space-3);
  font-size: var(--size-nav); line-height: 1.375;
  letter-spacing: var(--track-nav);
  color: var(--ink);
  transition: border-color var(--motion-1) var(--ease-standard),
              color var(--motion-1) var(--ease-standard);
}
.rail-nav a:hover { border-left-color: var(--grid); }
/* "true" is the landing's scroll-driven section; "page" is the sub-page you are on */
.rail-nav a[aria-current="true"],
.rail-nav a[aria-current="page"] { font-weight: var(--weight-semibold); border-left-color: var(--ink); }
.rail-top { font-weight: var(--weight-semibold); }
/* The eight sections are nested under Pitch-ul and nowhere else, and nothing said so:
   the indent and the hairline are the only cue, and they read as decoration. A chevron
   to the right of the label names the relationship and gives it a control.
   The row keeps the label's own height. The button is a 44px §10.4 target pulled back
   into the line with a negative block margin, so the hit area is legal without adding
   22px to a rail that already fits 1024x768 with nothing to spare; the 11px it borrows
   at each end falls in the flex gap, where nothing else is clickable. */
.rail-top-row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.rail-top-row .rail-top { flex: 1 1 auto; min-width: 0; }
.rail-toggle {
  flex: none; width: var(--hit-target-min); height: var(--hit-target-min);
  margin-block: calc((var(--hit-target-min) - 22px) / -2);
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; padding: 0; cursor: pointer; color: var(--quiet);
  transition: color var(--motion-1) var(--ease-standard);
}
.rail-toggle:hover { color: var(--ink); }
.rail-chev {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: butt; stroke-linejoin: miter;
  transition: transform var(--motion-2) var(--ease-standard);
}
/* closed points the way it will open, which is the convention every file tree uses */
.rail-toggle[aria-expanded="false"] .rail-chev { transform: rotate(-90deg); }
@media (prefers-reduced-motion: reduce) { .rail-chev { transition: none; } }
/* set on <html> before first paint by the inline script in the page head, so a rail
   that was left closed never draws open and then snaps shut */
.rail-closed .rail-sections { display: none; }

.rail-group { display: flex; flex-direction: column; gap: 10px; }
.rail-group-h { color: var(--quiet); padding-left: var(--space-3); }
/* the landing's own sections, nested under Pitch-ul and only on the landing */
.rail-sections {
  display: flex; flex-direction: column; gap: 9px;
  margin: 2px 0 2px var(--space-3);
  border-left: var(--stroke-hair) solid var(--grid);
}
.rail-sections a { border-left-width: var(--stroke-med); margin-left: -1px; }
.rail-nav .n { font-family: var(--font-mono); font-size: var(--size-caption); letter-spacing: var(--track-caption); margin-right: var(--space-2); }

.rail-foot { flex: none; display: flex; flex-direction: column; gap: var(--space-3); }
.rail-foot-row { display: flex; align-items: center; gap: var(--space-3); }

/* ── the top bar (<1024) ────────────────────────────────────────────────────
   Logo left, burger right, and nothing else. The crumb counted sections at a
   visitor who is already looking at them, and the docked CTA took a strip of every
   phone screen for a button that is one tap away in the menu. */
.topbar {
  display: none;
  position: sticky; top: 0; z-index: 20;
  height: var(--header-h);
  background: var(--paper);
  border-bottom: var(--stroke-hair) solid var(--grid);
  padding-left: var(--page-x);
  align-items: center; justify-content: space-between; gap: var(--space-3);
}
.topbar-bar {
  position: absolute; left: 0; bottom: -1px;
  height: 3px; width: 0; background: var(--red);
  will-change: width;
}
.topbar-burger {
  flex: 0 0 auto;
  height: var(--header-h); min-width: var(--hit-target-min);
  padding: 0 var(--page-x) 0 var(--space-4);
  display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2);
  background: none; border: 0; color: var(--ink); cursor: pointer;
}
.topbar-burger .ic { width: 22px; height: 22px; }

/* the shared icon rule — butt caps and miter joins, never Lucide's round ones */
.ic {
  width: 22px; height: 22px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: butt; stroke-linejoin: miter;
}

/* ── the menu sheet ─────────────────────────────────────────────────────── */
.menu { position: fixed; inset: 0; z-index: 40; }
.menu[hidden] { display: none; }
.menu-scrim {
  position: absolute; inset: 0; background: rgba(27, 35, 31, 0.55);
  opacity: 0; transition: opacity var(--motion-2) var(--ease-standard);
}
.menu.is-open .menu-scrim { opacity: 1; }
.menu-sheet {
  position: absolute; inset: 0 0 0 auto;
  width: min(420px, 100%); height: 100%;
  background: var(--paper);
  border-left: var(--stroke-med) solid var(--ink);
  display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform var(--motion-3) var(--ease-standard);
  padding-bottom: env(safe-area-inset-bottom);
}
.menu.is-open .menu-sheet { transform: translateX(0); }
@media (prefers-reduced-motion: reduce) {
  .menu-scrim, .menu-sheet { transition: none; }
}

.menu-head .lockup { width: 124px; }
.menu-head {
  flex: none; height: var(--header-h);
  padding: 0 var(--space-4) 0 var(--page-x);
  border-bottom: var(--stroke-hair) solid var(--grid);
  display: flex; align-items: center; justify-content: space-between;
}
.menu-x {
  width: var(--hit-target-min); height: var(--hit-target-min);
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; padding: 0; color: var(--ink); cursor: pointer;
}
/* contain, or dragging past the end of this list chains into the pinned page behind */
.menu-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: var(--space-6) var(--page-x);
}
.menu-group + .menu-group {
  margin-top: var(--space-8); padding-top: var(--space-6);
  border-top: var(--stroke-hair) solid var(--grid);
}
.menu-h { color: var(--quiet); margin-bottom: var(--space-3); }
.menu-link {
  display: flex; align-items: center; gap: var(--space-4);
  min-height: 52px; color: var(--ink);
  font-size: var(--size-h3); line-height: 1.2;
  font-weight: var(--weight-semibold);
  border-bottom: var(--stroke-hair) solid var(--grid);
}
.menu-link:last-child { border-bottom: 0; }
.menu-link:hover, .menu-link:focus-visible { color: var(--red); }
.menu-n {
  font-family: var(--font-mono); font-weight: var(--weight-medium);
  font-size: var(--size-label); letter-spacing: var(--track-label);
  color: var(--quiet); flex: none;
}
.menu-link-sm { font-size: var(--size-body); font-weight: var(--weight-regular); min-height: var(--hit-target-min); }

.menu-foot {
  flex: none; padding: var(--space-4) var(--page-x) var(--space-6);
  border-top: var(--stroke-hair) solid var(--grid);
  display: flex; flex-direction: column; gap: var(--space-3);
}
.theme-wide {
  width: 100%; min-height: 52px;
  display: flex; align-items: center; justify-content: flex-start; gap: var(--space-3);
  padding: 0 var(--space-4);
  border: var(--stroke-hair) solid var(--grid);
}
.theme-wide .ic { width: 24px; height: 24px; }
.theme-wide .label-t { white-space: nowrap; }
.theme-wide:hover { border-color: var(--ink); }

/* pinned rather than just overflow-hidden — the inline `top` JS sets holds the offset */
body.is-locked { position: fixed; left: 0; right: 0; width: 100%; overflow: hidden; }

/* Every auto-fit grid floor is wrapped in min(…, 100%): a bare 300px track cannot
   shrink, so at 320px — minus a scrollbar, minus two 20px gutters — the card ran
   35px past the edge and took the page with it. */

/* ══ components ═════════════════════════════════════════════════════════════ */

/* §1.3 button */
.btn {
  font-family: var(--font-sans); font-weight: var(--weight-semibold);
  font-size: var(--size-button); line-height: 1;
  letter-spacing: var(--track-button); text-transform: uppercase;
  text-decoration: none; border: 0; border-radius: 0; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--hit-target-min);
  padding: var(--space-3) var(--space-6);
  transition: background var(--motion-1) var(--ease-standard),
              color var(--motion-1) var(--ease-standard);
}
.btn-lg { padding: var(--space-4) var(--space-8); min-height: 56px; }
/* Every plate that asks for the visitor's next move is Command Red. That is more
   than one red element on the page — §3.4 is broken here on purpose, because the
   alternative is an ink plate that reads as structure rather than as an invitation. */
.btn-primary { background: var(--cta); color: var(--cta-ink); }
.btn-primary:hover { background: var(--cta-hover); color: var(--cta-ink); }
.btn-secondary { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 var(--stroke-med) var(--cta); }
.btn-secondary:hover { background: var(--cta); color: var(--cta-ink); }
.btn-full { width: 100%; }
.btn[disabled] { opacity: 0.4; cursor: not-allowed; }

/* the arrow link, used everywhere the comps use one */
.go { font-size: var(--size-body); line-height: var(--line-body); display: inline-block; }

/* §4.4 form 5 — label chip */
.chip {
  display: inline-block; font-family: var(--font-mono);
  font-weight: var(--weight-medium); font-size: 12px; line-height: 16px;
  letter-spacing: var(--track-label); text-transform: uppercase;
  padding: 4px 6px;
}
.chip-ink { background: var(--ink); color: var(--paper); }

/* theme toggle — shows the mode you will get, not the one you are in */
.theme {
  width: var(--hit-target-min); height: var(--hit-target-min);
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  background: none; border: 0; padding: 0; cursor: pointer;
  color: var(--ink);
  transition: color var(--motion-1) var(--ease-standard);
}
.theme:hover { color: var(--red); }

/* The language switch sits beside the theme control and behaves like it: same hit
   target, same ink, same red on hover. It is set in mono because it reads as a code
   (EN / RO) rather than as a word, and mono is where this site puts codes. */
.lang {
  min-width: var(--hit-target-min); height: var(--hit-target-min);
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  padding: 0 var(--space-2); text-decoration: none;
  color: var(--ink);
  transition: color var(--motion-1) var(--ease-standard);
}
.lang-c {
  font-family: var(--font-mono); font-size: var(--size-caption);
  letter-spacing: var(--track-caption); text-transform: uppercase;
}
.lang:hover { color: var(--red); }
/* In the phone sheet it is a full-width row, matching .theme-wide above it. */
.lang-wide {
  width: 100%; min-height: 52px;
  justify-content: flex-start; gap: var(--space-3);
  padding: 0 var(--space-4);
  border: var(--stroke-hair) solid var(--grid);
}
.lang-wide .label-t { white-space: nowrap; }
.lang-wide:hover { border-color: var(--ink); }

/* ══ §01 the chart ══════════════════════════════════════════════════════════
   Two series on one scale from zero: the months before as a dashed ghost, the
   months after as the command line. The only dots on the plot are the numbers
   the legend names. */
/* The chart is the hero's evidence, not a section under it: no plate, no frame, no
   legend. Its two series are told apart by pattern and by a label sitting on each
   line, which is what §10.3 asks for anyway — a legend is a lookup table you make
   the reader hold in their head. */
.chart { margin: var(--space-12) 0 0; padding: 0; background: none; border: 0; }
/* The VENIT · € / TIMP · LUNI row is gone. It restated what the plot already says — the
   y-ticks are the figures, L1–L6 are the months — and cost two more marks plus 40px of
   height in a frame that was already carrying too many objects. The unit moved into the
   tag, which was going to be read anyway. */
/* The ceiling is what keeps the chart subordinate: 208px of plot against a 120px headline
   is evidence; the 300px this used to reach was a second poster, and it is where most of
   the chart's old visual weight lived. The two layout regimes get their own figure rather
   than one vw curve spanning both, because the chart's width does not move with the
   viewport in the same direction in each — single-column it is capped at 560, two-column
   it is a fraction of the page. `aspect-ratio` was the other way to write this and is a
   trap here: with `min-height` set, Chrome resolves the ratio back onto the width and the
   plot grew to 343px inside a 265px column at 320. */
.chart-plot { width: 100%; height: clamp(150px, 28vw, 208px); }
.chart-plot svg { width: 100%; height: 100%; overflow: visible; }
.chart-gridline { stroke: var(--chart-grid); stroke-width: 1; }
/* the origin. §6.1 — zero unless the axis says otherwise, so zero is drawn. */
.chart-axis { stroke: var(--ink); stroke-width: 1; opacity: 0.45; }
.chart-tick {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em;
  fill: var(--quiet);
}
.chart-xlab {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em;
  fill: var(--quiet);
}
.chart-ghost-line {
  fill: none; stroke: var(--chart-ghost); stroke-width: 1.5;
  stroke-dasharray: 5 5; stroke-linecap: butt; stroke-linejoin: miter;
}
.chart-ghost-dot { fill: var(--chart-ghost); }
.chart-line {
  fill: none; stroke: var(--chart-line); stroke-width: 2;
  stroke-linecap: butt; stroke-linejoin: miter;
}
.chart-dot { fill: var(--chart-line); }

/* §9.1 — the chart draws once, at constant speed, then it holds.
   `both` fill mode means the resting state is the finished state. */
@keyframes chart-draw { from { stroke-dashoffset: var(--len); } to { stroke-dashoffset: 0; } }
@keyframes chart-in   { from { opacity: 0; } to { opacity: 1; } }
.chart-anim .chart-ghost { animation: chart-in var(--motion-2) var(--ease-standard) both; }
.chart-anim .chart-line  {
  stroke-dasharray: var(--len);
  animation: chart-draw var(--motion-4) var(--ease-chart) var(--motion-2) both;
}
.chart-anim .chart-dots  { animation: chart-in var(--motion-2) var(--ease-standard) 960ms both; }
@media (prefers-reduced-motion: reduce) {
  .chart-anim .chart-ghost, .chart-anim .chart-line, .chart-anim .chart-dots { animation: none; }
  .chart-anim .chart-line { stroke-dasharray: none; }
}

/* the labels that replaced the legend — one on each series, §7.2 wording */
.chart-mark {
  font-family: var(--font-mono); font-weight: var(--weight-medium);
  font-size: 12px; letter-spacing: 0.08em;
}
.chart-mark-ghost { fill: var(--chart-ghost); }
.chart-mark-line { fill: var(--chart-line); }

/* ══ §02 the portfolio, as coverflow ════════════════════════════════════════
   One track holding every frame, centred on the one that plays, with its neighbours
   leaning in either side so the next thing is visible rather than hidden behind an
   arrow. The stage is absolutely centred over the track and holds the only <video> on
   the page — selecting moves the track, never the video element.
   A thumbnail grid stood here before and was the wrong answer: it turned the library
   into a contact sheet you scan, when the point of the section is that you watch one. */
.cf {
  /* the width of the centre frame, and so of every frame. Capped by viewport height as
     well, so a 9:16 frame never runs past the fold on a laptop. */
  --cf-w: min(clamp(190px, 21vw, 300px), calc(58dvh * 9 / 16));
  --cf-gap: var(--space-4);
  --cf-step: calc(var(--cf-w) + var(--cf-gap));
  margin-top: var(--space-10);
}
.cf-chrome {
  display: flex; justify-content: space-between; align-items: center;
  gap: var(--space-3);
  width: var(--cf-w); margin: 0 auto var(--space-3);
}

.cf-viewport {
  position: relative; overflow: hidden;
  height: calc(var(--cf-w) * 16 / 9);
  outline-offset: 3px;
}
.cf-track {
  --cf-i: 0;
  position: absolute; inset: 0;
  display: flex; align-items: center; gap: var(--cf-gap);
  padding-left: calc(50% - var(--cf-w) / 2);
  transform: translateX(calc(var(--cf-i) * var(--cf-step) * -1));
  transition: transform var(--motion-3) var(--ease-standard);
  will-change: transform;
}
.cf-item {
  flex: 0 0 var(--cf-w);
  height: calc(var(--cf-w) * 16 / 9);
  padding: 0; border: 0; border-radius: 0;
  background: var(--panel); cursor: pointer; overflow: hidden;
  transform: scale(0.74); opacity: 0.38;
  transition: transform var(--motion-3) var(--ease-standard),
              opacity var(--motion-3) var(--ease-standard);
}
.cf-item img { width: 100%; height: 100%; object-fit: cover; }
.cf-item:hover { opacity: 0.7; }
/* the centre frame sits at full size directly under the stage */
.cf-item.is-on { transform: scale(1); opacity: 1; }

.cf-stage {
  position: absolute; top: 50%; left: 50%;
  width: var(--cf-w); height: calc(var(--cf-w) * 16 / 9);
  transform: translate(-50%, -50%);
  border: var(--stroke-med) solid var(--ink);
  background: var(--panel); overflow: hidden;
}
.cf-stage video { width: 100%; height: 100%; object-fit: cover; background: var(--panel); }
/* The stage takes the new frame the moment you press next, so while the track is still
   sliding it would sit on top of the frame you are leaving — two different reels in one
   box, which is what read as broken. It steps aside for the slide and comes back. */
.cf-stage { transition: opacity var(--motion-1) var(--ease-standard); }
.cf.is-moving .cf-stage { opacity: 0; pointer-events: none; }
/* the silent jump back into the middle copy */
.cf-track.no-anim { transition: none; }

.cf-nav {
  width: var(--cf-w); margin: var(--space-3) auto 0;
  display: flex; gap: var(--space-2);
}
.cf-nav button {
  flex: 1; min-height: var(--hit-target-min);
  border: var(--stroke-med) solid var(--ink); background: none; cursor: pointer;
  font-family: var(--font-mono); font-weight: var(--weight-medium);
  font-size: var(--size-label); letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--ink);
  transition: background var(--motion-1) var(--ease-standard),
              color var(--motion-1) var(--ease-standard);
}
.cf-nav button:hover { background: var(--ink); color: var(--paper); }

.cf-out {
  margin-top: var(--space-10);
  display: flex; align-items: center; justify-content: center;
  gap: var(--space-6); flex-wrap: wrap;
}

@media (prefers-reduced-motion: reduce) { .cf-track, .cf-item { transition: none; } }

/* Below the rail there is no coverflow. Darius asked for it on desktop, and on a 390
   screen a 190px centre frame with two neighbours either side is a thumbnail, not a
   portfolio — the reel has to own the column. The track is hidden and the stage takes
   the whole width, capped by viewport height so a 9:16 frame still fits above the fold.
   Prev/next and the swipe still move it; it is the same one reel, just one-up. */
@media (max-width: 1023px) {
  .cf { --cf-one: min(100%, calc(66dvh * 9 / 16)); }
  .cf-track { display: none; }
  .cf-viewport {
    height: auto; aspect-ratio: 9 / 16;
    width: var(--cf-one); margin-inline: auto;
  }
  .cf-stage { width: 100%; height: 100%; }
  .cf-chrome, .cf-nav { width: var(--cf-one); }
}

.reel-chrome-r { display: flex; align-items: center; gap: var(--space-3); }
.reel-btn-t {
  background: none; border: 0; padding: 0 2px; cursor: pointer; color: var(--ink);
  font-family: var(--font-mono); font-weight: var(--weight-medium);
  font-size: var(--size-label); letter-spacing: var(--track-label); text-transform: uppercase;
}
.reel-btn-t:hover { color: var(--red); }
/* The sound control. A word alone was missed, and it never said which state it was
   in — so the glyph carries the state and the word stays as its name. */
.reel-snd {
  display: inline-flex; align-items: center; gap: var(--space-2);
  background: none; border: 0; padding: 0 2px; cursor: pointer; color: var(--ink);
  font-family: var(--font-mono); font-weight: var(--weight-medium);
  font-size: var(--size-label); letter-spacing: var(--track-label); text-transform: uppercase;
}
.reel-snd:hover { color: var(--red); }
.reel-snd.is-on { color: var(--red); }
.snd-ic { width: 18px; height: 18px; }
/* the waves are what you get, the slash is what you have */
.snd-ic .wv { opacity: 0; stroke-linecap: round; }
.reel-snd.is-on .snd-ic .wv { opacity: 1; }
.reel-snd.is-on .snd-ic .sl { opacity: 0; }
/* §9.1, and `brand-overrides.md` 04: a cue may run a finite number of cycles and then
   rest — never a loop. This one shows the control doing its own job three times: the
   slash lifts, the waves travel out, and it settles back to muted. */
@keyframes snd-cue-sl { 0%, 18%, 82%, 100% { opacity: 1 } 30%, 70% { opacity: 0 } }
@keyframes snd-cue-w1 { 0%, 18%, 82%, 100% { opacity: 0 } 30%, 70% { opacity: 1 } }
@keyframes snd-cue-w2 { 0%, 30%, 76%, 100% { opacity: 0 } 42%, 66% { opacity: 1 } }
.reel-snd.is-cue .snd-ic .sl  { animation: snd-cue-sl 900ms var(--ease-standard) 3; }
.reel-snd.is-cue .snd-ic .wv1 { animation: snd-cue-w1 900ms var(--ease-standard) 3; }
.reel-snd.is-cue .snd-ic .wv2 { animation: snd-cue-w2 900ms var(--ease-standard) 3; }
@media (prefers-reduced-motion: reduce) {
  .reel-snd.is-cue .snd-ic .sl,
  .reel-snd.is-cue .snd-ic .wv1,
  .reel-snd.is-cue .snd-ic .wv2 { animation: none; }
}
.reel-stamp {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--space-3);
  background: linear-gradient(to top, rgba(27,35,31,0.86), rgba(27,35,31,0));
  color: #F1F2EC;
  pointer-events: none;
}
.reel-play {
  position: absolute; inset: 0; width: 100%; height: 100%;
  background: none; border: 0; cursor: pointer; padding: 0;
  display: flex; align-items: center; justify-content: center;
}
.reel-play svg { width: 56px; height: 56px; }
.reel-play polygon { fill: #F1F2EC; }
.reel-play rect { fill: rgba(27,35,31,0.5); }
.reel-play[hidden] { display: none; }
/* ══ the filter row · portofoliu.html, blog.html, analize-de-piata.html ═════
   Written for the archive, where two rows compose: the kind, then the industry inside
   it. The two index pages take the same row for their tags — one row, since a subject
   has one axis — rather than a second filter idiom on the same site. Same buttons,
   same counts, same pressed state, same live line under it; only the noun in the count
   changes, and that is set in js/site.js, not here. */
.arch-filters { margin-top: var(--space-12); }
.arch-row + .arch-row { margin-top: var(--space-6); }
.arch-row-h { color: var(--quiet); margin-bottom: var(--space-3); }
.arch-bar { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.arch-filters .arch-row:last-child {
  padding-bottom: var(--space-6);
  border-bottom: var(--stroke-med) solid var(--ink);
}
.arch-filter-n { color: var(--quiet); margin-left: 2px; }
.arch-filter[aria-pressed="true"] .arch-filter-n { color: inherit; opacity: 0.75; }
.arch-filter {
  min-height: var(--hit-target-min);
  padding: var(--space-2) var(--space-4);
  background: none; border: var(--stroke-hair) solid var(--grid);
  color: var(--ink); cursor: pointer;
  transition: background var(--motion-1) var(--ease-standard),
              color var(--motion-1) var(--ease-standard),
              border-color var(--motion-1) var(--ease-standard);
}
.arch-filter:hover { border-color: var(--ink); }
.arch-filter[aria-pressed="true"] {
  background: var(--ink); color: var(--paper); border-color: var(--ink);
}
.arch-count { margin-top: var(--space-4); color: var(--quiet); }

.arch-grid {
  margin-top: var(--space-8);
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(168px, 100%), 1fr));
  gap: clamp(16px, 0.5rem + 1.4vw, 32px);
}
.arch-frame { margin: 0; }
.arch-frame[hidden] { display: none; }
.arch-play {
  position: relative; display: block; width: 100%; padding: 0;
  border: var(--stroke-hair) solid var(--grid); background: var(--panel);
  aspect-ratio: 9 / 16; cursor: pointer; overflow: hidden;
}
.arch-play video { width: 100%; height: 100%; object-fit: cover; }
.arch-play::after {
  content: ""; position: absolute; inset: 0;
  box-shadow: inset 0 0 0 0 var(--ink);
  transition: box-shadow var(--motion-1) var(--ease-standard);
  pointer-events: none;
}
.arch-play:hover::after { box-shadow: inset 0 0 0 2px var(--ink); }
.arch-cue {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  transition: opacity var(--motion-1) var(--ease-standard);
}
.arch-cue svg { width: 44px; height: 44px; }
.arch-cue rect { fill: rgba(27, 35, 31, 0.5); }
.arch-cue polygon { fill: #F1F2EC; }
.arch-play.is-playing .arch-cue { opacity: 0; }

.arch-meta { margin-top: var(--space-3); display: flex; flex-direction: column; gap: 2px; }
.arch-kind { align-self: flex-start; color: var(--quiet); }
/* "Reclamă" used to be Command Red here, which put ten reds in one grid — §3.4 asks
   for one per composition, and at 12px the dark-mode red measures 4,02:1, under AA.
   The distinction is carried by weight and tone instead: full Ink against quiet. */
.arch-kind.is-ad { color: var(--ink); font-weight: var(--weight-semibold); }
.arch-client { font-size: var(--size-small); line-height: var(--line-small); font-weight: var(--weight-semibold); }
.arch-stamp { color: var(--quiet); }
.arch-none { margin-top: var(--space-8); }

/* ══ the empty shells · blog / materiale / analize ══════════════════════════ */
.empty {
  margin-top: var(--space-16);
  border-top: var(--stroke-med) solid var(--ink);
  padding-top: var(--space-6);
  max-width: var(--measure-body);
}

/* the index of what is being written */
.posts {
  margin-top: var(--space-10);
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(272px, 100%), 1fr));
  gap: var(--space-10) var(--space-8);
}
.post { display: flex; flex-direction: column; color: var(--ink); }
.post[hidden] { display: none; }
/* The tag line is the card's own copy of the filter row: every tag the subject carries,
   in the order it declares them, separated by a mid dot rather than by a second frame —
   these are labels on a card, not controls. Under an active filter the matching one is
   lifted to Ink, so the pressed button and the card agree. */
.post-k { margin-top: var(--space-4); color: var(--quiet); }
.post-tag + .post-tag::before { content: "·"; margin: 0 0.5ch; }
.post-tag.is-on { color: var(--ink); }
.post-t {
  margin-top: var(--space-3);
  font-size: var(--size-h3); line-height: var(--line-h3);
  letter-spacing: var(--track-h3); font-weight: var(--weight-semibold);
}
.post-s {
  margin-top: auto; padding-top: var(--space-6); color: var(--quiet);
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4);
}
/* One element takes the hover, and it is the thing you are about to open. Colouring the
   whole card put the kicker and the state line in Command Red as well — three reds per
   card and a §3.4 count that fails on hover alone. */
a.post:hover .post-t { color: var(--red); }

/* ══ the covers ═════════════════════════════════════════════════════════════
   The figure a subject card and its article page carry — inline SVG, generated in
   js/site.js §4d from the post's position and nothing else. No file, no request.

   The card used to head with a stroke-med Ink rule; that rule is now the cover's
   bottom edge, so the label and the title still hang from the same line and every
   cover in a row aligns at the top of the card. Sides and top are a Grid hairline,
   like the archive frames (§4.3 — a frame is a line).

   Strokes are non-scaling, so they are the token in real pixels rather than the token
   times whatever the card's width happens to be. §4.2 says stroke tracks how a surface
   is viewed, not how wide its canvas is: the card takes the 1440 web row and the
   article's hero takes the deck row above it. */
.post-cover, .art-cover {
  --cv-med: var(--stroke-med);
  --cv-hair: var(--stroke-hair);
  position: relative; display: block; overflow: hidden;
  aspect-ratio: 16 / 10;
  background: var(--panel);
  border: var(--stroke-hair) solid var(--grid);
  border-bottom: var(--stroke-med) solid var(--ink);
}
.post-cover .cv, .art-cover .cv { width: 100%; height: 100%; }

.cv-f, .cv-i, .cv-s, .cv-si, .cv-o, .cv-g {
  stroke-linecap: butt; stroke-linejoin: miter; vector-effect: non-scaling-stroke;
}
/* Every mass is bounded in Ink. That is what makes Khaki usable on a light panel —
   at 2,01:1 the fill alone has no edge, and a hairline gives it one without spending a
   second colour on it. The other two accents are unchanged by it; the rule is the same
   for all three so the ten figures read as one set. */
.cv-f  { fill: var(--cov); stroke: var(--ink); stroke-width: var(--cv-hair); }
.cv-i  { fill: var(--ink); stroke: none; }
.cv-s  { fill: none; stroke: var(--cov); stroke-width: var(--cv-med); }
.cv-si { fill: none; stroke: var(--ink);  stroke-width: var(--cv-med); }
.cv-o  { fill: none; stroke: var(--ink);  stroke-width: var(--cv-hair); }
.cv-g  { fill: none; stroke: var(--grid); stroke-width: var(--cv-hair); }
.cv-dash { stroke-dasharray: 9 7; }

/* The whole card is the link, so under the pointer the cover is what answers — the
   archive's inset ring, same device, same duration. Keyboard focus is left to the
   global :focus-visible outline, which already draws round the whole card; both at
   once is two rings for one state. */
.post-cover::after {
  content: ""; position: absolute; inset: 0;
  box-shadow: inset 0 0 0 0 var(--ink);
  transition: box-shadow var(--motion-1) var(--ease-standard);
  pointer-events: none;
}
a.post:hover .post-cover::after { box-shadow: inset 0 0 0 2px var(--ink); }

/* ══ articol.html ═══════════════════════════════════════════════════════════ */
.art-meta {
  margin-top: var(--space-8);
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
}
.art-cat { color: var(--quiet); }
/* The hero sits on the reading column's outer measure — wider than the body, narrower
   than the page, so the article reads as a column rather than as a spread. */
.art-cover {
  --cv-med: 3px;             /* §4.2, the deck row — the same mark, viewed larger */
  --cv-hair: var(--stroke-light);
  margin-top: var(--space-10); max-width: var(--measure-max);
}
.art-col { margin-top: var(--space-12); max-width: var(--measure-body); }
.art-col h2:first-child { margin-top: 0; }
.art-col h2 { margin-top: var(--space-10); }
.art-col p { margin-top: var(--space-4); }
.art-rule { margin-top: var(--space-16); max-width: var(--measure-max); }
.art-out {
  margin-top: var(--space-10);
  display: flex; gap: var(--space-6); align-items: center; flex-wrap: wrap;
}

/* ══ §03 stations ═══════════════════════════════════════════════════════════ */
.stations {
  margin-top: var(--space-10);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(272px, 100%), 1fr));
  gap: var(--space-8);
}
.station { border-top: var(--stroke-med) solid var(--ink); padding-top: var(--space-6); }
/* With the invented step titles gone, the outcome line is the card's head — it is
   the only thing in the step that says what you walk away with. */
.station-out {
  margin-top: var(--space-4);
  font-size: var(--size-lead); line-height: var(--line-lead);
  font-weight: var(--weight-semibold);
}
/* §7 — drawing. Manual v2.5.0.
   §7.5 no longer describes the line as a set of caps and joins; it specifies it as
   geometry — points offset perpendicular to the run by three seeded sine harmonics and
   emitted as cubics, amplitude 0,375 × stroke, 72px base wavelength, envelope 0,5,
   corners overshooting 1,6 in / 3 out, the second pass reseeded at +977 and offset
   +0,7 / +0,6. So the path data is generated, not drawn by hand: `tools/draw.js`.
   §7.6 never: perspective, isometric, any depth cue, shading, clip-art, a second red
   element, a figure with a face.
   The three icons are Darius's own sketch — lupă, ciocan, roți dințate — restruck to
   §7.5 rather than replaced. Framed, because the sketch frames them.
   Each drawing is authored at the size it renders (220 units, 220px), so the stroke
   token is literally the manual's 2px rather than 2px times a scale factor. */
.drawing { margin-top: var(--space-6); color: var(--ink); }
.dw { width: 100%; max-width: 220px; height: auto; }
.dw-ink, .dw-ink2 {
  fill: none; stroke: currentColor; stroke-width: var(--draw-stroke);
  stroke-linecap: butt; stroke-linejoin: miter;
}
/* struck twice — the same gesture reseeded, barely offset. Never a blur, never a shadow */
.dw-ink2 { opacity: var(--draw-second-pass-opacity); }
/* §3.4 / §7.3 — the one red element in the sequence, in the panel where the decision
   happens. A filled mark, so it is not struck twice. */
.dw-cmd { fill: var(--red); stroke: none; }

/* ══ §04 numbers ════════════════════════════════════════════════════════════ */
.numbers {
  margin-top: var(--space-12);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(248px, 100%), 1fr));
  gap: var(--space-8);
}
.numblock { display: flex; flex-direction: column; align-items: flex-start; }
.numblock-rule { height: var(--stroke-heavy); width: 100%; background: var(--ink); margin-bottom: var(--space-4); }
.numblock-fig {
  font-family: var(--font-mono); font-weight: var(--weight-semibold);
  font-size: var(--size-number); line-height: var(--line-number);
  letter-spacing: var(--track-number); color: var(--ink);
}
.numblock-qual {
  margin-top: var(--space-4); font-family: var(--font-mono);
  font-weight: var(--weight-medium); font-size: var(--size-data);
  line-height: var(--line-data); letter-spacing: var(--track-label);
  text-transform: uppercase;
}
.numblock-period {
  margin-top: var(--space-2); font-family: var(--font-mono);
  font-size: var(--size-data); line-height: var(--line-data);
  letter-spacing: 0.02em; color: var(--water);
}
/* The §4.6 source line is deliberately absent from §04 — removed on Darius's explicit
   instruction ("nobody cares"), against the manual's requirement that a number carry one.
   The derivation for each figure lives in the HIVE_PROOF comment in js/data.js instead.
   The period line stays; he objected to the source only. */
/* §4.6 hard rule — the decimal comma at 0.46 of the figure, zero line-height, −0.10em
   each side. At full size it descends 18px past the baseline at a 96px figure and
   inflates the line box past its own leading.
   `.case-fig` is the same figure at the same size role, so it takes the same rule: 4,95
   is one number and cannot be set two ways on two pages of one site. */
.numblock-comma, .case-comma { font-size: 0.46em; line-height: 0; margin-inline: -0.1em; }

/* ══ §05 prices ═════════════════════════════════════════════════════════════ */
.prices {
  margin-top: var(--space-10);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: var(--space-8);
}
.price {
  border: var(--stroke-med) solid var(--ink);
  padding: clamp(20px, 0.75rem + 1.8vw, 32px);
  display: flex; flex-direction: column;
}
.price-fig { margin-top: var(--space-4); display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.price-fig b {
  font-family: var(--font-mono); font-weight: var(--weight-semibold);
  font-size: clamp(2.5rem, 1.9rem + 1.5vw, 3rem); line-height: 1.08;
}
.price-fig .small { font-weight: var(--weight-regular); }
/* One line under the figure, saying what the figure is. The card used to carry a second
   number here — "+ buget de campanii, minim 1.000 €" — which turned the price into the
   first term of a sum and sent the reader looking for the second. */
.price-sub { margin-top: var(--space-2); color: var(--quiet); }
.price-sep { margin-top: var(--space-6); border-top: var(--stroke-hair) solid var(--grid); }
.price-h { margin-top: var(--space-6); color: var(--quiet); }
/* What you get is the body of the card now, so it is set at Body rather than Small and
   given the room the total line used to take. */
.price ul.price-list { margin-top: var(--space-4); margin-bottom: var(--space-8); }
/* `ul.ticks li` is one class more specific than `.price-list li`, so the Small it sets
   won the cascade and this rule did nothing until it was written to match. */
.price ul.price-list li { font-size: var(--size-body); line-height: 1.5; }
.price ul.price-list li + li { margin-top: var(--space-2); }
/* The budget, pinned to the foot of both cards so they align whatever the lists do.
   It is an arrangement, not an addend: what it says is where the money goes and whose
   account it leaves, and the floor comes after that. */
.price-foot {
  margin-top: auto; padding-top: var(--space-4);
  border-top: var(--stroke-med) solid var(--ink);
}
.price-foot p { margin-top: var(--space-2); color: var(--ink); opacity: 0.82; }
/* the two terms both cards would otherwise have to repeat */
.price-terms {
  margin-top: var(--space-6);
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-8);
  color: var(--quiet);
}

/* The content-only option. This was a bordered band with a red-ringed button; the band
   was cut and the line demoted to a hairline footnote in ink, on the argument that the
   least valuable action should not carry the loudest control on the section.
   Reversed 05.08.2026 by Darius: at footnote weight nobody sees it, and §05 ends up with
   no Command Red anywhere in it. So it reads as an offer again — Lead, semibold, with the
   ask on a red plate. It still sits below the two priced cards and outside their borders,
   so the tiers keep first read; this is the second read, not a third tier.

   A plate rather than red type, and that is measured, not taste: --red as text is 5,00:1
   on paper but 4,02:1 on the dark field — under AA at any size we would set this. --cta
   under the constant --cta-ink label is 5,00:1 light / 4,56:1 dark, and the plate itself
   clears 3:1 against both grounds. Contrast-solved in both themes, which red type is not.

   This plate is the one red element in the §05 composition. brand-overrides 02 counts the
   rail's fixed APLICĂ as persistent chrome, separately — nothing else here goes red. */
.offer-alt {
  margin-top: var(--space-8);
  padding-top: var(--space-6);
  border-top: var(--stroke-hair) solid var(--grid);
  font-size: var(--size-lead); line-height: var(--line-lead);
  font-weight: var(--weight-semibold);
  color: var(--ink);
  display: flex; align-items: center; flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
}

/* ══ §06 the test ═══════════════════════════════════════════════════════════ */
.quiz-wrap {
  margin-top: var(--space-4); border-top: var(--stroke-med) solid var(--ink);
  padding-top: var(--space-8);
  display: flex; gap: var(--space-12); flex-wrap: wrap; align-items: flex-start;
}
.quiz-intro { flex: 1 1 340px; min-width: 0; }
.quiz-card {
  flex: 0 1 340px; width: 340px; max-width: 100%;
  border: var(--stroke-hair) solid var(--grid); padding: var(--space-6);
}
/* The right column is the section's argument drawn, not a spec list for the test. It is
   a 220-unit drawing, so the column is 220 wide and the copy takes the rest — the two
   still meet at the top of the block, which is what balances them. */
.quiz-wrap .drawing { flex: 0 0 220px; max-width: 220px; margin-top: 0; }
.quiz-meter { margin-top: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); }
.quiz-meter i { display: block; height: 1px; background: var(--grid); transition: background var(--motion-1) var(--ease-standard); }
.quiz-meter i.on { background: var(--ink); }

.quiz { margin-top: var(--space-10); display: none; }
.quiz.open { display: block; }
.q {
  border: 0; border-top: var(--stroke-hair) solid var(--grid);
  margin: 0; padding: var(--space-6) 0; min-inline-size: 0;
}
.q:first-child { border-top: var(--stroke-med) solid var(--ink); }
/* a legend cuts a notch in its fieldset's border by default — float it so the rule
   above stays a rule */
.q legend { float: left; width: 100%; padding: 0; margin: 0; }
.q-title { clear: both; margin-top: var(--space-2); font-size: var(--size-lead); line-height: var(--line-lead); font-weight: var(--weight-semibold); }
.q-opts { margin-top: var(--space-4); display: flex; gap: var(--space-6); flex-wrap: wrap; }

.choice {
  display: inline-flex; align-items: center; gap: var(--space-3);
  min-height: var(--hit-target-min); cursor: pointer;
  font-size: var(--size-small); line-height: var(--line-small); color: var(--ink);
}
.choice input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.choice .box {
  width: 24px; height: 24px; flex: 0 0 auto;
  border: var(--stroke-med) solid var(--ink); background: transparent;
  display: flex; align-items: center; justify-content: center;
}
.choice .box svg { width: 14px; height: 14px; opacity: 0; }
.choice .box polyline { fill: none; stroke: var(--paper); stroke-width: 3; stroke-linecap: butt; stroke-linejoin: miter; }
.choice input:checked + .box { background: var(--ink); }
.choice input:checked + .box svg { opacity: 1; }
.choice input:focus-visible + .box { outline: var(--focus-width) solid var(--focus-ring); outline-offset: var(--focus-offset); }

.verdict { margin-top: var(--space-8); border: var(--stroke-med) solid var(--ink); padding: var(--space-8); display: none; }
.verdict.open { display: block; }
/* the verdict's headline is an h2 in the markup and always has been — the rule named
   h3 only, so the title sat hard against the chip above it */
.verdict h2, .verdict h3 { margin-top: var(--space-3); }
.verdict p { margin-top: var(--space-4); max-width: var(--measure-body); }

/* ══ teste.html · the chooser and the calculator ════════════════════════════
   The page offers tools and opens in none of them: the cards are the choice, and the
   tool appears under them once one is picked. A tool that is not built is a card as
   well — quiet, with no ink rule over it and no press state — because a promise made
   in a paragraph under a working tool reads as a roadmap, and a card that is visibly
   inert reads as the truth. */
.tool-pick {
  margin-top: var(--space-12);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(272px, 100%), 1fr));
  gap: var(--space-8);
}
.tool-card {
  display: flex; flex-direction: column; align-items: flex-start; text-align: left;
  gap: var(--space-3);
  background: none; color: var(--ink);
  border: var(--stroke-hair) solid var(--grid);
  border-top: var(--stroke-med) solid var(--ink);
  padding: var(--space-6);
  transition: background var(--motion-1) var(--ease-standard),
              border-color var(--motion-1) var(--ease-standard);
}
button.tool-card { cursor: pointer; }
button.tool-card:hover { border-color: var(--ink); }
.tool-card[aria-pressed="true"] { background: var(--panel); border-color: var(--ink); }
.tool-k { color: var(--quiet); }
.tool-card[aria-pressed="true"] .tool-k { color: var(--ink); }
.tool-t {
  font-size: var(--size-h3); line-height: var(--line-h3);
  letter-spacing: var(--track-h3); font-weight: var(--weight-semibold);
}
.tool-d { color: var(--ink); }
.tool-s { margin-top: auto; padding-top: var(--space-3); color: var(--quiet); }
/* not built: the ink rule comes off, the title goes quiet, and the state line says so.
   No opacity anywhere — a dimmed card is an unreadable card, not an honest one. */
.tool-card.is-soon { border-top: var(--stroke-hair) solid var(--grid); }
.tool-card.is-soon .tool-t, .tool-card.is-soon .tool-d { color: var(--quiet); }

.tool { margin-top: var(--space-16); }
.tool[hidden] { display: none; }
.tool > .quiz-wrap { margin-top: var(--space-10); }

/* three fields, one row where there is room for one. `.field` is the application
   form's, unchanged — an input on this site looks like an input on this site. */
.calc {
  margin-top: var(--space-10);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(232px, 100%), 1fr));
  gap: var(--space-8);
}
.calc .field .hint { color: var(--quiet); opacity: 1; }
/* the placeholder is an example, not a value — it has to be legible and it has to be
   visibly not what you typed */
.calc .field input::placeholder { color: var(--quiet); opacity: 1; }
.calc-say {
  margin-top: var(--space-10); max-width: var(--measure-body);
  font-size: var(--size-lead); line-height: var(--line-lead);
  font-weight: var(--weight-medium);
}
.calc-figs {
  margin-top: var(--space-10);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(216px, 100%), 1fr));
  gap: var(--space-8);
}
.calc-fig { border-top: var(--stroke-med) solid var(--ink); padding-top: var(--space-4); }
.calc-fig-v {
  font-family: var(--font-mono); font-weight: var(--weight-semibold);
  font-size: var(--size-h2); line-height: 1.1; letter-spacing: var(--track-number);
}
.calc-fig-q { margin-top: var(--space-3); }
/* the arithmetic, with this reader's own numbers in it — the figure above is checkable
   on paper, which is the only reason to trust a calculator you did not write */
.calc-fig-f { margin-top: var(--space-2); color: var(--quiet); }

/* ══ §07 faq ════════════════════════════════════════════════════════════════
   Heading, then the questions directly under it, then the way to ask one that is not
   listed — Darius, 06.08. The two-column version put the heading on one side and the
   accordion on the other; this reads top to bottom instead, and the closing row gives
   the section a base rather than trailing off.
   The accordion is held to a measure on purpose: the row is a flex with the sign pushed
   to its far edge, so a full-width row strands the plus half a screen from the question
   it belongs to. */
.faq { max-width: min(100%, 42rem); margin-top: var(--space-10); }
.faq-item { border-top: var(--stroke-hair) solid var(--grid); }
.faq-item:last-of-type { border-bottom: var(--stroke-hair) solid var(--grid); }
.faq-q {
  width: 100%; min-height: var(--hit-target-min);
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4);
  text-align: left; background: none; border: 0; padding: var(--space-4) 0; cursor: pointer;
  font-weight: var(--weight-semibold); font-size: var(--size-body); line-height: 1.4;
  color: var(--ink);
}
.faq-q:hover { color: var(--red); }
.faq-sign { font-family: var(--font-mono); font-weight: var(--weight-regular); flex: none; }
.faq-a {
  display: none; padding: 0 0 var(--space-6);
  max-width: var(--measure-body); font-size: var(--size-small); line-height: var(--line-body);
}
.faq-item.open .faq-a { display: block; }

.faq-foot {
  margin-top: var(--space-8); max-width: min(100%, 42rem);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-6); flex-wrap: wrap;
}
.faq-ask { font-size: var(--size-lead); line-height: var(--line-lead); font-weight: var(--weight-medium); }

/* ══ the application ════════════════════════════════════════════════════════
   The form is aplica.html's. `.promises` is shared: the same three lines close the
   form there and §08 on the landing, which is the ask without the form. */
.form {
  margin-top: var(--space-12); max-width: 840px;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: var(--space-8);
}
.field { display: flex; flex-direction: column; gap: var(--space-2); }
.field label { color: var(--ink); }
.field input, .field textarea {
  font: var(--weight-regular) var(--size-body)/var(--line-body) var(--font-sans);
  color: var(--ink); background: var(--paper);
  border: var(--stroke-med) solid var(--ink); border-radius: 0;
  padding: 10px var(--space-3); min-height: var(--hit-target-min);
  width: 100%; outline-offset: var(--focus-offset);
}
.field textarea { min-height: auto; resize: vertical; }
.field .hint { color: var(--ink); opacity: 0.7; }
.span-all { grid-column: 1 / -1; }
.promises {
  margin-top: var(--space-12); border-top: var(--stroke-med) solid var(--ink);
  padding-top: var(--space-4);
  display: flex; gap: var(--space-8) var(--space-8); flex-wrap: wrap;
}

/* ══ §08 the close ══════════════════════════════════════════════════════════
   The ask on the left, the terms it comes with on the right. As one capped column the
   section left the right half of a 1440 screen empty and ran the three promises across
   the bottom as a row of small type, where they read as a footer rule rather than as
   part of the offer. Standing in their own column, level with the headline, they read
   as the conditions attached to the ask — which is what they are.
   Only §08's copy of `.promises` is restyled; the form on aplica.html keeps the row. */
.close-main .lead { max-width: var(--measure-lead); }
@media (min-width: 1024px) {
  .close-wrap {
    display: grid; align-items: start;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    gap: clamp(32px, 1rem + 2.5vw, 64px);
  }
  .close-side .promises {
    margin-top: 0; padding-top: 0;
    display: flex; flex-direction: column; gap: 0;
  }
  .close-side .promises span {
    padding: var(--space-4) 0;
    border-bottom: var(--stroke-hair) solid var(--grid);
  }
  .close-side .promises span:last-child { border-bottom: 0; }
}
.sent { margin-top: var(--space-4); display: none; }
.sent.open { display: block; }

/* ══ footer ═════════════════════════════════════════════════════════════════
   Contact, social and legal are filled from HIVE_ORG in data.js. Anything without a
   value renders nothing at all — an agency asking for €1.500 a month should either
   show its registration details or not gesture at a place where they would go. */
.foot {
  margin-top: var(--space-32);
  border-top: var(--stroke-med) solid var(--ink);
  padding-top: var(--space-10);
}
.foot-top {
  display: grid; gap: var(--space-10) var(--space-8);
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
}
.foot-brand { grid-column: 1 / -1; }
.foot-brand .lockup { max-width: 180px; }
.foot-line { margin-top: var(--space-4); max-width: 42ch; color: var(--ink); opacity: 0.78; }
@media (min-width: 900px) {
  .foot-top { grid-template-columns: 1.9fr 1fr 1fr 1fr 1fr; }
  .foot-brand { grid-column: auto; }
}
.foot-col-links { margin-top: var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
.foot-col-links a { font-size: var(--size-small); line-height: var(--line-small); }
.foot-col-links .caption { color: var(--quiet); }

.foot-social { margin-top: var(--space-6); display: flex; gap: var(--space-2); flex-wrap: wrap; }
.foot-social a {
  width: var(--hit-target-min); height: var(--hit-target-min);
  display: flex; align-items: center; justify-content: center;
  border: var(--stroke-hair) solid var(--grid); color: var(--ink);
  transition: border-color var(--motion-1) var(--ease-standard),
              color var(--motion-1) var(--ease-standard);
}
.foot-social a:hover { border-color: var(--ink); color: var(--red); }
.foot-social .ic { width: 20px; height: 20px; }

.foot-legal {
  margin-top: var(--space-10); padding-top: var(--space-4);
  border-top: var(--stroke-hair) solid var(--grid);
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--space-3) var(--space-8); justify-content: space-between;
}
.foot-legal .caption { color: var(--quiet); }
.foot-legal-links { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-6); }
.foot-legal-links a {
  font-family: var(--font-mono); font-size: var(--size-caption);
  letter-spacing: var(--track-caption); text-transform: uppercase;
  color: var(--quiet);
}
.foot-legal-links a:hover { color: var(--red); }
.foot-legal:empty, .foot-social:empty, .foot-legal-links:empty { display: none; }
/* The language switch shares the legal row, because that row is the only one present
   on every page of both builds. It is not a legal link, so a separator sets it apart
   rather than a colour of its own — and it borrows the site's own `·`, not a new
   idiom. On the campaign pages the switch is a rail-sub and needs none of this. */
.foot-legal-links .lang-switch::before {
  content: '·'; margin-right: var(--space-6); color: var(--grid);
}

/* The lockup ships as ink-on-paper. Masked with currentColor it follows the theme
   instead of needing a second file. */
.lockup {
  display: block; width: 100%; max-width: 208px; aspect-ratio: 463.38 / 109;
  background: currentColor; color: inherit;
  -webkit-mask: url("../assets/hive_lockup-h_currentcolor.svg") no-repeat left center / contain;
          mask: url("../assets/hive_lockup-h_currentcolor.svg") no-repeat left center / contain;
}

/* ══ studii-de-caz ══════════════════════════════════════════════════════════
   Seven studies, one structure. The old three were a paragraph and three bullets each
   and read as blurbs; a case study has to answer what happened, what we did, how, and
   why it worked, and the result has to be the thing the client actually got — revenue,
   not a ratio. The source and the hedging lines are gone at Darius's instruction; the
   conflict with §4.6 is logged in brand-overrides.md. */
.case {
  margin-top: var(--space-20);
  border-top: var(--stroke-heavy) solid var(--ink);
  padding-top: var(--space-6);
}
.case-head { display: flex; align-items: baseline; gap: var(--space-4); flex-wrap: wrap; }
.case-n { color: var(--quiet); }
.case-when { color: var(--quiet); margin-left: auto; }

/* the result and the three figures that qualify it, on one band */
.case-hero {
  margin-top: var(--space-8);
  display: grid; gap: var(--space-8) var(--space-12);
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  align-items: end;
}
.case-result { border-left: var(--stroke-command) solid var(--red); padding-left: var(--space-6); }
.case-fig {
  font-family: var(--font-mono); font-weight: var(--weight-semibold);
  font-size: var(--size-number); line-height: var(--line-number);
  letter-spacing: var(--track-number);
}
/* §4.6 — the decimal comma is set at 0.46 of the figure and pulled in on both sides,
   so a thousands separator never opens a hole in a number this size. */
.case-comma { font-size: 0.46em; line-height: 0; margin: 0 -0.06em 0 -0.04em; }
.case-unit { font-size: 0.42em; margin-left: 0.24em; letter-spacing: 0; }
.case-qual {
  margin-top: var(--space-4); font-family: var(--font-mono);
  font-weight: var(--weight-medium); font-size: var(--size-data);
  letter-spacing: var(--track-label); text-transform: uppercase;
}
.case-period {
  margin-top: var(--space-2); font-family: var(--font-mono);
  font-size: var(--size-data); line-height: var(--line-data);
  letter-spacing: 0.02em; color: var(--water);
}
.case-stats { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.case-stats li {
  display: flex; align-items: baseline; gap: var(--space-4);
  border-top: var(--stroke-hair) solid var(--grid); padding-top: var(--space-2);
}
.case-stats b {
  font-family: var(--font-mono); font-weight: var(--weight-semibold);
  font-size: var(--size-lead); letter-spacing: var(--track-number);
  flex: 0 0 auto; min-width: 7ch;
}
.case-stats span {
  font-family: var(--font-mono); font-size: var(--size-caption);
  letter-spacing: var(--track-caption); text-transform: uppercase; color: var(--quiet);
}

/* the four parts, two up — the reading measure still binds each one */
/* Two up, never three: auto-fit gave three columns at 1920 and left "De ce a funcționat"
   orphaned on a row of its own with two empty cells beside it. Four parts want 2x2. */
.case-story {
  margin-top: var(--space-12);
  display: grid; gap: var(--space-10) var(--space-12);
  grid-template-columns: 1fr;
}
@media (min-width: 860px) { .case-story { grid-template-columns: 1fr 1fr; } }
.case-part .body, .case-part .ticks { margin-top: var(--space-3); }
.case-part .body { max-width: var(--measure-body); }

/* the test's two ways out — both always present, the emphasis flips with the verdict */
.verdict-out {
  margin-top: var(--space-8);
  display: flex; align-items: center; gap: var(--space-6); flex-wrap: wrap;
}

/* ══ breakpoints ════════════════════════════════════════════════════════════ */

/* below the rail: the top bar carries the whole of it */
@media (max-width: 1023px) {
  .rail { display: none; }
  .topbar { display: flex; }
  .shell { display: block; }
  .page { max-width: 720px; margin: 0 auto; padding-bottom: var(--space-16); }
  .sec { scroll-margin-top: calc(var(--header-h) + 8px); }
  h1 { max-width: none; }
  /* the frame hugs the stage rather than stretching past it */
  /* `nowrap` matters: stacked, this is a column flex container, and a *wrapping* one
     takes each line's cross size — here the width — from its widest item. The strip's
     max-content width is 35 cells side by side, so `stretch` stretched the whole column
     to 2.952px and the page scrolled sideways at 320, 390 and 768. Single-line, the
     cross size is the container's own definite width and the strip clips inside it. */
  /* the strip is the section's full width here, not the frame's */
  .quiz-card { flex: 1 1 100%; width: 100%; }
  .foot { margin-top: var(--space-16); }
}

/* tablet: a taller bar, more room to breathe */
@media (min-width: 768px) and (max-width: 1023px) {
  :root { --header-h: 56px; }
  .page { max-width: 840px; }
}

/* laptop: the rail is on, but the margins are not yet the full 80 */
@media (min-width: 1024px) and (max-width: 1279px) {
  :root { --rail-w: 224px; }
}

/* very small phones. The 17px body override that used to live here is now the floor of
   the `--size-body` ramp itself, so it held at every width below 390 rather than only
   below 360; the override was doing nothing and is gone. */
@media (max-width: 359px) {
  .q-opts { flex-direction: column; gap: var(--space-2); }
  .reel-chrome { flex-wrap: wrap; }
}

@media print {
  .rail, .topbar, .cf-nav, .cf-chrome, .theme { display: none !important; }
  .page { max-width: none; }
}
