/* ============================================================================
   Isometricland — the two money pages.  ("pay.css")

   Donate and Buy are NOT the same transaction, and the page must not let anyone
   confuse them, so each is built around a different physical object from the
   midway:

     DONATE  ->  the brass TIP JAR on the counter. You drop something in. Nothing
                 comes back out. Gold, the --give nav accent.
     BUY     ->  a dated TICKET with a tear-off stub. It is a claim on something
                 that happens on a named day, and if that day never comes the
                 ticket is worth its face value back. Red, the --buy nav accent.

   Everything below is the same cabinet as the rest of the site (skeuo.css):
   espresso panels, brass rims, embossed cream. Nothing new is invented — the
   ticket and the jar are assembled out of the game's own bevel recipe.
   ============================================================================ */

/* Page accent. Each page sets --accent* once on <main> and every plate, rim,
   glow and chip on that page reads from it, so the two pages are one stylesheet
   with two tunings rather than two near-copies. */
/* NOTE the names: the four plate stops are --acc-p*, NOT --plate-*. .btn in
   skeuo.css declares --plate-* on ITSELF, and a value declared on the element
   beats one inherited from an ancestor — so a plate colour set on .pay could
   never reach a .btn inside it. The accent has to arrive under its own name and
   be handed to --plate-* at the button. */
.pay{
  --accent-hi:#FFE9A8; --accent:#F5C25A; --accent-mid:#C99230; --accent-dk:#7E5A12;
  --acc-pa:#F1C658; --acc-pb:#C68A20; --acc-pc:#9a6a12; --acc-pd:#82570B;
  max-width:1120px; margin:0 auto; padding:0 20px 72px;
}
.pay--buy{
  --accent-hi:#FFC9A6; --accent:#E27040; --accent-mid:#BE3F1E; --accent-dk:#841C0C;
  --acc-pa:#E27040; --acc-pb:#BE3F1E; --acc-pc:#a5300f; --acc-pd:#841C0C;
}

/* ══ HERO ═════════════════════════════════════════════════════════════════
   Same shape as the About page's opening: one line, centred, set big. */
.pay__hero{ text-align:center; padding:54px 0 30px; }
/* The page's own name, hung above the headline as a brass plaque — the same
   in-world nameplate the midway hangs over a ride. It is a PLAQUE and not bare
   letters because bare accent-coloured type on the grass is unreadable: red on
   green is the one pairing this palette must never set as loose text. */
.pay__eyebrow{ margin:0 0 20px; font-size:12px; letter-spacing:.22em; }
.pay__hook{
  margin:0 auto; max-width:22ch;
  font-size:clamp(30px,4.6vw,54px); text-wrap:balance; font-style:italic;
}
.pay__hook .hl{
  color:var(--accent); font-weight:700; font-style:normal;
  text-shadow:0 2px 0 var(--emboss-dark), 0 3px 6px rgba(0,0,0,.5),
              0 0 22px rgba(245,194,90,.45);
}
.pay__lead{
  margin:20px auto 0; max-width:62ch;
  font-size:18.5px; line-height:1.7; text-shadow:0 1px 0 rgba(0,0,0,.45);
}

/* ══ THE EMPTY SLOTS ══════════════════════════════════════════════════════
   The owner writes every word of the persuading. These are the holes those
   words go in, and they are meant to look unmistakably unfinished until he
   fills them — a dashed brass box you cannot mistake for finished copy.
   (skeuo.css already carries .slot / .slot-note for the same purpose.)      */
.wordslot{
  display:block; margin:18px auto; max-width:62ch;
  border:1px dashed var(--brass-mid); border-radius:9px;
  background:rgba(20,10,3,.55);
  padding:14px 18px; text-align:left;
  font-family:var(--font-mono); font-size:13px; line-height:1.6; color:#e9c98a;
}
.wordslot b{ color:var(--brass-highlight); font-weight:700; }
.wordslot--hook{ text-align:center; font-size:14px; }

/* ══ PANELS ═══════════════════════════════════════════════════════════════
   The game's dialog window: espresso plate, brass rim, sunk inner edge. */
.plate{
  /* ⚑ THE PADDING IS A NAMED QUANTITY because something else has to equal it.
     .pay--legal's rule-board bleeds to this plate's inside edge, which means a
     negative margin of exactly this much — and the 760px rule below already
     changes it. Two copies of one number in two rules is how they drift; the
     board asks the plate instead of re-deriving. */
  --plate-py:34px; --plate-px:38px; --plate-r:12px;
  background:linear-gradient(180deg,#2F2114 0%,#1B1108 100%);
  border:1px solid var(--brass-mid); border-radius:var(--plate-r);
  box-shadow:0 0 4px 1px rgba(0,0,0,.5) inset, var(--shadow-deep);
  padding:var(--plate-py) var(--plate-px);
}
.plate + .plate{ margin-top:26px; }
.plate__title{
  margin:0 0 6px; font-size:23px; color:var(--label-hi);
  font-family:var(--font-display); font-weight:700;
  text-shadow:0 2px 0 var(--emboss-dark), 0 3px 6px rgba(0,0,0,.5);
}
.plate p{ margin:0 0 1em; font-size:17px; line-height:1.7; text-shadow:0 1px 0 rgba(0,0,0,.45); }
.plate p:last-child{ margin-bottom:0; }

/* The little brass nameplate that heads a panel, borrowed from the midway.
   The page eyebrow is the same object at a different size, so they share the
   one recipe rather than drifting apart as two near-copies. */
.tag,
.pay__eyebrow{
  display:inline-block; margin:0 0 16px;
  background:linear-gradient(180deg,#3a2410 0%,#25160a 100%);
  border:2px solid var(--accent-mid); border-radius:8px;
  padding:6px 16px; color:var(--label-hi);
  font-family:var(--font-display); font-weight:700; font-size:12.5px;
  letter-spacing:.16em; text-transform:uppercase;
  text-shadow:0 -1px 0 #000, 0 1px 0 rgba(255,233,168,.18);
  box-shadow:0 3px 5px rgba(0,0,0,.55), inset 0 0 9px rgba(0,0,0,.6),
             inset 0 1px 0 rgba(255,233,168,.20);
}

/* ══ THE LEGAL PAGES — /terms and /privacy  (prefix: .pay--legal) ══════════
   Owner, 2026-08-21: "maybe make the text more stylized. I don't like the
   'small' buttons at the top for privacy - terms, should be a screen wide
   banner."

   ── THE OBJECT ─────────────────────────────────────────────────────────────
   ⭐⭐⭐ A PARK POSTS ITS RULES ON A BOARD AT THE GATE. That is the whole design
   argument, and it is why this page of all pages gets to be loud: the terms of
   an amusement park are not a footnote in the real world, they are a painted
   signboard the width of the entrance that you walk past on the way in — RIDE
   POLICIES, PARK RULES, HEIGHT REQUIREMENTS. So every section head stops being
   a small brass nameplate hung on a panel and becomes the board itself,
   spanning the panel edge to edge. The page reads as the front gate rather than
   as fine print, which is exactly the inversion the owner asked for.

   ⚠ SCOPED TO .pay--legal, AND THAT IS NOT TIMIDITY. `.tag` and `.pay__eyebrow`
   share ONE recipe (the rule about 60 lines above) and that recipe is also worn
   by /buy, /board, /donate, /thanks and /admin. Restyling the shared rule would
   have turned every nameplate on the site into a gate board — a fan-out nobody
   asked for, invisible in the diff, and landing on the two pages that take
   money. The modifier is on <main> in terms.html and privacy.html only.

   ⚠ THE ORNAMENTS ARE CSS SHAPES, NEVER CHARACTERS. This codebase has been
   bitten twice: the placement gizmo drew "ENTER ▯" because SKTypeface.Default
   has no U+2713, and part_coastersign.css records the same rule for its own
   ornaments ("both are drawn as PATHS, never as characters — tofu the moment a
   font lacks them"). A diamond is a rotated square, which no font can fail to
   have. (The ✓/✕ already in .compare and .plainlist stay — those are shipped
   and verified rendering, and swapping working glyphs is not this pass's job.)

   ── THE FACE ───────────────────────────────────────────────────────────────
   Rye, the 1880s American wood type the mark itself is set in — skeuo.css
   already loads it for exactly this reason ("a headline set in it reads as the
   park's own signage rather than a web font"). It is an INLINE type, so it
   needs SIZE to read: at 12px letterspaced it turns to mud. The board is wide
   precisely because it can then afford clamp(15px … 21px), and that is the size
   at which Rye's stripes become legible ornament instead of noise.        ══ */

/* ── THE BOARD ─────────────────────────────────────────────────────────────
   Wood ground, brass rails top and bottom, a dark seam at the base where the
   board meets the panel. The gradient is skeuo.css's .wood recipe — the same
   five-stop plank the toolbar wears — rather than a new brown, so the board
   belongs to the same cabinet as the header above it. */
.pay--legal .plate > .tag,
.pay--legal .pay__eyebrow{
  display:flex; align-items:center; justify-content:center; gap:.85em;
  text-align:center;
  border:none; border-radius:0;
  padding:15px 24px;
  background:
    linear-gradient(90deg,
      rgba(0,0,0,0) 0%, rgba(0,0,0,.09) 5%, rgba(0,0,0,0) 10%,
      rgba(0,0,0,.09) 20%, rgba(0,0,0,0) 30%, rgba(0,0,0,.083) 40%,
      rgba(0,0,0,0) 50%, rgba(0,0,0,.09) 60%, rgba(0,0,0,0) 70%,
      rgba(0,0,0,.07) 85%, rgba(0,0,0,0) 100%),
    /* ⚠ A DARKER PLANK THAN THE TOOLBAR, ON PURPOSE AND ON A MEASUREMENT.
       Reusing skeuo.css's .wood ramp verbatim put --wood-highlight (#C39668) at
       the top of the board, and cream lettering across that scored p05 3.63 —
       over the 3.0 bar, but with a worst ink pixel of 2.39, i.e. the tops of
       the letters were under it. The toolbar's plank is light because it is UI
       chrome carrying 12px labels; a gate rule-board is a STAINED board with
       light lettering, which is both the real object and the darker ground the
       type needs. Same five-stop shape, same grain overlay, ramped down. */
    linear-gradient(180deg, #8A5A33 0%, #6D4525 18%,
                    #52331A 55%, #38220F 95%, #291808 100%);
  /* Rails as INSETS rather than borders, so the board's own corner radius is
     not fought by four separate border segments. */
  box-shadow:
    inset 0 1px 0 rgba(255,233,168,.30),
    inset 0 2px 0 rgba(126,90,18,.55),
    inset 0 -2px 0 rgba(126,90,18,.55),
    inset 0 -3px 0 rgba(0,0,0,.55),
    0 3px 7px rgba(0,0,0,.45);
  font-family:"Rye", var(--font-display), Georgia, serif;
  font-weight:400;
  font-size:clamp(15px, 2.05vw, 21px);
  line-height:1.25;
  letter-spacing:.055em;        /* Rye is already wide; .16em shatters it */
  text-transform:uppercase;
  color:var(--label-hi);
  text-shadow:0 -1px 0 rgba(0,0,0,.85), 0 2px 0 var(--emboss-dark),
              0 3px 7px rgba(0,0,0,.55);
}

/* ⚑ THE LABEL IS ITS OWN SPAN, AND THAT IS A MEASUREMENT REQUIREMENT AS MUCH AS
   A TYPOGRAPHIC ONE. tools/contrast_probe.py finds a background by re-rendering
   with the text `visibility:hidden` — point it at the board and it hides the
   board's WOOD as well, so the score compares cream against whatever lies
   behind: grass in the hero, the dark plate in a section. Measured that way the
   same ink on the same ground scored 1.89 and 10.44. ⭐ Two readings 5x apart
   for one colour pair is not a finding about the design, it is the instrument
   reporting that it was aimed at the wrong object. The span is what makes the
   ink hideable without taking its own background with it.

   (It also restores text-wrap:balance, which does nothing on a flex CONTAINER
   whose text is an anonymous item — it needs a real block to balance.) */
.pay--legal .tag__t{ display:block; text-wrap:balance; }

/* The board's finials. A rotated square — no font involved. */
.pay--legal .plate > .tag::before,
.pay--legal .plate > .tag::after,
.pay--legal .pay__eyebrow::before,
.pay--legal .pay__eyebrow::after{
  content:""; flex:none;
  width:10px; height:10px; transform:rotate(45deg);
  background:linear-gradient(135deg, var(--brass-highlight) 0%,
                             var(--brass-light) 45%, var(--brass-mid) 100%);
  box-shadow:0 0 0 1px rgba(0,0,0,.55), 0 1px 2px rgba(0,0,0,.5);
}

/* ── THE BOARD BLEEDS TO THE PANEL'S EDGE ──────────────────────────────────
   The negative margin IS the plate's padding, read from the plate rather than
   retyped — so the 760px rule that shrinks that padding moves the board with it
   and there is no width to keep in step by hand. */
.pay--legal .plate > .tag{
  margin:calc(var(--plate-py) * -1) calc(var(--plate-px) * -1) 30px;
  border-radius:calc(var(--plate-r) - 1px) calc(var(--plate-r) - 1px) 0 0;
}

/* ── THE PAGE'S OWN BOARD ───────────────────────────────────────────────────
   The hero eyebrow is the same object standing free above the headline, so it
   keeps all four corners and spans the whole content column. */
.pay--legal .pay__eyebrow{
  margin:0 0 30px; border-radius:11px;
  box-shadow:
    inset 0 1px 0 rgba(255,233,168,.30),
    inset 0 2px 0 rgba(126,90,18,.55),
    inset 0 -2px 0 rgba(126,90,18,.55),
    0 0 0 1px var(--wood-line),
    0 4px 10px rgba(0,0,0,.5);
  font-size:clamp(16px, 2.4vw, 25px);
  padding:17px 24px;
}

/* ══ THE CLAUSES ══════════════════════════════════════════════════════════
   ⭐ MOST OF THIS PAGE *IS* A NUMBERED LIST, so the numeral is the single
   highest-leverage piece of type on it. A default decimal marker was the one
   element that still said "web page" after the boards went in. Each clause now
   opens with a struck brass medallion — the park token, on the same radial
   recipe .promise__seal already uses (`circle at 36% 30%`), so the coin catches
   light from the same direction as everything else in this cabinet.

   ⚠ list-style:none REMOVES THE SEMANTIC MARKER, so the count comes back as a
   CSS counter on the same <ol>. The markup stays an ordered list — the clauses
   are cross-referenced BY NUMBER in the prose ("the refund right in clause 2"),
   which makes the numbering load-bearing rather than decorative. */
.pay--legal .terms ol{
  list-style:none; margin:0; padding:0; counter-reset:clause;
}
.pay--legal .terms li{
  counter-increment:clause;
  position:relative; margin:0 0 20px; padding-left:56px; min-height:36px;
  font-size:16.5px; line-height:1.72; color:var(--label);
}
.pay--legal .terms li:last-child{ margin-bottom:0; }
.pay--legal .terms li::before{
  content:counter(clause);
  position:absolute; left:0; top:-1px;
  width:36px; height:36px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(circle at 36% 30%,
    #F9DE97 0%, #EFC873 22%, #D2A03F 52%, #A9781F 78%, #6E4E0F 100%);
  color:#2A1806;
  font-family:var(--font-display); font-weight:700; font-size:15.5px;
  letter-spacing:0;
  text-shadow:0 1px 0 rgba(255,240,196,.55);
  box-shadow:0 0 0 1px var(--wood-line), 0 2px 4px rgba(0,0,0,.6),
             inset 0 1px 0 rgba(255,255,255,.5), inset 0 -2px 4px rgba(0,0,0,.28);
}

/* The privacy page's summary wears the same coin, struck with a tick instead of
   a number, so "the short version" reads as the same kind of list as the
   clauses under it rather than as a different component. */
.pay--legal .plainlist li{
  padding-left:46px; min-height:28px; margin-bottom:16px; font-size:16.5px;
}
.pay--legal .plainlist li::before{
  content:"✓";
  left:0; top:1px; width:28px; height:28px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(circle at 36% 30%,
    #F9DE97 0%, #EFC873 22%, #D2A03F 52%, #A9781F 78%, #6E4E0F 100%);
  color:#2A1806; font-size:15px; font-weight:700;
  text-shadow:0 1px 0 rgba(255,240,196,.55);
  box-shadow:0 0 0 1px var(--wood-line), 0 2px 4px rgba(0,0,0,.6),
             inset 0 1px 0 rgba(255,255,255,.5);
}

/* ══ THE PROSE ════════════════════════════════════════════════════════════
   Warmer, larger and on a shorter measure than the site default. A terms page
   is the one page on this site somebody reads top to bottom in one sitting, so
   it is set for READING rather than for scanning — and 17px across a 1040px
   panel is a ~90-character line, well past the point where the eye starts
   losing its place on the way back to the left edge. */
.pay--legal .plate p{
  font-size:17px; line-height:1.78; color:var(--label);
}
.pay--legal .plate > p:first-of-type{ margin-top:0; }

/* ⭐ ONE MEASURE, AND IT IS CENTRED IN THE BOARD RATHER THAN LEFT-HUGGING.
   The panel is ~1040px wide because the RULE-BOARD wants to be that wide; the
   prose does not. At 17px that panel is a ~122-character line, and comfortable
   reading tops out around 75-85 — so a full-width paragraph here is a line the
   eye loses on the way back to the left edge.

   The first cut capped only <p> and left the clause <li>s running the full
   width, which was worse than either choice on its own: the same panel showed a
   700px paragraph above a 1040px clause, and the ragged right edge read as text
   that had run out rather than as a decision. One measure for both, and
   `margin-inline:auto` centres the column so the slack sits evenly on both
   sides — a printed page inside a signboard, which is the object this is.

   ⚠ .compare and .plats are deliberately NOT in this list. They are figures,
   not prose: a two-column comparison and a platform row both want the whole
   panel, and capping them would strand them against the left edge. */
.pay--legal .plate p,
.pay--legal .terms ol,
.pay--legal .plainlist{
  max-width:80ch; margin-left:auto; margin-right:auto;
}

/* The lead under the headline gets the display face and a little air — it is
   the one paragraph on the page that is a VOICE rather than a term. */
.pay--legal .pay__lead{
  font-family:var(--font-display);
  font-size:19.5px; line-height:1.72; max-width:58ch; color:var(--label-hi);
}
.pay--legal .pay__hook{ max-width:26ch; }

/* ══ NARROW ═══════════════════════════════════════════════════════════════ */
@media (max-width:760px){
  /* The finials go first. A 10px diamond either side of a wrapped two-line
     board reads as two stray specks, and the board's job is the WORDS. */
  .pay--legal .plate > .tag::before,
  .pay--legal .plate > .tag::after,
  .pay--legal .pay__eyebrow::before,
  .pay--legal .pay__eyebrow::after{ display:none; }
  .pay--legal .plate > .tag,
  .pay--legal .pay__eyebrow{ padding:13px 16px; letter-spacing:.03em; }

  /* The coin shrinks with the measure; a 36px medallion beside a 300px column
     is a bullet the size of the text it introduces. */
  .pay--legal .terms li{ padding-left:44px; font-size:16px; }
  .pay--legal .terms li::before{ width:30px; height:30px; font-size:14px; }
  .pay--legal .plainlist li{ padding-left:38px; font-size:16px; }
  .pay--legal .plainlist li::before{ width:24px; height:24px; font-size:13px; }
  .pay--legal .plate p{ font-size:16.5px; }
  .pay--legal .pay__lead{ font-size:17.5px; }
}

/* ══ THE TICKET (buy.html) ════════════════════════════════════════════════
   Body on the left carries what the ticket is FOR; the stub on the right
   carries the price and the tear. They are divided by a real perforation. */
.ticket{
  display:grid; grid-template-columns:1fr 400px;
  margin:12px 0 0;
  background:linear-gradient(180deg,#33230F 0%,#1D1207 100%);
  border-radius:14px;
  box-shadow:0 0 0 1px var(--wood-line), 0 0 0 3px var(--accent-mid),
             0 0 0 4px var(--wood-line), 0 16px 34px rgba(0,0,0,.55);
}
.ticket__body{ padding:34px 36px 32px; min-width:0; }

/* ── THE MARK ON THE TICKET ───────────────────────────────────────────────
   The ticket carries the LOGO, not the word set in a UI face — the same brass
   wordmark the nav wears, with the little park behind it cut away.

   ⚑ IT IS AN <img>, AND THAT IS THE WHOLE DESIGN. The nav lockup is INLINE
   SVG in every page (tools/stamp_logo.py puts it there, because the per-letter
   hop cannot be expressed against an image), and its ids — hkg0..hkg12,
   hkbrass, hkgloss — are DOCUMENT-GLOBAL. A second inline copy in the same
   document makes all 468 of its `<use href="#hkgN">` ambiguous, and the browser
   resolves each to whichever element is FIRST in tree order. Today that is the
   nav, so the damage would land here and land silently; move a ticket above a
   header on some future page and the polarity flips and the NAV breaks instead.
   An <img> is a separate document, so the collision cannot happen at all.

   Two more things come free from that choice: js/logo.js binds with
   querySelectorAll('svg.lg') and cannot reach inside an image, so the ticket
   mark is inert (the hop is a nav affordance, not a ticket one); and
   stamp_logo.py's LIVE counters — which are EQUALITIES on whole-file counts,
   `svg.lg == 1`, `lg-wm-face == 13` — stay satisfied, where an inline copy
   would fail five of its seven rows.

   The file is DERIVED, never hand-cut: `python tools/make_wordmark.py` re-reads
   header_lockup.svg after every re-forge. A pasted snapshot would sit here
   showing last week's letterforms beside a nav showing this week's, on one
   screen, with nothing to report it.

   ⚠ THE ASPECT IS NOT THE NAV'S. Scene-free the mark is ~7.04:1, where the
   full lockup is 3.32:1 — a box sized for the nav's ratio is more than twice
   too tall. The width/height attributes in the markup carry the derived box so
   the row reserves the right space before the image loads. */
.ticket__name{ margin:0 0 20px; text-align:center; }
.ticket__logo{
  display:block; width:100%; max-width:470px; height:auto; margin:0 auto;
  filter:drop-shadow(0 3px 7px rgba(0,0,0,.55));
}

/* ── THE FLOURISHES ───────────────────────────────────────────────────────
   A gold printer's ornament over the mark and its mirror under it, so the
   wordmark reads as SET on the ticket rather than dropped on it.

   ⚑ ONE ORNAMENT, DRAWN ONCE, USED TWICE. The pair is a `<defs>` group plus two
   `<use>`, the second flipped `scaleY(-1)` — not two hand-authored paths. A
   mirrored pair authored twice is a pair that stops being a mirror the first
   time one half is tweaked, and this ornament is symmetrical enough that
   nobody would notice for weeks.

   ⚑ EVERY ID IN IT CARRIES THE `tkf-` PREFIX. buy.html ALREADY inlines the nav
   lockup, whose ids (hkg0..hkg12, hkbrass, hkgloss) are document-global; an
   unprefixed `gold` or `orn` gradient here is exactly how a `url(#…)` starts
   resolving to somebody else's paint. Same reason give.css's components state
   the rule for their own namespaces.

   The width is tied to the mark's, not to the column's, so the three pieces
   stay one stacked object at every width. */
.flourish{
  display:block; width:100%; max-width:470px; height:auto; margin:0 auto;
  filter:drop-shadow(0 2px 3px rgba(0,0,0,.5));
}
/* Pulled in tight against the mark. The ornament's box carries ~13 units of
   padding above and below its own wave (so the curls are never clipped), which
   at render size is real empty space — without the negative margins the three
   pieces read as three stacked objects instead of one framed one. */
.flourish--top{ margin-bottom:-10px; }
.flourish--bot{ margin-top:-8px; }

/* ── THE TICKET BODY'S TWO COLUMNS ────────────────────────────────────────
   The pre-order line, the platform slider and the Android/iOS row sit left; the
   calendar fills the space on their right.

   ⛔ IT IS FLEX-WRAP, NOT A GRID WITH A BREAKPOINT, AND THAT IS THE WHOLE FIX.
   The first build was `grid-template-columns: 1fr auto` collapsing at the 760px
   phone breakpoint. But this row does not live in the viewport — it lives in
   .ticket__body, which is `1fr` of the ticket's own `1fr 360px`. So between
   about 768px and 1000px of VIEWPORT the row still had two columns while its
   CONTAINER had already shrunk to 368px, and the fixed 230px calendar ate all
   of it: the slider measured 392 -> 296 -> 172 -> 92 -> **40px**, with three OS
   labels overflowing a control narrower than one of them.

   ⭐ A MEDIA QUERY ASKS THE VIEWPORT; THIS ROW NEEDED TO ASK ITS OWN BOX. Every
   viewport breakpoint that could fix it is a guess about the stub's width, the
   page padding and the max-width all at once — change any one and the guess is
   wrong again. `flex-wrap` asks the real question directly: the calendar drops
   to its own line exactly when 320 + 26 + 230 no longer fits, whatever the
   viewport is doing. It needs no query, and it cannot go stale when the stub
   is resized. (Container queries would also work; wrap is simpler and has no
   support floor at all.)

   `margin-inline:auto` on the side costs nothing while the two are side by side
   — the main column's flex-grow has already eaten the free space — and centres
   the calendar the moment it wraps onto a line of its own. */
.tk-cols{
  display:flex; flex-wrap:wrap; align-items:flex-start; gap:18px 26px;
}
.tk-cols__main{
  flex:1 1 320px; min-width:0;      /* 320px is the slider's comfortable floor:
                                       three cells of ~104px, no label wrap */
  display:flex; flex-direction:column; gap:16px;
}
.tk-cols__side{ flex:0 1 auto; min-width:0; margin-inline:auto; }

/* The perforation: a dashed brass seam with a punched hole at each end. The
   holes are filled with the grass the page sits on, so they read as cut clean
   through the card rather than printed on it. */
/* ⚑ THE STUB IS WHAT SETS THE TICKET'S HEIGHT, so its padding is a lever on the
   OTHER column. Its content (shield + roundel) runs ~30px taller than the body
   column's does, so the grid stretches the body to match and the surplus lands
   as dead card under the calendar. When the creed gained its shield the stub
   grew 36px and every one of those pixels showed up as blank space on the LEFT
   — the owner's own complaint, moved rather than fixed. The padding and the gap
   were trimmed by the same amount, so the card is the height it always was.
   Both ornaments carry their own transparent margin (the medallion's ring
   starts 23 units inside its box, the shield's pendant 8), so 20/8/18 here
   reads as roughly 43/37/41 on screen. */
.ticket__stub{
  position:relative; padding:20px 26px 18px; text-align:center;
  border-left:2px dashed rgba(201,146,48,.55);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px;
}
.ticket__stub::before,
.ticket__stub::after{
  content:""; position:absolute; left:-11px; width:20px; height:20px; border-radius:50%;
  /* A hole has to show the ground THROUGH it, so it carries the body's own
     grass — same tile, same size, and crucially the same background-attachment:
     fixed. Fixed positions a tile against the VIEWPORT, not the element, so the
     diamonds inside the hole land on exactly the same grid as the diamonds
     around the ticket and the card reads as punched clean through. A flat
     --grass-dk fill instead of the tile is a green DOT sitting on the card:
     the tile is two greens, so a single one of them never disappears. */
  background-color:var(--grass-dk);
  background-image:var(--grass-tile);
  background-size:64px 32px;
  background-attachment:fixed;
  box-shadow:inset 0 2px 4px rgba(0,0,0,.8), inset 0 -1px 0 rgba(255,233,168,.10);
}
.ticket__stub::before{ top:-11px; }
.ticket__stub::after { bottom:-11px; }

/* ── THE PRICE, IN ITS MEDALLION ──────────────────────────────────────────
   The price and "one time" ride inside a blue disc with a brass ring — the
   painted price roundel on a midway booth.

   ⚑ THE DISC IS A SQUARE GRID CELL, NOT A PADDED PILL. `aspect-ratio:1` with
   `display:grid; place-items:center` is what keeps it a CIRCLE: pad a box until
   it looks round at one font size and it is an egg at the next, and this text
   changes size twice (the phone rule below, and again if the price ever does).

   ⚑ THE BLUE IS LIT FROM THE TOP-LEFT, LIKE EVERY OTHER ROUND THING IN THIS
   CABINET. .promise__seal's brass disc uses `radial-gradient(circle at 36% 30%)`
   and so does this, or the ticket would carry two spheres lit from different
   suns. Only the hue differs — blue, so the one control that takes money does
   not read as more brass on a brass ticket.

   ⚑ AND THE NUMERALS KEEP THEIR EMBOSS. The temptation on a coloured disc is a
   flat white; the dark under-shadow is what stops "12" dissolving into the
   mid-blue at the centre of the gradient. */
/* The frame and the roundel are ONE object: the medallion sits behind, and the
   disc is a PERCENTAGE of it (208/340 = 61.2%) rather than a fixed 208px — so
   when the rig narrows on a phone the disc keeps landing exactly in the frame's
   hole instead of drifting out of it. */
.price-rig{
  position:relative; width:340px; max-width:100%; aspect-ratio:1;
  margin:0 auto; display:grid; place-items:center;
}
.price-rig__frame{
  position:absolute; inset:0; width:100%; height:100%; pointer-events:none;
  filter:drop-shadow(0 3px 6px rgba(0,0,0,.55));
}
.price{
  position:relative;
  display:grid; place-items:center; align-content:center;
  width:61.2%; aspect-ratio:1; margin:0; border-radius:50%;
  font-family:"Rye", Georgia, serif; color:#FFF7DD;
  line-height:.9; letter-spacing:.01em;
  background:
    radial-gradient(circle at 36% 30%, #7FC2F2 0%, #2F79C9 34%, #1B4C93 66%, #0E2A5C 100%);
  box-shadow:
    0 0 0 3px var(--brass-mid),
    0 0 0 4px var(--wood-line),
    0 0 0 6px rgba(255,233,168,.30),
    inset 0 3px 10px rgba(255,255,255,.30),
    inset 0 -8px 18px rgba(0,0,0,.45),
    0 8px 20px rgba(0,0,0,.55),
    0 0 26px rgba(79,166,255,.22);
  text-shadow:0 2px 0 rgba(6,22,48,.85), 0 3px 0 rgba(0,0,0,.45), 0 6px 14px rgba(0,0,0,.55);
}
/* Sized off the RIG, not the viewport: cqw is a percentage of the container, so
   the numerals shrink in step with the disc they sit in. Without a container
   query the px sizes stay put while the disc scales and the price overflows its
   own roundel at the first narrow width. */
.price-rig{ container-type:inline-size; }
.price__cur{ font-size:9.4cqw; vertical-align:top; position:relative; top:.42em; margin-right:.04em; }
.price__int{ font-size:23.5cqw; }
.price__dec{ font-size:9.4cqw; vertical-align:top; position:relative; top:.42em; }
.price__note{
  display:block; margin-top:4px;
  font-family:var(--font-display); font-size:3.5cqw; letter-spacing:.18em;
  text-transform:uppercase; color:#CFE6FF; text-shadow:0 1px 0 rgba(6,22,48,.9);
}
/* The stub carries the creed and the price, and no button: the one action on
   this ticket is the pill in the left column. */

/* ══ THE CALENDAR ═════════════════════════════════════════════════════════
   A little November 2026 wall calendar in the space right of the pre-order
   line, with release day ringed in green — and the day after ringed in red,
   labelled, in handwriting, "Some other game."

   ⚑ THE JOKE IS THE POINT, SO IT HAS TO LOOK HAND-DONE. Two perfect CSS
   circles read as UI; what sells it is a marker loop that overshoots where it
   closes, sits a couple of degrees off square, and is drawn in one stroke.
   That is why both rings are SVG paths that wrap ~1.05 turns with a tail,
   rather than `border-radius:50%`.

   ⚑ THE HANDWRITING IS MEASURED, NOT ASSUMED. There is no script face in
   website/assets/fonts, so this is a SYSTEM stack — and a stack that silently
   falls through to Trebuchet would kill the gag with no error anywhere, which
   is the failure mode this project has already been bitten by. Measured on
   2026-08-18 by canvas width-difference (document.fonts.check() cannot see
   system faces): Ink Free 296px, Segoe Script 357px and Segoe Print 358px all
   resolve on Windows; Bradley Hand / Marker Felt are the macOS entries; and the
   generic `cursive` resolves to Comic Sans MS, which is the floor everywhere.
   Every rung of the stack is a genuine handwriting face — there is no rung that
   quietly gives up and returns a UI sans.

   ⚑ AND THE ARROW IS ONE OVERLAY IN THE GRID'S OWN COORDINATES. The tempting
   build is a rotated border on the 19 cell plus a separate line element; that
   needs the cell's pixel position, which changes with the font, the zoom and
   the platform. Instead the cells are a FIXED 30x26 grid, the overlay carries
   `viewBox="0 0 210 182"` — exactly 7x30 by 7x26 — and the arrow's endpoint is
   arithmetic on that grid (the 19 is column 4, row 3, so its centre is
   4.5x30=135, 2.5x26+HEAD). Nothing is eyeballed and nothing drifts. */
.cal{
  position:relative; width:230px; flex:none;
  padding:20px 10px 10px; border-radius:10px;
  background:linear-gradient(180deg,#F6EEDC 0%,#E7DAC0 100%);
  box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-mid),
             0 6px 16px rgba(0,0,0,.5);
}
/* the two punch holes of a wall calendar, so it reads as an object */
.cal::before,
.cal::after{
  content:""; position:absolute; top:5px; width:7px; height:7px; border-radius:50%;
  background:#2A1806; box-shadow:inset 0 1px 1px rgba(0,0,0,.8);
}
.cal::before{ left:46px; }
.cal::after { right:46px; }

.cal__head{
  margin:0 0 6px; text-align:center;
  font-family:"Rye", Georgia, serif; font-size:15px; line-height:1.1;
  color:#8E2413;                        /* the red a cheap calendar prints in */
  text-shadow:0 1px 0 rgba(255,255,255,.6);
}
.cal__grid{
  width:100%; border-collapse:collapse; table-layout:fixed;
  font-family:var(--font-display); font-size:12px; color:#3A2A16;
}
.cal__grid th{
  width:30px; height:16px; padding:0; font-size:9.5px; font-weight:700;
  letter-spacing:.04em; color:#8A6A3A; text-transform:uppercase;
}
.cal__grid td{
  width:30px; height:26px; padding:0; text-align:center; vertical-align:middle;
  position:relative; font-variant-numeric:tabular-nums;
}
.cal__grid td:empty{ visibility:hidden; }

/* The marker rings. Absolutely centred on their own cell, so they cannot drift
   from the number they ring however the grid is laid out. */
.cal__ring{
  position:absolute; left:50%; top:50%; width:30px; height:26px;
  transform:translate(-50%,-50%); pointer-events:none;
}
.cal__ring svg{ display:block; width:100%; height:100%; overflow:visible; }
.cal__d--go{ font-weight:700; color:#14532A; }
.cal__d--no{ font-weight:700; color:#7A1E0F; }

/* ── THE POINTER AND THE NOTE ─────────────────────────────────────────────
   ⛔ THE ARROW LIVES IN THE GRID'S BOX, NOT THE CARD'S. The first build put it
   on `.cal` with `inset:0` and a `viewBox="0 0 130 96"`. An <svg> with the
   default `preserveAspectRatio` SCALES ITS VIEWBOX TO FIT its element box and
   centres the result — so those coordinates were silently remapped onto a
   230x190 card, and the arrow came out enlarged, re-centred and pointing
   through the "November 2026" header instead of at the 19.

   ⭐ The lesson generalises: a viewBox is not a pixel grid until the element
   box has the SAME aspect. So the overlay is now a child of .cal__gridwrap,
   whose box IS the table — 7x30 wide by (16 head + 5x26) tall = 210x146 — and
   the viewBox says exactly that. Now "the 19 is at column 4, row 3, so its
   centre is 4.5x30=135, 16+2.5x26=81" is arithmetic that lands, and it stays
   landed if the note or the header ever changes height.

   `overflow:visible` is what lets the tail run BELOW the grid to meet the note
   without a second coordinate system. */
.cal__gridwrap{ position:relative; }
.cal__arrow{
  position:absolute; inset:0; overflow:visible; pointer-events:none;
}
.cal__hand{
  margin:16px 0 0 8px;
  font-family:"Ink Free","Segoe Script","Bradley Hand","Marker Felt","Segoe Print","Comic Sans MS",cursive;
  font-size:17px; line-height:1.05; color:#B8321C;
  transform:rotate(-3.5deg); transform-origin:left center;
  text-shadow:0 1px 0 rgba(255,255,255,.45);
}

/* ══ THE PRE-ORDER LINE ═══════════════════════════════════════════════════
   "Pre-Order — Game releases November 18th, 2026", set as a painted sign
   rather than as a sentence: CHANNEL LETTERS, the dimensional kind bolted to a
   midway board — a cream face, a hairline trim cap, and a red can standing off
   the panel behind it.

   ⚑ THE FACE IS RYE, AND IT HAD TO BE CHECKED RATHER THAN CHOSEN. Rye is the
   1880s American wood type the wordmark itself is cut from, and — the part that
   decides it — its @font-face is in skeuo.css (:47), which buy.html links.
   The obvious alternative, Lilita One, is the face the donate page's Googie
   marquee uses; its only @font-face is give.css:639, and buy.html does NOT link
   give.css. `font-family:"Lilita One"` here would silently fall through to
   Trebuchet with no error in the console and no sign in review — visible only
   to the owner, which is the worst class of bug this page could ship.

   ⚑ THE CAN IS A CHAINED SHADOW, NOT A PARALLEL LIST. Each offset is expressed
   against the previous one, so six .035em steps build ONE solid .175em
   extrusion whose bands run nearest-the-face first. A parallel list of the same
   six offsets produces six separate ghosts instead of a side — the same trap
   part_continue.css records for the donate marquee's letters.

   ⚑ NO background-clip:text HERE. text-shadow paints ABOVE an element's own
   background, so a clipped gradient face would put the can's colour on TOP of
   the letters as smears — source reads perfectly, render is mud. The face is a
   flat cream and the depth is all shadow. */
/* ── THE PANEL THE LINE SITS IN ───────────────────────────────────────────
   A reddish-tan plate with a silver bezel, so the one sentence the ticket makes
   reads as a plaque rather than as loose type on the card.

   ⚑ THE SILVER IS A REAL BEZEL, NOT A FLAT BORDER COLOUR. `box-shadow` can only
   spread solid colours, so a chrome ring needs the two-background trick: the tan
   is painted to the PADDING box and the chrome gradient to the BORDER box, with
   the border itself transparent. That gets a proper metal horizon — bright above
   the line, a dark band at it, a warm return below — instead of one grey that
   reads as a disabled outline. Same chrome recipe the donate midway uses for its
   rails, restated here because buy.html does not link give.css.

   ⚠ background-clip is the load-bearing part; without `padding-box`/`border-box`
   both layers paint to the same box and the tan covers the chrome entirely. */
/* ⚑ THE PILL IS THE BUTTON. It used to be a caption, with a disabled "Buy" and
   a separate "Pre-Order" over in the stub — which put a pre-order on the left of
   the ticket and a second one on the right, saying the same thing twice. There
   is one action on this page now and this is it.

   It is an <a>, not a <button>, because it navigates to a checkout. Everything
   that makes it feel like a control — the press, the lift, the focus ring — is
   here; the platform it carries is appended by js/pay.js. */
.po{
  position:relative;                 /* the stamp is absolute inside it */
  display:block; text-decoration:none; cursor:pointer; text-align:left;
  transition:transform .12s ease, box-shadow .12s ease, filter .12s ease;
  /* ⛔ ONE SHORTHAND, NOT A LONGHAND FOLLOWED BY ONE. This first read
     `padding-right:132px` on its own line and then `padding:15px 20px 17px`
     three lines later — and a shorthand RESETS every longhand before it, so the
     stamp lane and the bottom margin were both silently dead. Nothing errors,
     nothing warns; the only tell was the date text measuring 85px UNDERNEATH
     the stamp and the pill sitting flush against the platform label.
     The right-hand 132px IS the stamp's lane. */
  margin:0 0 18px; padding:15px 132px 17px 20px;
  border:3px solid transparent; border-radius:13px;
  background:
    linear-gradient(180deg,#96583A 0%,#7C4327 52%,#5C2F17 100%) padding-box,
    linear-gradient(180deg,#FFFFFF 0%,#E6F1F5 16%,#B6CBD4 42%,#7A929C 49%,
                    #566A73 52%,#C8DBE2 62%,#F6FBFD 84%,#A9BFC8 100%) border-box;
  box-shadow:
    0 0 0 1px var(--wood-line),
    inset 0 1px 0 rgba(255,236,214,.26),
    inset 0 -6px 14px rgba(0,0,0,.30),
    0 6px 16px rgba(0,0,0,.45);
}
.po:hover{
  filter:brightness(1.09);
  box-shadow:
    0 0 0 1px var(--wood-line),
    inset 0 1px 0 rgba(255,236,214,.32),
    inset 0 -6px 14px rgba(0,0,0,.28),
    0 9px 22px rgba(0,0,0,.5), 0 0 22px rgba(226,112,64,.22);
}
/* A press has to MOVE, or a big plate reads as a picture of a button. */
.po:active{ transform:translateY(2px); filter:brightness(.96); }
.po:focus-visible{ outline:3px solid var(--brass-highlight); outline-offset:3px; }

/* ── IT IS A <button> NOW, AND A BUTTON IS NOT AN ANCHOR ──────────────────
   The pill was an <a> for as long as its href was a placeholder. It performs an
   action now — js/pay.js POSTs for a Stripe Checkout Session and redirects — so
   it is a <button>, and three UA defaults have to be undone that an <a> never
   had: a button does NOT fill its container (it shrink-wraps), does NOT inherit
   the page's font (it takes the OS control font), and carries a platform
   appearance that would repaint the whole plate on iOS.

   ⚠ `font:inherit` and not a font stack. .po__lead and .po__date set Rye on
   themselves, but the button's own box is what the `clamp()`s inside them
   resolve against — and a button that silently reverted to 13px system UI would
   leave both children reading from the wrong cascade. */
button.po{
  width:100%; font:inherit; color:inherit;
  -webkit-appearance:none; appearance:none;
}
/* Disabled means "the round trip to Stripe is in flight", which is a WAIT, not
   a refusal — so the cursor says progress rather than not-allowed, and the
   plate dims without moving. Suppressing the hover lift matters: a plate that
   still brightens under the pointer reads as pressable and gets pressed again. */
button.po[disabled]{ cursor:progress; filter:saturate(.5) brightness(.82); transform:none; }
button.po[disabled]:hover{ filter:saturate(.5) brightness(.82); box-shadow:
  0 0 0 1px var(--wood-line),
  inset 0 1px 0 rgba(255,236,214,.26),
  inset 0 -6px 14px rgba(0,0,0,.30),
  0 6px 16px rgba(0,0,0,.45); }

/* ── WHAT THE MONEY BUYS ──────────────────────────────────────────────────
   Two lines above the pill. Deliberately quiet — this is the ticket's small
   print, sitting between a wordmark and a plate that both shout, and it earns
   its place by being the only thing on the page that says what the product IS.
   The lead of each line is brass so the eye can take both facts in one pass
   without reading either sentence. */
.tk-what{
  margin:0 0 8px; text-align:center; text-wrap:balance;
  font-size:15px; line-height:1.55; color:#E4D2B0;
  text-shadow:0 1px 0 rgba(0,0,0,.55);
}
.tk-what--plats{ margin-bottom:20px; }
.tk-what__l{ color:var(--brass-highlight); font-weight:700; }

/* ── WHEN THE TILL WILL NOT OPEN ──────────────────────────────────────────
   Hidden until js/pay.js has something to say. Coral rather than brass because
   it is the one message on this ticket that is not good news, and it must not
   be mistaken at a glance for more of the sales copy. */
.po-err{
  margin:-8px 0 16px; padding:11px 14px;
  border:1px solid #8A3A22; border-radius:9px;
  background:rgba(120,40,20,.30);
  font-size:14px; line-height:1.55; color:#FFD9C6;
}
.po-err a{ color:#FFE9A8; }


/* ── THE PILL AND ITS STAMP ───────────────────────────────────────────────
   A round rubber stamp, inked in the same coral as the TBA and the sold-out
   stamp, tilted the way a hand-stamp lands. Two rings and a hairline, because
   one ring is a badge and two rings are a stamp. */
/* ⚑ ON the button, at its right end — a hand-stamp landing on a ticket, tilted
   the way a hand lands it. pointer-events:none so the decoration can never
   swallow the click it is advertising. */
.po-stamp{
  position:absolute; right:16px; top:50%;
  width:96px; height:96px; border-radius:50%; pointer-events:none;
  display:grid; place-items:center; text-align:center;
  transform:translateY(-50%) rotate(-13deg);
  color:#FFD9C4; opacity:.95;
  border:3px solid #FFCDB5;
  box-shadow:inset 0 0 0 4px #FFCDB5;
  font-family:var(--font-display); font-weight:700; line-height:1.05;
  font-size:16px; letter-spacing:.09em; text-transform:uppercase;
  text-shadow:0 1px 2px rgba(0,0,0,.55);
}
.po-stamp span{ display:block; }
.po-stamp em{ display:block; font-style:normal; font-size:11px; letter-spacing:.14em; opacity:.85; }

/* ── THE CREED ────────────────────────────────────────────────────────────
   The donate page's three promises, struck as an arched sign over the price.

   ⚑ IT IS INLINE SVG BECAUSE OF THE FONT. Rye is a document @font-face, and an
   <img>-referenced SVG is a SEPARATE DOCUMENT that cannot see it — the motto
   would fall back to a UI serif silently, with nothing in the console and no
   sign in review. The same trap this file already records for Lilita One.

   Each line is drawn twice: a dark copy pushed down for the emboss, then the
   face with a SILVER stroke sitting behind a GOLD fill. paint-order:stroke puts
   the metal behind the letter rather than on top of it.

   ⛔ AND THE STROKE IS HAIRLINE-THIN ON PURPOSE — 0.9, not the 2.6 this shipped
   with for one render. RYE IS AN INLINE FACE: its glyphs carry nested contours
   (the white inline down the middle of each stem), and a stroke strokes EVERY
   one of them, so a heavy weight floods the letter from the inside out and the
   whole motto turns to silver mush. This project has the trap written down
   already; I walked into it anyway, and only rendering the four candidates side
   by side settled it. Alfa Slab One and Limelight flood the same way at 2.2 —
   the answer was not a different face, it was a thinner keyline. */
/* ── THE SHIELD THE CREED SITS IN ─────────────────────────────────────────
   The frame and the motto are ONE object, stacked absolutely in a shared box —
   the same construction .price-rig uses for the roundel a few lines below, and
   for the same reason: the ornament is an <img> (its ids stay in their own
   document) while the thing it frames is not.

   ⚑ BOTH DRAW IN THE SAME 340 × 230 VIEWBOX, 1:1. That is not a coincidence to
   be tidied up later — tools/make_creed_shield.py ASSERTS that every letter
   clears every piece of gold by at least nine units, and that assertion is only
   worth anything while the two documents share one coordinate system. Scale the
   rig, not one half of it.

   ⚑ ASPECT-RATIO, NOT A HEIGHT. The rig is a fixed 340 wide on the desktop stub
   and shrinks to the column on a phone; a pinned pixel height would let the
   frame and the text come apart at exactly the widths nobody tests. */
.creed-rig{
  position:relative; width:340px; max-width:100%; aspect-ratio:340 / 230;
  margin:0 auto;
}
.creed-rig__frame{
  position:absolute; inset:0; width:100%; height:100%; pointer-events:none;
  filter:drop-shadow(0 3px 6px rgba(0,0,0,.55));
}
.creed{ position:absolute; inset:0; display:block; width:100%; height:100%; }
.creed text{
  font-family:"Rye", Georgia, serif; font-size:16.5px; letter-spacing:.01em;
  text-anchor:middle;
}
/* the emboss copy is a RED-black now, not a brown one: on the maroon body a
   brown shadow reads as a second, muddier colour under every letter, where a
   near-black of the plaque's own hue reads as depth */
.creed .cr-sh{ fill:#2A0709; opacity:.92; transform:translateY(2.1px); }
.creed .cr-tx{
  fill:url(#cr-gold);
  stroke:url(#cr-silver); stroke-width:0.78; stroke-linejoin:round;
  paint-order:stroke;
}
.creed .cr-hi{ fill:url(#cr-hi); }
/* the motto's second half, a step smaller so it reads as the same sentence
   continuing rather than as a fourth promise */
.creed .cr-sm{ font-size:14px; }
.creed .cr-sh .cr-hi{ fill:#2A0709; }
.po__lead{
  display:block;
  font-family:"Rye", Georgia, serif;
  font-size:clamp(26px,3.4vw,38px); line-height:1.02; letter-spacing:.01em;
  color:#FFF6E2;
  /* the can is darker than it was: on the new tan ground the old #96280F sat
     only a step away from the panel and the letters lost their edge */
  text-shadow:
    .035em .035em 0 #6E1A09,
    .07em  .07em  0 #5C1406,
    .105em .105em 0 #4A0F04,
    .14em  .14em  0 #380B02,
    .175em .175em 0 #260701,
    .19em  .21em  10px rgba(0,0,0,.75);
}
/* The date is the same sign at reading size — still Rye, so the two lines are
   one object, but cut in brass instead of enamel so it reads as the sub-line
   and not as a second headline competing with the first. */
.po__date{
  display:block; margin-top:9px; text-wrap:balance;  /* never orphan "2026" */
  font-family:"Rye", Georgia, serif;
  font-size:clamp(16px,1.9vw,21px); line-height:1.25; color:#FFE6B4;
  text-shadow:0 1px 0 #6B470C, 0 2px 0 #4C3208, 0 4px 8px rgba(0,0,0,.6);
}

/* ══ THE PLATFORM SLIDER ══════════════════════════════════════════════════
   Windows / Mac / Linux, as a three-position slider with a brass thumb that
   travels to the one you picked.

   ⚑ THREE REAL <input type="radio">, RESTYLED — NOT DIVS PRETENDING. This file
   already states the doctrine, four screens down, for the consent box: "a real
   checkbox, restyled — not a div pretending. Keyboard, screen readers and form
   semantics all come free that way, and consent is the last control on the page
   that should be improvised." A purchase PLATFORM is the same class of control,
   on the same page, and it buys the entire keyboard contract — arrow keys, Home
   and End, roving focus, the group's accessible name from the <legend>, forced-
   colours rendering, and a form value — for zero lines of JavaScript. There is
   no keyboard code here and therefore none to get wrong.

   ⚑ THE INPUT IS NOT display:none. A hidden input is not focusable, which
   throws away everything above. It is laid over its own cell at opacity 0 with
   pointer-events:none, so the LABEL takes the pointer while the INPUT keeps the
   focus ring and the keyboard.

   ⚑ THE LABELS ARE WORDS, NOT MARKS. The tempting version puts the Windows
   flag, the Apple logo and a penguin in the three cells. Two of those three are
   trademarks, on a page that takes money; the penguin is not Linux's mark to a
   distro user; a picture-only label is vague to a screen reader and unreadable
   in forced colours; and each mark would need inline SVG <defs> whose ids can
   silently repaint someone else's gradient. The word is the label. */
.os-set{
  margin:0 0 4px; padding:0; border:0; min-width:0;   /* a fieldset defaults to
                                    min-width:min-content, which stops it
                                    shrinking inside the ticket's grid column */
}
.os-cap{
  padding:0; margin:0 0 9px;
  font-family:var(--font-display); font-size:11.5px; font-weight:700;
  letter-spacing:.2em; text-transform:uppercase;
  color:var(--brass-light); text-shadow:0 1px 0 rgba(0,0,0,.7);
}
.os-rig{
  --os-i:0;
  --os-t1:#7FB4EC; --os-t2:#2E6FB7; --os-t3:#123C71; --os-tx:#EAF4FF;
  position:relative; display:grid; grid-template-columns:repeat(3,1fr);
  width:100%; padding:5px; border-radius:12px; isolation:isolate;
  background:linear-gradient(180deg,#120A03 0%,#241505 100%);
  box-shadow:inset 0 2px 6px rgba(0,0,0,.9), 0 0 0 1px var(--wood-line),
             0 0 0 2px var(--brass-dark), 0 3px 8px rgba(0,0,0,.45);
}
/* The travelling plate. It is the .chip[aria-pressed="true"] gradient from the
   donate midway (--acc-pa..--acc-pd), reused rather than re-mixed, so the two
   pages' "this one is chosen" reads as one material. */
/* ⚑ A COLOUR PER POSITION (owner, 2026-08-18: "Windows, Mac and Linux, each
   'slide' should have a different color"). The three are the fairground enamels
   the countdown plates already use — blue, green, amber — so the ticket and the
   marquee share one paintbox rather than inventing a second.

   The label colour travels with them: dark ink reads on green and amber and
   would be mud on the blue, so --os-tx is part of the same swap rather than a
   single colour chosen to be a compromise on all three. */
.os-thumb{
  position:absolute; z-index:0; top:5px; bottom:5px; left:5px;
  width:calc((100% - 10px) / 3); border-radius:9px;
  background:linear-gradient(180deg,var(--os-t1) 0%,var(--os-t2) 52%,var(--os-t3) 100%);
  box-shadow:inset 0 1px 0 rgba(255,247,221,.5), inset 0 -2px 4px rgba(0,0,0,.35),
             0 2px 6px rgba(0,0,0,.55), 0 0 13px rgba(226,112,64,.35);
  transform:translateX(calc(var(--os-i) * 100%));
  transition:transform .22s cubic-bezier(.35,.9,.35,1);
}
/* ⚠ A SLIDER THAT SLIDES ON A FIRST PAINT IS A GLITCH, NOT AN ANIMATION. The
   page may restore a saved platform before the first frame, and the thumb must
   simply BE there rather than travel from Windows. js/pay.js adds .os-rig--set
   one frame after it seats the initial value; until then there is no
   transition to run. */
.os-rig:not(.os-rig--set) .os-thumb{ transition:none; }

.os-opt{ position:relative; display:block; }
.os-in{
  position:absolute; inset:0; width:100%; height:100%; margin:0;
  opacity:0; pointer-events:none;     /* focusable and keyboard-driven; the
                                         LABEL takes the pointer */
}
.os-face{
  position:relative; z-index:1; display:block; cursor:pointer;
  padding:11px 6px 10px; border-radius:9px; text-align:center;
  font-family:var(--font-display); font-weight:700; font-size:13.5px;
  letter-spacing:.09em; text-transform:uppercase;
  color:var(--brass-light); text-shadow:0 1px 0 rgba(0,0,0,.75);
  transition:color .18s ease, text-shadow .18s ease;
}
.os-face:hover{ color:var(--brass-highlight); }
.os-in:checked + .os-face{
  color:var(--os-tx); text-shadow:0 1px 0 rgba(0,0,0,.30);
}
/* The ring goes on the LABEL because the input it belongs to is invisible. */
.os-in:focus-visible + .os-face{
  outline:3px solid var(--brass-highlight); outline-offset:2px;
}
/* The slider fills the column; the not-yet panel is the row underneath it. */

/* ── ANDROID & iOS — NOT ON SALE, AND IT MUST LOOK IT ─────────────────────
   ⚑ THIS PANEL IS NOT A FOURTH SLIDER POSITION, and the whole design is about
   making that unmissable. Three of these platforms can be bought today and two
   cannot; a control that offers all five identically would sell somebody a
   phone build that does not exist. So it is OUTSIDE the fieldset, carries no
   input, cannot be focused, cannot be clicked, and is painted as a dimmed
   plate with a rubber stamp across it rather than as a bright chip.

   `pointer-events:none` is deliberate belt-and-braces on top of "there is no
   control here": it means a determined click cannot even produce a focus ring
   that might read as a selection. */
.os-tba{
  position:relative; width:100%;
  display:flex; flex-direction:row; align-items:center; justify-content:space-between;
  gap:12px; padding:8px 14px; border-radius:12px;
  pointer-events:none; overflow:hidden;
  background:linear-gradient(180deg,#1B1108 0%,#120A03 100%);
  box-shadow:inset 0 2px 6px rgba(0,0,0,.85), 0 0 0 1px var(--wood-line),
             0 0 0 2px var(--brass-dark), 0 3px 8px rgba(0,0,0,.4);
}
.os-tba__n{
  font-family:var(--font-display); font-weight:700; font-size:13px;
  letter-spacing:.07em; text-transform:uppercase;
  color:#8A7A60;                       /* dimmer than --label-dim: not for sale */
  text-shadow:0 1px 0 rgba(0,0,0,.8);
}
/* The stamp: ink on a rubber stamp, set at an angle, with the double rule a
   real one has. Rotated in its own layer so the plate's box stays square. */
.os-tba__stamp{
  flex:none; transform:rotate(-7deg);
  padding:2px 12px 3px; border-radius:5px;
  border:2px solid #B4552F; border-top-width:3px; border-bottom-width:3px;
  font-family:var(--font-display); font-weight:700; font-size:15px;
  letter-spacing:.18em; color:#D9743F;
  text-shadow:0 1px 0 rgba(0,0,0,.6);
  opacity:.92;
}

/* The thumb's travel, owned by CSS. :has() is already this codebase's
   vocabulary (give.css uses .gc-continue-rig:has(.paying)). */
.os-rig:has(#os-mac:checked){ --os-i:1; --os-t1:#6FD9A2; --os-t2:#1E9E62; --os-t3:#0B5433; --os-tx:#08301C; }
.os-rig:has(#os-lin:checked){ --os-i:2; --os-t1:#FFD470; --os-t2:#EFA31D; --os-t3:#8A5406; --os-tx:#3A2406; }

/* Where :has() is missing the thumb cannot know where to stand, so it is
   withdrawn entirely and the chosen cell lights itself instead. The control
   still says which platform is selected — which is the part that matters when
   the answer decides which build someone is sold. */
@supports not (selector(:has(*))){
  .os-thumb{ display:none; }
  .os-in:checked + .os-face{
    background:linear-gradient(180deg,var(--os-t1) 0%,var(--os-t2) 52%,var(--os-t3) 100%);
    box-shadow:inset 0 1px 0 rgba(255,247,221,.5), 0 2px 6px rgba(0,0,0,.55);
  }
}
/* Forced colours: hand the control back to the OS. A slider that survives by
   being pretty is worth less than one somebody can read. */
@media (forced-colors: active){
  .os-thumb{ display:none; }
  .os-face{ color:CanvasText; text-shadow:none; }
  .os-in:checked + .os-face{ color:CanvasText; text-shadow:none; outline:2px solid CanvasText; }
}
@media (prefers-reduced-motion: reduce){
  .os-thumb{ transition:none; }
}

/* what the ticket admits you to — a checked list, not a feature grid */
.gets{ list-style:none; margin:0; padding:0; }
.gets li{
  position:relative; padding:0 0 0 30px; margin:0 0 11px;
  font-size:16.5px; line-height:1.55; text-shadow:0 1px 0 rgba(0,0,0,.45);
}
.gets li::before{
  content:""; position:absolute; left:0; top:.42em;
  width:13px; height:13px; transform:rotate(45deg);
  background:linear-gradient(135deg,var(--brass-highlight) 0%,var(--brass-light) 45%,var(--brass-dark) 100%);
  box-shadow:0 0 0 1.5px var(--wood-line);
}
.gets li:last-child{ margin-bottom:0; }

/* ══ THE JAR (donate.html) ════════════════════════════════════════════════
   A brass-mouthed box with a coin slot. Amounts are chips you press. */
.jar{
  max-width:520px; margin:0 auto;
  text-align:center;
}
.jar__slot{
  width:132px; height:15px; margin:0 auto 26px; border-radius:8px;
  background:linear-gradient(180deg,#0B0602 0%,#1A1006 62%,#3A2A16 100%);
  box-shadow:inset 0 3px 5px rgba(0,0,0,.95),
             0 0 0 2px var(--brass-mid), 0 0 0 3px var(--wood-line),
             0 1px 0 4px rgba(255,233,168,.10);
}
.chips{
  display:flex; flex-wrap:wrap; gap:11px; justify-content:center; margin:0 0 22px;
}
.chip{
  font-family:"Rye", Georgia, serif; font-size:20px; color:var(--label-hi);
  min-width:84px; padding:13px 16px 11px; border:none; border-radius:10px; cursor:pointer;
  background:linear-gradient(180deg,#5a3a1e,#3d2712);
  box-shadow:0 3px 4px rgba(0,0,0,.55), 0 0 0 1px var(--wood-line),
             0 0 0 2px var(--brass-dark), inset 1px 1px 0 rgba(255,233,168,.25);
  text-shadow:0 1px 0 var(--emboss-dark);
  transition:filter .12s ease, transform .06s ease, box-shadow .12s ease;
}
.chip:hover{ filter:brightness(1.14);
  box-shadow:0 3px 4px rgba(0,0,0,.55), 0 0 0 1px var(--wood-line),
             0 0 0 2px var(--brass-light), inset 1px 1px 0 rgba(255,247,221,.5); }
.chip:active{ transform:translateY(1px); filter:brightness(.93); }
.chip[aria-pressed="true"]{
  background:linear-gradient(180deg,var(--acc-pa) 0%,var(--acc-pb) 40%,var(--acc-pc) 85%,var(--acc-pd) 100%);
  color:#2a1806; text-shadow:0 1px 0 rgba(255,247,221,.45);
  box-shadow:0 3px 4px rgba(0,0,0,.6), 0 0 0 1px var(--wood-line),
             0 0 0 2px var(--brass-highlight), 0 0 12px rgba(255,208,106,.45),
             inset 1px 1px 0 rgba(255,247,221,.6);
}
.chip:focus-visible{ outline:3px solid var(--brass-highlight); outline-offset:3px; }

/* the "something else" field — a sunk brass-lipped window, like the game's
   own numeric entries */
.jar__own{ display:flex; align-items:center; justify-content:center; gap:10px; margin:0 0 24px; }
.jar__own label{ font-size:14px; color:var(--label-dim); }
.jar__field{
  display:inline-flex; align-items:center; gap:4px;
  background:linear-gradient(180deg,#120A03 0%,#241505 100%);
  border-radius:9px; padding:8px 13px;
  box-shadow:inset 0 2px 5px rgba(0,0,0,.9), 0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark);
}
.jar__field span{ font-family:"Rye", Georgia, serif; font-size:19px; color:var(--brass-light); }
.jar__field input{
  width:88px; background:transparent; border:none; outline:none;
  font-family:"Rye", Georgia, serif; font-size:19px; color:var(--label-hi);
}
.jar__field:focus-within{ box-shadow:inset 0 2px 5px rgba(0,0,0,.9), 0 0 0 1px var(--wood-line),
                                     0 0 0 2px var(--brass-highlight), 0 0 10px rgba(255,208,106,.4); }

/* ══ THE COUNTDOWN — A LUNA PARK BULB MARQUEE ═════════════════════════════
   "Game Releasing In", and the four cells under it, built as a Coney Island
   marquee: white incandescent bulbs on a night-sky board, a crescent MOON at
   the left end and a big STAR at the right, and four enamel plates each
   painted its own colour.

   THIS REPLACED A NEON SIGN, ON THE OWNER'S CALL: "the neon looks kinda weird.
   what about lit bulbs, Luna Park - CLASSIC coney island". He is right about
   the period, and the reason is worth writing down rather than re-litigating:
   NEON IS 1930s AND LUNA PARK IS 1903. A tube sign belongs to a diner or a
   motel; a park midway of that era is BULBS — thousands of them, outlining
   every edge of every tower. The moon is not decoration either, it is the
   name: Luna.

   ⚑ BULBS ARE DRAWN AS A DOTTED STROKE, NOT AS ELEMENTS. Every lit edge here —
   the four rails, the moon's crescent, the star's points — is one path with
   `stroke-linecap:round` and a dasharray of `0 <pitch>`, which paints a round
   dot every <pitch> units ALONG THAT PATH whatever shape it is. That is the
   whole trick: the bulbs follow the curve for free, they stay evenly spaced
   around corners, and a fifty-bulb crescent costs one <path> instead of fifty
   absolutely-positioned spans. Each lit edge is drawn TWICE — a wide, blurred,
   low-alpha copy underneath for the halo the glass throws, and a small hot copy
   on top for the filament.

   ⚑ THE RAILS ARE CSS, THE ORNAMENTS ARE SVG, AND THAT SPLIT IS DELIBERATE. A
   rail has to stretch with the cabinet, and stretching an SVG stretches its
   dots into ovals. So the four rails are repeating radial-gradients on strips
   (round dots, immune to the box's aspect), while the moon and star — fixed
   shapes that must never distort — are SVG.

   ⚑ "FAR MORE COLORFUL AND INDIVIDUALIZED" (owner). Each cell is its own
   enamel: signal red, amber, park green, royal blue, in that order, left to
   right. The four hues are the fairground's own primaries and they are also
   the donate midway's chip run, so the two pages share a paintbox rather than
   inventing a second one. The NUMERALS stay cream on every cell — four
   different coloured numbers would be a ransom note, and the number is the
   thing being read.

   ⚑ ONE ANIMATION, AND IT IS FOUR ELEMENTS. A real marquee chases, and dead
   bulbs read as a broken sign. But animating ~90 individual bulbs would be ~90
   animated layers on a page that is otherwise still. Instead each RAIL slides
   its own background-position by exactly one bulb pitch, so the whole chase is
   four background-position animations. Honoured `prefers-reduced-motion`, and
   the sign is fully lit and legible with the animation off — the chase is the
   only thing that stops.

   ⚑ AND NOTHING PER-DIGIT. js/pay.js rewrites each cell's textContent every
   second, so any per-digit span or running animation inside a cell is destroyed
   on the next tick. The cells are lit by their PLATE, never by their text. */
.oc{
  --oc-bulb:#FFF6DC;                    /* the filament, near-white and warm    */
  --oc-bulb-hot:#FFFFFF;
  --oc-bulb-glow:rgba(255,226,150,.55); /* what the glass throws                */
  --oc-pitch:30px;                      /* bulb spacing, uniform on all sides   */
  --oc-cycle:2.6s;                      /* one lap of the chase                 */
  --oc-lag:-0.055s;                     /* per-bulb delay; js/pay.js overwrites */
  --oc-inset:13px;                      /* how far inside the rim the string runs */
  /* ⚠ THE ORNAMENTS NEED THEIR OWN, TIGHTER PITCH. The rim is a long straight
     run where the eye joins the dots for you; a crescent is not. At the rim's
     30px pitch the moon held FIFTEEN lamps and read as scattered dots rather
     than as a moon — the placement was correct (measured: 68x82px of span in a
     104px box, exactly a crescent), it was simply too sparse to describe a
     curve. Density is what makes an outline an outline. */
  --oc-orn-pitch:13px;
  position:relative; margin:26px 0 0; padding:23px 30px 31px;
  border-radius:16px; text-align:center; isolation:isolate; overflow:hidden;
  background:
    radial-gradient(120% 86% at 50% 6%, rgba(255,214,140,.16) 0%, rgba(0,0,0,0) 60%),
    linear-gradient(180deg,#1B2A55 0%,#141C38 42%,#0B0F20 100%);
  box-shadow:
    0 0 0 1px var(--wood-line),
    0 0 0 3px var(--brass-mid),
    0 0 0 4px var(--wood-line),
    inset 0 1px 0 rgba(255,233,168,.16),
    0 14px 30px rgba(0,0,0,.55);
}

/* ── THE BULBS ────────────────────────────────────────────────────────────
   ⭐ THIS IS Mt. MONEY'S RECIPE, PORTED. The owner asked why the donate page's
   marquee looks so much better than this one did, and the answer was four
   concrete things — none of them "more glow":

     1. A BULB IS AN ELEMENT WITH A SOCKET, not a tile of background. Each one is
        a brass collar with dull glass inside it, and the glass highlight is
        OFF-CENTRE (42% 34%) — that offset is what makes a circle read as a
        sphere. A gradient centred at 50% 50% is a disc, and fifty discs are a
        dotted line.
     2. THE LIT FILAMENT IS A SEPARATE LAYER WITH REAL BLOOM — three stacked
        box-shadows at 9 / 22 / 44 px. Bloom cannot be baked into a background
        gradient, because a gradient stops at the edge of its own tile; that is
        why the old rails had a halo you could not see.
     3. THE CHASE IS A SHORT HARD CREST WITH A SOFT TAIL (part_mtmoney.css says
        it outright: "a chase reads as MOVEMENT only if the bright band is
        narrow. A slow sine over the whole cycle is a wave, not a chase"). The
        old version lit every third bulb on a square wave, which is a pattern,
        not a movement.
     4. THE UNLIT BULB IS NOT OFF — it sits at .13, a warm filament that never
        fully dies, so the run is continuous even where the light is not.

   Only OPACITY animates. A keyframed box-shadow re-rasterises the bloom on every
   bulb every frame, and this border is on screen the whole time.

   Positions come from js/pay.js, which walks the perimeter at a uniform pitch
   and the moon/star OUTLINES by arc length. Uniform pitch is the point: a
   `space-between` rail puts them 30px apart across the top and 52px down the
   side, and the eye catches that instantly on a string it should read as one. */
.oc-bulb{
  position:absolute; z-index:1;
  width:15px; height:15px; margin:-7.5px 0 0 -7.5px;   /* left/top are centres */
  border-radius:50%; pointer-events:none;
  background:
    radial-gradient(circle at 42% 34%, #EFE7D6 0%, #B4A894 34%, #8B8070 52%, rgba(0,0,0,0) 53%),
    linear-gradient(180deg,#F5C25A 0%,#C99230 44%,#5C4210 100%);
  box-shadow:0 1px 2px rgba(0,0,0,.7), inset 0 1px 0 rgba(255,247,221,.55);
}
.oc-bulb::after{
  content:"";
  position:absolute; left:50%; top:50%;
  width:11px; height:11px; margin:-5.5px 0 0 -5.5px;
  border-radius:50%;
  background:radial-gradient(circle at 45% 38%, #FFFFFF 0%, #FFF4DE 46%, #FFE7BE 78%, rgba(255,231,190,0) 100%);
  box-shadow:
    0 0 9px 2px rgba(255,252,244,.90),
    0 0 22px 7px rgba(255,246,226,.50),
    0 0 44px 16px rgba(255,242,214,.22);
  opacity:.13;                                   /* the always-warm filament */
  animation:oc-chase var(--oc-cycle) linear infinite;
  animation-delay:calc(var(--i) * var(--oc-lag));
}
/* the ornaments' bulbs are smaller, or a crescent is six lamps and a smudge */
.oc__orn .oc-bulb{ width:9px; height:9px; margin:-4.5px 0 0 -4.5px; }
.oc__orn .oc-bulb::after{
  width:6.5px; height:6.5px; margin:-3.25px 0 0 -3.25px;
  box-shadow:
    0 0 7px 1px rgba(255,252,244,.88),
    0 0 16px 5px rgba(255,246,226,.46),
    0 0 30px 11px rgba(255,242,214,.20);
}
@keyframes oc-chase{
  0%  { opacity:1; }
  8%  { opacity:.62; }
  19% { opacity:.13; }
  100%{ opacity:.13; }
}

/* ── The moon and the star ────────────────────────────────────────────────
   Luna Park's own two signs, one at each end, on the centre line of the
   heading. They are hidden below 900px rather than shrunk: at small sizes the
   bulb pitch would have to shrink with them and a crescent of six dots is not
   a moon, it is a smudge. */
/* ⚑ VERTICALLY CENTRED, NOT TOP-PINNED (owner, 2026-08-18: "the star and moon
   are too high up and need to be vertically centered"). They were hung from
   `top`, so each sat at whatever height its own box happened to give it and the
   two did not even agree with each other. Centring on the cabinet is one rule
   that holds however tall the sign becomes — and it keeps holding when the
   heading wraps to two lines at a narrow width. */
.oc__orn{
  position:absolute; z-index:2; top:50%; transform:translateY(-50%);
  pointer-events:none;
}
.oc__orn--moon{ left:40px; width:128px; height:128px; }
.oc__orn--star{ right:32px; width:156px; height:156px; }
.oc__orn svg{ display:block; width:100%; height:100%; }
.oc-bulbs{ position:absolute; inset:0; pointer-events:none; }

/* ── The sign's own writing ───────────────────────────────────────────────
   Cream, lit from above by its own bulbs — a painted board catching the light,
   NOT a glowing tube. The warm halo is small and tight for exactly that reason:
   paint reflects, it does not emit. */
.oc__head{
  position:relative; z-index:3;
  margin:0 0 15px; font-family:"Rye", Georgia, serif;
  font-size:clamp(23px,3.6vw,40px); line-height:1.06; letter-spacing:.015em;
  color:#FFF4D8;
  text-shadow:
    0 2px 0 #6B3F12,
    0 3px 0 #4A2B0C,
    0 5px 12px rgba(0,0,0,.6),
    0 0 22px rgba(255,214,140,.30);
}

.oc__clock{
  position:relative; z-index:3;
  display:flex; gap:16px; justify-content:center; flex-wrap:wrap; margin:0;
}

/* ── The four enamel plates ───────────────────────────────────────────────
   A painted metal plate with a bright top edge, a dark foot, and a brass rim —
   the same three-part read as every other object in this cabinet, just in four
   colours instead of one. */
.oc__cell{
  --oc-c:#D93A2B; --oc-c-hi:#F27A62; --oc-c-lo:#7E1A10;
  position:relative; min-width:134px; padding:16px 14px 12px; border-radius:12px;
  background:
    linear-gradient(180deg,
      var(--oc-c-hi) 0%, var(--oc-c) 22%, var(--oc-c) 62%, var(--oc-c-lo) 100%);
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.34),
    inset 0 -3px 8px rgba(0,0,0,.45),
    0 0 0 1px var(--wood-line),
    0 0 0 3px var(--brass-mid),
    0 0 0 4px var(--wood-line),
    0 5px 14px rgba(0,0,0,.5);
}
.oc__cell:nth-child(2){ --oc-c:#EFA31D; --oc-c-hi:#FFD470; --oc-c-lo:#8A5406; }
.oc__cell:nth-child(3){ --oc-c:#1E9E62; --oc-c-hi:#6FD9A2; --oc-c-lo:#0B5433; }
.oc__cell:nth-child(4){ --oc-c:#2E6FB7; --oc-c-hi:#7FB4EC; --oc-c-lo:#123C71; }

.oc__n{
  display:block; font-family:"Rye", Georgia, serif; font-size:50px; line-height:1;
  font-variant-numeric:tabular-nums;    /* so the seconds do not jitter the row */
  color:#FFF7E4;
  text-shadow:0 2px 0 rgba(0,0,0,.42), 0 3px 6px rgba(0,0,0,.4);
}
.oc__l{
  display:block; margin-top:7px; font-family:var(--font-display); font-size:10.5px;
  font-weight:700; letter-spacing:.2em; text-transform:uppercase;
  color:rgba(255,247,228,.92); text-shadow:0 1px 0 rgba(0,0,0,.45);
}

/* Opening day: the plates go and the heading says so. */
.oc__clock.is-open{
  display:block; font-family:"Rye", Georgia, serif; font-size:clamp(20px,3vw,30px);
  color:#FFF4D8; text-shadow:0 2px 0 #6B3F12, 0 4px 10px rgba(0,0,0,.55);
}

@media (prefers-reduced-motion: reduce){
  /* Stop the chase, but leave every bulb LIT rather than leaving a third of
     them hot and the rest dim in a frozen pattern that reads as broken. */
    }
/* Forced colours: the bulbs and the enamel are both gone by definition, so give
   the plates a real edge back or they become four invisible boxes. */
@media (forced-colors: active){
    .oc__cell{ border:1px solid CanvasText; }
  .oc__head, .oc__n, .oc__l{ text-shadow:none; }
}

/* ══ THE PROMISE ══════════════════════════════════════════════════════════
   The refund undertaking is the whole difference between these two pages, so
   on Buy it gets its own lit plate rather than a line in a terms list. */
.promise{
  border-color:var(--accent-mid);
  box-shadow:0 0 4px 1px rgba(0,0,0,.5) inset, 0 0 22px rgba(226,112,64,.18), var(--shadow-deep);
}
.promise__seal{
  float:right; width:104px; height:104px; margin:0 0 14px 26px; border-radius:50%;
  display:grid; place-items:center; text-align:center;
  background:radial-gradient(circle at 36% 30%,#FFF3CF 0%,#F5C25A 42%,#A9761A 100%);
  box-shadow:0 3px 8px rgba(0,0,0,.6), 0 0 0 2px var(--wood-line), 0 0 20px rgba(255,208,106,.4);
  color:#2a1806; font-family:var(--font-display); font-weight:700;
  font-size:12px; line-height:1.2; letter-spacing:.08em; text-transform:uppercase;
  text-shadow:0 1px 0 rgba(255,247,221,.5);
}

/* ══ THE TWO MECHANISMS, SIDE BY SIDE ═════════════════════════════════════
   Every page has to answer "so what is the difference?" in one glance. */
.compare{ display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-top:26px; }
.compare__col{
  background:linear-gradient(180deg,#2F2114 0%,#1B1108 100%);
  border:1px solid var(--brass-dark); border-radius:12px; padding:24px 26px 26px;
  box-shadow:0 0 4px 1px rgba(0,0,0,.5) inset, var(--shadow-drop);
}
/* the one you are standing on is lit; the other is the door out */
.compare__col--this{ border-color:var(--accent); box-shadow:0 0 4px 1px rgba(0,0,0,.5) inset,
                     0 0 16px rgba(255,208,106,.20), var(--shadow-drop); }
.compare__h{
  margin:0 0 12px; font-family:var(--font-display); font-weight:700; font-size:17px;
  color:var(--label-hi); letter-spacing:.04em;
  text-shadow:0 1px 0 var(--emboss-dark);
}
.compare__col ul{ list-style:none; margin:0 0 18px; padding:0; }
.compare__col li{
  position:relative; padding-left:22px; margin-bottom:9px;
  font-size:15.5px; line-height:1.55;
}
.compare__col li::before{
  content:"—"; position:absolute; left:0; color:var(--brass-mid);
}
.compare__col li.yes::before{ content:"✓"; color:#7FC46A; font-weight:700; }
.compare__col li.no::before { content:"✕"; color:#C9663F; font-weight:700; }

/* ══ TERMS ════════════════════════════════════════════════════════════════
   Small, plain, and readable — never grey-on-grey mouse type. What it says is
   the actual deal, so it is set at a size a person can read. */
.terms{ margin-top:26px; }
.terms ol{ margin:0; padding-left:1.3em; }
.terms li{ margin:0 0 12px; font-size:15.5px; line-height:1.65; color:var(--label); }
.terms li:last-child{ margin-bottom:0; }
.terms strong{ color:var(--brass-highlight); }

/* ══ THE LEGAL PAGES (/terms, /privacy) ═══════════════════════════════════
   Two additions on 2026-08-21, when the "unfun page" became a real terms page
   and a privacy policy was written beside it.

   ⚠ .pay__stamp SITS IN THE HERO, WHICH IS ON THE GRASS. This file already
   states the rule twice (for .pay__eyebrow and for .fineway): dim or
   accent-coloured type set loose on the bright green tile is legible as a shape
   and not as words. So the date gets a dark ground of its own, the same
   brass-lipped chip recipe as .plat and .fineway — the cheapest object in the
   cabinet that puts a readable field under a sentence.

   ⚑ AND IT IS A REAL SENTENCE, NOT A DECORATION. "Last updated <date>" is the
   one line on a terms page that a reader is entitled to check before relying on
   anything below it, and it is what makes "changes are not retroactive"
   verifiable rather than a claim. Keep it visible; never shrink it into the
   ornament. */
.pay__stamp{
  display:inline-block; margin:18px 0 0; padding:7px 16px; border-radius:20px;
  background:rgba(20,10,3,.72);
  box-shadow:0 0 0 1px rgba(126,90,18,.55), var(--shadow-drop);
  font-size:13px; color:var(--label-dim);
}

/* The privacy page's summary, and any list on these pages that is a set of
   plain statements rather than a numbered contract. .terms styles an <ol>; this
   is its <ul> sibling, and it carries a brass tick because every line under it
   is something the site DOES rather than something it reserves. */
.plainlist{ list-style:none; margin:0; padding:0; }
.plainlist li{
  position:relative; margin:0 0 12px; padding-left:1.5em;
  font-size:15.5px; line-height:1.65; color:var(--label);
}
.plainlist li:last-child{ margin-bottom:0; }
.plainlist li::before{
  content:"✓"; position:absolute; left:0; top:0;
  color:#7FC46A; font-weight:700;
}
.plainlist strong{ color:var(--brass-highlight); }

/* ══ PLATFORM ROW ═════════════════════════════════════════════════════════ */
.plats{ display:flex; gap:14px; flex-wrap:wrap; margin-top:4px; }
.plat{
  flex:1 1 210px; padding:18px 20px; border-radius:11px;
  background:linear-gradient(180deg,#2a1a0c,#180d05);
  box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark), var(--shadow-drop);
}
.plat__n{
  display:block; font-family:var(--font-display); font-weight:700; font-size:16px;
  color:var(--label-hi); text-shadow:0 1px 0 var(--emboss-dark);
}
.plat__s{ display:block; margin-top:5px; font-size:14px; color:var(--label-dim); }
/* (.plat--soon is gone with the "mobile announcement coming soon" tile it was
   written for — 2026-08-18, when the platform story became three shipping
   platforms and stopped having a pending one. A rule whose selector matches
   nothing is indistinguishable from a live one to the next reader.) */

/* ══ THE WAY OUT TO THE FINE PRINT ════════════════════════════════════════
   One line under the buy page pointing at /terms.

   ⚠ IT HAS TO BE ON SOMETHING. The first draft set it as loose .act__fine
   text, which is `--label-dim` (#A89880) — and the buy page's <main> sits
   directly on the GRASS TILE, not on a panel. This file already writes the rule
   down forty lines above, for .pay__eyebrow: bare dim or accent-coloured type
   on the grass is unreadable, and "red on green is the one pairing this palette
   must never set as loose text". Rendering it proved the point immediately: the
   sentence was legible as a shape and not as words.

   So it is a small brass-lipped chip, the same recipe as .plat and .tally li —
   the cheapest object in the cabinet that still puts a dark ground under a
   sentence. */
.fineway{ display:flex; justify-content:center; margin-top:26px; }
.fineway p{
  margin:0; padding:12px 22px; border-radius:11px; text-align:center;
  background:linear-gradient(180deg,#2F2114 0%,#1B1108 100%);
  box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark),
             0 0 4px 1px rgba(0,0,0,.5) inset, var(--shadow-drop);
  font-size:15px; line-height:1.55; color:var(--label);
  text-shadow:0 1px 0 rgba(0,0,0,.6);
}
.fineway a{
  color:var(--brass-highlight); font-weight:700;
  text-decoration:underline; text-underline-offset:3px;
  text-decoration-color:var(--brass-dark);
}
.fineway a:hover{ text-decoration-color:var(--brass-highlight); }

/* ══ THE ACTION ═══════════════════════════════════════════════════════════ */
.act{ display:flex; flex-direction:column; align-items:center; gap:12px; }
.act .btn{ width:100%; max-width:340px; }
.act__fine{ font-size:13.5px; color:var(--label-dim); text-align:center; max-width:44ch; }

/* The big action button wears the page's own accent. */
.btn--pay{
  --plate-a:var(--acc-pa); --plate-b:var(--acc-pb);
  --plate-c:var(--acc-pc); --plate-d:var(--acc-pd);
}
/* On gold, cream text on a light plate is unreadable — the embossing flips to
   dark ink with a lit top edge, exactly as .btn--donate does in skeuo.css. */
.pay--give .btn--pay{ color:#2a1806; text-shadow:0 1px 0 rgba(255,247,221,.4); }

/* ══ FORM CONTROLS ════════════════════════════════════════════════════════
   The game's own sunk-window look: a dark recess with a brass lip, lit when
   focused. Used by the donor questions and by the review queue. */
.field{ display:block; margin:0 0 16px; text-align:left; }
.field__label{
  display:block; margin:0 0 6px;
  font-family:var(--font-display); font-weight:700; font-size:13px;
  color:var(--label-hi); letter-spacing:.04em; text-shadow:0 1px 0 var(--emboss-dark);
}
/* text-align:left explicitly: .jar centres its contents (the chips and the coin
   slot want that), and a hint paragraph dropped straight into it would inherit
   the centring and read as a pull-quote instead of small print. */
.field__hint{ display:block; margin:5px 0 0; font-size:12.5px; color:var(--label-dim);
  line-height:1.45; text-align:left; }
.field__input{
  width:100%; padding:11px 13px; border:none; border-radius:9px;
  font-family:var(--font-body); font-size:15.5px; color:var(--label-hi);
  background:linear-gradient(180deg,#120A03 0%,#241505 100%);
  box-shadow:inset 0 2px 5px rgba(0,0,0,.9), 0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark);
}
.field__input::placeholder{ color:#7a6a52; }
.field__input:focus{
  outline:none;
  box-shadow:inset 0 2px 5px rgba(0,0,0,.9), 0 0 0 1px var(--wood-line),
             0 0 0 2px var(--brass-highlight), 0 0 10px rgba(255,208,106,.4);
}

/* Two questions side by side where they belong together. */
.field-row{ display:grid; grid-template-columns:1fr 1fr; gap:0 16px; }
@media (max-width:600px){ .field-row{ grid-template-columns:1fr; } }

/* ── Consent ──────────────────────────────────────────────────────────────
   A real checkbox, restyled — not a div pretending. Keyboard, screen readers
   and form semantics all come free that way, and consent is the last control
   on the page that should be improvised. */
.check{
  display:flex; align-items:flex-start; gap:11px; margin:0 0 13px;
  cursor:pointer; text-align:left;
}
.check input{
  appearance:none; -webkit-appearance:none; flex:none;
  width:21px; height:21px; margin:1px 0 0; border-radius:6px; cursor:pointer;
  background:linear-gradient(180deg,#120A03 0%,#241505 100%);
  box-shadow:inset 0 2px 4px rgba(0,0,0,.9), 0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark);
  transition:box-shadow .12s ease, background .12s ease;
}
.check input:checked{
  background:linear-gradient(180deg,var(--acc-pa) 0%,var(--acc-pb) 45%,var(--acc-pd) 100%);
  box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-highlight),
             0 0 10px rgba(255,208,106,.45), inset 1px 1px 0 rgba(255,247,221,.6);
}
/* the tick, drawn rather than a glyph so it never depends on a font */
.check input:checked::after{
  content:""; display:block; width:6px; height:11px; margin:2px 0 0 6px;
  border:solid #2a1806; border-width:0 2.5px 2.5px 0; transform:rotate(43deg);
}
.check input:focus-visible{ outline:3px solid var(--brass-highlight); outline-offset:3px; }
.check__text{ font-size:15px; line-height:1.5; color:var(--label); }
.check__text b{ color:var(--label-hi); }
.check__text small{ display:block; margin-top:3px; font-size:12.5px; color:var(--label-dim); line-height:1.45; }

/* The sub-questions that only matter once the box above is ticked. Dimmed
   rather than hidden: a control that appears out of nowhere makes a form feel
   like it is moving under you, and this way the shape of the page never jumps. */
.reveal{
  margin:14px 0 0 32px; padding:16px 18px 4px;
  border-left:2px solid var(--brass-dark); border-radius:0 9px 9px 0;
  background:rgba(0,0,0,.22);
  opacity:.42; pointer-events:none; transition:opacity .18s ease;
}
.reveal.is-on{ opacity:1; pointer-events:auto; border-left-color:var(--accent); }

/* ══ THE CARD FIELD ═══════════════════════════════════════════════════════
   Stripe's Payment Element renders inside an iframe it owns — that is what
   keeps card data off this page entirely and the compliance burden at its
   lowest tier. It is themed through Stripe's appearance API in js/donate.js,
   not from here; this only builds the recess it sits in. */
.cardwell{
  margin:0 0 20px; padding:18px 16px; border-radius:11px; text-align:left;
  background:linear-gradient(180deg,#1a1006 0%,#241505 100%);
  box-shadow:inset 0 2px 6px rgba(0,0,0,.75), 0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark);
  min-height:64px;
}

.step{ display:none; }
.step.is-active{ display:block; }

.paying{ opacity:.55; pointer-events:none; }

/* what you are about to give, restated above the card — nobody should type a
   card number without the number they are agreeing to in view */
.confirmbar{
  display:flex; align-items:baseline; justify-content:center; gap:10px;
  margin:0 0 18px; padding:12px 16px; border-radius:9px;
  background:rgba(0,0,0,.3); box-shadow:inset 0 0 0 1px var(--brass-dark);
}
.confirmbar__amt{ font-family:"Rye",Georgia,serif; font-size:27px; color:var(--label-hi); }
.confirmbar__lbl{ font-size:13px; color:var(--brass-light); letter-spacing:.1em; text-transform:uppercase; }
.linkish{
  background:none; border:none; padding:0; cursor:pointer;
  font-family:var(--font-body); font-size:13.5px; color:var(--brass-light);
  text-decoration:underline; text-underline-offset:3px;
}
.linkish:hover{ color:var(--brass-highlight); }

/* errors — loud enough to see, never styled as a scold */
.notice{
  margin:0 0 16px; padding:12px 15px; border-radius:9px; text-align:left;
  font-size:14.5px; line-height:1.55;
  background:rgba(120,30,12,.35); box-shadow:inset 0 0 0 1px #C9663F; color:#FFD9C6;
}
.notice--ok{ background:rgba(30,80,40,.32); box-shadow:inset 0 0 0 1px #7FC46A; color:#D6F0CC; }
.notice[hidden]{ display:none; }

/* ══ THE BOARD ════════════════════════════════════════════════════════════ */
.board{ margin:0; padding:0; list-style:none; }
.board__row{
  display:grid; grid-template-columns:58px 1fr auto; gap:0 16px; align-items:center;
  padding:14px 18px; border-radius:10px; margin-bottom:9px;
  background:linear-gradient(180deg,#2a1a0c,#180d05);
  box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark), var(--shadow-drop);
}
/* the top three wear brass, the way a midway board would */
.board__row--1{ box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-highlight), 0 0 16px rgba(255,208,106,.4), var(--shadow-drop); }
.board__row--2{ box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-light), 0 0 10px rgba(255,208,106,.22), var(--shadow-drop); }
.board__row--3{ box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-mid), var(--shadow-drop); }
.board__rank{
  font-family:"Rye",Georgia,serif; font-size:25px; color:var(--brass-light);
  text-align:center; text-shadow:0 2px 0 #2A1806;
}
.board__who{ min-width:0; }
.board__name{ font-family:var(--font-display); font-weight:700; font-size:17px; color:var(--label-hi);
  text-shadow:0 1px 0 var(--emboss-dark); overflow-wrap:anywhere; }
.board__meta{ margin-top:3px; font-size:13.5px; color:var(--brass-light); overflow-wrap:anywhere; }
.board__meta em{ color:var(--label-dim); font-style:normal; }
.board__amt{ font-family:"Rye",Georgia,serif; font-size:24px; color:var(--label-hi); white-space:nowrap;
  text-shadow:0 2px 0 #2A1806; }
.board__amt--hidden{ font-family:var(--font-body); font-size:13px; color:var(--label-dim); letter-spacing:.06em; }
@media (max-width:600px){
  .board__row{ grid-template-columns:44px 1fr; }
  .board__amt{ grid-column:2; font-size:20px; margin-top:4px; }
  .board__rank{ font-size:21px; }
}

/* the write-in tallies — what people keep asking for */
.tally{ display:flex; flex-wrap:wrap; gap:9px; margin:0; padding:0; list-style:none; }
.tally li{
  display:inline-flex; align-items:baseline; gap:8px;
  padding:8px 14px; border-radius:20px;
  background:linear-gradient(180deg,#3a2410,#25160a);
  box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark);
  font-size:14.5px; color:var(--label);
}
.tally b{ color:var(--label-hi); }
.tally span{ font-family:"Rye",Georgia,serif; font-size:15px; color:var(--accent); }

/* ══ THE REVIEW QUEUE ═════════════════════════════════════════════════════ */
.entry{
  display:grid; grid-template-columns:26px 1fr; gap:0 14px;
  padding:15px 18px; border-radius:10px; margin-bottom:10px; text-align:left;
  background:linear-gradient(180deg,#2a1a0c,#180d05);
  box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-dark);
}
/* a flagged entry is marked for ATTENTION, not for guilt — it means "read this
   one", and it is amber rather than red for exactly that reason */
.entry--flagged{ box-shadow:0 0 0 1px var(--wood-line), 0 0 0 2px #C9923052, 0 0 0 3px #C99230; }
.entry__field{ margin:0 0 5px; font-size:14.5px; color:var(--label); overflow-wrap:anywhere; }
.entry__field b{ display:inline-block; min-width:104px; color:var(--brass-light); font-weight:400; font-size:12.5px;
  letter-spacing:.08em; text-transform:uppercase; }
.entry__flags{ display:flex; flex-wrap:wrap; gap:6px; margin-top:9px; }
.entry__flag{
  padding:3px 10px; border-radius:12px; font-size:11.5px; letter-spacing:.06em; text-transform:uppercase;
  background:#4a2d12; color:#FFD98A; box-shadow:inset 0 0 0 1px #C99230;
}
.queuebar{
  position:sticky; bottom:0; z-index:5;
  display:flex; gap:12px; align-items:center; flex-wrap:wrap;
  margin-top:18px; padding:14px 18px; border-radius:11px;
  background:linear-gradient(180deg,#3a2410 0%,#1B1108 100%);
  box-shadow:0 -4px 14px rgba(0,0,0,.5), 0 0 0 2px var(--brass-mid);
}
.queuebar__count{ flex:1; font-size:14px; color:var(--brass-light); }

/* ══ Phone ════════════════════════════════════════════════════════════════ */
@media (max-width:820px){
  .compare{ grid-template-columns:1fr; }
}
@media (max-width:760px){
  .pay{ padding:0 14px 52px; }
  .pay__hero{ padding:36px 0 26px; }
  .pay__hook{ max-width:none; }
  .plate{ --plate-py:24px; --plate-px:20px; --plate-r:10px;
          padding:var(--plate-py) var(--plate-px) 26px; }

  /* The stub stops being a torn-off right-hand edge and becomes the bottom of
     the ticket, so the perforation and its punched holes turn with it. */
  .ticket{ grid-template-columns:1fr; }
  .ticket__body{ padding:26px 22px 22px; }
  .ticket__stub{
    border-left:none; border-top:2px dashed rgba(201,146,48,.55);
    padding:26px 22px 24px;
  }
  .ticket__stub::before,
  .ticket__stub::after{ left:auto; top:-11px; bottom:auto; }
  .ticket__stub::before{ left:-11px; }
  .ticket__stub::after { right:-11px; }

  .price__int{ font-size:56px; }

  /* The countdown keeps FOUR cells on a phone rather than wrapping to 2×2: a
     wrapped clock reads as two clocks. The bulb pitch shrinks with the cabinet
     so the rails keep whole bulbs instead of clipping one at each corner. */
  .oc{ padding:22px 12px 19px; --oc-pitch:15px; }
  .oc__clock{ gap:7px; }
  .oc__cell{
    min-width:0; flex:1 1 0; padding:11px 3px 9px; border-radius:9px;
    box-shadow:
      inset 0 2px 0 rgba(255,255,255,.34), inset 0 -3px 8px rgba(0,0,0,.45),
      0 0 0 1px var(--wood-line), 0 0 0 2px var(--brass-mid),
      0 0 0 3px var(--wood-line), 0 4px 10px rgba(0,0,0,.5);
  }
  .oc__n{ font-size:27px; }
  .oc__l{ font-size:8.5px; letter-spacing:.1em; }
  
  .os-rig{ max-width:none; }
  .promise__seal{ float:none; margin:0 auto 18px; }

  .tk-cols{ gap:22px; }
  /* the shield and the roundel are one pair and keep ONE measure — narrow them
     together or the plaque starts overhanging the medallion under it */
  .price-rig{ width:300px; }
  .creed-rig{ width:300px; }
}

/* The moon and star are HIDDEN rather than scaled below 900px. A crescent needs
   enough bulbs to read as a crescent; shrunk to phone width it is six dots and
   a smudge, and a smudge beside a countdown looks like a rendering fault. The
   rails and the four plates carry the Coney Island read on their own. */
@media (max-width:900px){
  .oc__orn{ display:none; }
}


/* ══ THE ORDER PAGE ═══════════════════════════════════════════════════════
   /order.html — where Stripe lands a buyer after a completed checkout. It runs
   .pay--buy so the accent matches the ticket they just came from; these two
   blocks are the only things it needs that /buy and /thanks do not already
   have between them. */

/* The receipt. A real <table> with row headers, because it IS tabular data —
   five labelled facts — and a screen reader reading "Delivered" before the date
   is the whole benefit. Two columns, the label column shrink-wrapped and dim. */
.ord{
  width:100%; border-collapse:collapse; margin:4px 0 0;
  font-size:16px; line-height:1.6;
}
.ord th{
  width:1%; white-space:nowrap; text-align:left; vertical-align:top;
  padding:10px 22px 10px 0;
  font-size:13px; font-weight:600; letter-spacing:.04em;
  color:var(--accent-mid);
  text-shadow:0 1px 0 rgba(0,0,0,.45);
}
.ord td{
  vertical-align:top; padding:10px 0;
  text-shadow:0 1px 0 rgba(0,0,0,.45);
}
.ord tr + tr th, .ord tr + tr td{ border-top:1px solid rgba(255,255,255,.07); }

@media (max-width:560px){
  /* Two narrow columns turn a five-row receipt into ten lines of two words. On
     a phone the label sits ABOVE its value, which is one line each and reads in
     the same order. */
  .ord th, .ord td{ display:block; width:auto; padding:0; }
  .ord th{ padding-top:14px; }
  .ord td{ padding-bottom:2px; }
  .ord tr + tr th{ border-top:0; }
  .ord tr + tr td{ border-top:0; }
}

/* ── THE LICENCE KEY ──────────────────────────────────────────────────────
   Set big, monospaced and spaced out, because this is a string somebody may
   read off a screen and type into a box, or read down a telephone. The
   alphabet it is drawn from already has the confusable letters removed
   (worker/src/preorder.js §1); this is the other half of the same job —
   ambiguity that survives the alphabet gets killed by the typography.

   user-select:all so one click takes the whole key and never half of it. */
/* ⚠ TWO CLASSES ON PURPOSE — `.plate p` OUT-SPECIFIES A LONE CLASS. The plate
   sets `margin:0 0 1em; font-size:17px` on every <p> inside it, at specificity
   (0,1,1); `.keyplate__key` alone is (0,1,0) and LOSES. The first cut of this
   block had the right declarations and none of them applied: the key rendered
   at body size, left-aligned, because its `margin:auto` and its `clamp()` were
   both being overridden by a rule written four screens up for ordinary prose.
   Nothing errors and nothing warns — the only tell is that the box looks like a
   paragraph. `.keyplate .keyplate__key` is (0,2,0) and wins cleanly.

   ⚠ AND IT IS A BLOCK, NOT AN inline-block. `.tag` is an inline <span>, so an
   inline-block paragraph after it JOINS ITS LINE — the key box sat to the RIGHT
   of the "Your licence key" plaque, baseline-aligned against it. A block starts
   its own line; `width:fit-content` is what keeps the box hugging the key
   rather than stretching the plate, which inline-block had been providing. */
.keyplate .keyplate__key{
  display:block; width:fit-content; max-width:100%;
  margin:6px auto 16px; padding:15px 26px;
  border:1px solid var(--accent-dk); border-radius:10px;
  background:rgba(0,0,0,.30);
  font-family:"SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
  font-size:clamp(19px,3.2vw,26px); font-weight:700; letter-spacing:.12em;
  color:var(--brass-highlight);
  text-shadow:0 1px 0 rgba(0,0,0,.7);
  /* One click takes the WHOLE key and never half of it. */
  user-select:all; -webkit-user-select:all;
  /* A key that wraps mid-group is a key somebody mis-types. It is 16 characters
     and always fits at these sizes; the scroll is the floor under a browser or
     a text-size setting that disagrees. */
  white-space:nowrap; overflow-x:auto;
}
.keyplate .keyplate__note{
  margin:0; text-align:center; font-size:15px; line-height:1.6; color:#C4B08A;
}
