/* ==========================================================================
   Cast Beacon — Draft 03 "Slate"
   Broadcast slate / test card. Flat blocks, hard edges, enormous type.
   No gradients (except inside the logo mark itself), no shadows,
   no border-radius anywhere above 2px.
   ========================================================================== */

:root{
  /* flat palette */
  --bone:#F0EDE6;
  --coal:#141110;
  --beam:#FF8A04;
  --deep:#FF6500;
  /* ONE ORANGE FOR TEXT, EVERYWHERE, and it is --beam.

     There was a darkened companion for bone here, on the reasoning that
     #FF8A04 on #F0EDE6 measures 2.0:1 and WCAG asks 4.5:1 of body text and
     3:1 of display. It was removed on purpose: an accent that changes value
     with its ground is two colours, and the brand is one. The call is the
     owner's, made twice, and this comment is the record of the trade rather
     than an argument against it — the mark is always a short phrase or a
     single full stop beside full-contrast ink, never a load-bearing sentence
     on its own. */

  --program:#EAB308;
  --stream:#8B5CF6;
  --control:#8A8279;
  --failover:#EF4444;
  --info:#14B8A6;

  /* ink, per block. every value below is >= 4.5:1 on its own ground */
  --on-bone:#141110;        /* 16.2:1 */
  --on-bone-2:#57534E;      /*  6.0:1 */
  --on-bone-3:#6E675E;      /*  4.8:1 */
  --rule-bone:#CFC8BB;

  --on-coal:#F0EDE6;        /* 16.2:1 */
  --on-coal-2:#B4ADA3;      /*  8.1:1 */
  --on-coal-3:#918A80;      /*  5.5:1 */
  --rule-coal:#39352E;      /*  1.54:1 — non-text hairline inside a plate */
  /* The header rule is not an interior hairline: it is the edge of a sticky
     bar that has to stay separate from the coal plates sliding under it.
     At --rule-coal it measured 1.54:1 and read as a smudge. 3.26:1. */
  --rule-bar:#6B655C;

  --on-beam:#141110;        /*  7.96:1 */
  /* Was #4A2F08 (5.22:1). At 10–11px mono with .15em tracking the CSS value is
     not what the eye gets: a rendered scan of the card numbers and the RTMPS
     captions put the darkest decile of the antialiased ink at #693E06 (3.88:1)
     and #704206 (3.60:1), with median ink at #B36305 (1.89:1). A label at
     1.89:1 is a texture, not a label. #2A1A04 is 7.15:1 as authored — 90% of
     the 7.96:1 ceiling that pure coal on this orange allows — so even the
     blended pixels stay above the small-text floor. */
  --on-beam-2:#2A1A04;      /*  7.15:1 */
  --rule-beam:#C26E02;      /*  1.61:1 — non-text hairline, decorative */

  --font:-apple-system,BlinkMacSystemFont,"SF Pro Display","SF Pro Text","Segoe UI",system-ui,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;

  --pad:clamp(20px,4.6vw,72px);
  --barh:56px;
}

/* ---------- reset ---------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  background:var(--coal);
  color:var(--on-bone);
  font-family:var(--font);
  font-size:17px;
  line-height:1.55;
  overflow-x:hidden;
  text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased;
}
img,svg{display:block;max-width:100%}
h1,h2,h3,p,dl,dd,ol,ul,figure{margin:0}
ol,ul{list-style:none;padding:0}
button,input{font:inherit;color:inherit}
table{border-collapse:collapse;width:100%}

.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip:rect(0 0 0 0);white-space:nowrap;border:0}

.skip{position:absolute;left:-9999px;top:0;z-index:99;background:var(--coal);
      color:var(--bone);padding:12px 18px;font-family:var(--mono);font-size:12px;
      text-transform:uppercase;letter-spacing:.14em;text-decoration:none}
.skip:focus{left:0}

/* ---------- focus ----------
   The ring is always the colour that clears 3:1 against the block it lands on:
   coal on bone and on orange, the beam on coal. */
:where(a,button,input,[tabindex]):focus-visible{
  outline:3px solid var(--coal);
  outline-offset:2px;
}
/* .skip is a SIBLING of .bar, not a descendant, so the .bar rule below never
   reached it — it drew a coal ring inside the coal bar (1.00:1). It is the
   first tab stop on the page, so it is named explicitly. */
.skip:focus-visible,
.plate--coal :where(a,button,input,[tabindex]):focus-visible,
.foot :where(a,button):focus-visible{outline-color:var(--beam)}
/* The bar is bone now, and --beam on bone is 2.07:1 — under 1.4.11's 3:1 for
   a focus indicator. Coal is 16.2:1 and matches every other light ground. */
.bar :where(a,button):focus-visible{outline-color:var(--coal)}
.plate--beam :where(a,button,input,[tabindex]):focus-visible{outline-color:var(--coal)}

/* ---------- shared type ---------- */
.mono,.ptag,.tc,.wl__label,.wl__fine,.st,.dest__m,.dest__i,.lim__i,
.slate dt,.foot__meta dt,.bars__seg span,.tbl th,.meas__k,.meas__s{
  font-family:var(--mono);
  font-size:11px;
  letter-spacing:.15em;
  text-transform:uppercase;
  font-weight:500;
}

.d1{
  /* The floor, not the curve. At 46px the display/body ratio fell to 2.9x at
     390px and the premise of the page went with it. 56px is the ceiling that
     still holds the authored three-line break at 390px: "Everywhere it" needs
     6.03x its font size and there are 350px of measure, so 58.1px is where
     the line splits and the hero starts orphaning words. Desktop is
     untouched — 11.3vw passes 56px at 496px wide. */
  font-size:clamp(56px,11.3vw,168px);
  line-height:.88;      /* .86 put the y of "Everywhere" 3.1px into the line below */
  letter-spacing:-.05em;
  font-weight:800;
  /* Optical alignment. Every other element on the page hangs off the rail by
     its layout box; display type has to hang off its INK, so the left
     sidebearing is pulled back. em-relative, so it scales with the clamp.
     -.055em was short: a rendered scan put the flat stems of "E" and "N" at
     x=68.0 against a 66.24 rail. The sidebearing measures .0658em, so that is
     what comes off — replacing the old figure, not stacking on it. The round
     "O" of line 2 still overhangs by ~6px, which is the point of aligning
     stems rather than boxes. */
  margin-left:-.066em;
}
.d1 .l{display:block}

/* THE HEADLINE COMES DOWN A FIFTH — ABOVE THE PHONE BAND ONLY.

   At 11.3vw the hero was three lines of display type across most of a wide
   screen: a lot of room spent asserting the argument before the section below
   it does the work of making it. On a phone the size was already right — the
   floor is a legibility floor, not a taste one — so this starts where the
   phone layout stops.

   AND THE ROOM IT GIVES BACK STAYS EMPTY. Shrinking the type alone would pull
   the lede and the form up behind it and the hero would simply be smaller,
   which is not the point; the point is the air. So the height the headline
   releases is handed back to its own box as padding — half above, half below,
   so the line block stays where it was optically rather than riding up under
   the plate tag.

   0.66em: three lines at a line-height of .88 lose .528 of the ORIGINAL size,
   which is .66 of the new one. Split, that is .33 either side. */
@media (min-width:761px){
  .hero h1.d1{
    font-size:clamp(56px,9.04vw,134px);
    padding:.33em 0;
  }
}
.d2{
  font-size:clamp(34px,5.4vw,76px);
  line-height:.92;
  letter-spacing:-.04em;
  font-weight:800;
}
.d2--wide{margin-bottom:clamp(36px,5vw,64px)}
.body{
  font-size:clamp(16px,1.25vw,19px);
  line-height:1.6;
  max-width:44ch;
}

/* ---------- plates ---------- */
.wrap{max-width:1560px;margin:0 auto;width:100%}
.plate{
  padding:clamp(56px,7vw,110px) var(--pad) clamp(64px,8vw,124px);
  border-top:1px solid transparent;
  /* --barh is the inner height; the bar's own bottom rule sits below it, so an
     anchor jump landed the plate under the rule. It was 1px out before and the
     thicker rule would have made it 2px. */
  scroll-margin-top:calc(var(--barh) + 2px);
}
.plate--bone{background:var(--bone);color:var(--on-bone);border-top-color:var(--coal)}
.plate--coal{background:var(--coal);color:var(--on-coal);border-top-color:var(--coal)}
.plate--beam{background:var(--beam);color:var(--on-beam);border-top-color:var(--coal)}

.plate--bone .body{color:var(--on-bone-2)}
.plate--coal .body{color:var(--on-coal-2)}

/* plate tag row */
.ptag{
  display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding-bottom:12px;margin-bottom:clamp(28px,4vw,54px);
  border-bottom:1px solid var(--rule-bone);
}
.plate--coal .ptag{border-bottom-color:var(--rule-coal)}
.plate--beam .ptag{border-bottom-color:var(--rule-beam)}
.ptag__l{white-space:nowrap}
.ptag__l::before{
  content:"";display:inline-block;width:8px;height:8px;
  background:var(--beam);margin-right:11px;
}
.plate--beam .ptag__l::before{background:var(--coal)}
/* Mono tracking is applied AFTER the last glyph too, so the eyebrow stopped
   2.5px short of the right edge every other terminal element hits. The trailing
   letter-space is taken back off. */
.ptag__r{text-align:right;color:var(--on-bone-3);margin-right:-.15em}
.plate--coal .ptag__r{color:var(--on-coal-3)}
.plate--beam .ptag__r{color:var(--on-beam-2)}

/* ---------- header bar ---------- */
/* A sticky bar does not have one ground behind it, it has three, and it has to
   hold against all of them. Coal failed on the coal plates — 02, 05 and the
   footer, about a third of the scroll — where it had no edge at all.

   Bone is the inverse trade and the better one. Against the coal and orange
   plates a light slab separates hard on its own. Against the bone plates it
   sits flush and a hairline carries the join, which is the ordinary editorial
   answer rather than a defect: the whole page is already built from flush
   bone-on-bone blocks divided by exactly this rule. */
.bar{
  position:sticky;top:0;z-index:40;
  background:var(--bone);color:var(--on-bone);
  border-bottom:1px solid var(--rule-bone);
}
.bar__in{
  max-width:1560px;margin:0 auto;height:var(--barh);
  padding:0 var(--pad);
  display:flex;align-items:center;gap:clamp(16px,3vw,44px);
  position:relative;          /* the nav is centred against this box */
}
.bar__logo{display:flex;align-items:center;color:var(--on-bone);text-decoration:none}
/* 22px left the lockup outweighed by its own neighbours — the nav is 600
   mono and the CTA is a filled block, and a thin logotype between them read
   as frail. 27px puts the wordmark's cap height in the same band as the nav
   without crowding the 76px bar. */
.lockup{height:27px;width:auto}
/* As a third flex child with auto margins the nav centred in the space LEFT
   OVER between the logo and the TC/CTA cluster — midpoint 616.25 against a
   content axis of 719.75, so it sat 103px off its own page. Taking it out of
   flow puts it on the container axis in every state and at every width. */
.bar__nav{
  position:absolute;left:50%;transform:translateX(-50%);
  display:flex;gap:clamp(14px,2vw,30px);
}
.bar__nav a{
  font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--on-bone-2);text-decoration:none;padding:6px 0;   /* 6.0:1 */
  border-bottom:1px solid transparent;
}
.bar__nav a:hover{color:var(--on-bone);border-bottom-color:var(--beam)}
.bar__right{display:flex;align-items:center;gap:clamp(12px,2vw,24px);margin-left:auto}
/* The one link in the bar. Same mono, same tracking and same size as the line
   beside it, because they are two facts of equal weight — where else to go,
   and when this arrives. Ink rather than muted, since one of them is a control
   and the other is a statement, and the difference has to be visible without
   an underline. */
.bar__to{
  font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--on-bone);text-decoration:none;padding:6px 0;
  border-bottom:1px solid transparent;white-space:nowrap;
}
.bar__to:hover{border-bottom-color:var(--beam)}
.bar__to.is-here{border-bottom-color:var(--beam)}
.tc{color:var(--on-bone-3);font-variant-numeric:tabular-nums;letter-spacing:.1em}  /* 4.8:1 */

/* ---------- mobile menu ----------
   A word, not a glyph: an icon would be the only icon in the system. Shown
   wherever .bar__nav is hidden; the <noscript> block in the head withdraws
   it if there is no JS to work it. */
.bar__menu{
  display:none;
  font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  font-weight:500;background:transparent;color:var(--on-bone-2);
  /* Not --rule-bone. This border is the visible bound of a control, which
     1.4.11 puts a 3:1 floor under, and a plate divider does not clear that:
     --rule-bone is 1.42:1 here and --rule-coal was 1.54:1 on the old coal bar,
     so this was already failing before the bar changed ground. --on-bone-3 is
     4.8:1 and is the value the timecode beside it already uses. */
  border:1px solid var(--on-bone-3);border-radius:0;padding:8px 12px;cursor:pointer;
}
.bar__menu:hover{color:var(--on-bone);border-color:var(--beam)}
.navmenu{
  display:none;
  background:var(--bone);border-top:1px solid var(--rule-bone);
  padding:0 var(--pad) 10px;
}
.navmenu[data-open="1"]{display:block}
.navmenu a{
  display:block;padding:16px 0;
  font-family:var(--mono);font-size:12px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--on-bone);text-decoration:none;border-bottom:1px solid var(--rule-bone);
}
.navmenu a:last-child{border-bottom:0}
.navmenu a:hover{color:var(--beam)}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--mono);font-size:11px;letter-spacing:.15em;text-transform:uppercase;
  font-weight:600;text-decoration:none;cursor:pointer;
  border:1px solid transparent;border-radius:0;
  padding:11px 18px;
  transition:background .12s linear,color .12s linear,border-color .12s linear;
}
.btn--beam{background:var(--beam);color:var(--coal);border-color:var(--beam)}
.btn--beam:hover{background:var(--bone);border-color:var(--bone)}
/* On a coal ground that hover reads as an invert. On the bone bar it painted
   a bone button on a bone bar: the CTA disappeared under the cursor. */
.bar__cta:hover{background:var(--coal);color:var(--bone);border-color:var(--coal)}
.btn--coal{background:var(--coal);color:var(--bone);border-color:var(--coal)}
.btn--coal:hover{background:transparent;color:var(--coal)}
.plate--coal .btn--coal{background:var(--bone);color:var(--coal);border-color:var(--bone)}
.bar__cta{padding:9px 16px}

/* ---------- PLATE 01 · hero ---------- */
/* The bar's own rule is the division here. Leaving the plate's coal top border
   in as well stacked #6B655C over #141110 over cream — three edges where the
   design has one. The first plate gives its border up; every other plate keeps
   the coal line, because there is no bar between them. */
.hero{padding-top:clamp(32px,3.6vw,52px);border-top-color:transparent}
.hero .ptag{margin-bottom:clamp(24px,3vw,40px)}
/* 19ch, not 15ch: the cap exists to stop the display line running wider than
   its authored break, and the longest line is now "Your cloud relay." at 17
   characters. Too tight a cap does not tidy the headline, it overrides the
   break and wraps it somewhere nobody chose. */
.hero .d1{margin-bottom:clamp(30px,3.6vw,50px);max-width:19ch}
/* The accent full stop. --deep on bone measures 2.52:1 (was 2.02:1 with
   --beam). Accepted as a decorative mark: it carries no information the
   sentence does not already carry, and it is 40px of solid ink. Deliberately
   NOT darkened further — a fourth orange would cost more than it buys. */
/* EVERY ORANGE MARK IN A SENTENCE IS THE BEAM, and on bone that means the
   beam darkened. This was --deep #FF6500: a different hue from the accent the
   page ends on (24° against 32°), and 2.6:1 on bone, which a full stop the
   size of a fist still does not get away with — large text needs 3:1. If an
   orange mark ever lands on a coal plate it wants --beam itself. */
.dot{color:var(--beam)}

/* The typewriter caret. Same colour as the dot it becomes — motion.js fades
   one out while the other fades in, at the same spot, so it reads as one
   mark resolving into what it always was rather than a swap. Solid while a
   line is actively typing; blinking is reserved for the pauses either side
   (before the first key, and the beat between lines), which is closer to how
   a person's cursor actually behaves than a constant blink would be.
   Only ever exists if motion.js created it, so there is no reduced-motion
   guard needed here specifically — the file that adds this class never runs
   under reduced motion in the first place, and the page's existing global
   `*{animation-duration:.001ms!important}` rule still catches it if that
   assumption is ever wrong. */
.type-caret{color:var(--beam)}
.type-caret--blink{animation:cb-caret-blink 1s steps(1,end) infinite}

/* The part of the line not yet typed: present in the layout, invisible to the
   eye. It is what stops a wrapping headline from re-breaking on every
   keystroke and dragging already-written words around with it. Not
   display:none and not opacity — it has to occupy its space to do its job. */
.type-ghost{visibility:hidden}
@keyframes cb-caret-blink{0%,49%{opacity:1}50%,100%{opacity:0}}

.hero__row{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(28px,4vw,64px);
  align-items:start;
  padding-bottom:clamp(32px,4vw,52px);
}
.lede{
  font-size:clamp(17px,1.35vw,20px);line-height:1.55;color:var(--on-bone-2);
  max-width:52ch;
}
.hero__act{justify-self:end;width:100%;max-width:520px}

/* ---------- slate metadata table ---------- */
.slate{
  display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  border-top:1px solid var(--coal);
}
/* No left padding on ANY cell. With 18px on cells 2–5 the first step measured
   279.5px against 261.5px for the rest — the opening column of the spec table
   was 18px wider than the four beside it, on a page whose whole claim is one
   grid. Flush to the track start, the steps are 261.5 / 261.5 / 261.6 / 261.5
   and cell 1 sits on the rail. */
.slate__cell{
  /* Off the rules on both sides. Every cell carries a divider on its right, so
     with no left padding the next cell's text started ON that line — five
     labels each pressed against the rule in front of them. The first cell
     keeps its zero, because that edge is not a divider, it is the page's own
     left rail and the whole grid hangs off it. */
  padding:20px 22px 22px 22px;
  border-right:1px solid var(--rule-bone);
}
.slate__cell:first-child{padding-left:0}
.slate__cell:last-child{border-right:0}
.slate dt{color:var(--on-bone-3);margin-bottom:8px}
.slate dd{
  font-size:clamp(15px,1.15vw,18px);font-weight:600;letter-spacing:-.01em;
  color:var(--on-bone);
}
.dash{font-weight:800}

/* ---------- colour bars ---------- */
.bars{background:var(--coal);padding:0 0 clamp(22px,3vw,34px)}
/* Full bleed, edge to edge — a colour bar is a test signal, not a column of
   body copy, and every reference test card runs its bars flush to the frame.
   The keys stay in the same six-column grid so each label still sits under
   its own swatch; only the outer margin is gone, with a little breathing
   room on the first/last label so PROGRAM and BEACON don't touch the glass. */
.bars__strip{
  display:grid;grid-template-columns:repeat(6,1fr);
  height:clamp(50px,5.6vw,73px);   /* 70% of the original clamp(72px,8vw,104px) */
}
.bars__strip i{background:var(--seg);display:block}
/* One line under the bar, and it is the claim rather than a legend. The six
   keys that used to name the signal types went with the eleven plates that
   explained them — on a page this short, a colour key is a glossary for a
   vocabulary nobody is being taught. */
.bars__note{
  font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;
  line-height:1.7;color:var(--on-coal-3);
  padding:clamp(18px,2.4vw,30px) var(--pad) 0;max-width:840px;
}

/* ---------- PLATE 02 · split ---------- */
.split{
  display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1.14fr);
  gap:clamp(32px,5vw,88px);
  align-items:start;
}
/* Both columns. A split does not always put the prose on the left — the scope
   section hangs one short headline in column A and the whole argument in
   column B, and with this scoped to __a its paragraphs ran together into one
   block with no air between them. */
.split .body{margin-top:clamp(20px,2.4vw,32px)}

/* destination table */
.tbl th{
  color:var(--on-coal-3);text-align:left;font-weight:500;
  padding:0 0 10px;border-bottom:1px solid var(--rule-coal);
}
.tbl td{
  padding:15px 0;border-bottom:1px solid var(--rule-coal);
  font-size:clamp(16px,1.3vw,20px);font-weight:600;letter-spacing:-.015em;
  vertical-align:baseline;
}
.tbl td:nth-child(2){
  font-family:var(--mono);font-size:12px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;color:var(--on-coal-2);width:24%;
}
.tbl td:nth-child(3){width:26%;text-align:right}
.tbl tr:last-child td{border-bottom:0}
.st{display:inline-flex;align-items:center;gap:8px;font-weight:600;font-size:11px}
.st::before{content:"";width:9px;height:9px;background:currentColor;flex:none}
.st--ok{color:var(--info)}
.st--wait{color:var(--program)}
.st--bad{color:var(--failover)}
.st--off{color:var(--control)}
.tbl__note{
  margin-top:22px;padding-top:18px;border-top:1px solid var(--rule-coal);
  font-size:15px;line-height:1.6;color:var(--on-coal-2);max-width:60ch;
}

/* ---------- PLATE 03 · the motif ---------- */
.meas{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  border-top:1px solid var(--rule-beam);
}
.meas__cell{
  padding:clamp(20px,2.4vw,32px) clamp(14px,1.6vw,24px) clamp(22px,2.6vw,34px);
  border-right:1px solid var(--rule-beam);
  display:flex;flex-direction:column;min-width:0;
}
.meas__cell:last-child{border-right:0}
.meas__cell:first-child{padding-left:0}
.meas__k{color:var(--on-beam-2);font-size:10px}
.meas__v{
  font-size:clamp(66px,8.6vw,132px);line-height:.86;letter-spacing:-.055em;
  font-weight:800;margin:clamp(18px,2.4vw,34px) 0 auto;
  font-variant-numeric:tabular-nums;
}
.meas__s{margin-top:clamp(16px,2vw,26px);color:var(--on-beam-2);font-size:10px}
.meas__cell--dash{background:var(--coal);color:var(--bone);border-right:0}
.meas__cell--dash .meas__k,.meas__cell--dash .meas__s{color:var(--on-coal-2)}
/* The dash keeps the numbers' size and baseline on purpose: it is the answer
   in the same place a number would have been, not a graphic standing in. */
.meas__v--dash{color:var(--beam);letter-spacing:0}

.motif__foot{
  margin-top:clamp(34px,4.4vw,62px);
  display:grid;grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr);
  gap:clamp(24px,4vw,72px);align-items:end;
}
.motif__line{
  font-size:clamp(26px,3.5vw,52px);line-height:1.04;letter-spacing:-.038em;
  font-weight:800;
}
.motif__sub{
  font-size:clamp(15px,1.15vw,18px);line-height:1.62;color:var(--on-beam-2);
  max-width:52ch;
}

/* ---------- PLATE 04 · vocabulary ---------- */
.vocab{border-top:1px solid var(--coal)}
.vocab__row{
  display:grid;
  grid-template-columns:auto minmax(190px,.62fr) minmax(0,1.38fr);
  gap:clamp(16px,2.4vw,44px);
  align-items:baseline;
  padding:clamp(20px,2.6vw,34px) 0;
  border-bottom:1px solid var(--rule-bone);
}
.vocab__chip{
  width:14px;height:14px;background:var(--chip);flex:none;
  transform:translateY(-2px);
}
.vocab__w{
  font-size:clamp(28px,3.9vw,56px);line-height:.95;letter-spacing:-.04em;font-weight:800;
}
.vocab__d{font-size:clamp(15px,1.2vw,18px);line-height:1.55;color:var(--on-bone-2);max-width:52ch}

/* ---------- PLATE 05 · reach ---------- */
.reach{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(32px,5vw,80px);align-items:center;
}
.reach__a .body{margin-top:clamp(20px,2.4vw,32px)}
.reach__b{border:1px solid var(--rule-coal);padding:clamp(16px,2vw,28px)}
.diag{width:100%;height:auto}
.diag__box rect{fill:none;stroke:var(--on-coal-3);stroke-width:1}
.diag__box .diag__box--key{stroke:var(--beam);stroke-width:2}
.diag__wire path{fill:none;stroke:var(--stream);stroke-width:1.5}
.diag__wire--prog path{stroke:var(--program)}
.diag__t text{
  fill:var(--bone);font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;
}
.diag__n text{
  fill:var(--beam);font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;
}

/* ---------- PLATE 06 · destinations ---------- */
.dest{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  border-top:1px solid var(--coal);border-left:1px solid var(--rule-bone);
}
.dest__c{
  border-right:1px solid var(--rule-bone);
  border-bottom:1px solid var(--rule-bone);
  padding:clamp(18px,2.2vw,30px);
  display:flex;flex-direction:column;gap:6px;min-height:clamp(120px,12vw,168px);
}
.dest__i{color:var(--on-bone-3);font-size:10px}
.dest__n{
  margin-top:auto;
  font-size:clamp(20px,2.2vw,32px);font-weight:800;letter-spacing:-.035em;line-height:1;
}
.dest__m{color:var(--on-bone-3);font-size:10px}
.dest__c--any{background:var(--coal);color:var(--bone);border-right-color:var(--coal)}
.dest__c--any .dest__i,.dest__c--any .dest__m{color:var(--on-coal-2)}
.dest__note{
  margin-top:clamp(24px,3vw,40px);font-size:clamp(15px,1.15vw,18px);
  line-height:1.6;color:var(--on-bone-2);max-width:62ch;
}
/* Plate 06 runs on orange (it is the accent beat between plate 03 and plate
   08). Dark ink only — never white. Measured on #FF8A04:
   card names #141110 = 7.96:1, labels/note #4A2F08 = 5.22:1. */
.plate--beam .dest{border-left-color:var(--rule-beam)}
.plate--beam .dest__c{border-right-color:var(--rule-beam);border-bottom-color:var(--rule-beam)}
.plate--beam .dest__i,
.plate--beam .dest__m,
.plate--beam .dest__note{color:var(--on-beam-2)}
.plate--beam .dest__c--any{border-right-color:var(--coal)}
.plate--beam .dest__c--any .dest__i,
.plate--beam .dest__c--any .dest__m{color:var(--on-coal-2)}

/* ---------- PLATE 07 · limits ----------
   Two columns, filled DOWN then across: 01–03 left, 04–06 right. In one
   column each hairline ran ~490px past the end of its own text. Now every
   rule terminates at the measure it belongs to.
   This plate is CREAM (see the note in the markup). Everything below was
   authored for coal and is re-mapped: rules to --rule-bone, prose to
   --on-bone (16.2:1), and the index numbers off --beam, which is 2.02:1 on
   cream and could not stay. --on-bone-2 is 6.0:1 and still reads as a label
   rather than as body. Darkening the orange instead would have bought a
   fourth orange, which this page has already refused once. */
.lim{
  margin-top:clamp(32px,4vw,56px);
  display:grid;grid-auto-flow:column;
  grid-template-columns:repeat(2,minmax(0,1fr));
  grid-template-rows:repeat(3,auto);
  column-gap:clamp(32px,5vw,88px);
}
.lim__row{
  display:grid;grid-template-columns:auto minmax(0,1fr);
  gap:clamp(14px,2vw,28px);
  padding:clamp(18px,2.2vw,28px) 0;
  border-top:1px solid var(--rule-bone);
  align-items:baseline;
}
/* the last row of each column closes the stack */
.lim__row:nth-child(3),.lim__row:nth-child(6){border-bottom:1px solid var(--rule-bone)}
.lim__i{color:var(--on-bone-2);font-size:11px}
.lim__row p{font-size:clamp(16px,1.35vw,21px);line-height:1.5;letter-spacing:-.015em;
            color:var(--on-bone)}

/* ---------- waitlist form ----------
   --on-bone-3 (4.77:1) does six jobs across this page. The conversion path is
   not one of them: the field label and the fine print step up to --on-bone-2
   (6.53:1) so the thing we are asking for is not the faintest text here. */
.wl__label{
  display:block;color:var(--on-bone-2);margin-bottom:10px;
}
.plate--beam .wl__label{color:var(--on-beam-2)}
.wl__field{display:flex;border:1.5px solid var(--coal);background:transparent}
.wl__input{
  flex:1 1 auto;min-width:0;
  background:transparent;border:0;border-radius:0;
  padding:0 16px;height:54px;
  font-size:16px;letter-spacing:-.01em;color:var(--on-bone);
}
.wl__input::placeholder{color:var(--on-bone-3);opacity:1}
.plate--beam .wl__input{color:var(--on-beam)}
.plate--beam .wl__input::placeholder{color:var(--on-beam-2)}
.wl__input:focus{outline:none}
.wl__field:focus-within{outline:3px solid var(--coal);outline-offset:2px}
.plate--coal .wl__field:focus-within{outline-color:var(--beam)}
.wl__btn{border-radius:0;flex:none;padding-left:30px;padding-right:30px;margin:-1px}
.wl__msg{
  min-height:20px;margin-top:10px;font-family:var(--mono);font-size:11px;
  letter-spacing:.1em;text-transform:uppercase;color:var(--on-bone-2);
}
.wl__msg[data-state="error"]{color:#A3231D}
.plate--beam .wl__msg{color:var(--on-beam-2)}
.plate--beam .wl__msg[data-state="error"]{color:#3D1010}
.wl__fine{
  font-size:11px;letter-spacing:.06em;text-transform:none;
  color:var(--on-bone-2);line-height:1.5;
}
.plate--beam .wl__fine{color:var(--on-beam-2)}

/* form states */
.wl[data-busy="1"] .wl__btn{opacity:.6;cursor:progress}
.wl__spin{
  width:11px;height:11px;border:2px solid currentColor;border-right-color:transparent;
  display:inline-block;margin-left:9px;animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}

.wl__done{border:1.5px solid var(--coal);padding:clamp(18px,2vw,26px)}
.wl__done h2{
  font-size:clamp(20px,2.4vw,34px);font-weight:800;letter-spacing:-.03em;line-height:1;
  margin-bottom:12px;
}
.wl__done p{font-size:15px;line-height:1.55;color:var(--on-bone-2);max-width:48ch}
.plate--beam .wl__done p{color:var(--on-beam-2)}
.wl__done .wl__demo{
  margin-top:14px;padding-top:12px;border-top:1px solid var(--rule-bone);
  font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
}
.plate--beam .wl__done .wl__demo{border-top-color:var(--rule-beam)}
/* One click back to a form, so a typo is not permanent. */
.wl__undo{
  margin-top:14px;background:transparent;border:0;border-bottom:1px solid currentColor;
  border-radius:0;padding:0 0 2px;cursor:pointer;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--on-bone-2);
}
.wl__undo:hover{color:var(--on-bone)}
.plate--beam .wl__undo{color:var(--on-beam-2)}
.plate--beam .wl__undo:hover{color:var(--on-beam)}

/* ---------- PLATE 08 · join ---------- */
.join .d1--join{margin-bottom:clamp(30px,4vw,54px);max-width:9ch}
.dot--coal{color:var(--coal)}
.join__row{
  display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr);
  gap:clamp(28px,4.5vw,80px);align-items:start;
}
.terms{
  border-top:1px solid var(--coal);
}
.terms>div{
  display:grid;grid-template-columns:minmax(120px,.5fr) minmax(0,1fr);
  gap:clamp(14px,2vw,28px);
  padding:14px 0;border-bottom:1px solid var(--rule-beam);
}
.terms>div:last-child{border-bottom:0}
.terms dt{
  font-family:var(--mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--on-beam-2);padding-top:3px;
}
.terms dd{font-size:15px;line-height:1.5;color:var(--on-beam)}
.wl--big{max-width:900px}
.wl--big .wl__field{border-width:2px}
.wl--big .wl__input{height:clamp(64px,7vw,92px);font-size:clamp(18px,2vw,28px);padding:0 clamp(14px,1.6vw,24px)}
.wl--big .wl__btn{font-size:12px;padding-left:clamp(22px,3vw,44px);padding-right:clamp(22px,3vw,44px);margin:-2px}
.wl--big .wl__msg{font-size:12px}
.wl--big .wl__fine{font-size:12px;max-width:52ch;margin-top:4px}

/* ---------- footer ---------- */
.foot{background:var(--coal);color:var(--on-coal);
      padding:0 var(--pad) clamp(30px,4vw,48px);border-top:1px solid var(--coal)}
/* Same rule as .bars__strip: rail to right edge, not a bleed. */
.foot__strip{display:grid;grid-template-columns:repeat(6,1fr);height:10px;
             margin:0 0 clamp(28px,4vw,52px)}
.foot__strip i{background:var(--seg);display:block}
.foot__in{
  display:flex;justify-content:space-between;align-items:flex-end;gap:32px;flex-wrap:wrap;
  padding-bottom:clamp(22px,3vw,36px);border-bottom:1px solid var(--rule-coal);
}
.lockup--foot{height:26px;color:var(--bone)}
.foot__line{margin-top:14px;font-family:var(--mono);font-size:11px;letter-spacing:.14em;
            text-transform:uppercase;color:var(--on-coal-3)}
.foot__meta{display:flex;gap:clamp(24px,4vw,56px);flex-wrap:wrap}
.foot__meta dt{color:var(--on-coal-3);margin-bottom:6px}
/* The same voice as everything else down here. These were 24px at weight 800
   — display type, in a footer whose every other line is 11px mono — and three
   answers set louder than the page's own headline is not emphasis, it is a
   different design arriving at the bottom of the page. They keep the label's
   face, size and tracking and are separated from it by brightness alone,
   which is the distinction the rest of the slate already uses. */
.foot__meta dd{
  font-family:var(--mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--on-coal);
}
/* The em dash that stands in for a figure we do not have. Scoped: the global
   .dash is 800 so it can hold its own beside the spec strip's 18px values, and
   it still has to. Down here it only has to be the same weight as the number
   it is waiting for. */
.foot__meta .dash{font-weight:inherit}
.foot__end{margin-top:clamp(18px,2vw,26px);font-family:var(--mono);font-size:11px;
           letter-spacing:.12em;text-transform:uppercase;color:var(--on-coal-3)}

/* ---------- reveals (default visible; JS opts in) ---------- */
.reveal{opacity:1}
html.js .reveal{opacity:0;transform:translateY(14px);
  transition:opacity .5s cubic-bezier(.2,.8,.2,1),transform .5s cubic-bezier(.2,.8,.2,1)}
html.js .reveal.in{opacity:1;transform:none}
/* anime.js is driving instead. Drop the transition or both are animating the
   same two properties, and the slower one wins the tail of every reveal. */
html.anime .reveal{transition:none}

/* ---------- the hero entrance guard ----------
   app.js and motion.js are deferred, so they run after first paint: without
   this the hero would paint, vanish, and animate back. The inline script in
   <head> sets html.cut, and THREE separate things remove it — the animator,
   the load event, and a 2s timer — because the failure mode is a blank
   headline. Reduced motion never sets it in the first place. */
html.cut .hero .ptag > *,
html.cut .hero .d1 .l,
html.cut .hero .lede,
html.cut .hero .hero__act,
html.cut .hero .slate__cell{opacity:0}
/* Paper has no scroll, so nothing ever intersects: without this, three whole
   plates print as empty fields. */
@media print{
  html.js .reveal{opacity:1!important;transform:none!important}
  html.cut *{opacity:1!important}
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width:1180px){
  .hero__row{grid-template-columns:1fr;gap:clamp(26px,4vw,40px)}
  .hero__act{justify-self:start;max-width:560px}
  .hero .d1{max-width:none}
  .slate{grid-template-columns:repeat(3,minmax(0,1fr))}
  .slate__cell:nth-child(3n){border-right:0}
  .slate__cell:nth-child(-n+3){border-bottom:1px solid var(--rule-bone)}
  .slate__cell:nth-child(n+4){padding-top:16px}
}
/* Centring the nav on the page axis instead of in the leftover space is right,
   but it costs clearance at the bottom of the nav's range: the gap from the
   last link to the TC/CTA cluster measured 62.3px at 1120, 23.6px at 1024 and
   14.3px at 1001 — below the bar's own 30.7px gap token from about 1042px
   down. The timecode is the decorative element in that cluster and it already
   leaves at 640, so it leaves earlier. Gap at 1001 goes back to 138.4px. */
/* The bar's right-hand line used to be a running timecode — decoration, so it
   left early to keep the nav off the CTA. It now says when the thing ships,
   which is the one fact a first-time visitor is looking for, and most of them
   are on a phone. So it stays down to the narrowest width the three elements
   fit at, and only then goes. */
@media (max-width:520px){
  /* Three things fit beside the logo on a laptop and two fit on a phone. The
     link is navigation and the line is a status, so the status goes. */
  .tc{display:none}
}
@media (max-width:1000px){
  .bar__nav{display:none}
  /* the plate list has to stay reachable once the nav goes. Present from the
     first paint, not gated on html.js — revealing it later reflows the bar.
     The <noscript> block in the head takes it away if JS never arrives. */
  .bar__menu{display:inline-flex}
  .lim{grid-auto-flow:row;grid-template-columns:1fr;grid-template-rows:none}
  .lim__row:nth-child(3){border-bottom:0}
  .lim__row:last-child{border-bottom:1px solid var(--rule-bone)}
  .split{grid-template-columns:1fr;gap:clamp(30px,5vw,48px)}
  .reach{grid-template-columns:1fr;gap:clamp(30px,5vw,48px)}
  .vocab__row{grid-template-columns:auto minmax(0,1fr);row-gap:10px}
  .vocab__d{grid-column:2}
  .motif__foot{grid-template-columns:1fr;gap:clamp(18px,3vw,28px)}
  .join__row{grid-template-columns:1fr;gap:clamp(26px,4vw,40px)}
}
@media (max-width:860px){
  .meas{grid-template-columns:repeat(2,minmax(0,1fr));border-left:0}
  .meas__cell:nth-child(2n){border-right:0}
  .meas__cell:nth-child(2n+1){padding-left:0}
  .meas__cell--dash{padding-left:clamp(14px,1.6vw,24px)}
  .meas__cell:nth-child(-n+2){border-bottom:1px solid var(--rule-beam)}
  .meas__cell--dash{border-right:0}
  .dest{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* The strip stays six-across at every width. It used to fold to 3+3, which
     turned a colour bar into a colour grid — and a test card that wraps is not
     reading as a test card any more. Six narrow columns is the whole point of
     the object, so the keys shrink to fit rather than the bars rewrapping. */
  .bars__strip{height:clamp(58px,13vw,104px)}
  .foot__in{align-items:flex-start;flex-direction:column}
}
@media (max-width:640px){
  body{font-size:16px}       /* .tc already left at 1080px */
  .wl__msg{min-height:34px}   /* the error wraps to two lines below 640px */
  .slate{grid-template-columns:repeat(2,minmax(0,1fr))}
  .slate__cell{border-bottom:1px solid var(--rule-bone);padding-top:14px;padding-bottom:14px}
  .slate__cell:nth-child(2n){border-right:0}
  .slate__cell:last-child{border-bottom:0}
  .ptag{flex-direction:column;align-items:flex-start;gap:6px}
  /* Stacked, the second line has to start where the FIRST line's text starts,
     not under its marker: 8px of square plus 11px of margin is 19px, so that
     is the indent. Without it line 2 sat at 20.0 against line 1's 39.5 and the
     eyebrow read as two unrelated fragments. */
  .ptag__r{text-align:left;padding-left:19px;margin-right:0}
  .wl__field{flex-direction:column;border-width:1.5px}
  .wl__input{height:52px;border-bottom:1.5px solid var(--coal)}
  .wl__btn{margin:0;width:100%;padding-top:14px;padding-bottom:14px}
  .wl--big .wl__field{border-width:1.5px}
  .wl--big .wl__input{height:60px;font-size:18px;border-bottom-width:1.5px}
  .wl--big .wl__btn{margin:0}
  .lim__row{grid-template-columns:auto minmax(0,1fr);gap:14px}
  .dest__c{min-height:112px}
  .foot__meta{gap:22px}
  .foot__meta dd{font-size:20px}
}
@media (max-width:420px){
  .dest{grid-template-columns:1fr;border-left:0}
  .dest__c{border-right:0;min-height:0;flex-direction:row;align-items:baseline;gap:12px}
  .dest__n{margin-top:0;margin-right:auto;font-size:22px}
  .dest__c--any{border-right:0}
}

/* ---------- reduced motion ---------- */
@media (prefers-reduced-motion:reduce){
  html.js .reveal{opacity:1;transform:none;transition:none}
  html.cut *{opacity:1!important}
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
                       transition-duration:.001ms!important;scroll-behavior:auto!important}
  .wl__spin{animation:none;border-right-color:currentColor}
}

/* ---------- print / forced colours ---------- */
@media (forced-colors:active){
  .btn,.wl__field,.plate{border-color:CanvasText}
}

/* Honeypot. Off-screen rather than display:none — a bot that skips hidden
   fields would sail past display:none, which defeats the point. tabindex="-1"
   keeps it out of the tab order so it is not an accessibility trap. */
.wl__hp{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}

/* ==========================================================================
   TEACHING SECTIONS
   The page's job changed: it explains the product before it argues for it, so
   these are the blocks that carry explanation. Numbered markers appear only
   where the content really is a sequence or a set — the four kinds of
   destination are a set, the laws are a pair — never as decoration.
   ========================================================================== */

/* A lead paragraph: the one that has to land before anything else is read. */
.body--lead{
  font-size:clamp(19px,1.6vw,25px);line-height:1.5;
  max-width:34ch;margin-top:clamp(22px,2.6vw,34px);
}
.plate--bone .body--lead{color:var(--on-bone)}
.plate--coal .body--lead{color:var(--on-coal)}
@media (min-width:900px){ .body--lead{max-width:46ch} }

/* ---------- the four kinds of destination ---------- */
.kinds{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  margin-top:clamp(36px,4.4vw,64px);
  border-top:1px solid var(--coal);
}
.kind{
  padding:clamp(20px,2.2vw,30px) clamp(16px,1.8vw,26px) clamp(24px,2.6vw,34px) 0;
  border-right:1px solid var(--rule-bone);
}
.kind:last-child{border-right:0}
.kind__i{
  display:block;font-family:var(--mono);font-size:10px;letter-spacing:.15em;
  color:var(--beam-ink,#A94E09);margin-bottom:14px;font-weight:600;
}
.kind__t{font-size:clamp(17px,1.4vw,21px);font-weight:800;letter-spacing:-.02em;
         line-height:1.15;margin-bottom:10px}
.kind__d{font-size:clamp(14px,1.05vw,15.5px);line-height:1.6;color:var(--on-bone-2)}

/* ---------- the two laws ---------- */
.laws{margin-top:clamp(26px,3vw,40px);display:grid;gap:clamp(20px,2.2vw,28px)}
.law{border-left:2px solid var(--beam);padding-left:clamp(14px,1.6vw,20px)}
.law dt{font-size:clamp(15px,1.2vw,18px);font-weight:800;letter-spacing:-.015em;
        line-height:1.2;margin-bottom:8px}
.law dd{margin:0;font-size:clamp(14px,1.05vw,15.5px);line-height:1.6;
        color:var(--on-coal-2)}
.plate--bone .law dd{color:var(--on-bone-2)}
.law strong{font-weight:700}
.law em{font-style:italic}

/* ---------- a studio canvas in a section ---------- */
.stu-host{margin-top:clamp(20px,2.4vw,32px)}

/* ---------- supporting points under a graph ---------- */
.studio-more{
  margin-top:clamp(34px,4vw,56px);
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0;border-top:1px solid var(--rule-coal);
}
.plate--bone .studio-more{border-top-color:var(--rule-bone)}
.studio-more li{
  padding:clamp(18px,2vw,26px) clamp(20px,2.4vw,34px) clamp(18px,2vw,26px) 0;
  font-size:clamp(14px,1.05vw,16px);line-height:1.6;
  color:var(--on-coal-2);border-bottom:1px solid var(--rule-coal);
}
.plate--bone .studio-more li{color:var(--on-bone-2);border-bottom-color:var(--rule-bone)}
.studio-more li strong{color:var(--on-coal);font-weight:700}
.plate--bone .studio-more li strong{color:var(--on-bone)}

/* ---------- a 2x2 of short explanations ---------- */
.two{
  margin-top:clamp(34px,4vw,56px);
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  border-top:1px solid var(--rule-bone);
}
.plate--coal .two{border-top-color:var(--rule-coal)}
.two__c{
  padding:clamp(20px,2.2vw,30px) clamp(20px,2.6vw,40px) clamp(22px,2.4vw,32px) 0;
  border-bottom:1px solid var(--rule-bone);
}
.plate--coal .two__c{border-bottom-color:var(--rule-coal)}
.two__c:nth-child(2n){border-right:0}
.two__t{font-size:clamp(15px,1.25vw,18px);font-weight:800;letter-spacing:-.015em;
        line-height:1.2;margin-bottom:9px}
.two__d{font-size:clamp(14px,1.05vw,15.5px);line-height:1.6;color:var(--on-bone-2)}
.plate--coal .two__d{color:var(--on-coal-2)}

/* ---------- the comparison, stated without naming anyone ---------- */
.vs{
  margin-top:clamp(34px,4vw,58px);
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(30px,4vw,72px);
  border-top:1px solid var(--coal);padding-top:clamp(24px,2.8vw,38px);
}
.vs__k{
  font-family:var(--mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--beam-ink,#A94E09);font-weight:600;margin-bottom:16px;
}
.vs__d{font-size:clamp(15px,1.15vw,17px);line-height:1.62;color:var(--on-bone-2);
       max-width:44ch}
.vs__d + .vs__d{margin-top:14px}
.vs__d em{font-style:italic;color:var(--on-bone)}
.vs__foot{
  margin-top:clamp(28px,3.2vw,44px);border-top:1px solid var(--rule-bone);
  padding-top:clamp(18px,2vw,26px);
  font-size:clamp(15px,1.2vw,18px);line-height:1.55;font-weight:600;
  max-width:60ch;
}

/* ---------- responsive ---------- */
@media (max-width:1000px){
  .kinds{grid-template-columns:repeat(2,minmax(0,1fr))}
  .kind:nth-child(2n){border-right:0}
  .kind:nth-child(-n+2){border-bottom:1px solid var(--rule-bone)}
  .studio-more,.two{grid-template-columns:minmax(0,1fr)}
  .vs{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:640px){
  .kinds{grid-template-columns:minmax(0,1fr)}
  .kind{border-right:0;border-bottom:1px solid var(--rule-bone)}
  .kind:last-child{border-bottom:0}
}


/* A graph plate splits differently from a prose plate. The canvas is a fixed
   768px and scales down to fit, so the column has to be wide enough that the
   8px port labels survive: at .72/1.28 the graph column is ~790px at 1440 and
   renders at 1:1. Text takes the narrower side, which suits the short display
   lines it carries anyway. */
.split--graph{grid-template-columns:minmax(0,.72fr) minmax(0,1.28fr)}
@media (max-width:1000px){ .split--graph{grid-template-columns:minmax(0,1fr)} }

/* THE LINE BETWEEN THE HEADLINE AND THE BODY.

   A feature section has three jobs and they do not fit in two voices. The
   headline names the reader's situation, the body explains the mechanism, and
   without something between them the headline has to do both — which is how a
   headline ends up describing a feature instead of a person's Tuesday. This is
   that middle voice: one sentence, larger than body copy and set tighter,
   saying plainly what the thing does so the headline above it is free to say
   why anyone should care. One sentence is the whole budget. */
/* THE ONE PHRASE IN A PARAGRAPH THAT IS THE POINT.

   Display weight and display tracking at body size, in the accent — the same
   mark the headline resolves into, borrowed for one clause. Not italic and not
   merely bold: those are emphasis inside a voice, and this is a change of
   voice. One per section, or it stops meaning anything.

   The colour flips with the ground, not with taste: 4.7:1 on bone, 6.4:1 on
   coal. */
.hi{
  font-weight:800;
  letter-spacing:-.02em;
  color:var(--beam);
}
/* Inside display type it carries the COLOUR only. The weight and the tracking
   are the headline's own and were never this class's to change — borrowing
   body-copy settings into a 76px line thinned it and opened it up mid-word. */
.d1 .hi,.d2 .hi{font-weight:inherit;letter-spacing:inherit}
/* motion.js splits an authored headline on its <br> so the lines can arrive
   one at a time. Block, because that is exactly what the <br> was doing. */
.mline{display:block}

.subhead{
  margin-top:clamp(18px,2vw,26px);
  font-size:clamp(17px,1.5vw,23px);
  line-height:1.35;
  letter-spacing:-.02em;
  font-weight:600;
  max-width:34ch;
}

/* Compact supporting points, for the text column of a graph plate. The 2x2
   grid these replace pushed a section well past one screen. */
.pts{margin-top:clamp(20px,2.2vw,30px);display:grid;gap:14px}
.pts__i{border-top:1px solid var(--rule-coal);padding-top:12px}
.plate--bone .pts__i{border-top-color:var(--rule-bone)}
.pts__t{font-size:clamp(14px,1.05vw,15.5px);font-weight:800;letter-spacing:-.01em;
        margin-bottom:5px}
.pts__d{font-size:clamp(13px,.95vw,14.5px);line-height:1.55;color:var(--on-coal-2)}
.plate--bone .pts__d{color:var(--on-bone-2)}

/* ==========================================================================
   PLATFORMS
   Windows ships. macOS and Linux compile but nobody has run a show on either,
   so they are drawn as coming — the limits plate says exactly that in words and
   the two must never disagree. State is carried by opacity AND a word, never by
   opacity alone.
   ========================================================================== */
/* Three marks, one colour, one size, evenly spaced — a row of platforms, not
   a ranked list. The names are gone with the ranking: a Windows flag, an apple
   and a penguin need no captions, and the row reads faster without three
   words competing with three pictures. The screen-reader line beside them
   carries all three names, so nothing is lost by not drawing them. */
.oslist{display:flex;align-items:center;gap:clamp(16px,1.8vw,24px);flex-wrap:wrap}
.os{display:inline-flex;align-items:center;color:var(--on-bone)}
.oslogo{width:20px;height:20px;flex:none;fill:currentColor}

/* ---------- the picker ---------- */
.osp{border:0;padding:0;margin:0 0 14px}
.osp__l{
  font-family:var(--mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--on-bone-3);padding:0;margin-bottom:9px;font-weight:600;
}
.plate--beam .osp__l{color:var(--on-beam-2)}
.osp__set{display:flex;gap:0;border:1px solid var(--coal)}
.osp__o{
  flex:1 1 0;min-width:0;position:relative;
  display:flex;align-items:center;justify-content:center;
  border-right:1px solid var(--coal);cursor:pointer;
}
.osp__o:last-child{border-right:0}
.osp__o span{
  display:block;width:100%;text-align:center;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
  font-weight:600;color:var(--on-bone-2);padding:11px 6px;
  transition:background .12s linear,color .12s linear;
}
/* The input stays in the layout and stays focusable — it is only visually
   covered by its own label, so keyboard and screen-reader use are unaffected. */
.osp__o input{position:absolute;opacity:0;width:100%;height:100%;margin:0;cursor:pointer}
.osp__o input:checked + span{background:var(--coal);color:var(--bone)}
.osp__o input:focus-visible + span{outline:3px solid var(--beam);outline-offset:-3px}
.osp__o:hover input:not(:checked) + span{background:rgba(20,17,16,.06)}

/* On the orange CTA plate the same control inverts to coal-on-orange. */
.plate--beam .osp__set{border-color:var(--coal)}
.plate--beam .osp__o{border-right-color:var(--coal)}
.plate--beam .osp__o span{color:var(--on-beam-2)}
.plate--beam .osp__o input:checked + span{background:var(--coal);color:var(--bone)}
.plate--beam .osp__o:hover input:not(:checked) + span{background:rgba(20,17,16,.09)}

/* ---------- the alpha explanation ---------- */
.wl__alpha{
  margin-top:10px;font-size:clamp(13px,.98vw,14.5px);line-height:1.55;
  color:var(--on-bone-2);max-width:52ch;
}
.plate--beam .wl__alpha{color:var(--on-beam-2)}

@media (max-width:480px){
  /* Three mono labels stop fitting one row well below this; stacking keeps each
     tap target full width rather than shrinking the type further. */
  .osp__set{flex-direction:column}
  .osp__o{border-right:0;border-bottom:1px solid var(--coal)}
  .osp__o:last-child{border-bottom:0}
}

/* A graph plate carries a fixed-height canvas, so it cannot shrink the way a
   prose plate can. Trimming its own padding is what brings it back to roughly
   one screen — the stated goal being that a reader sees a whole section at once
   rather than two thirds of one. */
.plate.has-graph{
  padding-top:clamp(40px,4.4vw,72px);
  padding-bottom:clamp(44px,4.8vw,80px);
}
.plate.has-graph .d2{font-size:clamp(30px,4.2vw,58px)}
.plate.has-graph .laws{margin-top:clamp(18px,2vw,26px);gap:clamp(14px,1.6vw,20px)}
.plate.has-graph .pts{margin-top:clamp(16px,1.8vw,24px);gap:11px}
.plate.has-graph .stu__reset{margin-top:10px}
.plate.has-graph .stu__hint{margin-top:8px}


/* A grid or flex child's automatic minimum size is its CONTENT, not zero, so any
   fixed-width descendant can push a track wider than the viewport. That is
   exactly what happened here: the studio canvas is a fixed 768px, and the
   mobile single-column track inherited it as a floor. Both columns are pinned
   to min-width:0 so content can never dictate the track again. */
.split__a,.split__b{min-width:0}

/* ==========================================================================
   MOBILE FORMAT
   Measured at 320/360/375/390/414/430/480/600/768 rather than guessed at.
   ========================================================================== */

/* The header CTA wrapped to two lines at 320 and 390 — "JOIN THE WAITLIST" is
   17 characters of tracked mono, which simply does not fit beside a logo and a
   menu button on a phone. Two labels, one word swapped for the sentence. The
   short one is aria-hidden and the long one stays in the accessibility tree, so
   the accessible name never becomes the abbreviation. */
.bar__cta-short{display:none}
.bar__cta{white-space:nowrap}
@media (max-width:520px){
  .bar__cta-long{display:none}
  .bar__cta-short{display:inline}
}

/* Tap targets. Measured under 40px: the logo link at 27px tall, the menu button
   at 35px, and each picker option at 38-39px. 44px is the smallest thing a
   thumb reliably hits, and the 56px bar has room for it. */
@media (max-width:1000px){
  .bar__logo{min-height:44px}
  .bar__menu{min-height:44px;padding:10px 14px}
  .bar__cta{min-height:44px}
  .osp__o span{padding:14px 8px}
  .navmenu a{padding:18px 0}
}

/* Captions that are actually sentences. The 10-11px mono is the site's label
   voice and stays that on desktop, but "Four signal types and one accent…" and
   the studio hint are full sentences, and at 10px on a phone they are a texture
   rather than a line of text. Raised only below 640px, and only for these two —
   the true labels keep their size. */
@media (max-width:640px){
  .bars__note{font-size:12px;line-height:1.65}
  /* .stu__hint is raised in studio.css — that file loads after this one, so an
     override here would lose the cascade on equal specificity. */
}


/* The headline's longest WORD sets the floor on the narrowest screens, not the
   longest line. "subscription" is 12 characters; at the 56px floor it needs
   about 316px and a 320px phone offers 280, so it overflowed the viewport while
   every wider screen was fine.

   Only screens that actually cannot fit it are reduced. 375 and 390 keep 56px,
   which is the floor the display/body ratio was set at — dropping it globally
   would have taken that ratio to 2.8x everywhere to solve a problem that exists
   at one width. */
@media (max-width:349px){
  .hero .d1{font-size:46px}
}
