/* SPDX-License-Identifier: GPL-3.0-or-later */

/*
 * THE BIG ONE — the record at the dock.
 *
 * Two authored worlds (Night verbatim from 03R; Day authored from the slip's
 * light-ground materials so gold and cyan keep their meaning), one DOM, two
 * compositions: the sheet below 1024px, the perimeter instrument above it
 * (03R §7r). No cards, no shadows, no glass: hairlines separate; boxes are used
 * exactly twice, both meaning enclosure (the locked-CATCH escrow, the slip input).
 *
 * Materials are semantic. Gold is money and nothing else; cyan is CATCH and
 * Bite is Hot; white is a closing window. The primary action is never gold —
 * the amount inside it is, because the amount is money.
 *
 * Motion in the record is scarce: ticks (tabular), drains (linear), and single
 * eases on settle. Nothing pulses. The lake earns the movement.
 */

/*==================================  type  ==================================*/

@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('./fonts/newsreader-latin-opsz-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Newsreader';
  font-style: italic;
  font-weight: 200 800;
  font-display: swap;
  src: url('./fonts/newsreader-latin-opsz-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('./fonts/ibm-plex-mono-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('./fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');
}

/*=================================  tokens  =================================*/

:root {
  --serif: 'Newsreader', Georgia, 'Times New Roman', serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  /* Night — 03R materials, verbatim. */
  --ground: #060a12;
  --sheet: #0a1220;
  --ink: #f2f0e8;
  --record: #9aa3ad;
  --muted: #7d8794;
  /* B-04: was #5d6571 (3.18:1 on --sheet, below WCAG AA's 4.5:1 for the
     12-20px figures it colours); lightened to clear AA with margin while
     staying dimmer than --muted (4.89:1 vs --muted's 5.15:1), preserving the
     "more washed out than muted" reading. */
  --stale: #798393;
  --gold: #e3c47c;
  --gold-deep: #bd9750;
  --cyan: #8fd6e2;
  --white-bar: #f2f0e8;
  --rule-1: rgba(242, 240, 232, 0.08);
  --rule-2: rgba(242, 240, 232, 0.1);
  --rule-3: rgba(242, 240, 232, 0.18);
  --rule-4: rgba(242, 240, 232, 0.25);
  --rule-ink: #f2f0e8;
  --action-ground: rgba(242, 240, 232, 0.08);
  --action-rule: rgba(242, 240, 232, 0.2);
  --slip-ground: #e6e4dc;
  --slip-ink: #060a12;
  --slip-muted: #4d5560;
  --slip-gold: #7a5b22;
  --slip-cyan: #155f6c;
  --slip-rule: rgba(6, 10, 18, 0.14);
  --scrim: rgba(6, 10, 18, 0.55);
  --substrate-top: linear-gradient(180deg, rgba(6, 10, 18, 0.75), rgba(6, 10, 18, 0));
  --substrate-bottom: linear-gradient(180deg, rgba(6, 10, 18, 0), rgba(6, 10, 18, 0.9) 45%);
  --substrate-side: linear-gradient(270deg, rgba(6, 10, 18, 0.94), rgba(6, 10, 18, 0.88) 70%, rgba(6, 10, 18, 0));
  --focus: #8fd6e2;
  --sheet-top: 250px;
  color-scheme: dark;
}

/* Day — the same place in daylight: paper substrates, ink, the slip's deepened
   gold and cyan so the materials mean the same thing at higher luminance.
   Light-ground gold/cyan sit one step below 03R's #8a6a2c / #1c6f7d: those
   measure 3.95:1 and 4.4:1 on the slip ground, under WCAG AA for the 12–16px
   figures they colour; #7a5b22 / #155f6c measure ≥ 4.9:1 (client-build addendum §7). */
:root[data-theme='day'] {
  --ground: #1a3552;
  --sheet: #ece9e0;
  --ink: #0d1420;
  --record: #3d4652;
  --muted: #55606c;
  /* B-04: was #7a828c (3.20:1 on --sheet). Darkened to clear AA with margin
     while staying lighter (less contrast) than --muted's 5.28:1. */
  --stale: #5f656d;
  --gold: #7a5b22;
  --gold-deep: #5e4619;
  --cyan: #155f6c;
  --white-bar: #0d1420;
  --rule-1: rgba(13, 20, 32, 0.08);
  --rule-2: rgba(13, 20, 32, 0.12);
  --rule-3: rgba(13, 20, 32, 0.2);
  --rule-4: rgba(13, 20, 32, 0.28);
  --rule-ink: #0d1420;
  --action-ground: rgba(13, 20, 32, 0.06);
  --action-rule: rgba(13, 20, 32, 0.24);
  --slip-ground: #f7f5ee;
  --slip-ink: #0d1420;
  --slip-muted: #4d5560;
  --slip-gold: #7a5b22;
  --slip-cyan: #155f6c;
  --slip-rule: rgba(13, 20, 32, 0.14);
  --scrim: rgba(20, 30, 45, 0.45);
  --substrate-top: linear-gradient(180deg, rgba(236, 233, 224, 0.92), rgba(236, 233, 224, 0));
  --substrate-bottom: linear-gradient(180deg, rgba(236, 233, 224, 0), rgba(236, 233, 224, 0.94) 45%);
  --substrate-side: linear-gradient(270deg, rgba(236, 233, 224, 0.96), rgba(236, 233, 224, 0.9) 70%, rgba(236, 233, 224, 0));
  --focus: #1c6f7d;
  color-scheme: light;
}

/* Founder correction: the lower record area (everything the dock renders
   below the strip — glance, depth column, record rows) keeps Night's
   dark-over-lake tokens in Day too. Those darker tones sit on the lake the
   same way in either theme; Day's own paler tokens read as a pale slab
   washing out the water. Verbatim copies of the Night values above. */
:root[data-theme='day'] .dock {
  --sheet: #0a1220;
  --ink: #f2f0e8;
  --record: #9aa3ad;
  --muted: #7d8794;
  --stale: #798393;
  --gold: #e3c47c;
  --gold-deep: #bd9750;
  --cyan: #8fd6e2;
  --white-bar: #f2f0e8;
  --rule-1: rgba(242, 240, 232, 0.08);
  --rule-2: rgba(242, 240, 232, 0.1);
  --rule-3: rgba(242, 240, 232, 0.18);
  --rule-4: rgba(242, 240, 232, 0.25);
  --rule-ink: #f2f0e8;
  --action-ground: rgba(242, 240, 232, 0.08);
  --action-rule: rgba(242, 240, 232, 0.2);
  --substrate-bottom: linear-gradient(180deg, rgba(6, 10, 18, 0), rgba(6, 10, 18, 0.9) 45%);
  --substrate-side: linear-gradient(270deg, rgba(6, 10, 18, 0.94), rgba(6, 10, 18, 0.88) 70%, rgba(6, 10, 18, 0));
}

/*==================================  base  ==================================*/

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.4;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

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

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

a {
  color: var(--ink);
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

button[disabled] {
  cursor: default;
  opacity: 0.5;
}

/* The two glyph roles: mono for anything that ticks, serif for facts of the game. */
.label {
  font: 500 11px/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

.m-gold {
  color: var(--gold);
}
.m-cyan {
  color: var(--cyan);
}
.m-ink {
  color: var(--ink);
}
.m-muted {
  color: var(--muted);
}
.m-white {
  color: var(--white-bar);
}

/*==================================  lake  ==================================*/

.lake {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
}

/*================================  controls  ================================*/

.controls {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 3;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: calc(6px + env(safe-area-inset-top, 0px)) 16px 0;
  pointer-events: none;
}

.controls > * {
  pointer-events: auto;
}

.controls h1 {
  font: 500 11px/1 var(--mono);
  letter-spacing: 0.22em;
  color: var(--ink);
  margin: 0;
  opacity: 0.85;
}

.brand {
  min-width: 0;
}

/* Desktop-only masthead additions (sprint-13 founder refinement): mobile
   keeps exactly the title it always had. */
.brand-sub,
.brand-social {
  display: none;
}

.control {
  font: 500 11px/1 var(--mono);
  letter-spacing: 0.08em;
  color: var(--ink);
  min-height: 32px;
  min-width: 32px;
  padding: 0 8px;
  border: 1px solid var(--rule-3);
  border-radius: 2px;
}

.control-connect {
  text-transform: none;
}

/*==================================  dock  ==================================*/

#app {
  position: relative;
  z-index: 2;
  height: 100%;
}

.dock {
  position: fixed;
  left: 0;
  right: 0;
  top: var(--sheet-top);
  bottom: 0;
  background: var(--sheet);
  border-top: 1px solid var(--rule-4);
  display: flex;
  flex-direction: column;
  padding: 0 20px calc(12px + env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

.banner,
.notice {
  position: fixed;
  left: 0;
  right: 0;
  z-index: 4;
  margin: 0;
  padding: 8px 20px;
  font: 400 12px/1.4 var(--serif);
  background: var(--sheet);
  color: var(--ink);
  border-bottom: 1px solid var(--rule-ink);
  overflow-wrap: anywhere;
}

.banner {
  top: calc(40px + env(safe-area-inset-top, 0px));
}

.notice {
  top: calc(40px + env(safe-area-inset-top, 0px));
  border-bottom-color: var(--rule-3);
  color: var(--record);
}

.banner + .notice {
  top: auto;
  bottom: 0;
  border-bottom: 0;
  border-top: 1px solid var(--rule-3);
}

/* Founder visual patch (founder UAT, 2026-09-16): `.notice` sits outside
   `.dock`, so in Day it inherited the light cream tokens and read as a pale
   card against the Twilight sky — the same issue `.tx-notice` had below,
   fixed the same way: the dark HUD tokens, re-scoped locally rather than
   reopening the Day palette. `--substrate-top` too: the desktop notice
   paints that gradient over `--sheet`, and Day's cream version turned the
   dark bar into a grey fade (founder UAT, 2026-09-16) — Night's value here
   makes the Day bar match Night's. */
:root[data-theme='day'] .notice {
  --sheet: #0a1220;
  --record: #9aa3ad;
  --rule-3: rgba(242, 240, 232, 0.18);
  --substrate-top: linear-gradient(180deg, rgba(6, 10, 18, 0.75), rgba(6, 10, 18, 0));
}

/*---- transaction notice ----*/

/*
 * Founder correction, sprint-13 final UAT: the old `.notice` bar rendered
 * every wallet-action outcome ("Steal the Spot: submitted — transaction
 * 0x…") and stayed until the next action replaced it — on desktop a
 * full-width bar cutting across the lake indefinitely. This is a distinct,
 * separate element (`main.ts`'s `txNotice`, never the old `notice` string),
 * compact and self-dismissing (lifecycle in `main.ts`; this is only the box).
 *
 * Mobile keeps the same top placement the founder already approved of for
 * `.notice`. Desktop moves it into the perimeter, above the Prize Purse,
 * instead of a full-width bar (see the `.glance`/`.g-purse` desktop rule for
 * the 24px right padding this aligns with).
 */
.tx-notice {
  position: fixed;
  z-index: 4;
  top: calc(40px + env(safe-area-inset-top, 0px));
  left: 16px;
  right: 16px;
  padding: 8px 10px;
  background: var(--sheet);
  color: var(--ink);
  border: 1px solid var(--rule-3);
  border-radius: 2px;
  font: 400 12px/1.4 var(--serif);
}

.tx-notice-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.tx-notice-text {
  flex: 1;
  min-width: 0;
  text-align: center;
}

.tx-notice-close {
  flex: none;
  color: var(--muted);
  font-size: 14px;
  line-height: 1;
  /* Sprint 15 accessibility pass (task 15.6): a 24 px target (WCAG 2.5.8) for
     the one dismiss control that had none — the glyph alone was 14 px. */
  min-height: 24px;
  min-width: 24px;
}

.tx-notice-link {
  display: inline-block;
  margin-top: 4px;
  font-size: 11px;
}

/* Founder visual patch (post-Sprint-14): the notice sits outside `.dock`, so
   in Day it inherited the cream slip-style tokens and read as a pale card on
   the lake. It keeps the dark HUD treatment in both worlds, at every width —
   the same Night values `:root[data-theme='day'] .dock` borrows, re-scoped
   as tokens (not literal colours) so the close control, the explorer link
   and the `.tx-notice-superseded` border keep their own contrast too. */
:root[data-theme='day'] .tx-notice {
  --sheet: #0a1220;
  --ink: #f2f0e8;
  --muted: #7d8794;
  --rule-3: rgba(242, 240, 232, 0.18);
  --rule-4: rgba(242, 240, 232, 0.25);
}

/*---- strip ----*/

.strip {
  height: 30px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font: 500 12px/1 var(--mono);
  letter-spacing: 0.14em;
  color: var(--muted);
  white-space: nowrap;
}

.strip-ink {
  color: var(--ink);
}

/* Founder visual patch: the "IN <unit>" run of the Lines Up readout is its
   own span (`render-dock.ts`) so the desktop masthead can darken it over the
   bright celestial art. `.strip-r` is a flex container, which drops the word
   gaps on either side of a child element at every width — these margins
   restore them. The colour itself is desktop-only, further down. */
.strip-emph {
  margin: 0 0.35em;
}

.strip-l,
.strip-r {
  display: inline-flex;
  align-items: center;
  gap: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.strip-phase {
  display: none;
}

/* B-06: shown inline at every width (desktop repositions it into a top-right
   pill below). Width-independent because wallet-state truth, not
   presentation, lives here: `.controls:has(~ #app .strip-account)` below
   reads this element's presence to decide whether the masthead's Connect
   action is stale, so hiding it only on mobile left mobile with no way to
   ever suppress that button once connected. */
.strip-account {
  display: inline;
  margin-left: 6px;
}

/* B-06: the Connect action and this address pill are mutually exclusive —
   was scoped to the desktop (min-width: 1024px) breakpoint only, so a
   connected mobile visitor still saw an enabled "Connect wallet" in the
   masthead. */
.controls:has(~ #app .strip-account) .control-connect {
  display: none;
}

.strip-controls {
  display: inline-flex;
  gap: 4px;
  margin-left: 10px;
}

.strip-controls .control {
  min-height: 24px;
  min-width: 24px;
  padding: 0 4px;
  border-color: var(--rule-2);
  font-size: 12px;
  letter-spacing: 0;
}

/*
 * Utility-control material (founder, 2026-09-16): header Connect wallet, the
 * Day/Night and Sound toggles, and the X/Discord icon buttons (the active
 * navigation item uses the same tokens, desktop only, further down). Clear molded plastic, not frosted glass: a
 * lightly smoked clear body you can see the sky through, a glossy lip along
 * the top edge where the moulding catches light, one curved reflection
 * across the face, a faint refraction of what sits behind it, and a soft
 * contact shadow.
 *
 * Light ink in BOTH themes. These controls sit on the deep-blue upper sky
 * (desktop) and the planet and aurora (mobile); dark ink there measured
 * about 1.5:1 on Connect wallet before this change. The smoked body keeps
 * light ink legible over the brighter patches as well.
 *
 * Declared AFTER `.strip-controls .control` so its border wins for the
 * toggles at equal specificity. Replaces Connect wallet's old 0.85 opacity
 * "defer": the translucency itself keeps it quieter than the dock slot's
 * primary Connect wallet, which is a primary action and deliberately
 * untouched. Positions stay with the desktop rules below (`position: fixed`
 * there overrides this `relative`).
 */
:root {
  --molded-body:
    linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.02) 48%, rgba(6, 10, 18, 0.1) 100%),
    rgba(6, 10, 18, 0.22);
  --molded-rim: rgba(255, 255, 255, 0.2);
  --molded-depth:
    inset 0 1px 0 rgba(255, 255, 255, 0.38),
    inset 0 -1px 0 rgba(255, 255, 255, 0.08),
    0 1px 1px rgba(0, 0, 0, 0.2),
    0 6px 14px -8px rgba(0, 0, 0, 0.45);
  --molded-gloss: linear-gradient(118deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.06) 42%, rgba(255, 255, 255, 0) 43%);
}

.controls .control-connect,
.strip-controls [data-theme-toggle],
.strip-controls [data-sound-toggle],
.brand-social .social-link {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  color: #f2f0e8;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35);
  border: 1px solid var(--molded-rim);
  border-radius: 6px;
  background: var(--molded-body);
  box-shadow: var(--molded-depth);
  -webkit-backdrop-filter: blur(2px) saturate(150%);
  backdrop-filter: blur(2px) saturate(150%);
  transition:
    border-color 160ms ease-out,
    background-color 160ms ease-out;
}

/* The curved reflection across the face, under the label. */
.controls .control-connect::before,
.strip-controls [data-theme-toggle]::before,
.strip-controls [data-sound-toggle]::before,
.brand-social .social-link::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--molded-gloss);
  pointer-events: none;
}

/* A single specular glint on the top lip. */
.controls .control-connect::after,
.strip-controls [data-theme-toggle]::after,
.strip-controls [data-sound-toggle]::after,
.brand-social .social-link::after {
  content: '';
  position: absolute;
  top: 0;
  left: 16%;
  width: 34%;
  height: 1px;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0));
  pointer-events: none;
}

.controls .control-connect:hover,
.strip-controls [data-theme-toggle]:hover,
.strip-controls [data-sound-toggle]:hover,
.brand-social .social-link:hover {
  border-color: rgba(255, 255, 255, 0.32);
  background-color: rgba(6, 10, 18, 0.14);
}

.controls .control-connect:active,
.strip-controls [data-theme-toggle]:active,
.strip-controls [data-sound-toggle]:active,
.brand-social .social-link:active {
  box-shadow:
    inset 0 1px 2px rgba(0, 0, 0, 0.3),
    inset 0 -1px 0 rgba(255, 255, 255, 0.06),
    0 1px 1px rgba(0, 0, 0, 0.2);
}

/*---- glance ----*/

/* The glance: ring left, Time on Spot and the Purse stacked in its margin,
   the relation and ruled rows below, the bar and the action at the bottom. */
.glance {
  flex: 1 0 auto;
  display: grid;
  grid-template-columns: 112px minmax(0, 1fr);
  grid-template-rows: auto auto auto 1fr;
  grid-template-areas:
    'ring time'
    'ring purse'
    'mid mid'
    'bottom bottom';
  column-gap: 16px;
  row-gap: 8px;
  align-items: center;
  margin-top: 10px;
  min-height: 0;
}

.g-ring {
  grid-area: ring;
  align-self: center;
}
.g-time {
  grid-area: time;
  align-self: end;
  min-width: 0;
}
.g-purse {
  grid-area: purse;
  align-self: start;
  min-width: 0;
}
.g-mid {
  grid-area: mid;
}
.g-bottom {
  grid-area: bottom;
  align-self: end;
}

.ring {
  width: 108px;
  height: 108px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--rule-4);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  text-align: center;
  padding: 0 8px;
}

.ring-full {
  border-color: var(--ink);
}
.ring-dashed {
  border-style: dashed;
}
.ring-closed {
  border-color: var(--rule-3);
}

.ring-label {
  font: 500 9px/1 var(--mono);
  letter-spacing: 0.16em;
  color: var(--muted);
}

.ring-holder {
  font: 500 12px/1 var(--mono);
  color: var(--ink);
  overflow-wrap: anywhere;
}

.ring-you .ring-holder,
.ring-dashed .ring-holder,
.ring-closed .ring-holder {
  font: 400 15px/1 var(--serif);
  overflow-wrap: normal;
  word-break: keep-all;
}

.ring-sub {
  font: 400 10px/1.2 var(--serif);
  color: var(--record);
}

.ring-sub.m-cyan {
  font: 500 10px/1.2 var(--mono);
  color: var(--cyan);
}

.margin-item .label {
  display: block;
  margin-bottom: 6px;
}

.margin-value {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}

.margin-note,
.relation-note,
.provenance {
  font: 400 11px/1.3 var(--serif);
  color: var(--muted);
  margin: 2px 0 0;
}

/* Figures: tabular mono. The exact value is one tap away. */
.fig {
  font: 500 14px/1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: left;
  min-height: 24px;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  overflow-wrap: anywhere;
}

.fig-figure {
  font-size: 20px;
}

.fig-small {
  font-size: 12px;
}

.fig .unit {
  font-size: 0.8em;
  color: inherit;
  opacity: 0.85;
}

.fig.unavailable {
  color: var(--muted);
  font-style: italic;
  font-family: var(--serif);
  font-weight: 400;
}

/* A figure that is a sentence (genesis: "No paid hold yet…") is a fact of the game: serif. */
.fig.fig-sentence {
  font: 400 12px/1.35 var(--serif);
  color: var(--record);
  cursor: default;
}

.fig.is-stale,
[data-stale] .m-gold,
[data-stale] .m-cyan,
[data-stale] .fig {
  color: var(--stale);
}

/* B-04: `.fig .unit`'s 0.85 opacity blends toward the ground and would drag
   an already-AA-minimum `--stale` back under 4.5:1 for the unit suffix of a
   stale figure. `--stale` is already the dimmed reading; the unit does not
   need to be dimmed twice. */
.fig.is-stale .unit,
[data-stale] .fig .unit {
  opacity: 1;
}

/*---- relation and ruled rows ----*/

.relation,
.ruled-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--rule-2);
  min-height: 40px;
  width: 100%;
  text-align: left;
}

.relation {
  flex-wrap: wrap;
}

.relation-label,
.ruled-label {
  font: 400 13px/1.2 var(--serif);
  color: var(--record);
  flex: 1;
  min-width: 0;
}

.relation-note {
  flex-basis: 100%;
}

.ruled-value {
  font: 500 13px/1 var(--mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ruled-row-action {
  color: inherit;
}

.ruled-row-bite .ruled-label {
  font-size: 12px;
}

/*---- price bar ----*/

.g-bottom {
  padding-top: 12px;
}

.bar-caption,
.bar-ends {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font: 400 10px/1 var(--mono);
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-bottom: 8px;
}

.bar-ends {
  color: var(--gold-deep);
  margin: 8px 0 10px;
}

.bar {
  position: relative;
  height: 2px;
  background: var(--rule-2);
}

.bar-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  background: var(--gold);
  transition: width 1s linear;
}

.bar-cyan {
  margin-top: 8px;
}
.bar-cyan .bar-fill {
  background: var(--cyan);
}

/* An empty bar is not a missing bar: a 2px end mark remains. */
.bar-end {
  position: absolute;
  right: 0;
  top: -1px;
  width: 2px;
  height: 4px;
  background: var(--gold);
}

.bar-frozen .bar-fill,
.bar-frozen .bar-end,
[data-stale] .bar-fill,
[data-stale] .bar-end {
  background: var(--stale);
  transition: none;
}

.is-frozen .bar-caption,
[data-stale] .bar-ends {
  color: var(--stale);
}

/*---- the slot ----*/

.slot {
  min-height: 56px;
}

.primary-action {
  width: 100%;
  min-height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: var(--action-ground);
  border: 1px solid var(--action-rule);
  border-radius: 2px;
  text-decoration: none;
  color: var(--ink);
}

.primary-label {
  font: 400 18px/1 var(--serif);
  color: var(--ink);
}

.primary-action .fig {
  font-size: 16px;
  min-height: 0;
}

.primary-action .dot {
  color: var(--muted);
}

.slot-text {
  min-height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 400 15px/1.3 var(--serif);
  color: var(--record);
  text-align: center;
  padding: 8px 0;
}

/*
 * The rail's primary action in molded clear plastic (founder, 2026-09-16) —
 * the heavier sibling of the utility-control material: a denser smoked body,
 * a brighter top lip, a deeper contact shadow, a larger radius. Same object
 * family, clearly the one that matters. Colour stays semantic: the label is
 * ink and the amount keeps its own gold; the material carries no tint.
 *
 * Scoped to `.slot` on purpose. The slip's irreversible confirm and the
 * interstitial's Continue share `.primary-action` (as `.slip-submit`) but sit
 * on the light slip ground, where this dark-sky material does not belong and
 * whose contrast is pinned by the A-S14-5 suite.
 *
 * Guardrail: a disabled or busy primary action is FLAT — no gloss, no lip, no
 * shadow, no refraction — so a state that means "do not press" never looks
 * pressable. The rail does not render a disabled button today (every
 * fail-closed state renders `.slot-text` instead); this holds for any that do.
 */
.slot .primary-action {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 8px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.13) 0%, rgba(255, 255, 255, 0.03) 50%, rgba(6, 10, 18, 0.16) 100%),
    rgba(6, 10, 18, 0.38);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    inset 0 -1px 0 rgba(255, 255, 255, 0.1),
    0 1px 2px rgba(0, 0, 0, 0.3),
    0 12px 26px -12px rgba(0, 0, 0, 0.6);
  -webkit-backdrop-filter: blur(3px) saturate(150%);
  backdrop-filter: blur(3px) saturate(150%);
  transition:
    border-color 160ms ease-out,
    background-color 160ms ease-out;
}

.slot .primary-action::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--molded-gloss);
  pointer-events: none;
}

.slot .primary-action::after {
  content: '';
  position: absolute;
  top: 0;
  left: 12%;
  width: 40%;
  height: 1px;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
  pointer-events: none;
}

.slot .primary-action:hover {
  border-color: rgba(255, 255, 255, 0.36);
  background-color: rgba(6, 10, 18, 0.3);
}

.slot .primary-action:active {
  box-shadow:
    inset 0 2px 4px rgba(0, 0, 0, 0.35),
    inset 0 -1px 0 rgba(255, 255, 255, 0.06),
    0 1px 1px rgba(0, 0, 0, 0.25);
}

.slot .primary-action:is([disabled], [aria-disabled='true'], [aria-busy='true']) {
  text-shadow: none;
  border-color: var(--action-rule);
  background: var(--action-ground);
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.slot .primary-action:is([disabled], [aria-disabled='true'], [aria-busy='true'])::before,
.slot .primary-action:is([disabled], [aria-disabled='true'], [aria-busy='true'])::after {
  content: none;
}

/*---- depth links ----*/

nav.primary {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin-top: 18px;
  padding-top: 12px;
  border-top: 1px solid var(--rule-2);
}

.nav-item {
  font: 500 12px/1 var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  min-height: 32px;
  display: inline-flex;
  align-items: center;
}

.nav-item::after {
  content: ' →';
  white-space: pre;
}

.nav-item.active {
  color: var(--ink);
}

/*---- depth: the six surfaces as ruled rows ----*/

.depth {
  flex: none;
  padding-bottom: 12px;
}

/* Founder UAT (2026-09-16): every surface's panel opens and closes from the
   navigation row, not just The Hot Spot's (`main.ts` sets `data-depth`:
   arriving at a surface opens it, clicking its active nav item again — or
   Escape — closes it). At every width, not only desktop: below 1024px the
   panel otherwise stayed on screen while the nav item said
   `aria-expanded="false"` (independent review, founder UAT patch). */
.dock .depth {
  display: none;
}

.dock[data-depth='1'] .depth {
  display: block;
}

.surface h2 {
  font: 300 26px/1.15 var(--serif);
  margin: 18px 0 8px;
  color: var(--ink);
}

.fields {
  margin: 8px 0;
}

.row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 9px 0;
  border-top: 1px solid var(--rule-1);
}

.row .label {
  font: 400 12px/1.3 var(--serif);
  text-transform: none;
  letter-spacing: 0;
  color: var(--record);
  flex: 1;
}

.value {
  font: 500 12px/1.3 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: right;
  overflow-wrap: anywhere;
}

.unit {
  color: var(--muted);
}

/* `Unavailable` is rendered in the muted colour and in italics so it cannot be
   mistaken for a reading at a glance. It is never a dash and never a zero. */
.value.unavailable {
  color: var(--muted);
  font-style: italic;
  font-family: var(--serif);
  font-weight: 400;
}

.value.provenance-stale,
.value.provenance-stale-derived,
.stale-mark {
  color: var(--stale);
}

.note {
  font: 400 13px/1.45 var(--serif);
  color: var(--record);
  max-width: 62ch;
  margin: 10px 0;
}

/* FR-19 contextual rows and the link to the register entry they summarise. */
.contextual {
  font: 400 13px/1.45 var(--serif);
  color: var(--record);
  max-width: 62ch;
  margin: 10px 0;
  padding-left: 10px;
  border-left: 1px solid var(--rule-2);
}

.truth-link {
  color: inherit;
  text-decoration: underline;
  white-space: nowrap;
}

/* FR-21 keystone sentence: the one-line distinction, set before the detail. */
.keystone {
  font: 500 14px/1.4 var(--serif);
  margin: 0 0 6px;
}

.action {
  border-top: 1px solid var(--rule-2);
  padding: 12px 0;
  margin: 12px 0;
  max-width: 62ch;
}

.bound,
.confirm {
  display: block;
  margin-bottom: 10px;
  font: 400 13px/1.4 var(--serif);
  color: var(--record);
}

.bound input {
  display: block;
  width: 100%;
  margin-top: 6px;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--rule-3);
  padding: 10px;
  font: 500 14px/1 var(--mono);
  font-variant-numeric: tabular-nums;
}

.action button[type='submit']:not(.primary-action) {
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--action-rule);
  background: var(--action-ground);
  border-radius: 2px;
  font: 400 15px/1 var(--serif);
}

.disabled-reason {
  font: 400 12px/1.4 var(--serif);
  color: var(--record);
  margin: 8px 0 0;
}

.disclosure {
  border-top: 1px solid var(--rule-2);
  padding-top: 10px;
  max-width: 62ch;
}

.truth-short {
  max-width: 62ch;
  border-top: 1px solid var(--rule-2);
  padding: 10px 0 16px;
}

/* Founder UAT (Sprint 15, 2026-09-18): the panel headings take the panel's own
   ink, as `.surface h2` does. Left to inherit, they took the page's Day ink
   (near-black) on the dark panel. The prose beneath keeps `--record`, Night's
   grey, in both themes. */
.truth-short h3 {
  font: 400 18px/1.3 var(--serif);
  margin: 8px 0;
  color: var(--ink);
}

.truth-short ul {
  margin: 0;
  padding-left: 20px;
  font: 400 13px/1.45 var(--serif);
  color: var(--record);
}

.truth-short li { margin: 6px 0; }

.disclosure h3 {
  font: 400 16px/1.3 var(--serif);
  margin: 12px 0 6px;
  color: var(--ink);
}

.disclosure p {
  font: 400 13px/1.45 var(--serif);
  color: var(--record);
}

.giga {
  margin: 12px 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.external {
  font: 400 15px/1.3 var(--serif);
  color: var(--ink);
  min-height: 32px;
  display: inline-flex;
  align-items: center;
}

.giga-note {
  margin: 0;
}

/*---- the record ----*/

.record {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--rule-2);
}

.record .label {
  margin-bottom: 8px;
}

.record-entry {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  gap: 10px;
  align-items: baseline;
  font: 400 11px/1.3 var(--mono);
  color: var(--record);
  padding: 5px 0;
}

.record-time {
  color: var(--muted);
}

.record-who {
  color: var(--ink);
}

.record-you .record-who {
  font-family: var(--serif);
  font-size: 12px;
}

.record-amount {
  font-variant-numeric: tabular-nums;
  color: var(--gold-deep);
}

.record-unavailable .record-what,
.record-empty {
  color: var(--muted);
  font-style: italic;
  font-family: var(--serif);
  font-size: 12px;
  margin: 4px 0;
}

/*==================================  slip  ==================================*/

.scrim {
  position: fixed;
  inset: 0;
  z-index: 5;
  background: var(--scrim);
}

.slip {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  top: auto;
  width: 100%;
  max-width: 100%;
  max-height: calc(100% - 40px);
  margin: 0;
  padding: 0 20px calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 6;
  background: var(--slip-ground);
  color: var(--slip-ink);
  border: 0;
  border-top: 2px solid var(--slip-ink);
  overflow-y: auto;
  font-family: var(--serif);
  transform: translateY(0);
  /* B-05: `--focus` is `:root`'s dark-world cyan (#8fd6e2), which measures
     1.28:1 on the slip's light ground in the default (Night) theme — the
     transaction path's only light surface. `--slip-cyan` already clears
     WCAG 1.4.11's 3:1 UI-component floor on both slip grounds (5.72:1 /
     6.67:1), so every `:focus-visible` ring inside the slip inherits it
     instead of the world-scoped token. */
  --focus: var(--slip-cyan);
}

.slip:not([open]) {
  display: none;
}

/*
 * The one-shot entrance animation. Deliberately NOT on the bare `.slip` rule
 * above: `paint()` (main.ts) recreates this dialog node on every repaint —
 * every 1s tick, every 10s poll, every settle-poll after a sent transaction —
 * same as the rest of the page. An animation on `.slip` itself replays on
 * every one of those recreations, which is exactly what sprint-13's P0 UAT
 * defect was: the slip visibly minimizing and re-expanding in a loop. This
 * class is added only on the render where the slip genuinely transitions from
 * closed to open (`DockUi.slipJustOpened`), never on a routine repaint of an
 * already-open slip.
 */
.slip.slip-entering {
  animation: slip-rise 320ms ease-out;
}

@keyframes slip-rise {
  from {
    transform: translateY(24px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.slip-form {
  border: 0;
  margin: 0;
  padding: 0;
  max-width: 560px;
  margin-inline: auto;
}

.slip-head {
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--slip-rule);
  margin-bottom: 12px;
}

.slip-title {
  font: 500 11px/1 var(--mono);
  letter-spacing: 0.14em;
  color: var(--slip-ink);
}

.slip-cancel {
  font: 400 14px/1 var(--serif);
  color: var(--slip-muted);
  min-height: 44px;
  padding: 0 4px;
}

.slip-steps {
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
}

.slip-step {
  display: grid;
  grid-template-columns: 20px 1fr auto;
  gap: 10px;
  align-items: baseline;
  padding: 8px 0;
  border-top: 1px solid var(--slip-rule);
  font: 400 14px/1.3 var(--serif);
}

.slip-step-index {
  font: 500 11px/1 var(--mono);
  color: var(--slip-muted);
}

.slip-step-detail {
  font: 400 11px/1.3 var(--mono);
  color: var(--slip-muted);
  text-align: right;
}

.slip-step-current .slip-step-label,
.slip-step-current .slip-step-index {
  color: var(--slip-ink);
  font-weight: 500;
}

.slip-step-done {
  color: var(--slip-muted);
  text-decoration: line-through;
}

.slip-step-next {
  color: var(--slip-muted);
}

.slip-note,
.slip-sentence {
  font: 400 14px/1.45 var(--serif);
  color: var(--slip-ink);
  margin: 8px 0;
}

.slip-note {
  color: var(--slip-muted);
  font-size: 12px;
}

.slip-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid var(--slip-rule);
}

.slip-row-label {
  font: 400 13px/1.3 var(--serif);
  color: var(--slip-muted);
  flex: 1;
}

.slip-row-value {
  font: 500 16px/1 var(--mono);
  font-variant-numeric: tabular-nums;
}

.slip-row .m-gold {
  color: var(--slip-gold);
}
.slip-row .m-cyan {
  color: var(--slip-cyan);
}
.slip-row .m-ink {
  color: var(--slip-ink);
}

.slip-split {
  padding: 6px 0;
  border-top: 0;
}

.slip-split + .slip-split {
  border-top: 0;
}

.slip-pct {
  font: 500 12px/1 var(--mono);
  color: var(--slip-ink);
  width: 44px;
  flex: none;
}

.slip-split .slip-row-value {
  font-size: 13px;
}

.slip h4.label {
  color: var(--slip-muted);
  margin: 14px 0 4px;
}

.slip-bound {
  display: block;
  margin: 10px 0;
  color: var(--slip-muted);
}

.slip-bound input {
  display: block;
  width: 100%;
  margin-top: 6px;
  background: #fff;
  color: var(--slip-ink);
  border: 1px solid var(--slip-ink);
  padding: 10px;
  font: 500 16px/1 var(--mono);
  font-variant-numeric: tabular-nums;
}

.slip-warning {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 10px;
  align-items: start;
  margin: 14px 0;
  padding: 12px 0;
  border-top: 1px solid var(--slip-ink);
  border-bottom: 1px solid var(--slip-ink);
}

.slip-warning .bang {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid var(--slip-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: 500 12px/1 var(--mono);
}

.slip-warning p {
  margin: 0;
  font: 400 14px/1.45 var(--serif);
}

.slip-ack {
  display: flex;
  gap: 10px;
  align-items: start;
  margin: 10px 0 14px;
  font: 400 13px/1.45 var(--serif);
  color: var(--slip-ink);
}

.slip-ack input {
  margin-top: 3px;
  width: 18px;
  height: 18px;
  flex: none;
}

.slip .disabled-reason {
  color: var(--slip-muted);
}

.slip-submit {
  position: sticky;
  bottom: 0;
  background: var(--slip-ink);
  border-color: var(--slip-ink);
  color: var(--slip-ground);
  margin-top: 6px;
  box-shadow: 0 -12px 12px -6px var(--slip-ground);
}

.slip-submit .primary-label {
  color: var(--slip-ground);
}

.slip-submit .m-gold {
  color: #f4dc98;
}

/* Security audit A-S14-5. `.slip-submit` paints itself `--slip-ink` (near
   black in both worlds), so every material inside it needs a light-on-dark
   value — `.m-gold` and `.m-ink` had one and `.m-cyan` did not, falling back
   to the world token `--cyan`. In Night that is #8fd6e2 and reads at 11.6:1;
   in Day it is #155f6c, a dark teal on near-black, measuring 2.54:1 — below
   AA (4.5:1) and below AA-large (3:1). That is the amount on the irreversible
   confirm button: the one figure on this control that is money. Fixed here
   rather than by reopening the Day palette, exactly as `.slip-row .m-cyan`
   one selector away already re-scopes cyan for the slip's light ground.
   #8fd6e2 on #0d1420 measures 11.46:1 and keeps cyan meaning CATCH. */
.slip-submit .m-cyan {
  color: #8fd6e2;
}

.slip-submit .m-ink {
  color: var(--slip-ground);
}

.slip-submit[disabled] {
  opacity: 0.4;
}

/*=============================  mobile sheet  ==============================*/

/* Founder visual patch (post-Sprint-14): in Day the mobile title inherited
   the world's dark ink and blended into the twilight sky art; it takes the
   light ink here, mobile only — the desktop Day masthead was not reported. */
@media (max-width: 1023px) {
  :root[data-theme='day'] .controls h1 {
    color: #f2f0e8;
  }
}

/*=============================  desktop perimeter  ==========================*/

@media (min-width: 1024px) {
  .dock {
    top: 0;
    background: transparent;
    border-top: 0;
    padding: 0;
    overflow: visible;
    pointer-events: none;
  }

  .dock > * {
    pointer-events: auto;
  }

  /* Masthead (sprint-13 founder refinement): a 112px band with the brand
     block anchored left by `.controls` (below), this centred Day/Lines-Up
     module, and the wallet + theme/sound cluster anchored right (also
     `.controls`, plus the fixed-positioned escapes further down) — then a
     quieter 32px nav row underneath, backed by the same two-tier scrim the
     strip always had. */
  /* Founder UAT (2026-09-16): the brand block steps in to the same 24px
     inset the bottom rail uses. */
  .controls {
    height: 112px;
    align-items: flex-start;
    padding: 22px 16px 0 24px;
  }

  /* Founder UAT (2026-09-16): title, subtitle and the social buttons read as
     one centred lockup rather than a ragged left edge. */
  .brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .brand h1 {
    font: 500 28px/1.05 var(--serif);
    letter-spacing: 0.01em;
    opacity: 1;
  }

  .brand-sub {
    display: block;
    max-width: 220px;
    margin: 4px 0 0;
    font: 500 12px/1.3 var(--mono);
    letter-spacing: 0.1em;
    color: var(--muted);
  }

  .brand-social {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: 8px;
  }

  /* Founder UAT (2026-09-16): logo buttons in the utility material (rule
     above), sized with the Day/Night and Sound toggles. */
  .social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    text-decoration: none;
  }

  .social-icon {
    display: block;
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35));
  }

  .social-icon-x {
    width: 14px;
    height: 13px;
  }

  .social-icon-discord {
    width: 18px;
    height: 18px;
  }

  .strip {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 112px;
    /* Founder visual patch: the Day counter levels with the title row instead
       of centring in the band (which sat it visibly lower than THE BIG ONE). */
    padding-top: 24px;
    background: var(--substrate-top);
    color: var(--record);
    font-size: 11px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 6px;
    pointer-events: none;
  }

  .strip > * {
    pointer-events: auto;
  }

  /* The centred game-state module (founder spec: Day primary, Lines Up
     secondary, "a single centred module"). `.strip-r`'s account/controls
     children escape to fixed positioning further down, leaving only the
     countdown text on this line. */
  .strip-l {
    font-size: 20px;
    letter-spacing: 0.06em;
  }

  .strip-r {
    font-size: 12px;
    letter-spacing: 0.14em;
    color: var(--muted);
  }

  /* Founder visual patch: the "IN <unit>" run of the Lines Up readout lands
     on the bright celestial art at the masthead centre, where `--muted` sits
     too close to the moon; only that run darkens (`render-dock.ts` wraps it;
     the base `.strip-emph` rule carries the word gaps). Desktop only: below
     1024 the strip sits on the solid dark sheet, where this ink would be
     illegible. Night only (founder UAT, 2026-09-16): Day's strip already
     takes the darker `--slip-ink` from the Day scope below, and this navy
     read lighter than the words around it there. */
  :root:not([data-theme='day']) .strip-emph {
    color: #1c2a3d;
  }

  /* Founder correction: the masthead brand block, the strip, and the
     depth-links nav all sit directly over the Day sky art with no backing,
     so they take one ink of their own here. Founder UAT (2026-09-16): that
     ink is now light, not dark — the top of the Day art is a deep-blue
     twilight sky with aurora, where dark ink measured about 1.5:1 and the
     light Connect wallet read far better than the title and nav beside it.
     All three tokens take the same light value, with the same faint shadow
     the utility controls carry to hold it over the brighter patches. Rules
     go light with them (the strip's address-pill border). */
  :root[data-theme='day'] .controls,
  :root[data-theme='day'] .strip,
  :root[data-theme='day'] nav.primary {
    --ink: #f2f0e8;
    --muted: #f2f0e8;
    --record: #f2f0e8;
    --rule-2: rgba(242, 240, 232, 0.1);
    --rule-3: rgba(242, 240, 232, 0.18);
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35);
  }

  /* Founder correction: no gradient slab behind the Day top strip — the text
     sits directly on the art, the way mobile Day already does; colour
     (above) carries legibility instead of a filled backing. Night keeps its
     scrim, unchanged — its sky needs the assist this one doesn't. */
  :root[data-theme='day'] .strip {
    background: none;
  }

  /* Theme and sound stop being an inline group and escape to their own fixed
     positions beside the wallet — the wrapper keeps no box of its own. */
  .strip-controls {
    display: contents;
  }

  .strip-phase {
    display: inline;
  }

  /* Wallet utility anchor, top-right: the Connect action (in `.controls`) and
     this address pill are mutually exclusive (the base rule's width-independent
     `:has()` swap decides which shows), so they share one slot. */
  .controls .control-connect {
    display: inline-flex;
    align-items: center;
    position: fixed;
    top: 26px;
    right: 100px;
    z-index: 3;
  }

  .strip-account {
    display: inline-flex;
    align-items: center;
    margin-left: 0;
    position: fixed;
    top: 26px;
    right: 100px;
    min-height: 32px;
    padding: 0 8px;
    border: 1px solid var(--rule-3);
    border-radius: 2px;
    font: 500 11px/1 var(--mono);
    letter-spacing: 0.04em;
    color: var(--ink);
    z-index: 3;
  }

  /* Day/Night and Sound sit to the right of the wallet slot, closest to the
     edge — the standard utility corner most sites use. The extra `.strip-controls`
     qualifier matches the base `.strip-controls .control` rule's specificity
     so this 32px sizing (matching the wallet slot) actually wins the cascade. */
  .strip-controls [data-theme-toggle],
  .strip-controls [data-sound-toggle] {
    position: fixed;
    top: 26px;
    min-height: 32px;
    min-width: 32px;
    z-index: 3;
  }

  [data-theme-toggle] {
    right: 56px;
  }

  [data-sound-toggle] {
    right: 16px;
  }

  .banner,
  .notice {
    top: 144px;
    left: 0;
    right: 0;
    background: var(--substrate-top);
    background-color: var(--sheet);
  }

  .banner + .notice {
    top: auto;
  }

  /* Founder correction: the perimeter above the Prize Purse, not a full-width
     bar cutting across the lake. Right-aligned to match `.glance`'s own 24px
     right padding. Founder visual patch: lowered from just above the band
     (322px) to sit directly above the Prize Purse figures. */
  .tx-notice {
    top: auto;
    left: auto;
    right: 24px;
    bottom: 140px;
    width: 260px;
  }

  /* The bottom dock rail: ring · Time on Spot | rows, bar + action | Purse · You.
     Two gradients that end before the angler; no container.
     Height carries margin above the richest measured tournament sub-state
     (B-01: holder + accrual-capped note + Chum row measured at 106px of
     `.g-mid`, pushing the price bar/CTA row up to 58px below the 1024×720
     viewport when the band was 300px) so the primary action never needs a
     scroll that this pointer-events:none rail cannot itself offer. */
  .glance {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 300px;
    padding: 48px 24px 22px;
    background: var(--substrate-bottom);
    grid-template-columns: 96px minmax(140px, 1fr) 340px minmax(180px, 1fr);
    grid-template-rows: auto auto;
    grid-template-areas:
      'ring time mid purse'
      'ring time bottom purse';
    column-gap: 28px;
    row-gap: 6px;
    align-items: end;
    max-width: 1280px;
    margin: 0 auto;
    pointer-events: none;
  }

  .glance > * {
    pointer-events: auto;
  }

  .g-ring,
  .g-time,
  .g-purse {
    align-self: end;
  }

  .g-purse {
    text-align: right;
  }

  /* Founder visual patch: 106px — deliberately short of mobile's 108px so
     the ring at 1024 stays clear of the water's edge. */
  .ring {
    width: 106px;
    height: 106px;
  }

  .relation,
  .ruled-row {
    margin-top: 0;
    padding-top: 6px;
    border-top: 0;
    min-height: 0;
  }

  .g-bottom {
    padding-top: 0;
  }

  .bar-caption,
  .bar-ends {
    margin-bottom: 6px;
  }

  .bar-ends {
    margin: 6px 0 10px;
  }

  .slot,
  .primary-action {
    min-height: 52px;
  }

  /* Row 2: a calmer, smaller nav than the masthead above it — centred rather
     than right-anchored, so six labels read as one quiet row. */
  nav.primary {
    position: absolute;
    top: 84px;
    left: 0;
    right: 0;
    height: 32px;
    margin: 0;
    padding: 0;
    border: 0;
    display: flex;
    justify-content: center;
    gap: 20px;
    align-items: center;
    flex-wrap: nowrap;
    white-space: nowrap;
  }

  /* Founder visual patch: the surrogate's base `.nav-item` went to 12px but
     this desktop override stayed at 10px, so every desktop viewport the
     founder judged rendered the nav at 10px — and 12px here runs the row
     into the brand's social links at 1024. Kept at what was approved on
     screen; the base rule (mobile) carries the 12px. */
  .nav-item {
    font-size: 10px;
    letter-spacing: 0.12em;
    min-height: 32px;
  }

  /* Founder visual patch: "Prize Purse" lands on the moon in the sky art,
     where `--muted` is too close in value; darkened by its existing href
     alone. Desktop only, like `.strip-emph` above — on the mobile sheet this
     ink would be illegible. Night only, for the same reason as `.strip-emph`:
     in Day the other nav items already carry the darker `--slip-ink`. */
  :root:not([data-theme='day']) nav.primary a[href='#purse']:not(.active) {
    color: #1c2a3d;
  }

  /* Founder UAT (2026-09-16): the active item is the one molded chip in the
     row — the same material as the utility controls (shared tokens), with
     the reflection but no lip glint, because `::after` is the item's arrow.
     Negative margins cancel the chip's padding so the row does not shift
     when the active item changes. The Night navy above skips the active
     item: that ink is for bare text over the moon, not inside a chip. */
  nav.primary .nav-item.active {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: 0 10px;
    margin: 0 -10px;
    color: #f2f0e8;
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35);
    border: 1px solid var(--molded-rim);
    border-radius: 6px;
    background: var(--molded-body);
    box-shadow: var(--molded-depth);
    -webkit-backdrop-filter: blur(2px) saturate(150%);
    backdrop-filter: blur(2px) saturate(150%);
  }

  nav.primary .nav-item.active::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: var(--molded-gloss);
    pointer-events: none;
  }

  /* Founder UAT (2026-09-16): the active item's arrow turns back on itself
     while its detail column is open — clicking it again closes the column.
     Desktop only: below 1024 the detail is inline and always shown. */
  .nav-item[aria-expanded='true']::after {
    content: ' ←';
  }

  .ring {
    padding: 0 4px;
  }

  .ring-label {
    font-size: 8px;
    letter-spacing: 0.12em;
  }

  .ring-you .ring-holder,
  .ring-dashed .ring-holder,
  .ring-closed .ring-holder {
    font-size: 14px;
    overflow-wrap: normal;
    word-break: keep-all;
  }

  /* Depth: a right-anchored column between the strip and the rail; a gradient
     substrate that ends before the angler and never boxes the lake. */
  .depth {
    position: absolute;
    top: 144px;
    right: 0;
    bottom: 300px;
    width: 480px;
    max-width: 44vw;
    padding: 12px 24px 12px 48px;
    overflow-y: auto;
    background: var(--substrate-side);
  }

  /* The record: quiet type in the dark water under the dock. Founder visual
     patch: down from above the band (304px) to sit just above the ring /
     TIME ON SPOT grouping; 1280 and 1440 move together. */
  .record {
    position: absolute;
    left: 24px;
    bottom: 152px;
    width: 360px;
    margin: 0;
    padding: 0;
    border: 0;
  }

  .record .label {
    display: none;
  }

  .record-entry {
    grid-template-columns: 40px 1fr auto;
    padding: 4px 0;
  }

  .slip {
    left: 50%;
    right: auto;
    bottom: 0;
    width: 560px;
    transform: translateX(-50%);
  }

  /* Same one-shot-only rule as the mobile `.slip.slip-entering` above, scoped
     to the desktop composition's own keyframes (horizontal centring is part of
     the resting transform on `.slip` itself, above — never conditional). */
  .slip.slip-entering {
    animation: slip-rise-desktop 320ms ease-out;
  }

  @keyframes slip-rise-desktop {
    from {
      transform: translate(-50%, 24px);
      opacity: 0;
    }
    to {
      transform: translate(-50%, 0);
      opacity: 1;
    }
  }
}

/* Narrow desktop: the rail becomes three rows; the record leaves the water.
   Height carries margin above the richest measured tournament sub-state
   (B-01: 106px of `.g-mid` at 1024×720 pushed the CTA 58px below the
   viewport at 300px — see the height comment on the base `.glance` rule). */
@media (min-width: 1024px) and (max-width: 1279px) {
  /* Founder UAT (2026-09-16): the centred brand lockup stays left-aligned in
     this band. The centred nav row starts under the brand block here, and a
     centred lockup put the Discord button on the active nav chip (measured
     24×21px at 1024px, clear from about 1100px); left-aligned, both stay
     clear of the row at every width in the band. */
  .brand {
    align-items: flex-start;
    text-align: left;
  }

  .brand-social {
    justify-content: flex-start;
  }

  .glance {
    height: 400px;
    grid-template-columns: 96px 1fr 1fr;
    grid-template-areas:
      'ring time purse'
      'mid mid mid'
      'bottom bottom bottom';
  }

  .record {
    display: none;
  }

  .depth {
    bottom: 400px;
  }

  /* N-02 (sprint-13 second re-review): the base `.tx-notice` rule sits
     `bottom: 322px` — 22px above the BASE `.glance` band's 300px height —
     but this narrow band's `.glance` is 400px tall, so the un-overridden
     base offset let the notice's bottom ~78px into the glance instead of
     resting above it. */
  .tx-notice {
    bottom: 422px;
  }
}

/* Wide: the rail's content stays at 1280 and the lake grows on both sides. */
@media (min-width: 1440px) {
  .glance {
    padding-left: 0;
    padding-right: 0;
  }
}

/*==============================  reduced motion  ============================*/

@media (prefers-reduced-motion: reduce) {
  .bar-fill {
    transition: none;
  }

  .slip.slip-entering {
    animation: none;
  }
}

/* No see-through material for players who ask for less transparency (the
   utility-control material, after `.strip-controls .control`). */
@media (prefers-reduced-transparency: reduce) {
  .controls .control-connect,
  .strip-controls [data-theme-toggle],
  .strip-controls [data-sound-toggle],
  .brand-social .social-link,
  nav.primary .nav-item.active,
  .slot .primary-action {
    background: #0a1220;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/*==============================  the terminal  =============================*/

/*
 * Sprint 14 — Lines Up!, Weigh-In, Catch for Cash, After (03R §4–§5).
 *
 * Nothing new in the grammar: the same strip, ring, margin items, relation
 * rows, ruled rows and one primary action. Three components the terminal
 * earns — the white window bar (D-7: a closing window is neither money nor
 * CATCH), the purse block 50/30/20, and the escrow box (the only box besides
 * the slip input, and it means enclosure) — plus the D-10 permissionless
 * ruled link and the one first-arrival interstitial. No red anywhere; a race
 * lost to another caller is a quiet notice, not an error.
 */

.bar-white .bar-fill {
  background: var(--white-bar);
}

/* The extension refill (03R 5d): the bar refills in one ease, once. */
.windowbar.is-refilled .bar-fill {
  transition: width 0.6s ease-out;
}

.margin-cutoff .margin-note,
.margin-highbid .margin-note,
.margin-minnext .margin-note {
  margin-top: 4px;
}

.margin-highbid.is-unsettled .label {
  color: var(--muted);
}

/* "none yet" is plain text, not cyan (03R 5f): no bid, no CATCH lit. */
.fig-none .fig-text {
  color: var(--record);
}

/* The escrow box: the locked-CATCH figure drawn inside a closed ruled box. */
.escrow {
  margin-top: 8px;
  padding: 8px 10px;
  border: 1px solid var(--rule-3);
  border-radius: 2px;
}

.escrow .relation {
  padding-top: 0;
  border-top: 0;
  margin-top: 0;
}

.pending-hold {
  width: 100%;
}

.mechanism {
  margin: 8px 0 0;
  font: 400 12px/1.45 var(--serif);
  color: var(--record);
}

/* The purse block 50 / 30 / 20. Open: bright gold. Closed/settled: matte. Future: quiet. */
.purse-block {
  margin-top: 8px;
  border-top: 1px solid var(--rule-2);
}

.purse-row {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  align-items: baseline;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--rule-1);
  font: 500 11px/1.3 var(--mono);
  letter-spacing: 0.08em;
  color: var(--muted);
}

.purse-pct {
  color: var(--muted);
}

.purse-name {
  color: var(--record);
}

.purse-open .purse-name {
  color: var(--ink);
}

.purse-open .fig {
  color: var(--gold);
}

.purse-closed .fig,
.purse-settled .fig {
  color: var(--gold-deep);
}

.purse-future .fig {
  color: var(--muted);
}

.purse-amount {
  display: flex;
  align-items: baseline;
  gap: 8px;
  justify-content: flex-end;
  flex-wrap: wrap;
}

.purse-winner {
  font: 400 11px/1.3 var(--mono);
  color: var(--record);
  letter-spacing: 0;
}

.purse-winner.record-you {
  color: var(--ink);
}

/* The burned figure goes dark and is struck through, once (03R 5f). */
.purse-burned .fig,
.record-struck {
  color: var(--muted);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  transition: color 0.8s ease-out;
}

.purse-note {
  grid-column: 2 / -1;
  font: 400 10px/1.3 var(--mono);
  letter-spacing: 0.04em;
}

.purse-caption {
  margin: 6px 0 0;
  font: 400 11px/1.4 var(--serif);
  color: var(--muted);
}

/* The D-9 raise: a depth link, ruled, never the primary action. */
.ruled-row-depth .ruled-label {
  color: var(--record);
  font: 400 12px/1.3 var(--serif);
}

/* The D-10 permissionless affordance: a small ruled button and its microcopy. */
.lifecycle {
  margin-top: 8px;
}

.lifecycle-call {
  min-height: 44px;
  cursor: pointer;
}

.lifecycle-call .ruled-label {
  color: var(--record);
  font: 400 13px/1.3 var(--serif);
}

.lifecycle-call .ruled-value {
  font: 400 10px/1.3 var(--mono);
  letter-spacing: 0.08em;
  text-transform: none;
}

.lifecycle-call[disabled] {
  cursor: default;
  opacity: 0.6;
}

.lifecycle-call[aria-busy='true'] .ruled-label {
  color: var(--muted);
}

/* After (03R 5g): the closing line in ink, then stillness. */
.closing {
  margin: 0;
}

.closing-line {
  margin: 0;
  font: 300 22px/1.2 var(--serif);
  color: var(--ink);
}

.closing-line + .closing-line {
  font-size: 15px;
  color: var(--record);
  margin-top: 4px;
}

.relation-souvenir .fig {
  color: var(--record);
}

/* The final hour of Weigh-In (03R 4d): the clock becomes the Figure. */
[data-final-hour] .margin-cutoff .fig-figure {
  font-size: 34px;
}

/* The interstitial (03R 4a): the slip's own materials, one Display line. */
.interstitial-display {
  margin: 0 0 8px;
  font: 300 30px/1.1 var(--serif);
  color: var(--slip-ink);
}

.interstitial-clock {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 12px 0 4px;
}

.interstitial-clock .fig {
  color: var(--slip-ink);
}

/* The benign race outcome (Task 14.5): quiet, like a confirmation, never red. */
.tx-notice-superseded {
  border-color: var(--rule-4);
}

/* The slip's amount rail: `800.00 of 1,258.50 free` · `min 2,459 · cap 3,200`. */
.slip-rail {
  margin: 2px 0 8px;
  font: 400 11px/1.3 var(--mono);
  letter-spacing: 0.04em;
  color: var(--slip-ink);
  opacity: 0.7;
}

@media (min-width: 1024px) {
  /* The rail keeps its shape (03R 7c/7d): the purse block takes the ring's
     place in the mid column, the high bid takes the price's place. */
  .purse-row {
    padding: 4px 0;
  }

  .closing-line {
    font-size: 20px;
  }

  [data-terminal] .g-time {
    min-width: 140px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .windowbar.is-refilled .bar-fill,
  .purse-burned .fig,
  .record-struck {
    transition: none;
  }
}

@media (min-width: 1024px) {
  /* The terminal carries more rows than the tournament rail (escrow box,
     purse block, mechanism sentences): the band grows to its content instead
     of clipping the primary action below the viewport (B-01's lesson). */
  [data-terminal] .glance {
    height: auto;
    min-height: 300px;
  }
}
