/* ══════════════════════════════════════════════════════════════════════════
   Office Rules — v11
   Built from the "OR v11" comp. White ground, five saturated fields
   (punch orange, solar yellow, lime, signal navy, coal), heavy rounding,
   Gabarito at poster scale, Archivo for reading, mono for receipts.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  --punch:  #F47421;
  /* Punch orange only clears 2.8:1 on a light ground, so small text and thin
     icons take the darkened cousin. Fills and buttons keep the brand orange. */
  --punch-ink: #B3520E;
  --solar:  #FED402;
  --lime:   #ACD037;
  --signal: #2D4894;
  --signal-lift: #3C55A4;
  --ink:    #231F20;
  --coal:   #171717;

  /* The focus ring reads against whatever it lands on, so the bands that are
     darker than the ring re-point it at white. Set per band, not per control. */
  --focus:  #2D4894;
  --paper:  #FFFFFF;
  --cream:  #FAF7F5;
  --card:   #F3F2EC;
  --line:   #E6E3DC;
  --dim:    #63666F;
  /* A control boundary, not a surface hairline. WCAG 1.4.11 asks 3:1 of
     anything that tells you where a control is, and --line manages 1.28:1
     against the white form panel. This clears 3:1 against all three grounds a
     control ever sits on — 3.40 on paper, 3.19 on cream, 3.14 on card — so one
     token covers inputs, format chips and FAQ tabs. The previous #949086 was
     tuned for white alone and measured 2.99 against its own cream fill.
     Warm rather than neutral so it stays in the cream family. */
  --control-line: #8F8B81;

  --shell: 1160px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);

  /* Band rhythm. Three weights, not one repeated value: the two bands that
     ask for a decision get air, the aside gets less, everything else sits in
     the middle. Scrolling the page should feel like a cadence. */
  --band:       clamp(3.5rem, 7vw, 6rem);
  --band-loose: clamp(4.75rem, 9.5vw, 8.5rem);
  --band-tight: clamp(2.75rem, 5vw, 4.25rem);

  --d1: clamp(2.5rem, 5vw, 4.5rem);
  --d2: clamp(1.95rem, 3.3vw, 2.85rem);
  --d3: clamp(1.2rem, 1.6vw, 1.4rem);

  --r-lg: 22px;
  --r-md: 16px;
  --r-sm: 12px;

  --sans: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --display: 'Gabarito', var(--sans);
  --mono: 'Courier Prime', ui-monospace, 'SF Mono', Menlo, monospace;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 92px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 1.0625rem/1.75 var(--sans);
  -webkit-font-smoothing: antialiased;
}

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

a { color: inherit; }

h1, h2, h3, h4 { margin: 0; font-family: var(--display); font-weight: 800; line-height: 1.12; letter-spacing: -.015em; }
p { margin: 0; }
ul, ol, dl { margin: 0; padding: 0; list-style: none; }

::selection { background: var(--solar); color: var(--ink); }

:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; border-radius: 4px; }

.vh {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; left: 1rem; top: -100px; z-index: 100;
  background: var(--ink); color: #fff; padding: .75rem 1.1rem;
  border-radius: 999px; font-weight: 700; font-size: .9375rem; text-decoration: none;
  transition: top .18s ease;
}
.skip:focus { top: 1rem; }

.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--gutter); }

/* ── Type helpers ──────────────────────────────────────────────────────── */
.d1 { font-size: var(--d1); font-weight: 900; letter-spacing: -.03em; line-height: 1.06; }
.d2 { font-size: var(--d2); font-weight: 800; letter-spacing: -.025em; line-height: 1.1; text-wrap: balance; }

/* Positioned, so the first line paints above the yellow mark below it — the
   descender on "building," clears the box instead of being covered by it. */
.d1__lift { position: relative; }

.d1 mark {
  background: var(--solar);
  color: inherit;
  padding: .04em .2em .13em;
  margin-left: -.2em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

.lede { font-size: 1.1875rem; line-height: 1.75; margin-top: 1.4rem; max-width: 34rem; }
.lede b { font-weight: 700; }
.sub { color: var(--dim); font-size: 1rem; margin-top: 1.15rem; max-width: 34rem; }
.prose { margin-top: 1.15rem; max-width: 40rem; }
.prose + .prose { margin-top: 1.35rem; }

.meter {
  font: 400 .75rem/1.4 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--dim);
}

.lead { max-width: 44rem; }
.lead .prose { margin-top: 1.25rem; }

/* ── Buttons ───────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: .6rem;
  border: 1.6px solid transparent; border-radius: 999px;
  padding: .95rem 1.6rem;
  font: 700 .9375rem/1 var(--sans);
  text-decoration: none;
  cursor: pointer;
  transition: transform .16s ease, background-color .16s ease, color .16s ease, box-shadow .16s ease;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn--sm { padding: .78rem 1.3rem; font-size: .875rem; }

/* In-flight, not unavailable. Opacity rather than a disabled fill per variant:
   four variants would need four, and this state is temporary. .62 keeps the
   label at 5:1 on the ink button, because a busy control still has to be read.
   aria-disabled, not :disabled — see the note in app.js. */
.btn[aria-disabled="true"] {
  opacity: .62;
  cursor: progress;
}
.btn[aria-disabled="true"]:hover,
.btn[aria-disabled="true"]:active { transform: none; }
.btn:disabled { opacity: .62; cursor: not-allowed; }
.btn:disabled:hover { transform: none; }

/* Ink, not white. Punch is a light fill: white on it is 2.85:1 and fails at
   any size, while ink clears 5.7:1. Swapping which element carries the orange
   never changed the ratio — only the text colour does. */
.btn--punch { background: var(--punch); color: var(--ink); }
.btn--punch:hover { background: #E0651A; }
.btn--lime { background: var(--lime); color: var(--ink); }
.btn--lime:hover { background: #9BC22B; }
.btn--ink { background: var(--coal); color: #fff; }
.btn--ink:hover { background: #000000; }
.btn--ghost { border-color: var(--ink); color: var(--ink); background: transparent; }
.btn--ghost:hover { background: var(--ink); color: #fff; }

.btn__arw { width: 16px; height: 16px; flex: none; }
.btn-row { display: flex; flex-wrap: wrap; gap: .85rem; margin-top: 1.8rem; }

/* ── Nav ───────────────────────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 40;
  background: var(--paper);
  transition: box-shadow .2s ease;
}
.nav[data-stuck="true"] { box-shadow: 0 1px 0 var(--line), 0 12px 28px -24px rgba(0,0,0,.5); }

.nav__in {
  max-width: 1340px; margin-inline: auto;
  padding: 1.1rem var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
}

.brand { display: inline-flex; align-items: center; gap: .6rem; text-decoration: none; }
.brand__mark { fill: var(--punch); flex: none; }
.brand b { font: 800 1.125rem/1 var(--display); letter-spacing: -.02em; }

.nav__links { display: flex; align-items: center; gap: 1.9rem; }
.nav__links a {
  text-decoration: none; font-size: .9375rem; font-weight: 500;
  transition: color .15s ease;
}
.nav__links a:not(.btn):hover { color: var(--punch-ink); }

.nav__toggle {
  display: none;
  background: none; border: 0; padding: .5rem; cursor: pointer; color: inherit;
}
.nav__toggle-bars { display: grid; gap: 5px; }
.nav__toggle-bars i { display: block; width: 24px; height: 2.5px; background: currentColor; border-radius: 999px; }

@media (max-width: 900px) {
  /* The only control that persists the whole way down a 13-screen page, so it
     gets a full 44px square rather than the 40×34 the bars alone made. */
  .nav__toggle { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; }
  .nav__links {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: flex-start; gap: .35rem;
    background: var(--paper);
    padding: .5rem var(--gutter) 1.4rem;
    border-bottom: 1px solid var(--line);
    box-shadow: 0 18px 30px -26px rgba(0,0,0,.5);
  }
  .nav__links a { padding: .6rem 0; font-size: 1.0625rem; }
  .nav__links .btn { margin-top: .6rem; }
  /* Only collapses once the script has wired the toggle up, so a failed
     app.js leaves a stacked but reachable menu rather than a dead button. */
  .nav__links[data-ready][data-open="false"] { display: none; }
}

/* Bars fold into a cross while the menu is open. */
.nav__toggle[aria-expanded="true"] .nav__toggle-bars i:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] .nav__toggle-bars i:nth-child(2) { opacity: 0; }
.nav__toggle[aria-expanded="true"] .nav__toggle-bars i:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }
.nav__toggle-bars i { transition: transform .2s ease, opacity .2s ease; }
@media (prefers-reduced-motion: reduce) { .nav__toggle-bars i { transition: none; } }

/* ══════════════════ HERO ══════════════════ */
.hero {
  position: relative; z-index: 1;      /* the art overhangs the next band */
  background: var(--paper);
  padding-top: clamp(2.5rem, 5vw, 4.5rem);
  /* Clip sideways only: the hexes run off the right edge without adding a
     scrollbar, while the meeple and die still hang into the band below. */
  overflow-x: clip;
}
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.14fr) minmax(0, 1fr);
  gap: clamp(1rem, 2.5vw, 2rem);
  align-items: center;
}
/* The tail of this column used to be empty padding. The price cue lives
   there now, so it only needs enough room to clear the band edge. */
.hero__copy { padding-bottom: clamp(1.5rem, 3vw, 2.5rem); }

/* ── Price cue ─────────────────────────────────────────────────────────────
   The page argues that the prices aren't behind a form. That argument fails
   if the first number is 2,500px down, so the rates sit in the first
   viewport, ruled off from the call to action rather than boxed in a card. */
.pricecue {
  margin-top: 1.6rem;
  padding-top: 1.1rem;
  border-top: 1.5px solid var(--line);
  max-width: 34rem;
}
.pricecue__rates {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: .35rem 1.4rem;
}
.pricecue__rates .meter { flex: none; }
.pricecue__rate { font-size: .9375rem; color: var(--dim); }
.pricecue__rate b {
  font: 900 2rem/1 var(--display);
  letter-spacing: -.03em; color: var(--ink);
}
.pricecue__rate span { font-size: .875rem; font-weight: 500; margin-left: .12em; margin-right: .3em; }
.pricecue__note { margin-top: .75rem; font-size: .8125rem; line-height: 1.6; color: var(--dim); }
.pricecue__note a {
  font-weight: 700; color: var(--punch-ink);
  text-underline-offset: 3px; white-space: nowrap;
}

/* Below this the row can't hold both rates, and wrapping mid-row left the
   second one hanging off the first's indent. Stack instead, so "From" and
   both figures share one left edge, and buy back the height that costs. */
@media (max-width: 620px) {
  .pricecue { margin-top: 1.3rem; padding-top: .9rem; }
  .pricecue__rates { display: grid; justify-items: start; gap: .15rem; }
  .pricecue__rate b { font-size: 1.75rem; }
  .pricecue__note { margin-top: .55rem; }
}

/* Short phones. What's being fought for here is viewport height, so height is
   what the query asks about: every interval above the rates tightens so the
   figures clear the fold on a 560px-tall window. */
@media (max-width: 900px) and (max-height: 620px) {
  .hero { padding-top: 1rem; }
  .lede { margin-top: 1rem; }
  .sub { margin-top: .85rem; }
  .btn-row { margin-top: 1.3rem; }
  .pricecue { margin-top: 1rem; padding-top: .75rem; }
}

/* The cluster runs to the edge of the viewport, so the orange hex is cut by
   it rather than sitting politely inside the shell. */
.hero__art {
  position: relative;
  align-self: end;
  min-height: 300px;
  margin-right: calc(-1 * var(--gutter) - (100vw - min(100vw, var(--shell))) / 2);
}
.hero__hexes {
  position: absolute; z-index: 1;
  right: -14%; top: 4%;
  width: 128%; height: auto;
}
.hx--fill { fill: var(--punch); }
.hx--line { fill: none; stroke: var(--solar); stroke-width: 34; }

.hero__host {
  position: relative; z-index: 2;
  width: 74%;
  margin: 0 auto;
}
.hero__meeple, .hero__dice { position: absolute; z-index: 3; }
.hero__meeple { width: 26%; left: 1%; bottom: -7%; }
.hero__dice   { width: 29%; right: -3%; bottom: -11%; }

@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; }
  /* Every row above the price cue is height the cue doesn't get. */
  .hero { padding-top: 1.75rem; }
  .hero__copy { padding-bottom: 1rem; }
  .hero__art { max-width: 30rem; margin-inline: auto; width: 100%; }
  .hero__hexes { right: -8%; width: 116%; }
}

/* ══════════════════ WHY ══════════════════ */
.why {
  position: relative; z-index: 0;
  background: var(--cream);
  padding-block: var(--band);
  overflow: hidden;
}
.why__grid {
  display: grid;
  grid-template-columns: minmax(0, .92fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
/* The photo runs off the left edge of the viewport rather than sitting in
   the shell — the comp's one asymmetry. */
.why__shot {
  position: relative;
  margin: 0;
  margin-left: calc(-1 * var(--gutter) - (100vw - min(100vw, var(--shell))) / 2);
  border-radius: 0 var(--r-lg) var(--r-lg) 0;
  overflow: hidden;
  background: var(--card);
}

/* The loop's own control. Parked in the corner that stays inside the frame
   when the figure bleeds off the left edge, and sized to a real touch target
   rather than to the icon. Solid rather than glass: it has to stay legible
   over whatever frame is underneath it, and a blur over playing video buys
   nothing for the repaint it costs. */
.vidbtn {
  position: absolute; right: 1rem; bottom: 1rem; z-index: 2;
  display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  border: 0; border-radius: 999px;
  background: rgba(23, 23, 23, .82);
  color: #fff; cursor: pointer;
  transition: background-color .14s ease, transform .14s ease;
}
.vidbtn:hover { background: var(--punch); transform: translateY(-1px); }
.vidbtn:active { transform: translateY(0); }
/* Navy on video is unreadable, so this control keeps its own white ring. */
.vidbtn:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

/* No nudge on the triangle: its centroid already sits half a unit right of
   the box centre, which is the optical correction. Shifting it again in CSS
   double-corrects and reads as misaligned. */
.vidbtn__icon { width: 20px; height: 20px; fill: currentColor; }
.vidbtn[data-playing="true"] .vidbtn__play { display: none; }
.vidbtn[data-playing="false"] .vidbtn__pause { display: none; }

@media (prefers-reduced-motion: reduce) {
  .vidbtn { transition: none; }
  .vidbtn:hover { transform: none; }
}
/* height:auto so the width/height attributes don't win over aspect-ratio. */
.why__shot video { display: block; width: 100%; height: auto; aspect-ratio: 613 / 545; object-fit: cover; }

.why__copy .d2 { max-width: 22ch; }

.points { margin-top: 2.6rem; display: grid; gap: 1.6rem; }
.points li { display: grid; grid-template-columns: 34px 1fr; gap: 1rem; align-items: start; }
/* 700, not 800: Archivo ships here at 400–700, so an 800 resolved to the 700
   face and rendered identically. This states what actually paints, and matches
   every other Archivo heading on the page. */
.points h3 { font-size: 1.0625rem; font-weight: 700; font-family: var(--sans); letter-spacing: 0; }
.points p { color: var(--dim); font-size: .9375rem; line-height: 1.55; margin-top: .25rem; }

.hex {
  display: grid; place-items: center;
  width: 34px; height: 30px; margin-top: 1px;
  font: 700 .8125rem/1 var(--sans); color: var(--ink);
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}
.hex--solar { background: var(--solar); }
.hex--lime  { background: var(--lime); }
.hex--punch { background: var(--punch); color: var(--ink); }

@media (max-width: 900px) {
  .why__grid { grid-template-columns: 1fr; }
  /* The die and the meeple hang down into this band once the hero stacks, so
     the photo needs somewhere to start that isn't underneath them. */
  .why { padding-top: calc(var(--band) + 2rem); }
  .why__shot { margin-left: calc(-1 * var(--gutter)); border-radius: 0 var(--r-lg) var(--r-lg) 0; }
  .why__shot video { aspect-ratio: 16 / 10; }
}

/* ══════════════════ FOUR WAYS ══════════════════ */
.ways { background: var(--paper); padding-block: var(--band); }

/* A real two-by-two: the axes are labels, not headings, so they take the same
   mono meter voice as every other label on the page. The column heads sit on
   the rule that opens their column and the row labels align to the top of
   their row, so both read as edges of the grid rather than floating text. */
.matrix {
  margin-top: clamp(2.5rem, 5vw, 3.75rem);
  display: grid;
  grid-template-columns: clamp(5.5rem, 8vw, 7.5rem) minmax(0, 1fr) minmax(0, 1fr);
  gap: 1.25rem;
}
.matrix__corner { margin: 0; }
.matrix__col,
.matrix__row {
  margin: 0;
  font: 400 .75rem/1.4 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--dim);
}
.matrix__col {
  align-self: end;
  padding-bottom: .55rem;
  border-bottom: 1.5px solid var(--line);
}
.matrix__row {
  align-self: start;
  padding-top: .35rem;
  text-align: right;
}

.card {
  display: flex; flex-direction: column; align-items: flex-start;
  background: var(--card);
  border: 1.5px solid #E9E7DF;
  border-radius: var(--r-lg);
  padding: clamp(1.4rem, 2.4vw, 1.9rem);
}
.card--pick { border: 2.5px solid var(--solar); }
.card h3 { font-size: var(--d3); }

/* The solar border measures 1.44:1 against the band, so on its own it told a
   low-vision reader nothing at all — the steer existed only for people who
   could see the colour. The label carries it in words now and the border goes
   back to being decoration. Beside the heading, never above it: a tag stacked
   over a heading is a kicker. */
.card__top {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: .9rem; width: 100%;
}
.card__flag {
  flex: none; margin-top: .2rem;
  background: var(--solar); color: var(--ink);
  border-radius: var(--r-xs);
  padding: .28rem .6rem;
  font: 700 .875rem/1.2 var(--sans);
  white-space: nowrap;
}
.card > p { margin-top: .9rem; font-size: 1rem; line-height: 1.6; }
/* Bottom margin, not a top margin on the button: the button keeps its auto
   top margin so every card in a row lands its CTA on the same line however
   long the copy runs. */
.card__meta { color: var(--dim); font-size: .875rem; margin-bottom: 1.5rem; }
.card .btn { margin-top: auto; }

@media (max-width: 900px) {
  .matrix { grid-template-columns: 1fr; gap: 1rem; }
  .matrix__corner, .matrix__col { display: none; }
  .matrix__row {
    text-align: left; padding-top: 0;
    font: 400 .75rem/1.4 var(--mono);
    letter-spacing: .12em;
    margin-top: 1.9rem; padding-bottom: .55rem;
    border-bottom: 1.5px solid var(--line);
  }
  .matrix__row:first-of-type { margin-top: 0; }
}

/* ══════════════════ PRICING ══════════════════ */
/* Navy ring on a navy band is 1:1. Nothing focusable sits directly on these
   two today, but the default has to be survivable if something ever does —
   and the calculator's own panels put it back, being white and solar. */
.pricing, .hosts { --focus: #FFFFFF; }
.calc { --focus: var(--signal); }

.pricing {
  background: var(--signal);
  color: #fff;
  padding-block: var(--band-loose);
}
.pricing .prose { color: #D7DEF3; }

.pricing__head {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: end;
}
.mono-note { font: 400 .8125rem/1.85 var(--mono); color: #B9C4E4; }

/* ── Calculator ────────────────────────────────────────────────────────── */
/* One sheet, not two cards with a gutter. The docket is always the longer
   column, and two separate cards forced to equal height left a hole in
   whichever one ran short. Joined, the extra height is just the sheet. */
.calc {
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
  border-radius: var(--r-lg);
  overflow: hidden;
}
.calc__controls {
  background: var(--paper); color: var(--ink);
  padding: clamp(1.5rem, 2.6vw, 2.1rem);
  display: grid; align-content: start; gap: 2rem;
}
.field { border: 0; padding: 0; margin: 0; min-width: 0; }
.field .meter { display: block; }

.headcount { display: flex; align-items: baseline; gap: .6rem; margin-top: .5rem; }
.headcount b { font: 900 3.1rem/1 var(--display); letter-spacing: -.03em; }
.headcount span { color: var(--dim); font-size: .9375rem; }

/* 24px tall so the drag target clears the 24×24 floor; the track inside it
   stays 5px. A finger gets more — see the coarse-pointer block below. */
.range {
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; height: 24px; margin: 1rem 0 0;
  background: transparent; cursor: pointer;
}
/* The hatch was ink over a near-black track — dark on dark, invisible, while
   the hint sentence pointed straight at it. White at .34 reads on both the
   bare track and the orange fill it overlaps. */
.range::-webkit-slider-runnable-track {
  height: 5px; border-radius: 999px;
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,.34) 0 3px, transparent 3px 6px) left/var(--minpct, 0%) 100% no-repeat,
    linear-gradient(var(--punch), var(--punch)) left/var(--fill, 30%) 100% no-repeat,
    #201F22;
}
.range::-moz-range-track {
  height: 5px; border-radius: 999px;
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,.34) 0 3px, transparent 3px 6px) left/var(--minpct, 0%) 100% no-repeat,
    linear-gradient(var(--punch), var(--punch)) left/var(--fill, 30%) 100% no-repeat,
    #201F22;
}
.range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 22px; height: 22px; margin-top: -8.5px;
  border-radius: 50%; background: var(--punch);
  border: 3px solid var(--paper);
  box-shadow: 0 1px 4px rgba(0,0,0,.28);
}
.range::-moz-range-thumb {
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--punch); border: 3px solid var(--paper);
  box-shadow: 0 1px 4px rgba(0,0,0,.28);
}

/* A finger, not a cursor. 24px is the floor a mouse needs, not the one a thumb
   wants, and this is the page's only drag — 52 headcounts across ~290px means
   about 5px a person, so the grab has to be forgiving. The input goes to 44px
   and the thumb to 28px; the painted track stays 5px, so nothing about the
   control looks heavier, it just stops being fiddly. Keyed on the pointer
   rather than the width, because a touchscreen laptop is 1440px wide and still
   has no cursor. */
@media (pointer: coarse) {
  .range { height: 44px; margin-top: .5rem; }
  .range::-webkit-slider-thumb { width: 28px; height: 28px; margin-top: -11.5px; }
  .range::-moz-range-thumb { width: 28px; height: 28px; }
}

.range__ends {
  display: flex; justify-content: space-between; margin-top: .35rem;
  font: 400 .6875rem/1 var(--mono); letter-spacing: .1em; color: #6E717A;
}
.range__hint { margin-top: .8rem; font-size: .8125rem; line-height: 1.5; color: var(--punch-ink); }

.pkg { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: .85rem; }
.pkg label { cursor: pointer; }
.pkg input { position: absolute; opacity: 0; width: 0; height: 0; }
.pkg span {
  display: inline-block;
  border: 1.5px solid var(--control-line); border-radius: 999px;
  padding: .62rem 1.05rem;
  font-size: .875rem; font-weight: 600;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.pkg label:hover span { border-color: var(--ink); }
.pkg input:checked + span { background: var(--coal); border-color: var(--coal); color: #fff; }
.pkg input:focus-visible + span { outline: 3px solid var(--signal); outline-offset: 3px; }

/* ── Receipt ───────────────────────────────────────────────────────────── */
.receipt {
  background: var(--solar); color: var(--ink);
  padding: clamp(1.5rem, 2.6vw, 2.1rem);
  display: flex; flex-direction: column;
}
.receipt .meter { color: #6A5A0A; }
.receipt__label { font: 400 .8125rem/1.6 var(--mono); margin-top: .75rem; }
.receipt__rows { margin-top: 1.1rem; display: grid; gap: .5rem; }
.receipt__rows > div {
  display: flex; justify-content: space-between; gap: 1rem;
  font: 400 .8125rem/1.6 var(--mono);
  border-bottom: 1px solid rgba(35,31,32,.14);
  padding-bottom: .45rem;
}
.receipt__rows dt, .receipt__rows dd { margin: 0; }
.receipt__rows dd { white-space: nowrap; }

/* Was .meter:nth-of-type(2), which counts paragraphs and landed on the label
   under "Estimate" instead. The total's label is the one that needs the air. */
.receipt dl + .meter { margin-top: 1.6rem; }
.receipt__total { font: 900 3.1rem/1 var(--display); letter-spacing: -.03em; margin-top: .3rem; }
.receipt__per { font: 400 .8125rem/1.5 var(--mono); margin-top: .5rem; }
/* Takes no room until it has something to say, the same way .form__status does.
   It used to toggle `hidden`, which is the one thing that stops a message being
   announced reliably — and the announcement now rides on the total's live
   region instead, so the reader gets one sentence rather than two racing ones. */
.receipt__flag:empty { display: none; }
.receipt__flag {
  margin-top: .7rem; font-size: .8125rem; line-height: 1.5; font-weight: 600;
  background: rgba(35,31,32,.1); border-radius: 10px; padding: .55rem .7rem;
}
.receipt__cta {
  margin-top: auto; padding-top: 1.6rem;
  font-weight: 700; font-size: .9375rem;
  text-underline-offset: 4px;
}

@media (max-width: 900px) {
  .pricing__head, .calc { grid-template-columns: 1fr; }
  .mono-note { margin-top: .5rem; }
}

/* ── Tiers ─────────────────────────────────────────────────────────────── */
/* Six tiers, so the track count has to divide by six — a five-up grid left
   Platform access stranded on a row of its own. */
.tiers {
  margin-top: 1.5rem;
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 1rem;
}
.tier {
  background: var(--signal-lift);
  border: 1.5px solid rgba(255,255,255,.16);
  border-radius: var(--r-md);
  padding: 1rem 1.1rem 1.15rem;
}
.tier[data-on="true"] { background: var(--paper); border-color: var(--solar); border-width: 2px; color: var(--ink); }
.tier__name { font-weight: 700; font-size: .875rem; }
.tier__price { font: 900 1.75rem/1.1 var(--display); letter-spacing: -.03em; margin-top: .35rem; }
.tier__price span { font: 500 .8125rem/1 var(--sans); letter-spacing: 0; }
.tier__price--word { font-size: 1.4rem; }
.tier__meta { font: 400 .6875rem/1.6 var(--mono); color: #D3DAF0; margin-top: .5rem; }
.tier[data-on="true"] .tier__meta { color: var(--dim); }

@media (max-width: 1180px) { .tiers { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 680px)  { .tiers { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ══════════════════ GAMES ══════════════════ */
.games { background: var(--paper); padding-block: var(--band-tight); }
.games .prose { color: var(--dim); max-width: 46rem; }

/* Five tiles of heading-plus-paragraph were the page's weakest structure, and
   they had no room for the titles that are the actual proof. Rows instead: the
   styles read down one column, the shelf holds the other. */
.games__grid {
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

.pick { border-top: 1.5px solid var(--line); padding-block: 1.4rem; }
.pick:last-child { padding-bottom: 0; }
.pick h3 { font-size: var(--d3); }
/* No max-width: the column is already the measure at ~68ch, and capping it
   again left every description wrapping two lines short of its own edge. */
.pick > p {
  margin-top: .5rem;
  font-size: .9375rem; line-height: 1.6; color: var(--dim);
}

/* The titles are evidence, so they get weight the description doesn't. Dot
   markers rather than hexes: the hexagon has three jobs already. */
.pick__titles { margin-top: .95rem; display: grid; gap: .35rem; }
.pick__titles li {
  position: relative; padding-left: 1.05rem;
  font-size: .875rem; font-weight: 600; line-height: 1.5;
}
.pick__titles li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--punch-ink);
}

/* Sticky, so the shelf rides the whole list rather than stranding at the top
   of a column twice its height. Clears the sticky nav.
   No frame: the render is cut out on white and the band is white, so it sits
   on the page rather than inside a tile. */
.boxes {
  margin: 0;
  position: sticky; top: 6.5rem;
}
.boxes img { display: block; width: 100%; height: auto; }

@media (max-width: 900px) {
  .games__grid { grid-template-columns: 1fr; gap: 2.25rem; }
  /* Above the list on a phone: the section's job here is to break up two
     serious bands, and it can't do that from the bottom of a long column. */
  .boxes { position: static; order: -1; max-width: 17rem; margin-inline: auto; }
  .picks { margin-top: 0; }
}

/* ══════════════════ HOSTS ══════════════════ */
.hosts {
  background: var(--signal); color: #fff;
  padding-block: var(--band);
}
.hosts__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
.hosts .d2 { max-width: 25ch; }
.hosts .prose { color: #D7DEF3; font-size: 1rem; }

.checks { display: grid; gap: .85rem; }
.checks li {
  background: var(--signal-lift);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--r-sm);
  padding: .95rem 1.1rem 1.05rem;
}
.checks h3 { font-family: var(--sans); font-size: .9375rem; font-weight: 700; letter-spacing: 0; }
.checks p { color: #D3DAF0; font-size: .875rem; line-height: 1.55; margin-top: .3rem; }

@media (max-width: 900px) {
  .hosts__grid { grid-template-columns: 1fr; }
  .hosts .d2 { max-width: none; }
}

/* ══════════════════ FAQ ══════════════════ */
.faq { background: var(--cream); padding-block: var(--band); }

.tabs { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.9rem; }
.tabs button {
  border: 1.5px solid var(--control-line); border-radius: 999px;
  background: transparent; color: var(--ink);
  padding: .62rem 1.15rem;
  font: 600 .875rem/1 var(--sans); cursor: pointer;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.tabs button:hover { border-color: var(--ink); }
.tabs button[aria-selected="true"] { background: var(--coal); border-color: var(--coal); color: #fff; }

/* 36.8px, because the tab sets line-height 1 where the format chips inherit 1.75
   and land at 47. Rather than pad the tab up — which would repaint the pill a
   different shape from every other pill on the page — the hit area is extended
   past it. Inset resolves against the padding box, so the 1.5px border has to be
   paid for on top of the 3.6px of reach: -5.1px nets the 44px. The row gap is
   9.6px, so two wrapped rows still keep 2.4px between their overlays. */
@media (pointer: coarse) {
  .tabs button { position: relative; }
  .tabs button::before { content: ""; position: absolute; inset: -5.1px 0; }
}

/* Full shell width: the rules are the structure here, so they should start
   and stop on the same edges as every other band. Line length is held by
   .qa__a, which is the only part that's actually read in long form. */
.qa { margin-top: 2.2rem; border-top: 1px solid #E4E0D9; }
.qa details { border-bottom: 1px solid #E4E0D9; }
.qa summary {
  display: flex; align-items: center; justify-content: space-between; gap: 2rem;
  padding: 1.15rem .25rem;
  font-weight: 600; font-size: 1rem;
  cursor: pointer; list-style: none;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary::after {
  content: ""; flex: none;
  width: 15px; height: 15px;
  background:
    linear-gradient(var(--punch-ink), var(--punch-ink)) center/100% 2.4px no-repeat,
    linear-gradient(var(--punch-ink), var(--punch-ink)) center/2.4px 100% no-repeat;
  transition: transform .2s ease;
}
.qa details[open] summary::after { transform: rotate(45deg); }
.qa__a { padding: 0 .25rem 1.35rem; max-width: 58rem; }
.qa__a p { color: var(--dim); font-size: .9375rem; line-height: 1.7; }

@media (prefers-reduced-motion: reduce) { .qa summary::after { transition: none; } }

/* ══════════════════ BOOK ══════════════════ */
/* Punch is light, so a ring only reads on it if the ring is dark: navy is
   2.99:1 and white is 2.85:1, both under the 3:1 that 1.4.11 asks of a control
   boundary. Ink is 5.88:1. Inside the form — a white panel on the band — the
   ring goes back to navy. */
.book { background: var(--punch); padding-block: var(--band-loose); --focus: var(--ink); }
.book__grid {
  display: grid;
  grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
.book .prose { color: #3A2216; max-width: 32rem; }
.book__mail {
  display: inline-block; margin-top: 1.6rem;
  font-weight: 700; text-underline-offset: 4px;
}

/* 29.8px of line box, and the only other way to reach the address is the form
   beside it. Padding would work — nothing is painted here — but it would push the
   one-pager box down, so the target is extended instead and the band keeps its
   spacing. */
@media (pointer: coarse) {
  .book__mail { position: relative; }
  .book__mail::before { content: ""; position: absolute; inset: -7.2px 0; }
}

/* Hairline, not tint alone — the Border Rule holds on the orange band too. */
.onepager {
  margin-top: 2.2rem;
  background: rgba(255,255,255,.22);
  border: 1.5px solid rgba(255,255,255,.42);
  border-radius: var(--r-md);
  padding: 1.35rem 1.5rem 1.5rem;
  max-width: 32rem;
}
.onepager h3 { font-family: var(--sans); font-size: 1rem; font-weight: 700; letter-spacing: 0; }
.onepager p { margin-top: .45rem; font-size: .9375rem; line-height: 1.6; color: #45261A; }
.onepager .btn { margin-top: 1.15rem; }

/* ── Form ──────────────────────────────────────────────────────────────── */
.form {
  background: var(--paper);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 2.8vw, 2.25rem);
  display: grid; gap: 1.1rem;
}
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
.form .field label {
  display: block; font-size: .875rem; font-weight: 600; margin-bottom: .45rem;
}
/* The white form panel sits on the orange band, so the ring goes back to navy
   here — white on white would be no ring at all. */
.form { --focus: var(--signal); }

.form input, .form select {
  width: 100%;
  font: 400 1rem/1.2 var(--sans); color: var(--ink);
  background: var(--cream);
  border: 1.5px solid var(--control-line); border-radius: 10px;
  padding: .8rem .9rem;
}
.form select { appearance: auto; }
.form input::placeholder { color: #6E717A; }
.form input:hover, .form select:hover { border-color: var(--ink); }

/* Optional is the exception here, so the marker goes on the two fields that
   are optional rather than on the four that aren't. Naming what's optional
   also answers the question a required-asterisk only raises. */
.form .field label span {
  font-weight: 400; color: var(--dim); font-size: .8125rem;
  margin-left: .3rem;
}

.form__send { display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap; margin-top: .3rem; }
.form__send .btn { flex: none; white-space: nowrap; }
.form__note { flex: 1 1 16rem; font-size: .8125rem; line-height: 1.5; color: var(--dim); }
/* The live region lives in the DOM from load, so it has to take no room until
   it has something to say. :empty does that without `hidden` un-registering it. */
.form__status:empty { display: none; }
.form__status {
  font-size: .9375rem; font-weight: 600;
  background: var(--cream); border-radius: 10px; padding: .75rem .9rem;
}
.form__status[data-state="error"] { background: #FDECE4; color: #A33607; }

@media (max-width: 900px) {
  .book__grid { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
  .form__row { grid-template-columns: 1fr; }
}

/* ══════════════════ FOOTER ══════════════════ */
/* Navy on coal is 2.11:1 — effectively no ring. White is the only thing that
   reads on this band. */
.foot { background: var(--coal); color: #fff; padding-block: clamp(3rem, 5vw, 4.5rem); --focus: #FFFFFF; }
.foot__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 3.5rem);
}
.brand--foot b { color: #fff; }
.foot__blurb { margin-top: 1.1rem; max-width: 32ch; font-size: .9375rem; line-height: 1.7; color: #A8ADB6; }
.foot h4 { font-family: var(--sans); font-size: .9375rem; font-weight: 700; letter-spacing: 0; }
/* The row gap moves inside the link so the target grows without the column
   getting taller: a 15px line in a 36px box, well past the 24px floor. */
.foot ul { margin-top: 1rem; display: grid; gap: .3rem; }
.foot ul a {
  display: inline-block; padding-block: .3rem;
  color: #A8ADB6; text-decoration: none; font-size: .9375rem;
}
.foot ul a:hover { color: #fff; }

/* On a touchscreen the 4.8px trough between two 36px links is the problem, not
   the links: a thumb landing in it hits whichever neighbour is closer. The gap
   goes to zero and its height goes inside the links instead, so the targets
   reach 44px and become contiguous — no dead strip left to mis-tap into. The
   column pays about 21px for that, which a footer can afford. The brand takes
   the same padding back out as negative margin, since it has no neighbour to
   collide with and no reason to move. */
@media (pointer: coarse) {
  .foot ul { gap: 0; }
  .foot ul a { padding-block: .5625rem; }
  .brand--foot { padding-block: .5625rem; margin-block: -.5625rem; }
}

.foot__legal {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: 1.5rem;
  border-top: 1px solid rgba(255,255,255,.12);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 1rem;
  font-size: .8125rem; color: #8A8F98;
}

@media (max-width: 760px) {
  .foot__grid { grid-template-columns: 1fr 1fr; }
  .foot__grid > :first-child { grid-column: 1 / -1; }
}

@media (prefers-reduced-motion: reduce) {
  .btn:hover { transform: none; }
  .skip { transition: none; }
}
