/* geoguess.es — the component library (docs/redesign/FINAL.md §4–5). Quiet Minimal: pills in flat ink, no
   borders on content, structure from spacing. One primary (solid ink) action per screen. Focus is always the 2 px
   signal ring; every control has hover, pressed, focus-visible, disabled; touch targets are ≥ 44 px.
   The legacy class names of the Chart Room library (.btn-gilt, .btn-indigo, .btn-outline, .btn-quiet, .card …)
   are kept as aliases so every page wears the new look before its owner migrates — new code uses the canonical
   names listed in FINAL.md §9. Feature packages style their pages in css/pages/<area>.css. */

/* ================================================================== buttons (§4) */
.btn {
  --btn-h: 44px;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  height: var(--btn-h); min-height: var(--btn-h); padding: 0 20px;
  border: 0; border-radius: var(--r-pill);
  background: var(--btn-2, var(--paper-2)); color: var(--ink);
  font-family: var(--font-ui); font-weight: 500; font-size: var(--fs-15); line-height: 1; letter-spacing: 0; white-space: nowrap;
  text-decoration: none; cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
  transition: background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease), transform var(--t-press) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.btn:hover { color: var(--ink); background: var(--btn-2h, var(--paper-3)); }
.btn:active:not(:disabled):not([aria-disabled="true"]) { transform: scale(.97); }
.btn .icon { width: 18px; height: 18px; }
/* primary: ink fill, paper label — ONE per screen (Play, Guess, Challenge, Create account) */
.btn-primary, .btn-gilt { background: var(--ink); color: var(--paper); box-shadow: var(--shadow-soft); }
.btn-primary:hover, .btn-gilt:hover { background: color-mix(in srgb, var(--ink) 86%, var(--paper)); color: var(--paper); }
/* secondary: a paper-2 pill (legacy outline / indigo / cream land here) */
.btn-secondary, .btn-outline, .btn-indigo, .btn-cream { background: var(--btn-2, var(--paper-2)); color: var(--ink); }
.btn-secondary:hover, .btn-outline:hover, .btn-indigo:hover, .btn-cream:hover { background: var(--btn-2h, var(--paper-3)); color: var(--ink); }
/* ghost: text only, a paper-2 wash on hover */
.btn-ghost, .btn-quiet, .btn-ghost-chrome { background: transparent; color: var(--ink); }
.btn-ghost:hover, .btn-quiet:hover, .btn-ghost-chrome:hover { background: var(--btn-2, var(--paper-2)); color: var(--ink); }
/* destructive: signal label on its wash; it always opens a confirm dialog. The confirm itself is solid. */
.btn-destructive, .btn-danger { background: var(--signal-wash); color: var(--signal-ink); }
.btn-destructive:hover, .btn-danger:hover { background: color-mix(in srgb, var(--signal) 18%, transparent); color: var(--signal-ink); }
.btn-destructive-solid, .btn-danger-solid { background: var(--signal); color: var(--on-signal); }
.btn-destructive-solid:hover, .btn-danger-solid:hover { background: color-mix(in srgb, var(--signal) 88%, var(--ink)); color: var(--on-signal); }
/* disabled keeps its label; a hint beside it says why */
.btn:disabled, .btn[aria-disabled="true"] { background: var(--btn-2, var(--paper-2)); color: var(--ink-faint); box-shadow: none; cursor: not-allowed; transform: none; }
.btn-ghost:disabled, .btn-quiet:disabled, .btn-ghost[aria-disabled="true"], .btn-quiet[aria-disabled="true"] { background: transparent; }
/* sizes: L 56 · M 44 (default) · S 36 with a 44 px hit area */
.btn-lg, .btn-xl { --btn-h: 56px; padding: 0 30px; font-size: var(--fs-16); }
.btn-sm { --btn-h: 36px; padding: 0 14px; font-size: var(--fs-13); gap: 8px; }
.btn-sm::before { content: ""; position: absolute; inset: -4px 0; }
.btn-sm .icon { width: 16px; height: 16px; }
.btn-block { display: flex; width: 100%; }
/* phones: a long label ("Email me a code to add a password") wraps inside its pill instead of pushing the page
   sideways; one-line buttons keep their height through min-height */
@media (max-width: 479.98px) {
  .btn:not(.btn-icon):not(.btn-pixel) { max-width: 100%; height: auto; padding-block: 8px; line-height: 1.25; white-space: normal; text-align: center; }
}
.btn-icon { width: var(--btn-h); padding: 0; }
/* the arrow that nudges on hover ("Play Blitz →") */
.btn .arrow { transition: transform var(--t-base) var(--ease); }
.btn:hover .arrow { transform: translateX(3px); }
/* busy: the verb plus three stepped dots (components.js busy()) */
.dots { display: inline-flex; gap: 5px; align-items: center; }
.dots i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .3; }
@media (prefers-reduced-motion: no-preference) {
  .dots i { animation: gg-dot 900ms steps(1, end) infinite; }
  .dots i:nth-child(2) { animation-delay: 300ms; } .dots i:nth-child(3) { animation-delay: 600ms; }
}
.dots i:nth-child(3) { opacity: 1; }
@keyframes gg-dot { 0% { opacity: 1; } 33% { opacity: .3; } }

/* icon buttons: 44 px circles (chat, menu, compass, zoom, close) */
.icon-btn { position: relative; display: inline-grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--ink); text-decoration: none; transition: background-color var(--t-fast) var(--ease); }
.icon-btn:hover { background: var(--btn-2, var(--paper-2)); color: var(--ink); }
.icon-btn:active:not(:disabled) { transform: scale(.95); }
.icon-btn:disabled { color: var(--ink-faint); cursor: not-allowed; background: transparent; }
.icon-btn .icon { width: 18px; height: 18px; }
.icon-btn-solid { background: var(--btn-2, var(--paper-2)); }

/* the stepped-pixel brass button (direction B) — the signed-out landing ONLY (FINAL.md §4.3).
   ::before is the edge + ledge, ::after the face; both use the same stepped polygon. The element is never
   clipped, so the focus ring survives. The press drops the face 2 px onto a ledge that shrinks 2 px. */
.btn.btn-pixel, .btn-pixel {
  --face: var(--brass-face); --edge: var(--brass-lo); --fg: var(--on-brass); --ledge: 6px;
  --cut: polygon(0 8px, 4px 8px, 4px 4px, 8px 4px, 8px 0, calc(100% - 8px) 0, calc(100% - 8px) 4px, calc(100% - 4px) 4px, calc(100% - 4px) 8px, 100% 8px, 100% calc(100% - 8px), calc(100% - 4px) calc(100% - 8px), calc(100% - 4px) calc(100% - 4px), calc(100% - 8px) calc(100% - 4px), calc(100% - 8px) 100%, 8px 100%, 8px calc(100% - 4px), 4px calc(100% - 4px), 4px calc(100% - 8px), 0 calc(100% - 8px));
  position: relative; isolation: isolate; display: inline-flex; align-items: center; justify-content: center; gap: 14px;
  height: auto; min-height: 66px; padding: 0 32px var(--ledge); border: 0; border-radius: 0; background: none; box-shadow: none;
  color: var(--fg); font: 500 var(--fs-18)/1.2 var(--font-ui); letter-spacing: -0.01em; text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: none; transform: none;
}
.btn-pixel::before, .btn-pixel::after { content: ""; position: absolute; clip-path: var(--cut); pointer-events: none; }
.btn-pixel::before { inset: 0; z-index: -2; background: var(--edge); }
.btn-pixel::after { inset: 0 0 var(--ledge) 0; z-index: -1; background: var(--face); }
.btn.btn-pixel:hover, .btn-pixel:hover { --face: var(--brass-hi); background: none; color: var(--fg); }
.btn.btn-pixel:active:not(:disabled), .btn-pixel:active:not(:disabled) { transform: none; padding-top: 2px; padding-bottom: calc(var(--ledge) - 2px); }
.btn-pixel:active:not(:disabled)::before { inset: 2px 0 0 0; }
.btn-pixel:active:not(:disabled)::after { inset: 2px 0 calc(var(--ledge) - 2px) 0; }
.btn-pixel:disabled, .btn-pixel[aria-disabled="true"] { --face: var(--paper-2); --edge: var(--line-2); --fg: var(--ink-faint); --ledge: 0px; background: none; cursor: not-allowed; }
.btn-pixel .px-icon { width: 18px; height: 18px; flex: none; background: currentColor; }
.btn-pixel-sm { --ledge: 4px; min-height: 52px; padding: 0 24px var(--ledge); font-size: 22px; }

/* key caps. A plain <kbd> is content (the guides' shortcut tables): ink-2 in an --edge outline (≥ 5.4:1).
   Inside a button it is a quieter hint that follows the label's colour at 72 % (≥ 6:1 on every pill, both themes). */
kbd { font-family: var(--font-ui); font-weight: 500; font-size: var(--fs-11); padding: 2px 6px; border: 1px solid var(--edge); border-radius: var(--r-1); color: var(--ink-2); line-height: 1.3; }
.btn kbd { color: color-mix(in srgb, currentColor 72%, transparent); border-color: currentColor; }
@media (pointer: coarse) and (hover: none) { .btn kbd, .d-lock kbd { display: none; } }

/* ================================================================== inputs (§5.1) */
.field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.field-label { font-size: var(--fs-13); font-weight: 400; color: var(--ink-2); padding-left: 20px; }
.field-hint { font-size: var(--fs-13); color: var(--ink-2); padding-left: 20px; }
.field-error { font-size: var(--fs-13); color: var(--signal); padding-left: 20px; }
.field-error::before { content: "! "; font-weight: 500; }
.input, .select, .textarea {
  height: 48px; width: 100%; min-width: 0; padding: 0 20px;
  background: transparent; color: var(--ink);
  border: 1px solid var(--edge); border-radius: var(--r-pill);
  font-size: var(--fs-15); font-family: var(--font-ui);
  transition: border-color var(--t-fast) var(--ease);
}
.input:hover, .select:hover, .textarea:hover { border-color: var(--ink-2); }
.input:focus, .select:focus, .textarea:focus { border-color: var(--ink); outline: 2px solid var(--focus); outline-offset: 2px; }
.input::placeholder, .textarea::placeholder { color: var(--ink-2); opacity: 1; }
.input[aria-invalid="true"], .select[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--signal); }
.input:disabled, .select:disabled, .textarea:disabled { border-color: var(--line-2); color: var(--ink-faint); cursor: not-allowed; }
.input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
/* no native clear ×: it was Chrome's blue, the only blue on the site; Esc clears and closes the search instead */
.input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.textarea { height: auto; min-height: 96px; padding: 12px 20px; line-height: var(--lh-body); border-radius: var(--r-3); resize: vertical; }
.select {
  appearance: none; -webkit-appearance: none; padding-right: 44px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-2) 50%), linear-gradient(135deg, var(--ink-2) 50%, transparent 50%);
  background-position: calc(100% - 25px) 52%, calc(100% - 20px) 52%; background-size: 5px 5px; background-repeat: no-repeat;
}
.select option { background: var(--raised); color: var(--ink); }
/* search: a pill with a leading magnifier — <label class="search-field"><svg class="icon">…<input class="input"></label> */
.search-field { position: relative; display: block; min-width: 0; }
.search-field > .icon { position: absolute; left: 18px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--ink-2); pointer-events: none; }
.search-field > .input { padding-left: 44px; }
.code-input { display: flex; gap: var(--sp-2); }
.code-input input { width: 44px; height: 52px; text-align: center; font-family: var(--font-ui); font-weight: 500; font-size: 22px; border: 1px solid var(--edge); border-radius: var(--r-2); background: transparent; color: var(--ink); }
/* checkboxes and radios keep the native control, tinted */
input[type="checkbox"], input[type="radio"] { accent-color: var(--ink); }

/* segmented pill (Rated/Casual, 30d/90d/1y/All): a paper-2 track, a raised thumb with a 1.5 px ink ring.
   Markup: <div class="segmented" role="radiogroup"><label><input type="radio"><span>Rated</span></label>…</div> */
.segmented { display: inline-flex; gap: 4px; padding: 4px; border: 0; border-radius: var(--r-pill); background: var(--btn-2, var(--paper-2)); height: auto; max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.segmented label { position: relative; display: inline-flex; align-items: center; justify-content: center; height: 36px; padding: 0 16px; border: 0; border-radius: var(--r-pill); font-size: var(--fs-14); font-weight: 400; color: var(--ink-2); cursor: pointer; white-space: nowrap; transition: background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease); }
.segmented label:hover { color: var(--ink); }
.segmented input { position: absolute; opacity: 0; pointer-events: none; }
.segmented label:has(input:checked) { background: var(--raised); color: var(--ink); font-weight: 500; box-shadow: 0 0 0 1.5px var(--ink); }
.segmented input:checked + span { color: var(--ink); }
.segmented label:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 2px; }
.segmented label:has(input:disabled) { color: var(--ink-faint); cursor: not-allowed; }
@media (pointer: coarse) { .segmented label { height: 40px; } .segmented label::after { content: ""; position: absolute; inset: -6px 0; } }

/* switch */
.toggle { display: inline-flex; align-items: center; gap: var(--sp-3); cursor: pointer; font-size: var(--fs-14); min-height: 44px; }
.toggle input { appearance: none; -webkit-appearance: none; width: 40px; height: 24px; border-radius: var(--r-pill); background: var(--paper-3); box-shadow: inset 0 0 0 1px var(--edge); position: relative; margin: 0; flex: none; cursor: pointer; transition: background-color var(--t-fast) var(--ease); }
.toggle input::after { content: ""; position: absolute; top: 3px; left: 3px; width: 18px; height: 18px; border-radius: 50%; background: var(--raised); box-shadow: 0 0 0 1px var(--edge); transition: transform var(--t-fast) var(--ease); }
.toggle input:checked { background: var(--ink); box-shadow: none; }
.toggle input:checked::after { transform: translateX(16px); background: var(--paper); box-shadow: none; }
.toggle input:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
.toggle input:disabled { opacity: .5; cursor: not-allowed; }

/* ================================================================== surfaces: there are no cards (§5.6)
   A .card is now plain flow: no fill, no border, no shadow. Sections are separated by space and a 12 px label. */
.card { background: transparent; border: 0; border-radius: 0; box-shadow: none; padding: 0; min-width: 0; }
.card-lg { padding: 0; }
.card-head { display: flex; align-items: baseline; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.card-head h2 { font-size: var(--fs-18); line-height: 1.4; letter-spacing: -0.01em; }
.card-head .flavour { margin: 2px 0 0; }
.card-head > div { flex: 1; min-width: 0; }
.card-head a { font-size: var(--fs-13); font-weight: 400; color: var(--ink-2); white-space: nowrap; padding-block: 12px; margin-block: -12px; } /* a 44 px target without moving the layout */
.card-head a:hover { color: var(--ink); }
.stack > .card + .card, .stack > section + section { margin-top: var(--sp-12); }
/* the one-line section head: label left, quiet link right */
.section-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); min-height: 44px; margin-bottom: var(--sp-2); }
.section-head h2, .section-head h3 { font-size: var(--fs-12); font-weight: 500; letter-spacing: var(--tracking-label); color: var(--ink-2); line-height: 1.5; }
.section-head a { font-size: var(--fs-13); color: var(--ink-2); display: inline-flex; align-items: center; min-height: 44px; }
.section-head a:hover { color: var(--ink); }
/* a rare raised well (the guess map, a pre-game card): radius 28, paper-2 */
.well { background: var(--paper-2); border-radius: var(--r-4); padding: var(--sp-6); --btn-2: var(--paper-3); --btn-2h: var(--line-2); }

/* lists: rows ≥ 48 px, no separators */
.list { display: flex; flex-direction: column; }
.list-row { display: flex; align-items: center; gap: var(--sp-3); min-height: 48px; padding: 6px 0; color: var(--ink); text-decoration: none; min-width: 0; }
a.list-row:hover .list-title { text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--ink-faint); }
.list-title { font-weight: 500; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.list-sub { color: var(--ink-2); font-size: var(--fs-13); }
.list-end { margin-left: auto; display: inline-flex; align-items: center; gap: var(--sp-2); flex: none; }

/* stats: a big number with a label above and one meta line under it */
.stat { display: flex; flex-direction: column; gap: 2px; min-width: 0; color: var(--ink); text-decoration: none; }
.stat-label { font-size: var(--fs-13); color: var(--ink-2); }
.stat-num { font-size: var(--fs-34); line-height: 1.15; letter-spacing: -0.03em; font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
.stat-sub { font-size: var(--fs-13); color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* key/value lines ("Peak  2,140 · today") */
.kv { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px var(--sp-4); font-size: var(--fs-14); }
.kv dt { color: var(--ink-2); } .kv dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }

/* legacy hub tiles, quietened */
.tc-grid { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--sp-2); }
.quick-duel .tc-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 767.98px) { .tc-grid, .quick-duel .tc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.tc-tile {
  --tc: var(--ink-2);
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px; text-align: left;
  padding: var(--sp-4); min-height: 0;
  background: transparent; color: var(--ink);
  border: 0; border-radius: var(--r-3);
  cursor: pointer; transition: background-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.tc-tile:hover { background: var(--paper-2); }
.tc-tile[aria-pressed="true"] { background: var(--raised); box-shadow: inset 0 0 0 1.5px var(--ink); }
.tc-tile .icon { width: 20px; height: 20px; margin-bottom: var(--sp-2); color: var(--ink-2); }
.tc-tile .tc-name { font-weight: 500; font-size: var(--fs-15); }
.tc-tile .tc-time { font-size: var(--fs-13); color: var(--ink-2); }
.tc-tile .tc-flavour { display: none; } /* the weather metaphors are gone (C "Taken out") */
.tc-tile .tc-live { margin-top: var(--sp-2); font-size: var(--fs-12); color: var(--ink-2); display: inline-flex; align-items: center; gap: 6px; }
.tc-bullet, .tc-blitz, .tc-rapid, .tc-classical, .tc-daily { --tc: var(--ink-2); }
.live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--signal); box-shadow: 0 0 0 3px var(--signal-wash); display: inline-block; flex: none; }
/* "2,184 playing now" */
.live { display: inline-flex; align-items: center; gap: 10px; color: var(--ink-2); font-size: var(--fs-13); }
.live::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--signal); box-shadow: 0 0 0 4px var(--signal-wash); flex: none; }

.mode-tile { display: flex; gap: var(--sp-3); align-items: flex-start; padding: var(--sp-3) var(--sp-4); border-radius: var(--r-3); text-decoration: none; color: var(--ink); }
.mode-tile:hover { background: var(--paper-2); color: var(--ink); }
.mode-tile .mode-icon { width: 24px; height: 24px; display: grid; place-items: center; background: transparent; color: var(--ink-2); flex: none; margin-top: 1px; }
.mode-tile .mode-icon .icon { width: 18px; height: 18px; }
.mode-tile b { display: block; font-size: var(--fs-15); font-weight: 500; }
.mode-tile span { font-size: var(--fs-13); color: var(--ink-2); }

/* difficulty tiers T1–T8: a calm grey ramp */
.tiers { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); border-radius: var(--r-3); overflow: hidden; }
.tier { padding: var(--sp-3); min-height: 84px; display: flex; flex-direction: column; gap: 2px; color: var(--ink); text-decoration: none; }
.tier .eyebrow { color: inherit; overflow-wrap: anywhere; } /* full strength: 85 % fell to 3.9:1 on the T5 grey */
.tier b { font-size: var(--fs-13); font-weight: 500; line-height: 1.3; }
.tier .mono { margin-top: auto; font-size: var(--fs-11); font-weight: 400; }
.tier-1 { background: var(--depth-1); } .tier-2 { background: var(--depth-2); } .tier-3 { background: var(--depth-3); } .tier-4 { background: var(--depth-4); }
.tier-5 { background: var(--depth-5); color: var(--depth-ink); } .tier-6 { background: var(--depth-6); color: var(--depth-ink); }
.tier-7 { background: var(--depth-7); color: var(--depth-ink); } .tier-8 { background: var(--depth-8); color: var(--depth-ink); }
@media (max-width: 767.98px) { .tiers { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ================================================================== tabs (§5.3): plain text, the selected one is
   ink + weight 500 + a 5 px signal dot underneath. No underline bar, no box. */
.tabs { display: flex; gap: 4px; overflow-x: auto; scrollbar-width: none; border: 0; }
.tabs::-webkit-scrollbar { display: none; }
.tabs [role="tab"] { position: relative; height: 44px; padding: 0 12px; border: 0; border-radius: var(--r-pill); background: transparent; color: var(--ink-2); font-weight: 400; font-size: var(--fs-14); display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; flex: none; transition: color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease); }
.tabs [role="tab"] .icon { width: 16px; height: 16px; }
.tabs [role="tab"]:hover { color: var(--ink); background: var(--paper-2); }
.tabs [role="tab"][aria-selected="true"] { color: var(--ink); font-weight: 500; box-shadow: none; }
.tabs [role="tab"][aria-selected="true"]::after { content: ""; position: absolute; left: 50%; bottom: 3px; width: 5px; height: 5px; margin-left: -2.5px; border-radius: 50%; background: var(--signal); }
/* more tabs off-screen: fade the edge that hides them (components.js scrollCue) */
.tabs.more-end { -webkit-mask-image: linear-gradient(to right, black calc(100% - 48px), transparent); mask-image: linear-gradient(to right, black calc(100% - 48px), transparent); }
.tabs.more-start { -webkit-mask-image: linear-gradient(to left, black calc(100% - 48px), transparent); mask-image: linear-gradient(to left, black calc(100% - 48px), transparent); }
.tabs.more-start.more-end { -webkit-mask-image: linear-gradient(to right, transparent, black 48px, black calc(100% - 48px), transparent); mask-image: linear-gradient(to right, transparent, black 48px, black calc(100% - 48px), transparent); }

/* ================================================================== chips, badges (§5.2) */
.chip { position: relative; display: inline-flex; align-items: center; gap: 8px; min-height: 32px; max-width: 100%; padding: 4px 14px; border: 1px solid var(--edge); border-radius: var(--r-pill); font-size: var(--fs-13); line-height: 1.3; font-weight: 400; color: var(--ink); background: transparent; text-decoration: none; transition: background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease); }
.chip .icon { width: 14px; height: 14px; }
button.chip, a.chip { cursor: pointer; }
button.chip:hover, a.chip:hover { background: var(--paper-2); color: var(--ink); }
.chip[aria-pressed="true"], .chip[aria-checked="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.chip-on { color: var(--ink); border-color: var(--edge); } /* legacy "allowed" chip: a plain outlined chip (only a pressed filter is filled) */
button.chip[aria-pressed="true"]:hover { background: color-mix(in srgb, var(--ink) 86%, var(--paper)); color: var(--paper); }
.chip-off { text-decoration: line-through; border-style: dashed; color: var(--ink-2); }
.chip:disabled { color: var(--ink-faint); border-color: var(--line-2); cursor: not-allowed; }
button.chip::after, a.chip::after { content: ''; position: absolute; inset: -7px 0; } /* 44 px hit area, same drawn pill */
/* touch screens: every control outside the game screen is at least 44 px tall */
@media (pointer: coarse) {
  :is(.btn:not(.btn-sm):not(.btn-pixel), .tabs [role="tab"], .st-tab, .input, .select, select):not(.g-screen *) { min-height: var(--hit-min); }
  .icon-btn:not(.g-screen *) { min-width: var(--hit-min); min-height: var(--hit-min); }
}
/* small text links keep their look but get a 44 px tall hit area on every pointer (FINAL.md §13): names in lists,
   tables and the landing board (the padding sits inside the clipped box, so ellipsis still works) */
a.who-name:not(.g-screen *) { padding-block: 12px; margin-block: -12px; }
.pill { display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 9px; border-radius: var(--r-pill); font-size: var(--fs-12); font-weight: 500; white-space: nowrap; background: var(--paper-2); color: var(--ink); }
.pill-win, .pill-info { background: var(--paper-2); color: var(--ink); }
.pill-loss, .pill-warn { background: var(--signal-wash); color: var(--signal-ink); }
.pill-neutral { background: var(--paper-2); color: var(--ink-2); }
/* badges (BOT, MOD, CHART MAKER): the only uppercase in the system */
.tag, .badge { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 7px; border-radius: var(--r-pill); background: var(--paper-2); color: var(--ink-2); font-size: var(--fs-11); font-weight: 500; letter-spacing: var(--tracking-badge); text-transform: uppercase; line-height: 1; vertical-align: middle; white-space: nowrap; flex: none; }
.tag .icon, .tag svg { width: 12px; height: 12px; }
.tag-you { background: var(--ink); color: var(--paper); }
.tag-bot { background: var(--paper-2); color: var(--ink-2); box-shadow: none; }
.tag-mod { background: var(--paper-2); color: var(--ink); }
.tag-admin { background: var(--signal-wash); color: var(--signal-ink); }
.count-badge { display: inline-grid; place-items: center; min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--r-pill); background: var(--signal); color: var(--on-signal); font-size: var(--fs-11); font-weight: 500; line-height: 1; font-variant-numeric: tabular-nums; }

/* ================================================================== identity (§5.9) */
.avatar { --d: 32px; width: var(--d); height: var(--d); border-radius: 50%; flex: none; overflow: hidden; display: grid; place-items: center; font-family: var(--font-ui); font-style: normal; font-weight: 500; font-size: calc(var(--d) * .42); line-height: 1; color: var(--ink); background: var(--paper-2); position: relative; }
.avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.avatar-24 { --d: 24px; } .avatar-40 { --d: 40px; } .avatar-44 { --d: 44px; } .avatar-96 { --d: 96px; }
.avatar-bot { background: var(--paper-2); color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--ink-2); }
/* the old pigment tiles are gone: every generated avatar is a paper-2 circle (the classes stay as no-ops) */
.pig-0, .pig-1, .pig-2, .pig-3, .pig-4, .pig-5 { background: var(--paper-2); }
/* presence: a solid ink dot (online) or an ink ring (in a game), always with words beside it */
.avatar:has(.presence) { overflow: visible; }
.presence { position: absolute; right: -1px; bottom: -1px; width: 10px; height: 10px; border-radius: 50%; box-shadow: 0 0 0 2px var(--paper); }
.presence-online { background: var(--ink); }
.presence-playing { background: var(--paper); box-shadow: 0 0 0 2px var(--paper), inset 0 0 0 2px var(--ink); }
/* flags: 20 × 15, 2 px radius, an inset hairline so white/black stripes keep their edge */
.flag { width: 20px; height: 15px; border-radius: 2px; outline: 1px solid var(--flag-edge); outline-offset: -1px; flex: none; object-fit: cover; display: inline-block; vertical-align: -2px; }
.flag-24 { width: 24px; height: 18px; }
.flag-rose { color: var(--ink-2); width: 15px; height: 15px; outline: none; }
.who { display: inline-flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%; }
.who-name { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); text-decoration: none; }
a.who-name:hover { text-decoration: underline; text-underline-offset: 4px; }
.rating { font-weight: 400; font-variant-numeric: tabular-nums; color: var(--ink-2); display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.rating .icon { width: 14px; height: 14px; }
.rating .prov { color: var(--ink-2); margin-left: -2px; } /* "1534?" */
/* deltas carry a sign (+9, −7, ±0): no colour needed */
.delta { display: inline-flex; align-items: center; font-weight: 400; font-size: var(--fs-13); font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--ink); }
.delta.dn, .delta.eq { color: var(--ink-2); }

/* ================================================================== dialogs and sheets (§5.7) */
.dialog { width: min(440px, calc(100vw - 2 * var(--sp-4))); max-height: calc(100dvh - 2 * var(--sp-6)); padding: 0; border: 0; border-radius: var(--r-4); background: var(--raised); color: var(--ink); box-shadow: var(--shadow-pop); --btn-2: var(--raised-2); --btn-2h: var(--raised-3); }
.dialog[open] { animation: gg-rise var(--t-panel) var(--ease); }
.dialog-wide { width: min(720px, calc(100vw - 2 * var(--sp-4))); }
.dialog::backdrop { background: var(--scrim); } /* ::backdrop inherits from its dialog in current engines; older ones fall back to the UA scrim */
.dialog-body { padding: var(--sp-8); overflow-y: auto; max-height: inherit; }
.dialog-head { display: flex; align-items: flex-start; gap: var(--sp-3); margin-bottom: var(--sp-5); }
.dialog-head > div { flex: 1; min-width: 0; }
.dialog-head h2 { font-size: var(--fs-22); }
.dialog-head .flavour { margin: var(--sp-2) 0 0; font-size: var(--fs-14); }
.dialog-close { margin: -10px -12px 0 0; }
/* stacked full-width pills: <div class="dialog-actions"> */
.dialog-actions { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-6); }
.dialog-actions .btn { width: 100%; }
.divider-or { display: flex; align-items: center; gap: var(--sp-3); color: var(--ink-2); font-size: var(--fs-13); margin: var(--sp-4) 0; }
.divider-or::before, .divider-or::after { content: ""; flex: 1; height: 1px; background: var(--line); }
@keyframes gg-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (max-width: 719.98px) {
  .dialog.sheet-on-phone, .dialog.sheet { width: 100vw; max-width: 100vw; max-height: calc(100dvh - var(--sp-6)); margin: auto 0 0; border-radius: var(--r-4) var(--r-4) 0 0; padding-bottom: env(safe-area-inset-bottom); }
  .dialog.sheet-on-phone .dialog-body, .dialog.sheet .dialog-body { padding: var(--sp-6) var(--sp-5) var(--sp-6); }
  .dialog.sheet-on-phone .dialog-body::before, .dialog.sheet .dialog-body::before { content: ""; display: block; width: 40px; height: 4px; border-radius: 2px; background: var(--raised-3); margin: -8px auto var(--sp-4); }
}
.google-btn { display: flex; align-items: center; justify-content: center; gap: 10px; height: 44px; border-radius: var(--r-pill); border: 1px solid var(--google-edge); background: var(--google-bg); color: var(--google-ink); font-family: var(--font-ui); font-weight: 500; font-size: var(--fs-14); text-decoration: none; }
.google-btn:hover { color: var(--google-ink); filter: brightness(.97); }

/* ================================================================== toasts, banners (§5.8) */
/* toast: an ink pill (paper at Night), bottom-centre; one line + one underlined action; role=status */
.toast { display: flex; align-items: center; gap: var(--sp-4); min-height: 52px; max-width: min(520px, calc(100vw - 2 * var(--sp-4))); padding: 9px 10px 9px 22px; border: 0; border-radius: 26px; background: var(--ink); color: var(--paper); box-shadow: var(--shadow-pop); font-size: var(--fs-14); animation: gg-rise var(--t-panel) var(--ease); }
.toast > div { flex: 1; min-width: 0; }
.toast b { display: block; font-size: var(--fs-14); font-weight: 500; }
.toast p { margin: 1px 0 0; font-size: var(--fs-13); color: color-mix(in srgb, var(--paper) 74%, var(--ink)); }
.toast a { color: var(--paper); text-decoration-color: currentColor; }
.toast-loss::before, .toast-warn::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--signal); flex: none; margin-right: -4px; }
.toast-action { flex: none; height: 36px; padding: 0 12px; border: 0; border-radius: var(--r-pill); background: transparent; color: var(--paper); font: inherit; font-weight: 500; text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }
.toast-action:hover { background: color-mix(in srgb, var(--paper) 12%, transparent); }
.toast-x { flex: none; width: 36px; height: 36px; display: grid; place-items: center; border: 0; border-radius: 50%; background: transparent; color: var(--paper); cursor: pointer; }
.toast-x:hover { background: color-mix(in srgb, var(--paper) 12%, transparent); }
.toast-x .icon { width: 16px; height: 16px; }
/* the ring inside a toast is drawn in paper: the signal ring on the ink (Night: paper) fill fell to 2.6:1 */
.toast :focus-visible { outline-color: var(--paper); outline-offset: 2px; }
/* banners: a quiet paper-2 row; cautions get the signal wash and a signal glyph (the words carry the meaning) */
.banner { display: flex; gap: var(--sp-3); align-items: center; padding: 12px 16px 12px 20px; border-radius: var(--r-3); font-size: var(--fs-14); line-height: 1.5; background: var(--paper-2); color: var(--ink); margin: 0; }
.banner > .icon { color: var(--ink-2); width: 18px; height: 18px; }
.banner-info, .banner-win { background: var(--paper-2); color: var(--ink); }
.banner-warn, .banner-loss { background: var(--signal-wash); color: var(--ink); }
.banner-warn > .icon, .banner-loss > .icon { color: var(--signal); }
.banner a { color: inherit; }

/* ================================================================== menus, tooltips (§5.10) */
.menu { min-width: 220px; max-width: calc(100vw - 16px); padding: 6px; background: var(--raised); border: 0; border-radius: var(--r-3); box-shadow: var(--shadow-pop); color: var(--ink); --btn-2: var(--raised-2); --btn-2h: var(--raised-3); animation: gg-rise var(--t-fast) var(--ease); }
.menu [role="menuitem"], .menu .menu-item { display: flex; align-items: center; gap: var(--sp-3); width: 100%; min-height: 44px; padding: 0 14px; border: 0; border-radius: var(--r-pill); background: transparent; color: var(--ink); text-decoration: none; font-size: var(--fs-14); font-weight: 400; text-align: left; cursor: pointer; }
.menu [role="menuitem"] .icon { width: 16px; height: 16px; color: var(--ink-2); }
.menu [role="menuitem"]:hover, .menu [role="menuitem"]:focus-visible { background: var(--raised-2); outline: none; }
.menu [role="menuitem"]:focus-visible { box-shadow: inset 0 0 0 2px var(--focus); }
.menu [role="menuitem"][aria-current="page"] { font-weight: 500; }
.menu-label { padding: 10px 14px 4px; font-size: var(--fs-12); font-weight: 500; letter-spacing: var(--tracking-label); color: var(--ink-2); }
.menu-sep { height: 1px; margin: 6px 8px; background: var(--line); border: 0; }
.menu-meta { margin-left: auto; color: var(--ink-2); font-size: var(--fs-13); }
.tooltip { position: absolute; z-index: var(--z-tooltip); max-width: 240px; padding: 6px 10px; border-radius: var(--r-1); background: var(--ink); color: var(--paper); font-size: var(--fs-12); pointer-events: none; }

/* ================================================================== tables (§5.5): one hairline between rows, 56 px rows,
   a 12 px ink-2 header, no zebra; secondary columns hide below 960 / 480 (page CSS) */
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-14); font-variant-numeric: tabular-nums; }
.table th { height: 40px; padding: 0 var(--sp-3); background: transparent; text-align: left; font-size: var(--fs-12); font-weight: 500; letter-spacing: var(--tracking-label); text-transform: none; color: var(--ink-2); border-bottom: 1px solid var(--line); white-space: nowrap; }
.table td { height: 56px; padding: 0 var(--sp-3); border-bottom: 1px solid var(--line); }
.table th:first-child, .table td:first-child { padding-left: 0; }
.table th:last-child, .table td:last-child { padding-right: 0; }
.table tbody tr:hover td { background: color-mix(in srgb, var(--paper-2) 50%, transparent); }
.table .r { text-align: right; }
.table tr.me td { background: var(--paper-2); font-weight: 500; }
.table-wrap { overflow-x: auto; max-width: 100%; }

/* ================================================================== empty, loading, errors (§5.11) */
.empty { display: flex; flex-direction: column; align-items: flex-start; text-align: left; gap: var(--sp-2); padding: var(--sp-6) 0; color: var(--ink-2); }
.empty > .icon { display: none; }
.empty h3 { font-size: var(--fs-15); font-weight: 500; color: var(--ink); }
.empty p { margin: 0; font-size: var(--fs-13); max-width: 48ch; }
.empty > .btn, .empty > a.btn { margin-top: var(--sp-2); }
.skeleton { background: var(--paper-2); border-radius: var(--r-1); position: relative; overflow: hidden; min-height: 12px; }
@media (prefers-reduced-motion: no-preference) { .skeleton { animation: gg-pulse 1.4s ease-in-out infinite; } }
@keyframes gg-pulse { 50% { opacity: .55; } }
/* the star rule (a flourish) is now a plain hairline */
.rule-star { display: flex; align-items: center; gap: 10px; color: var(--ink-2); }
.rule-star::before, .rule-star::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.rule-star .icon { display: none; }
.rule-star > :not(.icon) { color: var(--ink-2); }
.hr { height: 1px; border: 0; margin: 0; background: var(--line); }

/* sextant loading mark: the index arm sweeps — the ONLY spinner (inline the mono/mark SVG with <g class="gg-arm">) */
/* DECISIONS #25 (Pierced plate logo): pivot 34.5px 15px, sweep -12deg…8deg */
.gg-arm { transform-box: view-box; transform-origin: 34.5px 15px; animation: sweep 1.6s var(--ease) infinite alternate; }
@keyframes sweep { from { transform: rotate(-12deg); } to { transform: rotate(8deg); } }
@media (prefers-reduced-motion: reduce) { .gg-arm { animation: none; } }
:root[data-motion="reduce"] .gg-arm { animation: none; }

/* ================================================================== game HUD primitives (§8) */
.hud-plate { background: var(--hud); -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px); border-radius: var(--r-4); box-shadow: var(--shadow-soft); padding: 12px 20px; color: var(--ink); }
.hud-pill { background: var(--hud); -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px); border-radius: var(--r-pill); box-shadow: var(--shadow-soft); color: var(--ink); }
.hp { position: relative; height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--ink) 14%, transparent); overflow: hidden; }
.hp-lost { display: none; }
.hp-fill { position: absolute; inset: 0 auto 0 0; border-radius: 3px; background: var(--ink); transition: width 400ms var(--ease); }
.hp-opp .hp-fill { inset: 0 0 0 auto; background: var(--ink); }
.hp-num { font-family: var(--font-ui); font-weight: 500; font-size: var(--fs-14); font-variant-numeric: tabular-nums; }
.limb { width: 200px; height: 46px; overflow: visible; }
.limb .track { stroke: var(--paper-3); }
.limb .fill { stroke: var(--ink); }
.limb.low .fill { stroke: var(--signal); }
.limb .ticks { stroke: var(--ink-faint); }
.limb .index { fill: var(--ink); }
.clock-digits { font-family: var(--font-ui); font-weight: 500; font-size: 26px; line-height: 1; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.clock-digits.low { color: var(--signal); }

/* ================================================================== the 404 (notfound.js): a Doto hero, nothing else */
.nf { padding-top: var(--sp-24); text-align: center; display: flex; flex-direction: column; align-items: center; }
.nf-title { font-size: clamp(44px, 9vw, 104px); margin: var(--sp-3) 0 0; text-wrap: balance; }
.nf-lead { margin: var(--sp-8) auto 0; text-wrap: balance; }
.nf-actions { justify-content: center; margin-top: var(--sp-8); }
/* an outline on a paper-2 well needs more than --edge (2.9:1) to stay ≥ 3:1 */
.well :is(.input, .select, .textarea, .chip) { border-color: var(--ink-2); }

/* ================================================================== forced colours (Windows High Contrast)
   Fills are replaced by Canvas there, so every state drawn with a fill gets a system-colour shape instead: the
   switch keeps its outline and knob, the chosen segment and chip get a Highlight ring, and the "current" dots
   under tabs and nav items are drawn in CanvasText (FINAL.md §13). */
@media (forced-colors: active) {
  :is(.toggle, .sw) input { forced-color-adjust: none; background: Canvas; box-shadow: none; border: 1px solid CanvasText; }
  :is(.toggle, .sw) input::after { background: CanvasText; box-shadow: none; }
  :is(.toggle, .sw) input:checked { background: Highlight; border-color: Highlight; }
  :is(.toggle, .sw) input:checked::after { background: HighlightText; }
  .toggle input:disabled { border-color: GrayText; }
  .toggle input:disabled::after { background: GrayText; }
  .segmented label:has(input:checked), .g-conf-opt[aria-checked="true"], .tc-tile[aria-pressed="true"], .bot-card:has(input:checked) { outline: 2px solid Highlight; outline-offset: -2px; }
  .chip[aria-pressed="true"], .chip[aria-checked="true"] { outline: 2px solid Highlight; outline-offset: 1px; }
  /* :root raises these above the page stylesheets' own signal-dot rules, which load later */
  :root :is(.tabs [role="tab"][aria-selected="true"], .topnav-link[aria-current="page"], .topnav-link.is-current, .st-tab[aria-current]:not([aria-current="false"]), .a-sublink[aria-current="page"])::after,
  :root :is(.ms-link[aria-current="page"], .set-nav a[aria-current="page"], .g-toc a[aria-current="page"])::before,
  :root :is(.live-dot, .count-badge, .tb-dot, .nt-dot), :root .live::before { forced-color-adjust: none; background: CanvasText; color: Canvas; }
}
