/* Trivit site — pass 3.
 *
 * The redesign's own stylesheet, beside `styles.css` rather than replacing it. The deployed
 * site is built from `styles.css` and the redesign from this file, so a half-finished pass
 * cannot reach the live site and both can be looked at side by side. The packet scopes the
 * work to build.js and styles.css; this is the one deviation, and it is what lets the flag
 * be real rather than a promise.
 *
 * Values come from `tokens.css`, which is Design's file verbatim. Nothing here re-picks a
 * colour or a size: if a number is not in the tokens it is a layout figure from the packet,
 * and it says which section it came from.
 */

/* ------------------------------------------------------------- dark on open
 *
 * Martin's ruling, and it overrides one line of tokens.css rather than editing it: that
 * file follows `prefers-color-scheme`, so on a light machine the site opened bone. The
 * room is dark on arrival whatever the operating system says, and light only when somebody
 * chooses it.
 *
 * Done here rather than in tokens.css so Design's file stays byte for byte theirs and the
 * deviation is visible. Same specificity as the rule it displaces, later in source order,
 * which is what makes it win -- and it stops matching the moment `data-room="light"` is
 * set, so the switch still works in both directions.
 */
@media (prefers-color-scheme: light) {
  :root:not([data-room="light"]) {
    --g: #191614;
    --g2: #211D1A;
    --ink: #F2EEE7;
    --dim: #A9A199;
    --hair: #39342F;
    --chev: #8B837A;
    --teal: #2F9686;
    --teal-edge: #227064;
    --onteal: #12100E;
  }
}

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

html,
body { margin: 0; padding: 0; }

body {
  background: var(--g);
  color: var(--ink);
  font-family: var(--ui);
  font-size: var(--t-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img,
svg { display: block; max-width: 100%; }

a { color: inherit; }

/* ------------------------------------------------------------------ the strip
 * Section 3. h40, the g2 ground, the day on the left and the count on the right,
 * with the room switch at the end. Every page carries it; /play carries the count
 * without the date, because the board keeps its own header.
 */
.strip {
  height: var(--strip-h);
  background: var(--g2);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 0 var(--pad);
  font-size: var(--t-caps);
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
}

.strip-l,
.strip-r { display: flex; align-items: center; gap: 10px; min-width: 0; }
.strip-r { margin-left: auto; }
.strip .dim { color: var(--dim); }
.strip .said { color: var(--ink); }

/* The switch: the two grounds themselves, 16px, the current one ringed. No sun, no moon. */
.rooms { display: flex; gap: 8px; margin-left: 18px; }
.rooms button {
  width: 16px;
  height: 16px;
  border-radius: 5px;
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: transform var(--state) var(--ease);
}
.rooms button:hover { transform: translateY(-1px); }
.rooms .r-light { background: #F0ECE4; }
.rooms .r-dark { background: #191614; }
.rooms button[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--ink); }

/* ------------------------------------------------------------------ the frame */
.wrap {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--pad);
}

.site-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 30px 0;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

.wm {
  font-size: var(--t-wordmark);
  font-weight: 900;
  letter-spacing: -.04em;
}

.headlinks { display: flex; gap: 32px; }
.headlinks a {
  font-size: var(--t-small);
  font-weight: 700;
  color: var(--dim);
  text-decoration: none;
}
.headlinks a[aria-current="page"] { color: var(--ink); }

/* No margin above it. The packet's own arithmetic for one screen at 1440x900 is
   strip 40 + header 92 + hero 640 + footer 116, and a margin here is what pushed the
   front page 69px past the fold. */
footer {
  border-top: 1px solid var(--hair);
  padding: 28px 0 44px;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.foot-links { display: flex; gap: 28px; }
.foot-links a {
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--dim);
  text-decoration: none;
}
.foot-links a[aria-current="page"] { color: var(--ink); }
.maker { font-size: var(--t-small); font-weight: 700; letter-spacing: .02em; }

/* Instagram and TikTok, in the gap after Feedback. They inherit the links' dim colour. */
.foot-social { display: inline-flex; gap: 14px; align-self: center; }
.foot-social a { display: block; line-height: 0; }
.foot-social svg { display: block; }

/* ------------------------------------------------------------------ controls */
.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--pill-h);
  padding: 0 var(--pill-pad);
  border-radius: var(--pill-r);
  background: var(--teal);
  color: var(--onteal);
  border: 0;
  border-bottom: 1px solid var(--teal-edge);
  font: inherit;
  font-size: var(--t-body);
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--state) var(--ease), filter var(--state) var(--ease);
}
.pill:hover { transform: translateY(-1px); filter: brightness(.94); }
.pill:active { transform: scale(.97); transition-duration: var(--press); }

/* The quiet way out. Not a weaker button: no pill, no fill, an underline of hair. */
.quiet {
  font-size: var(--t-body);
  font-weight: 700;
  text-decoration: none;
  border-bottom: 1px solid var(--hair);
  padding-bottom: 2px;
}

/* The recruiting ask, which sits inside a dim sentence and must not be teal. */
.ask {
  font-weight: 700;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--chev);
}

.soon {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--dim);
}
.soon .dot {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--teal);
}

/* ------------------------------------------------------------------ the cards
 * Geometry is the app's and is not re-picked here: the faces are always white and
 * the hues never move, in either room. Only the ground around them changes.
 */
.card {
  background: var(--card);
  border: 1px solid var(--cardline);
  border-radius: var(--card-r);
  display: grid;
  place-items: center;
}

/* ------------------------------------------------------------------ front page
 * Section 4. The statement at 88, the cards fanned to the right.
 *
 * The column is 620, not the packet's 600. Measured: "or all different." sets to 613px
 * at 88/900/-.045em, so 600 breaks it onto a third line and the packet's own "two lines"
 * fails. The type size was the ruled decision and the column width was not, so the column
 * gives. Twenty pixels come off the fan's side, which has a whole fr to spare.
 */
.landing {
  display: grid;
  grid-template-columns: 620px 1fr;
  gap: 56px;
  align-items: center;
  min-height: 640px;
  padding: 40px 0 80px;
}

.serifline {
  font-family: var(--ed);
  font-style: italic;
  font-size: var(--t-serif);
  color: var(--dim);
  margin: 0 0 18px;
}

.statement {
  font-size: var(--t-statement);
  line-height: .96;
  letter-spacing: -.045em;
  font-weight: 900;
  margin: 0 0 26px;
}

.lsub {
  font-size: var(--t-lede);
  line-height: 1.6;
  color: var(--dim);
  max-width: 34ch;
  margin: 0 0 36px;
}

.actions { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }

.recruit {
  margin: 40px 0 0;
  font-size: var(--t-body);
  font-weight: 600;
  color: var(--dim);
  max-width: 44ch;
}
.recruit .askline { display: block; margin-top: 10px; }

/* The fan. Absolute so the three overlap; the middle one forward.
 *
 * The cards are the app's own `triadCard`, which is an SVG locked to 100:140 -- so a
 * 260-wide card is 364 tall, not the 312 in the packet. That 312 is the retired 115x138
 * proportion; 100:140 was blessed when the app's own aspect lock went in, and the site
 * must not carry a card shape the game no longer draws.
 */
/* Every number here is --hero-w times a ratio, so a breakpoint resizes the fan by
   changing one token. Each card starts .577 of a card after the last (so they overlap by
   .423), the outer two twice that apart; the
   height is a card plus the 48 it is dropped by, twice. */
.fan {
  position: relative;
  height: calc(var(--hero-w) * 1.4 + 96px);
  min-width: calc(var(--hero-w) * 2.154);
}
.fan .tc {
  position: absolute;
  width: var(--hero-w);
  height: auto;
  filter: drop-shadow(0 1px 0 var(--cardline));
  transition: opacity var(--intro) var(--ease), transform var(--intro) var(--ease);
}
/* The three arrive left to right, --intro-gap apart. f1 needs no delay, which
   is why it does not carry one -- 0 is the default and writing it would invite
   somebody to keep the three in step by editing all three.
 *
 * The gap does more for how slow this reads than the duration does. At 800ms
 * card three does not begin until card one is 90% arrived, so it reads as three
 * arrivals rather than one spread. tokens.css carries the measurements.
 *
 * Reduce Motion needs no exception here: the `transition: none` below is the
 * shorthand, which resets transition-delay with everything else, and
 * --intro-gap is zeroed at the token besides. */
.fan .f1 { left: 0; top: 48px; transform: rotate(calc(var(--hero-tilt) * -1)); }
.fan .f2 { left: calc(var(--hero-w) * .577); top: 8px; z-index: 2;
           transition-delay: var(--intro-gap); }
.fan .f3 { left: calc(var(--hero-w) * 1.154); top: 48px; transform: rotate(var(--hero-tilt));
           transition-delay: calc(var(--intro-gap) * 2); }

/* The intro: the cards rise and fade in, once. `data-intro` is set before paint and
   cleared a frame later, so there is no state to leave behind. */
html[data-intro="run"] .fan .f1 { opacity: 0; transform: translateY(12px) rotate(calc(var(--hero-tilt) * -1)); }
html[data-intro="run"] .fan .f2 { opacity: 0; transform: translateY(12px); }
html[data-intro="run"] .fan .f3 { opacity: 0; transform: translateY(12px) rotate(var(--hero-tilt)); }

/* The mark opens into the cards.
 *
 * The fan is not three arbitrary cards: solid teal round, hollow red angular, hatched
 * indigo notched are the trivet's own three shapes in the trivet's own three hues. So
 * the icon resting where the cards will be, then spreading as they arrive, says the
 * thing the icon means -- it is a trio -- rather than decorating the load.
 *
 * At rest (no data-intro, which is also the no-script and reduced-motion state) the
 * mark is already gone and the cards are already there, so nothing depends on the
 * script running.
 */
.introshape {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--hero-w) * .68);
  height: calc(var(--hero-w) * .68);
  transform: translate(-50%, -50%) scale(2.4);
  opacity: 0;
  z-index: 3;
  pointer-events: none;
  transition: transform var(--intro) var(--ease), opacity var(--intro) var(--ease);
}
.introshape svg { display: block; width: 100%; height: 100%; }
html[data-intro="run"] .introshape { transform: translate(-50%, -50%) scale(1); opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .fan .tc,
  .introshape { transition: none; }
}

/* ------------------------------------------------- the shared two-column page
 * Support and Privacy are the same shape: a heading column on the left, the
 * thing itself on the right. Section 8 and 9.
 */
.twocol {
  display: grid;
  grid-template-columns: 600px 1fr;
  gap: 56px;
  align-items: center;
  padding: 48px 0 72px;
}

.pagehead {
  font-size: var(--t-page);
  line-height: .98;
  letter-spacing: -.045em;
  font-weight: 900;
  margin: 0 0 24px;
}

.lede {
  font-size: var(--t-lede);
  line-height: 1.65;
  color: var(--dim);
  max-width: 40ch;
  margin: 0 0 32px;
}
.lede-sm { font-size: var(--t-body); font-weight: 600; color: var(--dim); }

/* ------------------------------------------------------------------ support
 * Section 8. The amounts are cards in the card's own 115/138 proportion, the
 * amount over its pips. The first three pips are a real trio.
 */
.tipgrid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  width: min(520px, 100%);
}

.tipcard {
  aspect-ratio: 115 / 138;
  background: var(--card);
  border: 1px solid var(--cardline);
  border-radius: var(--tip-r);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  font: inherit;
  color: #1C1917;            /* the card face is white in both rooms, so its ink is too */
  cursor: pointer;
  transition: transform var(--press) var(--ease), box-shadow var(--state) var(--ease);
}
.tipcard:hover { transform: translateY(-2px); }
.tipcard:active { transform: scale(.97); }
/* Chosen: the board's own selection language, a 2px ink inset rather than a new colour. */
.tipcard[aria-checked="true"] { box-shadow: inset 0 0 0 2px #1C1917; }

.tipamt {
  font-size: var(--t-panel);
  font-weight: 900;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.tippips { display: block; }

.plate {
  margin: 20px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--hair);
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--dim);
  max-width: 520px;
}
.platelabel {
  display: inline-block;
  margin-right: 10px;
  font-size: var(--t-caps);
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
}

/* Privacy sits its rows against the top, not the middle: six of them are taller than
   two lines of heading and centring would strand the heading in space. */
.twocol-top { align-items: start; }

/* ------------------------------------------------------------------- one column
 * Feedback and Sent. The form is the page, so nothing sits beside it.
 */
.onecol { max-width: 620px; padding: 48px 0 72px; }
.pagehead-sm { font-size: var(--t-head); line-height: 1; letter-spacing: -.04em; }

/* The page a Trivit link lands on without the app: one button, one line under it. */
.linkgo { margin-top: 26px; }
.linkagain { margin-top: 22px; }

/* ------------------------------------------------------------------ the form
 * Section 9. Fields are card faces: white in both rooms, like every other card on
 * the site, so a form is made of the same material as the game.
 */
.fb { display: grid; gap: 20px; margin-top: 8px; }
.fl { display: grid; gap: 8px; }
.fl > span {
  font-size: var(--t-caps);
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--dim);
}
.fl > span em { font-style: normal; text-transform: none; letter-spacing: .02em; opacity: .8; }

.fb input,
.fb textarea {
  width: 100%;
  background: var(--card);
  color: #1C1917;
  border: 1px solid var(--cardline);
  border-radius: var(--field-r);
  padding: 0 16px;
  font: inherit;
  font-size: var(--t-body);
}
.fb input { height: var(--field-h); }
.fb textarea { padding: 14px 16px; min-height: 132px; line-height: 1.5; resize: vertical; }
.fb .pill { justify-self: start; }

.fr { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }

/* The honeypot. Off screen rather than display:none, which some fillers skip. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* The two states. Neither is painted until the pre-body script has decided which. */
.v-test { display: none; }
html[data-about="testing"] .v-fb { display: none; }
html[data-about="testing"] .v-test { display: inline; }

/* ------------------------------------------------------------------ privacy
 * Section 9. Six labelled rows, 160/1fr, hairlines between and none at the ends.
 */
.prows { display: grid; }
.prow {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 32px;
  padding: 28px 0;
  border-top: 1px solid var(--hair);
}
.prow:first-child { border-top: 0; padding-top: 0; }
.plabel {
  font-size: var(--t-caps);
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--dim);
  padding-top: 4px;
}
.ptext { font-size: var(--t-lede); line-height: 1.65; color: var(--dim); }
.ptext a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--chev); }

/* -------------------------------------------------------------- how to play
 * Section 5. A dark head carrying the statement, then a bone body, because that
 * part is for reading. Two things follow from the split:
 *
 * The head sits on the page room rather than being pinned dark, so the light room
 * gets one continuous bone page instead of a black band it never asked for. Only
 * the body is fixed, by .room-bone in tokens.css.
 *
 * The body redeclares the tokens rather than the colors, so everything inside it
 * -- rail, cards, chips, ramp -- is written once against --ink and --dim and comes
 * out right in either room with no second set of rules.
 */
.howhead { padding: 30px 0 88px; }
.howbody {
  background: var(--g);
  color: var(--ink);
  padding: 72px 0 0;
}

/* The rail is a sidebar on wide screens and is pinned, so the reader always knows
   which of the five they are in. 208 is the widest name plus its chip. */
.howgrid {
  display: grid;
  grid-template-columns: 208px 1fr;
  gap: 72px;
  align-items: start;
}
.howcol { min-width: 0; max-width: 720px; }

.rail {
  position: sticky;
  top: 40px;
  display: grid;
  gap: 4px;
}

/* The board's own progress language rather than a list of links: ahead is the dashed
   empty chip, passed is filled, and the current one takes the ink face -- the same
   three states a trio chip has. Only the name changes weight, never its size, so
   nothing in the rail moves as you scroll. */
.railchip {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 0;
  text-decoration: none;
  color: var(--dim);
  transition: color var(--state) var(--ease);
}
.rc {
  width: var(--chip);
  height: var(--chip);
  flex: none;
  border-radius: var(--chip-r);
  border: 1px dashed var(--chev);
  display: grid;
  place-items: center;
  transition: background var(--state) var(--ease), border-color var(--state) var(--ease);
}
.rcn {
  font-size: var(--t-small);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: transparent;
}
.rcname { font-size: var(--t-body); font-weight: 600; }

.railchip.passed .rc,
.railchip.current .rc { border-style: solid; }
.railchip.passed .rc { background: var(--hair); border-color: var(--hair); }
.railchip.passed .rcn { color: var(--dim); }
.railchip.current { color: var(--ink); }
.railchip.current .rc { background: var(--ink); border-color: var(--ink); }
.railchip.current .rcn { color: var(--g); }
.railchip:hover { color: var(--ink); }

/* The last section keeps its 88 like the rest. The footer takes no margin of its own
   -- that is deliberate and the front page depends on it -- so whatever sits above the
   rule has to carry the gap, and here that is the section. */
.hsec { padding: 0 0 88px; scroll-margin-top: 40px; }
.hsect {
  font-size: var(--t-section);
  font-weight: 700;
  letter-spacing: -.025em;
  margin: 0 0 28px;
}
.hlede {
  font-size: var(--t-lede);
  line-height: 1.65;
  color: var(--dim);
  max-width: 56ch;
  margin: 0 0 32px;
}

/* The check. Three steps, and the numeral is the display face at 52 rather than a
   bullet -- it is the only place on the page that counts anything, so it is allowed
   to be large. Hanging in its own column keeps the sentences on one left edge. */
.checks { display: grid; gap: 28px; }
.chk {
  display: grid;
  grid-template-columns: 68px 1fr;
  gap: 20px;
  align-items: baseline;
}
.chkn {
  font-size: var(--t-numeral);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -.045em;
  font-variant-numeric: tabular-nums;
  color: var(--chev);
}
.chk p {
  font-size: var(--t-lede);
  line-height: 1.55;
  margin: 0;
  max-width: 46ch;
}

/* The four traits. Values on the row, the label hanging off it. */
.glossary { border-top: 1px solid var(--hair); }
.gloss {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 24px;
  align-items: center;
  padding: 22px 0;
  border-bottom: 1px solid var(--hair);
}
.gl {
  font-size: var(--t-caps);
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--dim);
}
.gi { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.gi > div { display: grid; justify-items: center; gap: 12px; }
.gs { height: 76px; display: grid; place-items: center; }
.gloss span { font-size: var(--t-small); color: var(--dim); }

/* Try it. Six real cards, and the verdict beneath is a fixed two lines so the board
   does not jump every time a pick changes what it says. */
.tryboard {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--card-gap);
  max-width: calc(var(--card-w) * 3 + var(--card-gap) * 2);
  margin: 0 0 24px;
}
.trycard {
  padding: 0;
  border: 0;
  background: none;
  line-height: 0;
  border-radius: var(--card-r);
  cursor: pointer;
  transition: transform var(--press) var(--ease), box-shadow var(--state) var(--ease);
}
.trycard .tc { border-radius: var(--card-r); display: block; width: 100%; height: auto; }
.trycard:active { transform: scale(.97); }
.trycard.on { box-shadow: 0 0 0 3px var(--ink); }
.trycard:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.verdict {
  display: grid;
  gap: 4px;
  min-height: 52px;
  margin: 0;
  align-content: start;
}
.vhead { font-size: var(--t-lede); font-weight: 700; }
.vline { font-size: var(--t-body); color: var(--dim); }

/* On the board. The chips are the app's, at the app's size; two are real and the
   rest are the dashed empties a part-solved board shows. */
.obchips { display: flex; gap: 5px; margin: 0 0 16px; }
.obchip,
.obchips .chip {
  width: var(--chip);
  height: var(--chip);
  border-radius: var(--chip-r);
  display: inline-grid;
  place-items: center;
  font-family: var(--ui);
  font-size: var(--t-small);
  font-weight: 700;
}
.obchip {
  padding: 0;
  border: 1px solid var(--hair);
  background: transparent;
  color: var(--dim);
  cursor: pointer;
  transition: background var(--state) var(--ease), color var(--state) var(--ease),
              border-color var(--state) var(--ease), transform var(--press) var(--ease);
}
.obchip:active { transform: scale(.92); }
.obchip.on { background: var(--ink); border-color: var(--ink); color: var(--g); }
.obchip:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.obchips .chip.empty { border: 1px dashed var(--chev); }

.obboard {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--card-gap);
  max-width: calc(var(--card-w) * 3 + var(--card-gap) * 2);
  margin: 0 0 16px;
}
/* The corner letter is the app's tag: it stays on the card once the trio is found,
   which is the whole point of the section. */
.obcard { position: relative; line-height: 0; transition: opacity var(--review) var(--ease); }
.obcard.quiet { opacity: var(--dim-review); }
.obcard .tc { border-radius: var(--card-r); display: block; width: 100%; height: auto; }
.obcard .tag {
  position: absolute;
  top: 7px;
  right: 7px;
  width: var(--tag);
  height: var(--tag);
  border-radius: var(--tag-r);
  background: var(--tag-face);
  color: var(--tag-ink);
  font-size: 10px;
  font-weight: 700;
  line-height: var(--tag);
  text-align: center;
}
.obcap { font-size: var(--t-body); font-weight: 600; color: var(--dim); margin: 0; }

/* The week. Seven figures on one baseline; Sunday is the heaviest because it is
   the hardest, which is the only thing the row has to say. */
.ramp {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  max-width: 420px;
  gap: 8px;
}
.ramp div { display: grid; justify-items: center; gap: 6px; }
.ramp b {
  font-size: 28px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.ramp b.su { font-weight: 900; }
.ramp span {
  font-size: var(--t-caps);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}

@media (prefers-reduced-motion: reduce) {
  .railchip, .rc, .trycard, .obchip, .obcard { transition: none; }
}

/* ------------------------------------------------------------------- /play
 * Section 6. The board in the middle at its designed width, the disclaimer and
 * the store action either side so neither competes with playing.
 *
 * #root's height is the board's own natural height, measured rather than guessed:
 * 874 at a 393 column, light, nothing found, fonts loaded. The board's chrome is
 * flex all the way down and will fill whatever box it is given, so an unset height
 * gives a board of nothing. See the note in build.js.
 */
/* 320 / 393 / 320, centred as a group. The sides were 1fr, which is why the page read
   as three unrelated things on a wide monitor: at 1440 each side computed to 363.5, so
   the copy sat at x=89 and the CTA at x=973, 884px apart with the board marooned between
   them. Fixed sides put the slack OUTSIDE the group, where it is margin, instead of
   between the copy and the CTA, where it is a void. */
.playgrid {
  display: grid;
  grid-template-columns: 320px var(--col-play) 320px;
  gap: 64px;
  justify-content: center;
  align-items: start;
  padding: 40px 0 72px;
}

#root {
  width: min(var(--col-play), 100%);
  height: var(--board-h, 874px);
  display: flex;
  flex-direction: column;
}
#root > * { flex: 1 1 auto; min-height: 0; min-width: 0; }

.playside { padding-top: 8px; }
.playside .lede { margin: 0; max-width: 30ch; }
/* The group is as wide as the pill and no wider, so the line under it centres on the
   pill rather than on a column three times its width. */
.playside-r {
  display: grid;
  justify-items: center;
  gap: 10px;
  text-align: center;
}
/* The grid gap is the whole distance. Without this the paragraph also keeps the
   browser's default 1em top margin, so the line sat ~29px under the pill when the
   layout asked for 14 -- and it read as two unrelated things rather than a button
   with its own small print. */
.playside-r .lede-sm { margin: 0; }

/* The store line. A quiet line rather than a second pill: the page keeps one filled
   button, and this is news rather than an action -- neither store has it yet. */
.storeline { margin: 28px 0 0; }

/* How's head has its own size, --t-page-2 at 64. Left on .pagehead's 72 the second
   sentence takes three lines and the <br> in the markup stops meaning anything. */
.howhead .pagehead { font-size: var(--t-page-2); line-height: 1; margin: 0; }

/* ================================================================ breakpoints
 * Four bands. 1440 is the design width -- the 1344 wrap plus its two 48s -- so
 * everything above it is untouched and the three below it give ground in order:
 * the columns narrow, then they stop being columns, then the type comes down.
 *
 * The bands change tokens wherever a token can carry the change, because the type
 * scale and the geometry are shared by six pages and a rule per page is six places
 * to forget one. Only the grids themselves are restated.
 */

/* --------------------------------------------------- 1120 to 1439: still columns
 * The wrap is already fluid; what does not fit is the pair of fixed columns beside
 * a 560px fan. The statement comes down one step and the fan with it.
 */
@media (max-width: 1439px) {
  :root {
    --pad: 40px;
    --t-statement: 72px;
    --t-page: 60px;
    --t-page-2: 56px;
    --t-figure: 64px;
    --hero-w: 216px;
  }
  .landing { grid-template-columns: 520px 1fr; gap: 44px; min-height: 560px; }
  .twocol { grid-template-columns: 460px 1fr; gap: 44px; }
  .howgrid { gap: 56px; }
  .playgrid { grid-template-columns: 260px var(--col-play) 260px; gap: 40px; }
}

/* ------------------------------------------------------ 760 to 1119: one column
 * Two columns stop being possible before the type does. Everything stacks in the
 * order it is written, except the board, which is the page it is on.
 */
@media (max-width: 1119px) {
  :root {
    --pad: 32px;
    --t-statement: 60px;
    --t-page: 52px;
    --t-page-2: 46px;
    --t-head: 42px;
    --hero-w: 200px;
  }

  .landing {
    grid-template-columns: 1fr;
    gap: 40px;
    min-height: 0;
    padding: 24px 0 64px;
  }
  .fan { margin: 0 auto; }

    /* minmax(0,...) rather than 1fr: a stacked column must be allowed to be
     narrower than the widest thing in it, or the widest thing sets the page width. */
  .twocol { grid-template-columns: minmax(0, 1fr); gap: 32px; align-items: start; }

  /* The rail lies down. It keeps all three states, so it still says where you are;
     it simply stops being a sidebar and stops being sticky, because a strip pinned
     to the top of a narrow screen is a strip taken off the reading. */
  .howgrid { grid-template-columns: 1fr; gap: 36px; }
  .howcol { max-width: none; }
  .rail {
    position: static;
    display: flex;
    flex-wrap: wrap;
    gap: 8px 18px;
  }
  .railchip { padding: 0; }

  /* The board goes first. The disclaimer beside it is context; the board is the
     thing the page is for, and on one column whatever is on top is the page. */
  .playgrid {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    gap: 32px;
    text-align: center;
  }
  .playgrid > :nth-child(2) { order: -1; }
  .playside .lede { max-width: 46ch; }

  .prow { grid-template-columns: 1fr; gap: 6px; }
  .plabel { padding-top: 0; }
}

/* ------------------------------------------------------------- under 760: phone
 * The type comes down properly here rather than being scaled: 88 to 40 is not one
 * headline getting smaller, it is a different setting of the same words.
 */
@media (max-width: 759px) {
  :root {
    --pad: 20px;
    --t-statement: 40px;
    --t-page: 38px;
    --t-page-2: 34px;
    --t-head: 32px;
    --t-panel: 38px;
    --t-figure: 52px;
    --t-numeral: 34px;
    --t-section: 22px;
    --t-serif: 21px;
    --t-lede: 16px;
    /*
     * The cards on Try it and On the board, at the size they are in the game.
     *
     * 115 is clamped by a 335 column to 106, which happens to be exactly the
     * browser board at /play -- same column, same gaps. It is NOT the board
     * anybody actually plays: the app's daily is about 90 at this width, once
     * the header, the meta row, the banner, the helper slot and the footer
     * have taken theirs out of an 812 screen.
     *
     * So the page was showing the game larger than the game shows it, and two
     * sections of six cards each were most of a screen apiece. Both boards
     * take their width from this one token -- .tryboard and .obboard are
     * max-width: calc(var(--card-w) * 3 + gap * 2) -- so it moves them
     * together.
     *
     * Phone only. On a wide screen the page and /play already agree at 115
     * against 114.
     */
  --card-w: 90px;

  /* The fan is 2.154 cards wide, so on the narrowest phones it has to follow the
       viewport rather than a fixed number: 148 overflows a 320 screen.
     *
     * 22vw, not 38. At 38 the fan measured 320 wide inside a 320 column -- the
     * whole of it -- because 2.154 cards at 38vw each is 82vw of screen before
     * the padding is counted. The clamp was written for the narrow end and
     * nobody checked what the middle term did at 375 and up. 22vw is about
     * half the column, which is a hero rather than the page.
     *
     * The floor and ceiling move with it. Leaving 112 would have meant nothing
     * changed on the smallest phones, which are the ones with least to spare. */
    --hero-w: clamp(78px, 22vw, 104px);
    --pill-pad: 28px;
    --strip-h: 36px;
  }

  /* The word Today goes and the date stays. Both do not fit tracked out at this
     width, and the date says Today by itself; the label without it says nothing. */
  .strip { gap: 12px; letter-spacing: .12em; }
  .strip-l .dim { display: none; }

  .site-head { padding: 22px 0; gap: 16px; }
  .headlinks { gap: 18px; }

  /* The fan goes first, and the gaps close.
   *
   * Two columns on a wide screen means the fan is seen at the same moment the
   * words are. Stacked, it fell to the BOTTOM: y603 on an 812 screen, ending at
   * 899, so the one picture on the page was half below the fold and arrived
   * after everything it was there to introduce.
   *
   * The gap above it was also being paid twice, by .landing's own 32 and the
   * fan's own margin. A phone browser keeps about 110px for its URL bar, so the
   * target is not 812 -- it is nearer 700, and every one of these points was
   * the difference between the whole page fitting and not.
   *
   * Sizes are untouched. This is all space between things. */
  .landing {
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 8px 0 56px;
  }
  .landing > .fan { order: -1; margin: 0 auto; }
  .site-head { padding: 16px 0; }
  .serifline { margin-bottom: 12px; }
  .statement { margin-bottom: 18px; }
  .lsub { margin-bottom: 24px; }
  .recruit { margin-top: 28px; }
  .lsub, .lede { max-width: none; }
  .actions { gap: 20px; }

  .howhead { padding: 22px 0 56px; }
  .howbody { padding: 44px 0 64px; }
  .hsec { padding-bottom: 64px; }

  /* The numeral gives up its own column: at 34 it no longer needs one, and the
     sentence needs the width more than the hang does. */
  .chk { grid-template-columns: 40px 1fr; gap: 14px; }
  .chk p { max-width: none; }
  .hlede { max-width: none; }

  /*
   * The board asks for its height instead of being told one.
   *
   * `#root` was a flat 874, measured once at one width. The board fills whatever
   * box it is handed, so anything the cards did not need became empty space
   * above the Hint -- 122px of it at 375, 150 at 360.
   *
   * The height it wants rises with the width, because the cards do. Measured by
   * raising the mount at each width until the cards stopped growing and reading
   * off what was left over:
   *
   *     360 -> 724    375 -> 752    393 -> 784    430 -> 856
   *
   * which is a straight line, 1.886 per pixel of width. Rounded a couple of
   * pixels generous on purpose: slack that small is invisible, where a shortfall
   * shrinks every card on the board.
   *
   * Phone band only. The desktop column is a fixed 393 and is left alone.
   *
   * Raised by 28 when the board gained the helper slot -- the trait row under
   * the banner. The slot is a fixed row above a `flex: 1` board, so every pixel
   * it takes comes out of the cards unless the mount is told about it. 48 was
   * the constant before it existed; 76 is the same line moved up by the row's
   * own height, measured from where the board container now starts (y168,
   * against y140 before).
   *
   * Capped where the board stops growing (Martin, 2026-10-11). The column is
   * min(393, 100%), so from a 433 window (393 and the page's 20 either side) the
   * cards are full size while 100vw kept climbing: at 640 the mount was 1283 for
   * cards that use 884, and the Hint sat 399 below the board. Recording the daily
   * videos in a tall, narrow window is exactly that band.
   */
  :root { --board-h: calc(76px + 1.886 * min(100vw, 433px)); }

  /*
   * The page reads once, top to bottom, and on a phone that was four and a half
   * screens -- 21% of which was gap before a word of content: six sections at 64
   * of padding is 384, six headings at 28 below is 168, four ledes at 32 below
   * is 128, and the hero band's 56 over the body's 44 is another 100.
   *
   * Every gap comes down by about a third and nothing changes shape: no copy
   * cut, no card resized, no section dropped. The space *between* blocks is the
   * space doing no work; the space *inside* them separates one worked example
   * from the next, so it is left alone -- that separation is the only cue a
   * reader gets that a new example started.
   *
   * Measured at 375: the page 3723 -> 3439, the first numbered step y499 -> 461.
   */
  .hsec { padding-bottom: 40px; }
  .hsect { margin-bottom: 18px; }
  .hlede { margin-bottom: 22px; }
  .howhead { padding-bottom: 40px; }
  .howbody { padding-top: 32px; }
  .checks { gap: 22px; }

  /* The rail goes. It is a progress indicator that cannot indicate progress at
     this width: the band above already made it `position: static`, so the state
     it carries -- filled for the chapter you are in, dashed for the rest --
     scrolls off in the first screen and never updates in view again. What is
     left is five jump links on a page somebody reads once, top to bottom, to
     learn a game they have not played. The 760-1119 chip row stays. */
  .rail { display: none; }

  /* A trait is a label and three values, and the label stays beside them the way
     it does on the desktop -- stacked, a five-letter word cost 31 of a 165pt row
     and made the phone a different design rather than the same one narrower.
     48 rather than 62: the tallest glyph on any row is the three-pip count stack
     at about 44, and the other three rows were paying for headroom they never
     used. */
  .gloss { grid-template-columns: 52px 1fr; gap: 12px; padding: 14px 0; }
  .gi { gap: 8px; }
  .gi > div { gap: 8px; }
  .gs { height: 48px; }

  .tipgrid { gap: 10px; }
  .foot-links { gap: 18px; }
}

/* --------------------------------------------------------- worked examples
 * Three triples judged trait by trait, between the traits and Try it.
 *
 * Its own class names throughout. `.chk` is already a numbered step in this
 * file and `.verdict` is already Try it's result -- the retired design used
 * both of those names for this, which is exactly the sort of collision that
 * looks fine until one of them changes.
 */
.wex { display: grid; gap: 18px; margin: 0 0 20px; }
.wcase { display: grid; gap: 0; }
.wtop { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.wcards { display: flex; gap: 5px; }
.wv b { display: block; font-size: 22px; line-height: 1; }
.wv span { display: block; font-size: var(--t-small); font-weight: 700; margin-top: 1px; }
.wv.ok { color: var(--valid); }
.wv.no { color: var(--invalid); }
/*
 * One line per trait: label, values, verdict. The verdict sits at the end,
 * where the eye lands after reading across, and it has to STAY on that line --
 * wrapping it underneath doubled every row and turned four traits into eight
 * lines. That is what the sizes here are for, not taste.
 */
.wtrait {
  display: grid;
  grid-template-columns: 46px 1fr auto;
  align-items: baseline;
  gap: 8px;
  font-size: 14px;
  line-height: 1.55;
}
.wtn {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--dim);
}
.wtv { color: var(--ink); }
.wts {
  font-size: 12px;
  font-weight: 600;
  color: var(--dim);
  text-align: right;
  white-space: nowrap;
}
.wts.bad { color: var(--invalid); }
/* The only line that generalises, so the only one at full strength. */
.wclose {
  margin: 0;
  font-size: var(--t-body);
  font-weight: 600;
  line-height: 1.5;
  color: var(--ink);
  max-width: 46ch;
}
@media (max-width: 759px) {
  .wcards .tc { width: 50px; height: 70px; }
  .wtrait { grid-template-columns: 44px 1fr auto; gap: 6px; font-size: 13.5px; }
  .wts { font-size: 11.5px; }
}

/* ------------------------------------------------------------------- invite
 * One address for both phones. Two rows rather than two buttons: a person is
 * only ever on one of these platforms, so this is a question being answered
 * rather than a choice between two actions, and a row can carry the sentence
 * that answering it needs.
 */
.reviewing {
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--dim);
  border-left: 2px solid var(--chev);
  padding-left: 16px;
  margin: 0 0 30px;
  max-width: 56ch;
}
.plats { display: grid; gap: 12px; margin: 0 0 22px; }
/* Name and sentence on the left, the code on the right spanning both rows. */
.plat {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  gap: 4px 24px;
  padding: 22px 24px;
  border: 1px solid var(--hair);
  border-radius: 14px;
  color: var(--ink);
}
.qr {
  grid-column: 2;
  grid-row: 1 / span 3;
  align-self: center;
  display: block;
  border-radius: 6px;
}
/* A phone is the one place the code is useless: you cannot scan your own
   screen. Below the tablet breakpoint it goes and the link does the work. */
@media (max-width: 759px) {
  .qr { display: none; }
}
/* Two codes per phone, one on screen at a time, in the column a single code used.

   Stacked, a phone camera saw both and could open the wrong step, so the radio buttons in
   `qrSteps` pick which code is drawn and the other is not drawn at all. One code and its two
   step buttons are shorter than either card's text, so neither card grows for them. The
   buttons stay narrower than the 132 code, so the column keeps its width and the text keeps
   its wrap. `steps-top` keeps the iPhone steps under the sentence if that ever changes. */
.qrpair {
  grid-column: 2;
  grid-row: 1 / span 3;
  align-self: center;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.qrpair.span4 { grid-row: 1 / span 4; }
.plat.steps-top { grid-template-rows: auto auto 1fr; }
.qrpick { position: absolute; top: 0; left: 0; width: 1px; height: 1px; margin: 0; opacity: 0; }
.qrone { display: none; }
.qrpick:nth-of-type(1):checked ~ .qrshow .qrone:nth-child(1),
.qrpick:nth-of-type(2):checked ~ .qrshow .qrone:nth-child(2) { display: block; }
.qrtabs { display: flex; gap: 8px; }
.qrtabs label {
  font-size: var(--t-small);
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  color: var(--dim);
  padding: 6px 9px;
  border: 1px solid var(--hair);
  border-radius: 999px;
  cursor: pointer;
}
.qrpick:nth-of-type(1):checked ~ .qrtabs label:nth-child(1),
.qrpick:nth-of-type(2):checked ~ .qrtabs label:nth-child(2) { color: var(--ink); border-color: var(--ink); }
.qrpick:nth-of-type(1):focus-visible ~ .qrtabs label:nth-child(1),
.qrpick:nth-of-type(2):focus-visible ~ .qrtabs label:nth-child(2) { outline: 2px solid var(--teal); outline-offset: 2px; }
/* After the pair's own display, or the pair wins and its buttons stay on a phone. */
@media (max-width: 759px) { .qrpair { display: none; } }
.scanline {
  font-size: var(--t-small);
  line-height: 1.6;
  color: var(--dim);
  max-width: 54ch;
  margin: 0 0 26px;
}
@media (max-width: 759px) { .scanline { display: none; } }
.platwho { font-size: var(--t-lede); font-weight: 700; }
/* The sentence sits under the name and clears the action, so a long one wraps
   into the row rather than against it. */
.platwhat { grid-column: 1; font-size: var(--t-body); line-height: 1.55; color: var(--dim); max-width: 46ch; }
/*
 * The note under the steps.
 *
 * `grid-column: 1` is not decoration: `.plat` is `1fr auto` with `.qr` pinned
 * to column 2, so a child that does not claim column 1 gets auto-placed beside
 * the QR and collapses the text column to a ribbon. `.platwhat`, `.platgo` and
 * `.steps` all declare it for the same reason.
 */
.platfoot {
  grid-column: 1;
  margin: 14px 0 0;
  font-size: var(--t-small);
  line-height: 1.55;
  color: var(--dim);
  max-width: 46ch;
}
.platgo {
  grid-column: 1;
  justify-self: start;
  margin-top: 10px;
  font-size: var(--t-body);
  font-weight: 700;
  color: var(--teal);
  text-decoration: none;
  white-space: nowrap;
}
.platgo:hover { text-decoration: underline; }
/* The iPhone row's order, where that row's link used to be.
 *
 * It is an ordered list because the order is the whole of the point: the join
 * link does nothing until TestFlight is installed, and somebody who taps it
 * first lands on Apple's refusal page. Three children either way -- the name,
 * the sentence, and this in the link's place -- so .qr's span of 3 still
 * reaches the bottom of the row and needs no exception.
 *
 * The numeral is positioned rather than laid out beside the text. A grid or
 * flex row makes the link one item and the words after it another, so
 * "Install TestFlight from the App Store." comes apart a word per line. */
.steps {
  grid-column: 1;
  list-style: none;
  counter-reset: step;
  margin: 12px 0 0;
  padding: 0;
  display: grid;
  gap: 8px;
  max-width: 44ch;
}
.steps li {
  counter-increment: step;
  position: relative;
  padding-left: 32px;
  font-size: var(--t-body);
  line-height: 1.5;
  color: var(--dim);
}
.steps li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 1px;
  width: 20px;
  height: 20px;
  border: 1px solid var(--chev);
  border-radius: 5px;
  color: var(--ink);
  font-size: 12px;
  font-weight: 700;
  display: grid;
  place-items: center;
}
.steps a { color: var(--teal); font-weight: 700; text-decoration: none; }
.steps a:hover { text-decoration: underline; }
.platnote { display: block; max-width: 56ch; }

@media (max-width: 759px) {
  .plat { padding: 18px 18px; gap: 4px 14px; }
}

/* ------------------------------------------------------------ joining on android
 * Cowork's guide (handoff 2026-09-14, android-join), on the site's own tokens so it follows the
 * page's room switch. A phone and a tablet get the lightbox from "See example"; a computer with
 * room beside the column gets the guide next to the Android QR codes, out of the card's flow.
 */
.tj, .exbox {
  --tj-ink: var(--ink); --tj-dim: var(--dim); --tj-line: var(--hair); --tj-div: var(--hair);
  --tj-accent: var(--teal); --tj-onaccent: var(--onteal);
  color: var(--tj-ink);
}
.tj { display: none; }
.tj-h { font-size: 19px; font-weight: 700; margin: 0 0 6px; }
.tj-sub { font-size: 14px; color: var(--tj-dim); margin: 0 0 14px; line-height: 1.5; }
.tj-shot { position: relative; max-width: 340px; margin: 0 auto 28px; }
.tj-shot img { width: 100%; height: auto; display: block; border-radius: 12px; border: 1px solid var(--tj-line); }
.tj-shot svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.tj-steps { margin: 0; padding: 0; list-style: none; counter-reset: tjs; }
.tj-steps li { counter-increment: tjs; position: relative; padding: 0 0 10px 42px; font-size: 14px; line-height: 1.55; }
.tj-steps li::before { content: counter(tjs); position: absolute; left: 0; top: -1px; width: 26px; height: 26px;
  border-radius: 13px; background: var(--tj-accent); color: var(--tj-onaccent);
  font-size: 14px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
.tj-quiet { color: var(--tj-dim); }
.tj-note { font-size: 13px; color: var(--tj-dim); border-top: 1px solid var(--tj-div);
  padding-top: 16px; margin-top: 6px; line-height: 1.5; }

/* Step 1: the message Google will show, quoted loud, and the link to what it looks like. */
.loud { font-weight: 800; color: var(--ink); letter-spacing: .01em; }
.seeex { color: var(--teal); font-weight: 700; text-decoration: none; white-space: nowrap; }
.seeex:hover { text-decoration: underline; }
.seeex:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; border-radius: 3px; }

dialog.exbox { border: 0; border-radius: 16px; padding: 0; width: min(360px, calc(100vw - 40px));
  background: var(--g); box-shadow: 0 18px 60px rgba(0, 0, 0, .45); }
dialog.exbox::backdrop { background: rgba(12, 10, 9, .66); }
.exbox-in { padding: 16px 16px 14px; outline: none; }
.exbox .tj-shot { max-width: 100%; margin: 0 0 14px; }
.exbox-line { font-size: 15px; line-height: 1.5; margin: 0 0 6px; }
.exbox-dim { font-size: 14px; line-height: 1.5; color: var(--dim); margin: 0 0 14px; }
.exbox-x { display: block; width: 100%; font: inherit; font-size: 15px; font-weight: 700; padding: 11px;
  border-radius: 999px; border: 1px solid var(--hair); background: none; color: var(--ink); cursor: pointer; }
/* The ring after a tap read as a heavy black outline; keyboard focus keeps it. */
.exbox-x:focus:not(:focus-visible) { outline: none; }
.exbox-x:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }

@media (min-width: 1180px) {
  /* grid-column is left auto: spanning the grid would make the grid area this absolute box's
     containing block, which starts 25px inside the card's edge. */
  .plats .plat { position: relative; }
  .tj { display: block; position: absolute; top: 0; left: auto; right: -366px; width: 330px; }
  .tj .tj-shot { max-width: 272px; margin: 0 0 16px; }
}

/* The board page's button carries "Now in beta / on iPhone and Android" on two lines. */
.pill.pill-two { height: auto; padding-top: 12px; padding-bottom: 12px; line-height: 1.3;
  text-align: center; flex-direction: column; }

/* How to play ends on the button it has been teaching toward. Inside the last section, so the
   section's own bottom room stays under it. */
.howplay { margin-top: 44px; }

/* ------------------------------------------------------------------ How to play
 *
 * Designed 30 September as F65-F72, after Martin found he wanted to explain the
 * rules before playing and this page could not do it: it was a reference
 * document -- a six-section rail, a glossary, worked examples -- where the app's
 * How to play makes you do the check yourself.
 *
 * So this is the app's screen, on the web. Every value came out of the app:
 * src/theme/tokens.ts, src/ui/RulesCard.tsx, src/ui/TraitCard.tsx,
 * src/ui/CheckTable.tsx, src/ui/CardGlyph.tsx. The examples are the app's own
 * TRIO and MISSES and the verdict sentences come from its verdictFor, so the
 * page says what the app says rather than a paraphrase of it.
 *
 * Two shapes. Below 900 it IS the app: a 393 column, 24 edges, 345 widgets,
 * 108 cards. At 900 and over it becomes a board -- a 300 rail carrying the
 * reading, the pieces in the room to its right.
 *
 * The old page's rules (.howgrid, .railchip, .howbody, .hsec, .checks, .wex and
 * the v3 .glossary) are still in this file: `const how` builds the pre-pass-3
 * design and OLD=1 still asks for it.
 * ------------------------------------------------------------------ */

.howp { max-width: 393px; margin: 0 auto; padding: 0 24px 56px; }

.howp-eyebrow {
  margin: 28px 0 18px;
  font-size: 11px; font-weight: 700; letter-spacing: 2.42px;
  text-transform: uppercase; color: var(--dim);
}
.howp-hero {
  margin: 0; max-width: 620px;
  font-family: var(--ed); font-style: italic; font-weight: 400;
  font-size: 38px; line-height: 40px; color: var(--accent);
}
.howp-s { margin-top: 40px; }
.howp-h2 { margin: 0; font-size: 28px; line-height: 30px; font-weight: 900; letter-spacing: -.7px; }
.howp-lead {
  margin: 12px 0 0; max-width: 620px;
  font-size: 17px; line-height: 25.5px; font-weight: 600; color: var(--dim); text-wrap: pretty;
}
.howp-h3 { margin: 28px 0 0; font-size: 21px; font-weight: 900; letter-spacing: -.32px; }

/* A segmented control, as the app draws it: a groove with the chosen face in it. */
.howp-track { display: flex; gap: 4px; padding: 4px; margin-top: 12px; border-radius: 12px; background: var(--track); }
.howp-seg {
  flex: 1; height: 40px; border-radius: 9px; border: 0; cursor: pointer;
  background: transparent; color: var(--ink);
  font-family: inherit; font-size: 13px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.howp-seg[aria-pressed="true"] { background: var(--face); }
.howp-mode { margin-top: 0; }
.howp-mode .howp-seg { font-size: 15px; }

.howp-rows { margin-top: 8px; }
.howp-row { padding: 12px 0; border-bottom: 1px solid var(--hair); display: grid; gap: 8px; }
.howp-rowhead { font-size: 11px; font-weight: 700; letter-spacing: 1.54px; color: var(--dim); }
.howp-rowline { display: flex; align-items: center; gap: 8px; }
.howp-rowline svg.lens { width: 46px; height: 64.4px; flex: none; display: block; }
.howp-rowv { display: flex; align-items: center; gap: 8px; padding-left: 8px; }
.howp-rowv span { font-size: 15px; font-weight: 700; }

.howp-widget { margin-top: 22px; }
/* The cards are drawn fluid and sized by their container, so one set of SVGs
   serves the phone's 108 and the board's 200 without being rendered twice. */
.howp-cards { display: flex; gap: 10px; margin-top: 20px; min-height: 151px; }
.howp-cards svg { flex: 1; min-width: 0; width: 100%; height: auto; display: block; }
.howp-chips { display: flex; gap: 8px; margin-top: 20px; }
.howp-chip {
  flex: 1; height: 44px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--hair); background: transparent; color: var(--ink);
  font-family: inherit; font-size: 11px; font-weight: 700; letter-spacing: 1.21px;
  text-transform: uppercase; display: flex; align-items: center; justify-content: center;
}
.howp-chip.on { background: var(--ink); border-color: var(--ink); color: var(--g); }
/* The step list and the caption belong to the board; the chips belong to the phone. */
.howp-steps, .howp-cap { display: none; }

/* Design fixed this height to the tallest of the eight sentences it can say, so
   nothing under it moves as the steps are tapped. */
.howp-verdict {
  margin: 16px 0 0; min-height: 85px;
  font-size: 21px; line-height: 28.35px; font-weight: 700; letter-spacing: -.21px; text-wrap: pretty;
}
.howp-verdict.fail { color: var(--no); }
.howp-verdict.trio { color: var(--ok); }
.howp-legend { margin: 12px 0 0; font-size: 15px; line-height: 22.5px; font-weight: 600; color: var(--dim); }

.howp-table { margin-top: 18px; border-bottom: 1px solid var(--hair); }
.howp-trow { display: flex; align-items: center; gap: 10px; padding: 11px 0; border-top: 1px solid var(--hair); }
.howp-tname {
  width: 58px; flex: none;
  font-size: 11px; font-weight: 700; letter-spacing: 1.54px; text-transform: uppercase; color: var(--dim);
}
.howp-trow.fails .howp-tname { color: var(--ink); }
.howp-tvals { flex: 1; font-size: 13px; font-weight: 600; }
.howp-tres { display: grid; justify-items: end; gap: 2px; }
.howp-tline { display: flex; align-items: center; gap: 6px; }
.howp-tverdict { font-size: 13px; font-weight: 700; }
.howp-trow.fails .howp-tverdict { color: var(--no); }
.howp-tkind { font-size: 11px; font-weight: 600; color: var(--dim); }

.howp-close { margin-top: 36px; }
.howp-closing { margin: 0; max-width: 620px; font-size: 21px; line-height: 27.3px; font-weight: 900; letter-spacing: -.42px; }
.howp-note { margin: 12px 0 0; max-width: 620px; font-size: 15px; line-height: 23.25px; font-weight: 600; color: var(--dim); }
.howp-footing { margin-top: 32px; width: 345px; max-width: 100%; display: grid; justify-items: center; gap: 16px; }
.howp-play {
  height: 56px; width: 100%; border-radius: 999px;
  background: var(--teal); color: var(--onteal); border: 0; border-bottom: 1px solid var(--teal-edge);
  font-size: 17px; font-weight: 700; letter-spacing: -.2px;
  display: flex; align-items: center; justify-content: center; text-decoration: none;
}

/* F66: 900, and the number is arithmetic rather than taste. A lens row is three
   46 cards on 8 gaps plus the tick and the word Trio, 221 rendered, so the pair
   needs 2 x 221 + 24 = 466 and the page needs 24 + 300 + 72 + 466 + 24 = 886.
   That is also why the page's own edges are 24 and the pair gap is 24: at 32 and
   48 the pair wanted 926 and overflowed between 900 and 926. */
@media (min-width: 900px) {
  .howp {
    max-width: 1180px; padding: 40px 24px 56px;
    display: grid; grid-template-columns: 300px minmax(0, 1fr);
    column-gap: 72px; row-gap: 72px; align-items: start;
  }
  /* `display: contents` lets each section hand its rail and its pieces straight
     to the page grid, so both rails land in the same 300 column. */
  .howp-s { margin-top: 0; display: contents; }
  .howp-read { display: grid; gap: 28px; align-content: start; }
  .howp-read .howp-lead { margin: -16px 0 0; }
  .howp-h3 { margin: 0; }
  .howp-pair {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: 24px; align-items: start; min-width: 0; padding-top: 4px;
  }
  .howp-board { display: grid; gap: 28px; min-width: 0; }
  .howp-widget { margin-top: 0; display: grid; justify-items: center; gap: 12px; }
  .howp-track.howp-mode { width: 300px; margin-top: 0; }
  .howp-cap { display: block; margin: 0; font-size: 15px; font-weight: 600; color: var(--dim); }
  .howp-chips { display: none; }
  .howp-steps { display: grid; gap: 8px; }
  .howp-step {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    height: 52px; padding: 0 18px; border-radius: 12px; cursor: pointer; text-align: left;
    border: 1px solid var(--hair); background: transparent; color: var(--ink); font-family: inherit;
  }
  .howp-step.on { background: var(--ink); border-color: var(--ink); color: var(--g); }
  .howp-steplabel { font-size: 13px; font-weight: 700; letter-spacing: 1.21px; text-transform: uppercase; }
  .howp-stepvals { font-size: 13px; font-weight: 600; color: var(--dim); }
  .howp-step.on .howp-stepvals { color: var(--onink); }
  .howp-cards {
    margin-top: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 200px));
    gap: 24px; justify-content: center; padding: 8px 0; min-height: 0;
  }
  .howp-verdict {
    margin: 0; min-height: 76px; font-size: 28px; line-height: 36px; letter-spacing: -.4px;
    text-align: center; max-width: 640px; justify-self: center;
  }
  /* F71. The legend was in the phone column only, which was an oversight rather
     than a decision: it is the one line naming what a trait can be, where the
     step list names what these three cards happen to be. */
  .howp-legend { margin: -16px 0 0; text-align: center; max-width: 640px; justify-self: center; }
  .howp-table { margin-top: 0; max-width: 640px; width: 100%; justify-self: center; }
  .howp-trow { gap: 16px; padding: 14px 0; }
  .howp-tname { width: 70px; }
  .howp-tvals { font-size: 15px; }
  .howp-tres { display: flex; align-items: center; gap: 8px; }
  .howp-tverdict { font-size: 15px; }
  .howp-tkind { font-size: 13px; }
  .howp-close {
    grid-column: 1 / -1; margin-top: 0; display: grid; gap: 32px;
    justify-items: center; text-align: center; padding: 24px 0 0;
  }
  .howp-closetext { display: grid; gap: 12px; max-width: 520px; }
  .howp-closing, .howp-note { margin: 0; max-width: none; text-wrap: balance; }
  .howp-footing { margin-top: 0; gap: 14px; }
}

@media (prefers-reduced-motion: no-preference) {
  .howp-seg, .howp-chip, .howp-step { transition: background-color .12s ease; }
}


/* The strip never wraps (Design, halloween-site-answers 8, 15 October). At 390 "WEDNESDAY 30
   SEPTEMBER", the longest date, broke onto two lines beside the count. Up to 430 the tracking
   drops to .06em and the gap to 8, and neither side wraps; below 380 the count reads "6 to find".
   The date is never shortened. */
.strip-l, .strip-r { white-space: nowrap; }
@media (max-width: 430px) {
  .strip { letter-spacing: .06em; gap: 8px; }
}
@media (max-width: 379px) {
  .strip-trios { display: none; }
}
