/* Tibo Reset — near-white blue-gray grid and dotted summary cards and a soft-yellow reset highlight. Tokens and roles: docs/UI-SPEC.md §1.
   Light is :root; dark is html[data-theme="dark"] (set before paint by theme.js). One breakpoint, 800px.
   Lengths are rem, n px of the design = n/16 rem: phones show the design at full size, and from 801px up the
   root is 75%, so the desktop layout is the same design at three quarters. Hairlines (1px) do not scale. */

@font-face {
  font-family: "Baloo 2";
  src: url("/assets/baloo2-latin.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;
  /* colour: ground and ink */
  --c-grid: #e7ebf1;
  --c-ground: #f3f6fa;
  --c-surface: #ffffff;
  --c-dot: #dfe5ed;
  --c-field: #f1f5fb;
  --c-text: #151515;
  --c-text-soft: #505a68;
  --c-edge: #151515;
  --c-cast: #151515;
  --c-rule: #c8d8ee;
  --c-rule-strong: #b3c6df;
  --c-scrim: rgb(28 22 16 / .5);
  /* colour: action */
  --c-brand: #5294ff;
  --c-brand-deep: #78acff;
  --c-on-brand: #151515;
  --c-brand-soft: #e9f0fc;
  --c-link: #2c528c;
  --c-focus: #2c528c;
  /* colour: pastels by meaning (text on them is always --c-on-tint) */
  --c-on-tint: #151515;
  --c-reset: #9ec5ff;
  --c-global: #fb923c;
  --c-banked: #f4d77c;
  --c-boost: #ffc79a;
  --c-watch: #f4d77c;
  --c-preview: #dde2e8;
  --c-later: #b9defa;
  --c-hatch: #151515;
  /* the RESET key on the beg / thanks button: one illustration, the same in both themes */
  --c-key: #e8464e;
  --c-key-top: #ff7d82;
  --c-key-plate: #d5dce5;
  --c-key-ring: #3b4350;
  --c-key-shine: #ffffff;

  /* scale: space */
  --sp-1: .25rem;
  --sp-2: .5rem;
  --sp-3: .75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  /* scale: type */
  --fs-1: .75rem;
  --fs-2: .8125rem;
  --fs-3: .875rem;
  --fs-4: 1rem;
  --fs-5: 1.125rem;
  --fs-6: 1.3125rem;
  --fs-h2: clamp(1.375rem, 2.6vw + .75rem, 1.8125rem);
  --fs-h1: clamp(1.75rem, 3.4vw + 1rem, 2.5rem);
  --fs-figure: clamp(2.75rem, 7vw + 1.375rem, 5.25rem);
  --fs-verdict: clamp(1.875rem, 3.6vw + 1rem, 2.875rem);
  --f-display: "Baloo 2", ui-rounded, system-ui, sans-serif;
  --f-body: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans", "PingFang SC", "Hiragino Sans", sans-serif;
  --f-mono: ui-monospace, "SFMono-Regular", "Cascadia Mono", Menlo, monospace;
  /* scale: radius, edge, cast shadow, tilt */
  --round-ctl: .3125rem;
  --round-chip: .375rem;
  --round-card: .5rem;
  --round-bubble: .5rem;
  --round-pill: 999px;
  --edge: .125rem;
  --cast: .3125rem;
  --cast-sm: .1875rem;
  --lift: var(--cast) var(--cast) 0 var(--c-cast);
  --lift-sm: var(--cast-sm) var(--cast-sm) 0 var(--c-cast);
  --tilt-card: 0deg;
  --tilt-sticker: 0deg;
  /* layout */
  --page: 67.5rem;
  --read: 66ch;
  --ctl: 2.5rem;
  --cell: .8125rem;
  --cell-gap: .3125rem;
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --c-grid: #273448;
  --c-ground: #131c2d;
  --c-surface: #1d2a40;
  --c-dot: #344156;
  --c-field: #172238;
  --c-text: #f4f7ff;
  --c-text-soft: #c0cee4;
  --c-edge: #dce7fa;
  --c-cast: #070d17;
  --c-rule: #35455c;
  --c-rule-strong: #50637e;
  --c-scrim: rgb(0 0 0 / .6);
  --c-brand: #8bb7ff;
  --c-brand-deep: #aacaff;
  --c-on-brand: #111b2c;
  --c-brand-soft: #263f62;
  --c-link: #aacaff;
  --c-focus: #aacaff;
  --c-on-tint: #151515;
  --c-reset: #8bb7ff;
  --c-global: #ee7d32;
  --c-banked: #dec77d;
  --c-boost: #f2ad7c;
  --c-watch: #eccb55;
  --c-preview: #b4bec9;
  --c-later: #93c4e8;
  --c-hatch: #1d2a40;
}

/* base */
*, ::before, ::after { box-sizing: border-box }
[hidden] { display: none !important }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100% }
/* the desktop scale; the cast shadows stay on whole pixels there, so their edges are sharp */
@media (min-width: 801px) { :root { font-size: 75%; --cast: 4px; --cast-sm: 2px } }
body {
  margin: 0;
  background: linear-gradient(var(--c-grid) 1px, transparent 1px), linear-gradient(90deg, var(--c-grid) 1px, transparent 1px), var(--c-ground);
  background-size: 4rem 4rem;
  color: var(--c-text);
  font: var(--fs-4)/1.55 var(--f-body);
  overflow-wrap: break-word;
  /* short pages keep the footer at the bottom of the screen */
  display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh;
}
img, svg { max-width: 100%; height: auto }
a { color: var(--c-link); text-decoration-thickness: .09375rem; text-underline-offset: .22em }
a:hover { text-decoration-thickness: .15625rem }
button, input, textarea, select { font: inherit; color: inherit }
:focus-visible { outline: .1875rem solid var(--c-focus); outline-offset: .1875rem }
h1, h2, h3 { margin: 0; text-wrap: balance }
h1 { font: 800 var(--fs-h1)/1.12 var(--f-display); letter-spacing: -.015em }
h2 { font: 800 var(--fs-h2)/1.18 var(--f-display) }
h3 { font-size: var(--fs-5); line-height: 1.35 }
[data-route="event"] h1 { font-size: var(--fs-h2) }
p { margin: 0 }
code, pre, kbd { font-family: var(--f-mono); font-size: .9em }
:not(pre) > code { padding: 1px .3125rem; background: var(--c-field); border: 1px solid var(--c-rule-strong); border-radius: .3125rem }
.skip {
  position: absolute; z-index: 50; left: var(--sp-2); top: -5rem;
  padding: var(--sp-2) var(--sp-4); background: var(--c-surface); color: var(--c-text);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-ctl); font-weight: 700;
}
.skip:focus { top: var(--sp-2) }
/* wins over the field rules; pinned to the top-left so a table that cannot shrink stays in the viewport */
.sr-only {
  position: absolute !important; top: 0; left: 0; width: 1px !important; height: 1px !important; margin: -1px; padding: 0 !important;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0 !important;
}

/* page frame */
.page { flex: 1 0 auto; width: 100%; max-width: var(--page); margin: 0 auto; padding: var(--sp-5) var(--sp-4) 0 }
main { display: grid; gap: var(--sp-6); margin-top: var(--sp-5); padding-bottom: var(--sp-7) }
main > * { min-width: 0 }

/* masthead: brand and controls share a row while they fit, then wrap; nav ↔ menu at 800px */
.masthead { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-5); padding: 1.125rem max(1.25rem, calc((100% - 65.5rem) / 2)); background: var(--c-surface); border-bottom: var(--edge) solid var(--c-edge) }
.masthead-brand { display: flex; align-items: center; gap: var(--sp-2); color: var(--c-text); text-decoration: none }
.masthead-avatar {
  width: 3.5rem; aspect-ratio: 1; border-radius: 50%;
  border: 0; box-shadow: var(--lift-sm);
}
.masthead-title { padding-top: .14em; font: 800 clamp(1.5rem, 2.4vw + .9375rem, 2.125rem)/1 var(--f-display); letter-spacing: -.012em }
.masthead-side { order: 2; display: flex; gap: var(--sp-2) }
.masthead-side > * {
  display: grid; place-items: center; width: var(--ctl); height: var(--ctl); padding: 0;
  font: 700 var(--fs-4)/1 var(--f-body); text-decoration: none;
}
.x-link-icon { width: 1rem; height: 1rem; fill: currentColor }
.theme-toggle-icons { display: grid }
.theme-toggle-icon, .lang-icon { grid-area: 1 / 1; width: 1.125rem; height: 1.125rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round }
.theme-toggle-icon--sun, [data-theme="dark"] .theme-toggle-icon--moon { display: none }
[data-theme="dark"] .theme-toggle-icon--sun { display: block }
html:not(.theme-controls-enabled) :is(.theme-toggle, .tz, .log-filter) { display: none }
.nav { order: 1; display: flex; gap: var(--sp-2); margin-left: auto }
.nav > a { min-height: var(--ctl); padding: 0 var(--sp-3); font: 650 var(--fs-3)/1 var(--f-body) }
@media (max-width: 800px) { .nav { display: none } }
/* above 800px the nav is the tab bar */
@media (min-width: 801px) { .menu-btn, .core-tabs { display: none !important } }
/* Native popover, aligned to the language button by app.js; header-aligned no-script fallback. */
.lang-menu {
  inset: var(--pop-top, 4.75rem) var(--pop-right, max(1.25rem, calc((100% - 65.5rem) / 2))) auto auto;
  margin: 0; padding: var(--sp-2); min-width: 8.75rem; max-width: calc(100vw - 1.5rem);
  max-height: calc(100dvh - var(--pop-top, 4.75rem) - .75rem); overflow-y: auto;
  color: var(--c-text); background: var(--c-surface);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-card); box-shadow: var(--lift);
}
@media (max-width: 800px) { .lang-menu { --pop-top: 3.75rem; --pop-right: 4rem } }
.lang-menu:popover-open { display: grid; gap: var(--sp-1) }
.lang-menu a { padding: .5rem var(--sp-4); color: var(--c-text); font-weight: 700; text-decoration: none; border-radius: var(--round-ctl) }
.lang-menu a:hover, .lang-menu [aria-current] { background: var(--c-watch); color: var(--c-on-tint) }

/* shown only while updates are delayed (ENDGAME invariant 8) */
.ticker { margin-top: var(--sp-4); font: var(--fs-2)/1.5 var(--f-mono) }
.ticker .dot { display: inline-block; vertical-align: -1px; width: .75rem; height: .75rem; border-radius: 50%; border: var(--edge) solid var(--c-edge); background: var(--c-watch) }

/* buttons: one face, three roles (plain, primary, sticker) */
.masthead-side > *, .nav > a, .btn, .subscription-action, .reset-plea-button, form[data-poll] button {
  color: var(--c-text); background: var(--c-surface); cursor: pointer;
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-ctl); box-shadow: var(--lift-sm);
  transition: transform .08s ease-out, box-shadow .08s ease-out, background-color .12s;
}
.nav > a, .btn, .subscription-action, .reset-plea-button, form[data-poll] button {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2); text-decoration: none;
}
.btn { min-height: var(--ctl); padding: .1875rem var(--sp-4) 0; font: 700 var(--fs-3)/1.1 var(--f-body) }
.subscription-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3) }
/* the two color sets (View::alertActions) shape the phone rows only; wider screens flow their buttons as one row */
.subscription-set { display: contents }
.subscription-action, .reset-plea-button, form[data-poll] button { min-height: 2.625rem; padding: 0 1rem; font: 700 var(--fs-3)/1.1 var(--f-body) }
.subscription-action svg { flex: none; width: 1.125rem; height: 1.125rem; margin-top: 0; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round }
.masthead-side > :hover, .nav > a:hover { background: var(--c-brand-soft) }
.btn:hover, .subscription-action:hover, .btn-sun { background: var(--c-watch); color: var(--c-on-tint) }
.subscription-action[aria-pressed="true"] { background: var(--c-reset); color: var(--c-on-tint) }
.reset-plea-button, button.subscription-action[type="submit"], form[data-poll] button { background: var(--c-brand); color: var(--c-on-brand) }
.reset-plea-button:hover, button.subscription-action[type="submit"]:hover, form[data-poll] button:hover { background: var(--c-brand-deep); color: var(--c-on-brand) }
/* Alert row, two colors: Telegram and Discord in the reset blue, X, QQ and email in the watch yellow; hover
   swaps a button to the other one. The browser button stays plain until it is on (then the reset blue). */
.subscription-action--telegram, .subscription-action--discord { background: var(--c-reset); color: var(--c-on-tint) }
.subscription-action--x, .subscription-action--qq, .subscription-action--email { background: var(--c-watch); color: var(--c-on-tint) }
.subscription-action--x:hover, .subscription-action--qq:hover, .subscription-action--email:hover { background: var(--c-reset); color: var(--c-on-tint) }
/* the X logo is filled, the other icons are strokes; "New" (View::NEW_UNTIL) is an ink tag that reads on either fill */
.subscription-action--x svg { fill: currentColor; stroke: none }
.new-tag { padding: .1875rem .3125rem .125rem; border-radius: .25rem; background: var(--c-on-tint); color: var(--c-watch); font: 800 var(--fs-1)/1 var(--f-mono); text-transform: uppercase }
/* The beg button as a small clicker (2026-10-19; plea.js counts, plea-fx.js draws). At rest the button looks as it
   always did. While a combo runs a badge floats over it; a heat bar lights its bottom edge with the tapping speed and
   drains, striped, through an overheat; +1s fly from the tap (at most 12); particles draw on one canvas that exists
   only while they fly. Reduced motion keeps the badge's text and nothing that moves. */
.plea-game{position:relative;width:14.375rem;max-width:100%;margin-left:auto;display:grid;gap:var(--cell-gap)}
/* the badge grows from the button edge that faces the middle of the screen (data-side, plea.js), so it stays in view */
.plea-hud {
  position: absolute; z-index: 3; left: 0; bottom: calc(100% + .375rem); pointer-events: none; transform-origin: 0 100%;
  visibility: hidden; opacity: 0; transform: translateY(.375rem) scale(.85); transition: opacity .15s, transform .15s, visibility 0s .15s;
}
.plea-game[data-side="end"] .plea-hud { left: auto; right: 0; transform-origin: 100% 100% }
.plea-game[data-hud] .plea-hud { visibility: visible; opacity: 1; transform: none; transition: opacity .15s, transform .2s cubic-bezier(.3, 1.6, .5, 1) }
.plea-feedback {
  display: inline-block; white-space: nowrap; padding: .25rem .625rem .1875rem; border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip);
  background: var(--c-surface); color: var(--c-text); box-shadow: var(--lift-sm); font: 800 var(--fs-2)/1.2 var(--f-body); font-variant-numeric: tabular-nums;
  transform-origin: inherit;
}
.plea-left{flex-shrink:0;font:var(--fs-1) var(--f-mono);font-variant-numeric:tabular-nums}
.plea-game .reset-plea-button{width:100%;min-height:3rem;touch-action:manipulation;user-select:none;-webkit-user-select:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:transparent}
/* RESET key (2026-10-12): the cap sinks while the button is pressed; smaller on phones */
.reset-key { flex: none; transform-origin: 50% 100%; width: var(--sp-7); height: calc(var(--sp-6) + var(--sp-2)); margin-block: -.375rem; overflow: visible; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round }
.rk-plate { fill: var(--c-key-plate) }
.rk-ring { fill: var(--c-key-ring) }
.rk-side { fill: var(--c-key) }
.rk-top { fill: var(--c-key-top) }
.rk-shine { fill: var(--c-key-shine); stroke: none; opacity: .7 }
.rk-word { fill: currentColor; stroke: none; font: 800 .5375rem/1 var(--f-mono); letter-spacing: .07em }
.rk-cap { transition: transform .06s ease-out }
.plea-label { font-weight: 800 }
@media (prefers-reduced-motion: no-preference) { .reset-plea-button:active .rk-cap { transform: translateY(.1875rem) } }
@media (max-width: 800px) {
  .reset-key { width: 2.375rem; height: 2rem; margin-block: -.25rem }
  .hero-reaction .reset-plea-button, .xp-profile .reset-plea-button { padding-inline: .75rem; gap: var(--sp-1) }
}
.reset-plea-button{position:relative}
[data-pray-count]{font-variant-numeric:tabular-nums;transform-origin:0 60%}
.plea-game[data-hud="combo"]:is([data-level="4"], [data-level="5"]) .reset-plea-button{background:var(--c-reset);color:var(--c-on-tint)}
.plea-source{color:var(--c-text-soft);font-size:var(--fs-1);text-align:right}
/* +1: an ink-outlined number that rises from the button's top edge, so the count stays readable; its fill heats up
   with the combo, blue to yellow, orange, red, pink and white-hot (one illustration, the same in both themes) */
.plea-burst {
  position: absolute; z-index: 2; left: 50%; top: 0; color: var(--c-brand); font: 800 1.5rem/1 var(--f-display); white-space: nowrap; pointer-events: none;
  -webkit-text-stroke: .25rem var(--c-on-tint); paint-order: stroke fill; transform: translate(-50%, -100%);
}
.plea-burst[data-level="1"] { color: var(--c-watch) }
.plea-burst[data-level="2"] { color: var(--c-global) }
.plea-burst[data-level="3"] { color: var(--c-key) }
.plea-burst[data-level="4"] { color: var(--c-key-top) }
.plea-burst[data-level="5"] { color: var(--c-key-shine); -webkit-text-stroke-color: var(--c-key) }
/* the badge: yellow, orange, red, then gold on ink */
.plea-game[data-level="1"] .plea-feedback { background: var(--c-watch); color: var(--c-on-tint) }
.plea-game[data-level="2"] .plea-feedback { background: var(--c-global); color: var(--c-on-tint) }
.plea-game[data-level="3"] .plea-feedback { background: var(--c-key); color: var(--c-on-tint) }
.plea-game:is([data-level="4"], [data-level="5"]) .plea-feedback { background: var(--c-on-tint); color: var(--c-watch) }
.plea-game[data-hud="ready"] .plea-feedback { background: var(--c-reset); color: var(--c-on-tint) }
/* the heat bar lies on the button's bottom edge, between its corners; the fill slides in from the left */
.plea-heat { position: absolute; left: var(--round-ctl); right: var(--round-ctl); bottom: calc(-1 * var(--edge)); height: calc(var(--edge) + .1875rem); overflow: hidden; pointer-events: none }
.plea-heat i { display: block; height: 100%; background: linear-gradient(90deg, var(--c-watch), var(--c-global) 55%, var(--c-key)); transform: translateX(-100%) }
.plea-game[data-fever] .plea-heat i { background: repeating-linear-gradient(90deg, var(--c-key) 0 .375rem, var(--c-global) .375rem .75rem); animation: plea-fever .3s linear infinite }
.plea-game:is([data-hud="max"], [data-hud="hot"]) .plea-heat i { background: repeating-linear-gradient(135deg, var(--c-key) 0 .3125rem, var(--c-key-top) .3125rem .625rem) }
@keyframes plea-fever { to { background-position: .75rem 0 } }
.plea-fx { position: fixed; inset: 0; z-index: 35; width: 100%; height: 100%; pointer-events: none }
/* iOS: the transparent label that forwards a tap to a hidden switch, for the haptic tick (plea-fx.js) */
.plea-haptic { position: absolute; inset: 0; z-index: 1; -webkit-tap-highlight-color: transparent; touch-action: manipulation }
.plea-haptic input { position: absolute; width: 1px; height: 1px; margin: 0; visibility: hidden }
/* The cast (plea-tibo.js), only while someone taps: Tibo's round portrait pops up beside the button, on the side that
   faces the middle of the screen, and sways on a spring; a 🥔 joins him from "Challenge accepted", is mashed at
   GODLIKE and rests through the cooldown. The rank stamp is a tilted sticker over the card. */
.plea-cast {
  position: absolute; z-index: 2; bottom: 0; left: calc(100% + .625rem); display: flex; align-items: flex-end; gap: .25rem; pointer-events: none;
  opacity: 0; transform: scale(.3); transform-origin: 0 100%; transition: opacity .15s, transform .25s cubic-bezier(.3, 1.6, .5, 1);
}
.plea-game[data-side="end"] .plea-cast { left: auto; right: calc(100% + .625rem); flex-direction: row-reverse; transform-origin: 100% 100% }
.plea-cast[data-on] { opacity: 1; transform: none }
.plea-tibo { position: relative; flex: none; width: 2.75rem; height: 2.75rem; transform-origin: 50% 100% }
.plea-tibo img { display: block; width: 100%; height: 100%; border-radius: 50%; filter: drop-shadow(.125rem .125rem 0 var(--c-cast)); transition: transform .3s }
.plea-tibo[data-doze] img { transform: rotate(16deg) translateY(.125rem) }
.plea-tibo[data-halo]::before {
  content: ""; position: absolute; left: 15%; right: 15%; top: -.5rem; height: .4375rem;
  border: .1875rem solid var(--c-watch); border-radius: 50%; box-shadow: 0 0 .5rem var(--c-watch);
}
/* the bubble sits on the portrait's top corner, below the badge's band (which ends .375rem over the button) */
.plea-bubble {
  position: absolute; left: 72%; top: -.375rem; padding: .125rem .3125rem; background: var(--c-surface); color: var(--c-text);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip); font-size: var(--fs-3); line-height: 1.2; white-space: nowrap;
}
.plea-game[data-side="end"] .plea-bubble { left: auto; right: 72% }
.plea-bubble:empty { display: none }
.plea-spud { display: none; font-size: 1.75rem; line-height: 1; transform-origin: 50% 100%; transition: transform .15s }
.plea-spud[data-mood] { display: block }
.plea-spud[data-mood="shake"] { animation: plea-quake .12s linear infinite alternate }
.plea-spud[data-mood="mashed"] { transform: scale(1.5, .35) }
.plea-spud[data-mood="rest"] { transform: rotate(80deg) scale(.9) }
@keyframes plea-quake { from { transform: translateX(-.0625rem) rotate(-6deg) } to { transform: translateX(.0625rem) rotate(6deg) } }
.plea-stamp { position: fixed; z-index: 36; display: grid; justify-items: center; gap: .375rem; pointer-events: none; opacity: 0 }
.plea-stamp b {
  color: var(--c-key-shine); font: 800 clamp(1.75rem, 7vw, 3rem)/1 var(--f-display); text-transform: uppercase; white-space: nowrap;
  -webkit-text-stroke: .375rem var(--c-on-tint); paint-order: stroke fill;
}
.plea-stamp[data-level="1"] b { color: var(--c-watch) }
.plea-stamp[data-level="2"] b { color: var(--c-global) }
.plea-stamp[data-level="3"] b { color: var(--c-key) }
.plea-stamp[data-level="4"] b { color: var(--c-key-top) }
.plea-stamp[data-top] b { color: var(--c-watch); font-size: clamp(2.75rem, 13vw, 5rem) }
.plea-stamp small { padding: .25rem .625rem; background: var(--c-on-tint); color: var(--c-watch); border-radius: var(--round-chip); font: 800 var(--fs-3)/1.2 var(--f-body) }
.plea-stamp small:empty { display: none }
.masthead-side > :active, .nav > a:active, .btn:active, .subscription-action:active, .reset-plea-button:active, form[data-poll] button:active, a.hero-verdict:active {
  transform: translate(var(--cast-sm), var(--cast-sm)); box-shadow: 0 0 0 var(--c-cast);
}
.row, .onward { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) }

/* fields */
input[type="email"], input[type="number"], input[type="search"], input[type="datetime-local"], textarea {
  min-height: 2.75rem; width: 100%; padding: var(--sp-2) var(--sp-3);
  color: var(--c-text); background: var(--c-field);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-ctl);
}
textarea { font: var(--fs-3)/1.5 var(--f-mono); resize: vertical }
::placeholder { color: var(--c-text-soft); opacity: 1 }
input[type="range"] { width: 100%; accent-color: var(--c-brand) }
input[type="radio"] { accent-color: var(--c-brand) }
label { font-size: var(--fs-3); font-weight: 700 }

/* text blocks */
.prose { display: grid; gap: var(--sp-3) }
.prose > * { max-width: var(--read) }
.prose > h1, .prose-wide > * { max-width: none }
.prose h2 { margin-top: var(--sp-4) }
.prose ul, .prose ol, .tile ol { margin: 0; padding-left: 1.3em }
.prose li + li, .tile ol li + li { margin-top: var(--sp-1) }
.kicker {
  color: var(--c-text-soft); font: 700 var(--fs-2)/1.4 var(--f-mono); text-transform: uppercase; letter-spacing: .07em;
}
.kicker a { color: inherit }
.lede { font-size: var(--fs-5); line-height: 1.5 }
.byline, .hero-sub { color: var(--c-text-soft); font-size: var(--fs-3); white-space: pre-wrap; font-variant-numeric: tabular-nums }
.byline a, .hero-explainer a, .data-line a { font-weight: 700 }
.help, .data-line, .section-sub { color: var(--c-text-soft); font-size: var(--fs-3) }
.section-head { display: grid; gap: var(--sp-1) }
.graph-section { display: grid; gap: var(--sp-4) }
/* from 801px up a calendar's legend sits beside its heading, on the line of the subtitle */
@media (min-width: 801px) {
  .graph-section:has(> .section-head + .graph-legend) { grid-template-columns: minmax(0, 1fr) auto }
  .graph-section:has(> .section-head + .graph-legend) > :not(.section-head, .graph-legend) { grid-column: 1 / -1 }
  .section-head + .graph-legend { align-self: end }
}

/* cards */
.tile {
  display: grid; align-content: start; gap: var(--sp-3); padding: clamp(1.125rem, 2vw + .625rem, 1.75rem);
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-card); box-shadow: var(--lift);
}
.tile > * { min-width: 0; max-width: 100% }
.tile > p { max-width: 70ch }
.split { display: grid; gap: var(--sp-5) }
.split > * { min-width: 0 }
.agent-grid { display: grid; gap: var(--sp-5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 21.25rem), 1fr)) }
@media (min-width: 801px) { .split { grid-template-columns: 1fr 1fr; align-items: start } }

/* home hero: the answer and the odds lead */
.hero { display: grid; gap: var(--sp-4) }
.hero-explainer { font-size: var(--fs-4) }
.hero-card {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3) var(--sp-5); margin-top: var(--sp-2);
  padding: clamp(1.25rem, 2.4vw + .625rem, 2rem);
  background: var(--c-surface);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-card); box-shadow: var(--lift);
  transform: rotate(var(--tilt-card));
}
.hero-card > * { flex: 1 1 100% }
.hero-card h1 { margin-top: -.375rem; font-size: clamp(1.5rem, 1.8vw + 1rem, 2rem); line-height: 1.15 }
/* h1 and the time toggle share the top row; the toggle drops under the h1 on phones */
.hero-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--sp-3) }
.hero-head h1 { flex: 1 1 18ch; min-width: 0 }
.tz {
  display: inline-flex; flex: none; justify-self: start; overflow: hidden;
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-ctl); box-shadow: var(--lift-sm);
}
.tz-btn {
  min-height: calc(var(--ctl) - 2 * var(--edge)); padding: .125rem var(--sp-3) 0; background: none; border: 0; cursor: pointer;
  color: var(--c-text); font: 700 var(--fs-2)/1 var(--f-body); white-space: nowrap;
}
.tz-btn + .tz-btn { border-left: var(--edge) solid var(--c-edge) }
.tz-btn:hover { background: var(--c-brand-soft) }
.tz-btn[aria-pressed="true"] { background: var(--c-watch); color: var(--c-on-tint) }
.tz-btn:focus-visible { outline-offset: -.3125rem }
.hero-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15.625rem), 1fr)); gap: var(--sp-4) var(--sp-5) }
.hero-promise a {
  display: inline-block; padding: .1875rem var(--sp-3) 1px; color: var(--c-on-tint); background: var(--c-watch);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip); font-weight: 800;
}
/* A hint that is not a promise ("Brewing") wears the neutral surface, here and as a sticker (.hero-verdict.tease
   has the sticker's own surface), so the promise's yellow reads as the stronger of the two. */
.hero-promise.tease a { color: var(--c-text); background: var(--c-surface) }
.promise {
  display: grid; gap: var(--sp-1); margin: 0; padding: var(--sp-3) var(--sp-4);
  background: var(--c-field); border: var(--edge) dashed var(--c-rule-strong); border-radius: var(--round-chip);
}
.promise > p { font-weight: 650 }
.promise footer { color: var(--c-text-soft); font-size: var(--fs-3) }
.hero-odds { flex: 0 1 auto; display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-4) }
.hero-figure-wrap { display: grid; gap: var(--sp-1); color: var(--c-text-soft) }
.hero-k, .meter-k { color: var(--c-text-soft); font: 700 var(--fs-1)/1.3 var(--f-mono); text-transform: uppercase; letter-spacing: .05em }
.hero-figure {
  padding: .5rem clamp(.6875rem, 1.6vw + .375rem, 1.125rem) 0; border-radius: var(--round-chip); background: var(--c-watch); color: var(--c-on-tint);
  font: 800 var(--fs-figure)/.95 var(--f-display); letter-spacing: -.025em; font-variant-numeric: tabular-nums;
}
.hero-figure-wrap > * { justify-self: start }
[data-odds="48"] .hero-figure { background: var(--c-later) }
.hero-verdict {
  flex: 0 1 auto; padding: .625rem 1.25rem .25rem;
  background: var(--c-surface); color: var(--c-text); border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip);
  box-shadow: var(--lift); font: 800 var(--fs-verdict)/1 var(--f-display); transform: rotate(var(--tilt-sticker));
}
.hero-verdict.yes { background: var(--c-global); color: var(--c-on-tint) }
.hero-verdict.promised { background: var(--c-watch); color: var(--c-on-tint) }
.hero-card .lede { max-width: 54ch }
.hero-footer {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding-top: var(--sp-3); border-top: var(--edge) dashed var(--c-rule-strong);
}
.hero-sub { font-family: var(--f-mono); font-size: var(--fs-2) }

/* figures: stat tiles and meters */
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 11.25rem), 1fr)); gap: var(--sp-3); margin: 0 }
.stat-tile {
  display: grid; align-content: start; gap: var(--sp-1); padding: var(--sp-3) var(--sp-4) var(--sp-2);
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip); box-shadow: var(--lift-sm);
}
.stat-tile dt { color: var(--c-text-soft); font-size: var(--fs-2); font-weight: 700 }
.stat-tile dd { margin: 0; font: 800 clamp(1.5rem, 2.4vw + .875rem, 2.25rem)/1.1 var(--f-display); font-variant-numeric: tabular-nums; white-space: nowrap }
@media (max-width: 480px) {
  .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2) }
  [data-route="home"] .stat-row { grid-template-columns: repeat(3, minmax(0, 1fr)) }
  .stat-tile dd { white-space: normal }
}
.meter { display: grid; gap: var(--sp-1); justify-items: start }
.meter-n { font: 800 clamp(2rem, 2.8vw + 1.25rem, 2.875rem)/1 var(--f-display); font-variant-numeric: tabular-nums }
.meter .meter-n {
  padding: .4375rem .875rem 0; color: var(--c-on-tint); background: var(--c-watch);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip); box-shadow: var(--lift-sm);
}
/* tracker hero: latest global reset and latest banked grant */
.meter .meter-n.reset { background: var(--c-global) }
.meter .meter-n.banked { background: var(--c-banked) }
.meter-n.status { font-size: var(--fs-6); padding-bottom: .3125rem }

/* heat calendar: --weeks columns fill the card (26 on home, every week since the first reset on /tracker,
   smaller cells there); reset = solid orange, banked = hatched yellow (both inked), none = plain fill */
.graph-legend { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); color: var(--c-text-soft); font-size: var(--fs-3) }
.legend-item { display: inline-flex; align-items: center; gap: var(--sp-1) }
.heat-wrap {
  overflow-x: auto; padding: var(--sp-4) var(--sp-5) var(--sp-5);
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-card); box-shadow: var(--lift);
}
/* phones scroll inside the card once a week column would drop under --cell */
.heat-wrap.is-long { --cell: .5625rem; --cell-gap: .1875rem }
/* at that size a 2 px edge is half the cell: phones draw it at 1 px */
@media (max-width: 800px) { .heat-wrap.is-long .heat-cell { border-width: .0625rem } }
.heat-months, .heat-body { min-width: calc(1.875rem + var(--weeks, 26) * (var(--cell) + var(--cell-gap))) }
.heat-months {
  display: grid; grid-template-columns: 1.875rem repeat(var(--weeks, 26), minmax(0, 1fr)); gap: var(--cell-gap); margin-bottom: var(--sp-2);
  color: var(--c-text-soft); font-size: var(--fs-1); line-height: 1.2; white-space: nowrap;
}
.heat-months span:not(:empty):has(+ span:not(:empty)) { visibility: hidden }
.heat-body { display: flex; gap: var(--cell-gap) }
.heat-wd { display: grid; grid-template-rows: repeat(7, 1fr); gap: var(--cell-gap); align-items: center; width: 1.875rem; flex: none; color: var(--c-text-soft); font-size: var(--fs-1); line-height: 1 }
.heat-board { flex: 1; display: grid; grid-auto-flow: column; grid-template-rows: repeat(7, auto); grid-auto-columns: minmax(0, 1fr); gap: var(--cell-gap) }
.heat-cell, .legend-chip {
  display: block; aspect-ratio: 1;
  background: var(--c-rule); border: var(--edge) solid var(--c-rule); border-radius: .3125rem;
}
.legend-chip { width: .9375rem; height: .9375rem }
.heat-cell.reset, .legend-chip--regular { background: var(--c-global); border-color: var(--c-edge) }
.heat-cell.banked, .legend-chip--banked {
  background: repeating-linear-gradient(-45deg, var(--c-banked) 0 .1875rem, var(--c-hatch) .1875rem .28125rem); border-color: var(--c-edge);
}
/* a global reset stands up from the page (banked grants and empty days lie flat): a hard shadow scaled to the gap,
   so it never reaches the next cell */
.heat-cell.reset, .legend-chip--regular {
  box-shadow: calc(var(--cell-gap) * .4) calc(var(--cell-gap) * .4) 0 var(--c-cast);
}
.heat-cell.is-future { visibility: hidden }
a.heat-cell:hover { transform: scale(1.18) }
/* hover card for a day (assets/heat.js), placed with fixed coordinates */
.heat-tip {
  position: fixed; z-index: 15; display: grid; gap: var(--sp-1); max-width: min(17.5rem, calc(100vw - 1rem)); padding: var(--sp-2) var(--sp-3);
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip); box-shadow: var(--lift-sm);
  font-size: var(--fs-2); line-height: 1.45; pointer-events: none;
}
.heat-tip .pill { justify-self: start }

/* home: Tibo's 28-day challenge (Pages::challenge), one square a day, 14 a row (7 on phones) */
.challenge-strip { display: grid; grid-template-columns: repeat(14, minmax(0, 1fr)); gap: var(--sp-1); margin: 0; padding: 0; list-style: none }
.cd, .cd-chip {
  display: grid; place-items: center; aspect-ratio: 1; border-radius: var(--round-ctl); border: var(--edge) solid var(--c-edge);
  background: var(--c-field); color: var(--c-on-tint); font: 800 var(--fs-3)/1 var(--f-display);
}
.cd-chip { display: inline-block; width: .9375rem; height: .9375rem; border-radius: .3125rem }
.cd.improvement, .cd-chip.improvement { background: var(--c-later) }
.cd.reset, .cd-chip.reset { background: var(--c-global) }
.cd.banked, .cd-chip.banked { background: var(--c-banked) }
/* today before Tibo has shipped: an empty dashed square (a grey fill read as the improvement blue) */
.cd.waiting, .cd-chip.waiting { background: var(--c-surface); color: var(--c-text); border-style: dashed }
.cd.ahead, .cd-chip.ahead { background: var(--c-surface); color: var(--c-text-soft); border-color: var(--c-rule-strong) }
.cd.quiet { color: var(--c-text-soft) }
.cd.is-today { box-shadow: var(--lift-sm) }
@media (max-width: 480px) { .challenge-strip { grid-template-columns: repeat(7, minmax(0, 1fr)) } }

/* reset-hour histogram */
.hist {
  display: flex; align-items: flex-end; gap: var(--sp-1); height: 6.5rem; padding: 0 .125rem;
  border-bottom: var(--edge) solid var(--c-edge);
}
.hist .bar { flex: 1; min-width: 0; background: var(--c-global); border: var(--edge) solid var(--c-edge); border-bottom: 0; border-radius: .3125rem .3125rem 0 0 }

/* tables */
.table { width: 100%; border-collapse: collapse; color: var(--c-text); font-size: var(--fs-3) }
.table th, .table td { padding: .625rem var(--sp-2) .625rem 0; border-bottom: var(--edge) dashed var(--c-rule-strong); text-align: left; vertical-align: baseline; overflow-wrap: anywhere }
.table td > code { white-space: nowrap }
.table thead th { border-bottom: var(--edge) solid var(--c-edge); font-size: var(--fs-2) }
.table tbody tr:first-child > * { border-top: var(--edge) dashed var(--c-rule-strong) }
.table thead + tbody tr:first-child > * { border-top: 0 }
.table th[scope="row"] { color: var(--c-text-soft); font-weight: 600 }
.table th[scope="row"] + td { padding-right: 0; text-align: right; font-weight: 700; font-variant-numeric: tabular-nums }

/* FAQ */
.faq { gap: 0 }
.faq h2 { margin-bottom: var(--sp-3) }
.acc { border-top: var(--edge) dashed var(--c-rule-strong) }
.acc h3 { font-size: inherit }
.acc-h {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); width: 100%; padding: .875rem 0;
  background: none; border: 0; color: var(--c-text); font: 700 var(--fs-5)/1.35 var(--f-body); text-align: left; cursor: pointer;
}
.acc-h::after {
  content: "+"; flex: none; display: grid; place-items: center; width: 2rem; height: 2rem; padding-top: .1875rem;
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip);
  font: 800 1.25rem/1 var(--f-display);
}
.acc.open .acc-h::after { content: "−"; background: var(--c-watch); color: var(--c-on-tint) }
.acc-b { display: none; max-width: var(--read); padding-bottom: var(--sp-4) }
.acc.open .acc-b { display: block }

/* Tibo log: speech bubbles from the avatar */
.log-list { display: grid; gap: var(--sp-4); margin: 0; padding: 0; list-style: none }
.log-item { display: grid; grid-template-columns: 2.875rem minmax(0, 1fr); gap: var(--sp-4); align-items: start }
.log-more { justify-self: start }
.log-avatar { width: 2.875rem; height: 2.875rem; border-radius: 50%; border: var(--edge) solid var(--c-edge); box-shadow: var(--lift-sm) }
.log-bubble {
  position: relative; display: grid; gap: var(--sp-2); padding: .875rem 1.25rem;
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-bubble); box-shadow: var(--lift);
}
.log-bubble::before {
  content: ""; position: absolute; left: -.6875rem; top: .9375rem; width: 1rem; height: 1rem; background: var(--c-surface);
  border-left: var(--edge) solid var(--c-edge); border-bottom: var(--edge) solid var(--c-edge); rotate: 45deg;
}
.log-item-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) .625rem; color: var(--c-text-soft); font-size: var(--fs-2) }
.log-item-time {
  padding: .125rem .6875rem 0; color: var(--c-on-tint); background: var(--c-watch);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-pill); font: 800 .9375rem/1.5 var(--f-display);
}
.log-item-abs, .xp-who { font-family: var(--f-mono); font-variant-numeric: tabular-nums }
.xp-who strong { font-family: var(--f-body); color: var(--c-text) }
.log-item-text { line-height: 1.5; overflow-wrap: anywhere }
.log-item-text.is-full { white-space: pre-line }
.log-item-title { color: var(--c-text); text-decoration: none }
.log-item-title:hover { text-decoration: underline }
.log-item-link { justify-self: start; font: 700 var(--fs-3)/1.4 var(--f-mono); text-decoration: none }
.log-item-link:hover { text-decoration: underline }
.log-bubble .help { font-size: var(--fs-2) }

.pill {
  display: inline-block; padding: 1px .625rem 0; color: var(--c-text); background: var(--c-surface);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-pill); font: 700 var(--fs-1)/1.6 var(--f-body); white-space: nowrap;
}
.pill.reset { background: var(--c-global); color: var(--c-on-tint) }
.pill.banked { background: var(--c-banked); color: var(--c-on-tint) }
.pill.boost { background: var(--c-boost); color: var(--c-on-tint) }
.pill.reset_preview, .pill.codex { background: var(--c-preview); color: var(--c-on-tint) }

/* ledgers: banked grants, status incidents */
.log { display: grid; margin: 0; padding: 0; list-style: none }
.log > li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-1) var(--sp-3); padding: var(--sp-3) 0; border-top: var(--edge) dashed var(--c-rule-strong) }
.log > li:last-child { border-bottom: var(--edge) dashed var(--c-rule-strong) }
.log > li > p { flex: 1 1 16.25rem }
.log > li > time { color: var(--c-text-soft); font: var(--fs-2) var(--f-mono) }
.log > li a { color: var(--c-text); text-decoration-color: var(--c-rule-strong) }
.log > li a:hover { color: var(--c-link); text-decoration-color: currentColor }

/* alerts email form */
form[data-email] { display: flex; flex-wrap: wrap; align-items: end; gap: var(--sp-3); margin-top: var(--sp-2) }
form[data-email] label { display: grid; gap: var(--sp-1); flex: 1 1 15rem }
form[data-email] .help { flex-basis: 100% }
/* the submit button matches the field's 44px (fields), not the 42/38px alert buttons, so their edges line up */
form[data-email] button { min-height: 2.75rem }

/* usage tracker, worth-it calculator, poll */
.tracker, [data-worth] { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fit, minmax(min(100%, 14.375rem), 1fr)) }
.tracker label, [data-worth] label, [data-tracker] > label, .paste { display: grid; gap: var(--sp-1); align-content: start }
[data-worth] > label, .tracker > label { align-content: space-between }
.span-2, [data-worth] > p { grid-column: 1 / -1 }
.tracker output { color: var(--c-text-soft); font: var(--fs-2) var(--f-mono) }
.tracker-out {
  display: grid; gap: var(--sp-1); padding: var(--sp-3) var(--sp-4);
  background: var(--c-field); border: var(--edge) dashed var(--c-rule-strong); border-radius: var(--round-chip);
  font-weight: 700; font-variant-numeric: tabular-nums;
}
[data-worth-out], [data-banked-cd] { font-size: var(--fs-5); font-variant-numeric: tabular-nums }
.dt { display: flex }
.dt .btn { width: 100%; justify-content: flex-start; font: 700 var(--fs-4)/1.2 var(--f-body); padding-top: 0 }
.stepper { display: flex; align-items: center; gap: var(--sp-2) }
.stepper input { width: 7ch; text-align: center }
.stepper .btn { min-width: 2.75rem; padding-inline: 0 }
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0 }
.chip {
  display: inline-flex; align-items: center; gap: var(--sp-1); min-height: 2.375rem; padding: .125rem .875rem 0;
  color: var(--c-text); background: var(--c-surface); text-decoration: none; cursor: pointer;
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-pill); font-weight: 700; font-size: var(--fs-3);
}
.chip:hover, .chip.is-on, .chip[aria-pressed="true"], .chip:has(input:checked) { background: var(--c-watch); color: var(--c-on-tint) }
form[data-poll] { display: grid; gap: var(--sp-3); justify-items: start }
/* forecast radar: CSS-only tabs over the post list (radio chips; the checked value picks the pane) */
.radar-tabs { margin-bottom: var(--sp-3) }
.radar-tabs input { position: absolute; width: 1px; height: 1px; margin: -1px; opacity: 0; pointer-events: none }
.radar-posts:has([value="latest"]:checked) [data-radar="signals"], .radar-posts:not(:has([value="latest"]:checked)) [data-radar="latest"] { display: none }

/* developers: code blocks */
.code-block { overflow: hidden; background: var(--c-field); border: var(--edge) solid var(--c-edge); border-radius: var(--round-chip) }
.code-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); padding: .375rem .375rem .375rem var(--sp-3);
  border-bottom: var(--edge) solid var(--c-edge); font: 700 var(--fs-2) var(--f-mono);
}
.code-head .btn { min-height: 2rem; padding: .125rem var(--sp-3) 0; font-size: var(--fs-3); box-shadow: none }
.code-block pre { margin: 0; padding: var(--sp-3); overflow-x: auto; font-size: var(--fs-2); line-height: 1.55 }

/* /X-posts */
/* the beg button (Pages::pray) sits at the profile card's right edge. Phones (2026-10-16, so the newest post shows on
   the first screen): the list page's intro keeps its H1 and alert buttons but not its kicker and lede, the card drops
   its line (all three said what the H1 says), and the card is one row (avatar, name over handle, button) whose button
   wraps under the name when the row is too narrow */
.xp-profile { grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--sp-4) }
.xp-profile .masthead-avatar { width: 3.5rem }
.xp-profile .plea-game { width: auto; min-width: 10.875rem }
.xp-name { font-size: var(--fs-5) }
@media (max-width: 800px) {
  .prose:has(+ .xp-profile) > :is(.kicker, .lede), .xp-profile .help { display: none }
  .xp-profile { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4) }
  .xp-profile .masthead-avatar { width: var(--ctl) }
  .xp-profile > div:not(.plea-game) { flex: 1 0 auto }
  .xp-profile .plea-game { min-width: 0; margin-left: 0 }
  .xp-name { font-size: var(--fs-3); line-height: 1.3 }
  .xp-name strong { display: block; font-size: var(--fs-4) }
}
.xp-strip { display: block; width: 100%; height: 4.5rem }
.xp-bar-posts { fill: var(--c-edge) }
.xp-bar-replies { fill: var(--c-brand) }
.xp-bar-none rect { fill: var(--c-rule-strong) }
.xp-strip a:hover rect { fill-opacity: .7 }
.statline { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); margin: 0; padding: 0; list-style: none; color: var(--c-text-soft); font-size: var(--fs-3) }
.statline li { display: grid }
.statline strong { color: var(--c-text); font: 800 1.75rem/1.1 var(--f-display) }
.statline strong a { color: inherit }
.xp-pill-row:not(:has(:not([hidden]))) { display: none }
/* Tabs on the left, the Date button on the right; its popover is placed under it by app.js. */
.xp-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-2) }
.xp-dates-btn { font-family: var(--f-body) }
.xp-dates-btn::after { content: ""; width: .4375rem; height: .4375rem; margin: -.3125rem 0 0 var(--sp-1); border: solid currentColor; border-width: 0 .125rem .125rem 0; rotate: 45deg }
.xp-bar:has(.xp-dates:popover-open) .xp-dates-btn { background: var(--c-watch); color: var(--c-on-tint) }
.xp-bar:has(.xp-dates:popover-open) .xp-dates-btn::after { margin-top: .1875rem; rotate: 225deg }
.xp-dates {
  inset: var(--pop-top, .75rem) var(--pop-right, .75rem) auto auto; margin: 0; padding: var(--sp-4);
  width: min(35rem, calc(100vw - 2 * var(--pop-right, .75rem))); max-height: calc(100dvh - var(--pop-top, .75rem) - .75rem);
  overflow-y: auto; overscroll-behavior: contain; color: var(--c-text); background: var(--c-surface);
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-card); box-shadow: var(--lift);
}
/* A phone has little room under the button: the panel may rise over it to keep a usable height. */
@media (max-width: 800px) {
  .xp-dates { --pop-h: min(35rem, calc(100dvh - 1.5rem)); top: min(var(--pop-top, .75rem), calc(100dvh - var(--pop-h) - .75rem)); max-height: var(--pop-h) }
}
.xp-dates:popover-open { display: grid; gap: var(--sp-2) }
.xp-dates .help { margin: 0 }
.xp-dates-month { margin: var(--sp-2) 0 0; font-weight: 800 }
.xp-dates ul { display: grid; grid-template-columns: repeat(auto-fill, minmax(4.875rem, 1fr)); gap: var(--sp-2); margin: 0; padding: 0; list-style: none }
.xp-date { display: grid; padding: .3125rem var(--sp-2); color: var(--c-text); text-decoration: none; border: 1px solid var(--c-rule-strong); border-radius: var(--round-ctl); font-size: var(--fs-2) }
.xp-date span { color: var(--c-text-soft) }
a.xp-date:hover, a.xp-date:focus-visible { background: var(--c-watch); color: var(--c-on-tint); border-color: var(--c-edge) }
a.xp-date:hover span, a.xp-date:focus-visible span { color: inherit }
.xp-date.is-none { color: var(--c-text-soft); border-style: dashed }
#xposts { display: grid; gap: var(--sp-6) }
.xp-day { display: grid; gap: var(--sp-4) }
.xp-day-h { font-size: var(--fs-6) }
.xp-day-h a { color: var(--c-text); text-decoration: none }
.xp-day-h a:hover { text-decoration: underline }
.xp-day-h .section-sub { font: var(--fs-2) var(--f-mono) }
/* The list's time toggle (2026-10-15) opens the newest day: on its heading's row, at the right; on phones above it. */
.xp-day > .tz { justify-self: end }
@media (min-width: 801px) {
  .xp-day:has(> .tz) { grid-template-columns: minmax(0, 1fr) auto; align-items: center }
  .xp-day > .tz { grid-area: 1 / 2 }
  .xp-day:has(> .tz) > .log-list { grid-column: 1 / -1 }
}
/* Earlier days fold (2026-10-15): each is one bar, its heading the summary; + / − as in .challenge-posts. */
details.xp-day { display: block }
details.xp-day > summary {
  display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); cursor: pointer; list-style: none;
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-card); box-shadow: var(--lift-sm);
}
details.xp-day > summary::-webkit-details-marker { display: none }
details.xp-day > summary::after { content: "+"; margin-left: auto; font: 700 var(--fs-6)/1 var(--f-body) }
details.xp-day[open] > summary::after { content: "−" }
details.xp-day > .log-list { margin-top: var(--sp-4) }
/* Phones (2026-10-15): a day heading stays on one line: smaller, no zone name (the toggle above names it), and wrapped
   greedily, so only a badge can move under it ("Reset announcement" does on most phones), never the date. */
@media (max-width: 800px) {
  .xp-day-h { font-size: var(--fs-5); text-wrap: wrap }
  .xp-day-h .section-sub { display: none }
  details.xp-day > summary { padding: var(--sp-3); gap: var(--sp-2) }
  details.xp-day .xp-day-h { font-size: var(--fs-3) }
}
.xp-replying, .xp-counts { font-size: var(--fs-2) }
.xp-events { margin: 0; padding-left: 1.3em }
.xp-row:focus { outline: none }
.xp-row:focus-visible .log-bubble { outline: .1875rem solid var(--c-focus); outline-offset: .1875rem }

/* footer */
.site-footer { border-top: var(--edge) solid var(--c-edge); background: var(--c-surface) }
.foot-grid {
  display: grid; gap: var(--sp-4) var(--sp-6); max-width: var(--page); margin: 0 auto; padding: var(--sp-6) var(--sp-4) var(--sp-7);
  color: var(--c-text-soft); font-size: var(--fs-3);
}
.foot-grid strong { color: var(--c-text); font: 800 var(--fs-6)/1.2 var(--f-display) }
.foot-grid > div { display: grid; gap: var(--sp-2); align-content: start }
.foot-brand { display: flex; align-items: center; gap: var(--sp-2) }
.foot-brand .masthead-avatar { width: 2rem; flex: none }
/* two even lines instead of a full line and a stray last word */
.foot-grid p { text-wrap: balance }
.foot-grid nav { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); align-content: start }
.foot-grid nav a { color: var(--c-text); font-weight: 650 }
@media (min-width: 801px) { .foot-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) } }

/* overlays: drawer, palette, toast */
.drawer { position: fixed; inset: 0; z-index: 20; display: none; justify-content: flex-end; background: var(--c-scrim) }
.drawer.open { display: flex }
.drawer-card {
  display: flex; flex-direction: column; gap: var(--sp-2); width: min(20rem, 86vw); height: 100%; overflow-y: auto;
  padding: var(--sp-5) var(--sp-4); background: var(--c-ground); border-left: var(--edge) solid var(--c-edge);
}
.drawer-card a {
  padding: .5625rem var(--sp-4) .3125rem; color: var(--c-text); background: var(--c-surface); text-decoration: none;
  border: var(--edge) solid var(--c-edge); border-radius: var(--round-ctl); box-shadow: var(--lift-sm); font: 800 var(--fs-5)/1.3 var(--f-display);
}
.drawer-card a.is-on { background: var(--c-watch); color: var(--c-on-tint) }
.cmd-layer { position: fixed; inset: 0; z-index: 30; display: none; padding: 12vh var(--sp-4) var(--sp-4); background: var(--c-scrim) }
.cmd-layer.open { display: block }
.cmd-card {
  max-width: 35rem; margin: 0 auto; padding: var(--sp-3);
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-card); box-shadow: var(--lift);
}
#cmd-input { min-height: 3.125rem; font-size: var(--fs-5) }
#cmd-list { max-height: 50vh; overflow-y: auto; margin: var(--sp-2) 0 0; padding: 0; list-style: none }
#cmd-list a { display: block; padding: .5625rem var(--sp-3); color: var(--c-text); font-weight: 700; text-decoration: none; border-radius: var(--round-ctl) }
#cmd-list a:hover, #cmd-list .is-active a { background: var(--c-watch); color: var(--c-on-tint) }
.toast {
  position: fixed; z-index: 40; left: 50%; bottom: var(--sp-5); max-width: calc(100% - 2rem);
  padding: .625rem var(--sp-4); color: var(--c-ground); background: var(--c-text); border-radius: var(--round-ctl);
  font-weight: 700; pointer-events: none; opacity: 0; transform: translate(-50%, .75rem); transition: opacity .18s, transform .18s;
}
.toast.show { opacity: 1; transform: translate(-50%, 0) }

/* quiet page tools, bottom right (View::pageTools): share opens a small menu; top shows after scrolling (app.js).
   Back-to-top glides in app.js on purpose: a page-wide scroll-behavior: smooth animates every programmatic
   scroll too, and split the beg button's tap batches in the browser check (2026-10-12). */
.page-tools { position: fixed; z-index: 18; right: var(--sp-4); bottom: var(--sp-4); display: grid; gap: var(--sp-2); justify-items: end }
.page-tools summary { list-style: none }
.page-tools summary::-webkit-details-marker { display: none }
.page-tools summary, .page-tools .to-top {
  display: grid; place-items: center; width: 2.375rem; height: 2.375rem; padding: 0; cursor: pointer;
  color: var(--c-text-soft); background: var(--c-surface); border: 1px solid var(--c-rule-strong); border-radius: var(--round-ctl); opacity: .85;
}
.page-tools summary:hover, .page-tools .to-top:hover, .share-pop[open] summary { color: var(--c-text); border-color: var(--c-edge); opacity: 1 }
.page-tools svg { width: 1.125rem; height: 1.125rem; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round }
.page-tools .to-top { display: none }
.page-tools .to-top.show { display: grid }
.share-pop { position: relative }
.share-menu {
  position: absolute; right: 0; bottom: calc(100% + var(--sp-2)); display: grid; min-width: 8.75rem; padding: var(--sp-1);
  background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-ctl); box-shadow: var(--lift-sm);
}
.share-menu a, .share-menu button {
  padding: .4375rem .625rem; color: var(--c-text); background: none; border: 0; border-radius: var(--round-ctl);
  font: 650 var(--fs-3)/1.3 var(--f-body); text-align: left; text-decoration: none; cursor: pointer; white-space: nowrap;
}
.share-menu a:hover, .share-menu button:hover { background: var(--c-brand-soft) }
@media (max-width: 800px) { .page-tools { right: var(--sp-3); bottom: var(--sp-3) } }

/* reduced motion: no press travel, no tilt, no transitions */
@media (prefers-reduced-motion: reduce) {
  *, ::before, ::after { transition: none !important; animation: none !important }
  .hero-card, .hero-verdict, :active, a.heat-cell:hover { transform: none !important }
  .plea-heat, .plea-cast, .plea-stamp { display: none }
}

/* Compact navigation and reset summary, October 2026 preview. */
.core-tabs .chip { border-radius: var(--round-ctl); font-family: var(--f-body) }
.core-tabs .chip.is-on { background: var(--c-brand); color: var(--c-on-brand); box-shadow: var(--lift-sm) }
.nav > a { border-color: transparent; box-shadow: none; background: transparent }
.nav > a.is-on { border-color: var(--c-edge); background: var(--c-brand); color: var(--c-on-brand); box-shadow: var(--lift-sm) }
.latest-reset-age { justify-self: start; padding: .4375rem 1.125rem 0; background: var(--c-watch); color: var(--c-on-tint); border-radius: var(--round-ctl); font: 800 clamp(2.5rem, 5.5vw, 4.25rem)/1.15 var(--f-display); letter-spacing: -.025em }
.hero-card { background-image: radial-gradient(var(--c-dot) .06875rem, transparent .09375rem); background-size: 1rem 1rem }
.hero-head { align-items: center; margin-bottom: var(--sp-3) }
.hero-card h1 { margin: 0; font: 700 clamp(1.0625rem, 1.7vw, 1.375rem)/1.3 var(--f-body); letter-spacing: -.015em }
.hero-card .plea-source, .xp-profile .plea-source { display: none }
[data-route="home"] .stat-tile { padding: 1.125rem 1.25rem; background: var(--c-surface) }
[data-route="home"] .stat-tile dt { font-weight: 500; margin-bottom: .3125rem }
[data-route="home"] .stat-tile dd { font-family: var(--f-body); font-size: 1.75rem; font-weight: 750 }
@media (max-width: 800px) {
  .masthead { gap: var(--sp-2); padding: var(--sp-3) var(--sp-4) }
  .masthead-title { font-size: 1.5625rem }
  .masthead-avatar { width: var(--ctl) }
  .masthead-side { gap: var(--sp-2) }
  .masthead-side > * { width: 2.125rem; height: calc(var(--ctl) - var(--sp-1)) }
  .page { padding-top: var(--sp-4) }
  main { margin-top: var(--sp-4); gap: var(--sp-5) }
  .hero { gap: var(--sp-3) }
  .hero-explainer { font-size: var(--fs-3) }
  /* alert row (2026-10-18), one color set a row: the browser button shares the first row with the first set, its
     label wrapping to two lines (7rem holds "Enable reset", 5.25rem half the Chinese label) before that set moves
     down; the second set fills the second row. Compact, so "Enable reset alerts", Telegram and Discord keep one line
     from 390 px; below 340 px (/alerts: 380 px, /zh: 360 px) the first set takes a row of its own. */
  .subscription-actions, .subscription-set { display: flex; flex-wrap: wrap; gap: var(--sp-2) .375rem }
  .subscription-set:last-child { flex-basis: 100% }
  .subscription-actions > [data-browser] { flex: 1 1 7rem; max-width: max-content }
  :lang(zh) .subscription-actions > [data-browser] { flex-basis: 5.25rem }
  .subscription-action { min-height: 2.375rem; gap: .375rem; padding-inline: .5rem; font-size: var(--fs-1) }
  .subscription-action svg { width: .875rem; height: .875rem }
  .hero-head { gap: var(--sp-4) }
  .hero-head h1 { flex-basis: 100% }
  .latest-reset-age { padding-inline: .75rem }
  [data-route="home"] .stat-tile { padding: .75rem .625rem }
  [data-route="home"] .stat-tile dt { font-size: var(--fs-1); line-height: 1.4 }
  [data-route="home"] .stat-tile dd { font-size: var(--sp-5) }
}
/* four masthead buttons beside the wordmark: below 375 px the 34 px buttons wrap to a second row (20 px short at 320) */
@media (max-width: 374px) {
  .masthead-side { gap: .375rem }
  .masthead-side > * { width: 1.75rem }
}
@media (max-width: 360px) {
  .masthead-title { font-size: 1.3125rem }
  .masthead-avatar { width: 2.125rem }
  .masthead-brand { gap: var(--sp-2) }
  .latest-reset-age { font-size: 2.25rem }
}

.challenge-panel { background: var(--c-surface); border: var(--edge) solid var(--c-edge); border-radius: var(--round-card); box-shadow: var(--lift-sm) }
.challenge-head { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-4) var(--sp-5) }
.challenge-posts summary::-webkit-details-marker { display: none }
.challenge-posts summary::after { content: "+"; font: 700 var(--fs-6)/1 var(--f-body) }
.challenge-posts[open] summary::after { content: "−" }
.challenge-icon { display: grid; place-items: center; flex: none; width: var(--sp-6); height: calc(var(--sp-6) + var(--edge)); background: var(--c-watch); color: var(--c-on-tint); border: var(--edge) solid var(--c-edge); border-top-width: calc(var(--sp-2) - var(--edge)); border-radius: var(--round-ctl); box-shadow: var(--lift-sm); font: 800 var(--fs-3)/1 var(--f-body) }
.challenge-panel h2 { font-size: var(--fs-6); flex: 1 }
.challenge-count { color: var(--c-text-soft); font: 600 var(--fs-2)/1 var(--f-mono); white-space: nowrap }
.challenge-content { display: grid; gap: var(--sp-4); padding: 0 var(--sp-5) var(--sp-5) }
@media (max-width: 800px) {
  .hero-card { padding: var(--sp-4); gap: var(--sp-2) }
  .hero-head { gap: var(--sp-3); margin-bottom: var(--sp-2) }
  .hero-head h1 { font-size: var(--fs-4) }
  .challenge-head { padding: var(--sp-3) var(--sp-4); gap: var(--sp-2) }
  .challenge-icon { width: calc(var(--sp-6) - var(--sp-1)); height: calc(var(--sp-6) - var(--edge)) }
  .challenge-panel h2 { font-size: var(--fs-5); line-height: 1.2 }
  .challenge-content { padding: 0 var(--sp-4) var(--sp-4) }
}

/* Reset statistics and calendar use the same semantic colors. */
.stat-row .stat-tile--reset { background: var(--c-global) }
.stat-row .stat-tile--banked { background: var(--c-banked) }
.stat-row .stat-tile--neutral { background: var(--c-field) }
.stat-row :is(.stat-tile--reset, .stat-tile--banked) :is(dt, dd) { color: var(--c-on-tint) }

.home-summary { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: var(--sp-5); align-items: start }
.home-forecast, .home-reset { min-width: 0; display: grid; justify-items: start; gap: var(--sp-3) }
.home-today { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2) }
.home-summary .hero-verdict { margin: 0; padding: var(--sp-1) var(--sp-3); font: 700 var(--fs-4)/1.2 var(--f-body); box-shadow: var(--lift-sm) }
/* While a promise or a hint is live the odds carry its sticker ("Promised", "Brewing"), which opens the
   forecast: a link, so it hovers and presses as the buttons do, the neutral one to the watch yellow and the
   yellow one to the reset blue. */
a.hero-verdict { text-decoration: none }
a.hero-verdict:hover { background: var(--c-watch); color: var(--c-on-tint) }
a.hero-verdict.promised:hover { background: var(--c-reset) }
.home-reset .latest-reset-age { max-width: 100%; font-size: clamp(1.75rem, 4vw, 3.5rem); line-height: 1.12; padding: var(--sp-2) var(--sp-3) 0 }
.home-reset .latest-reset-age.reset { background: var(--c-reset) }
.home-reset .latest-reset-age.banked { background: var(--c-banked) }
.reset-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) }
.reset-kind { text-transform: capitalize }
/* The last reset's time follows the time toggle, so it wears the toggle's selected color; it may wrap on a narrow phone. */
.reset-when { background: var(--c-watch); color: var(--c-on-tint); font-family: var(--f-mono); white-space: normal }
.hero-reaction { display: flex; justify-content: flex-end }
.hero-reaction .plea-game { width: auto; min-width: 10.875rem }
.challenge-posts summary { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); cursor: pointer; list-style: none; color: var(--c-link); font-weight: 700; border-top: 1px solid var(--c-rule); padding-top: var(--sp-3) }
.challenge-posts .log-list { margin-top: var(--sp-4) }
@media (max-width: 800px) {
  /* the odds column never gets narrower than its figure (320 px: 97 px figure in an 84 px share) */
  .home-summary { grid-template-columns: minmax(max-content, .7fr) minmax(0, 1.3fr); gap: var(--sp-3) }
  .home-forecast .hero-figure { font-size: clamp(2.625rem, 12vw, 4rem); padding-inline: var(--sp-2) }
  /* the promise sticker takes the figure's side padding, so it is never the wider of the two (320 px: 97 px figure) */
  .home-forecast .hero-verdict { padding-inline: var(--sp-2) }
  .home-reset .latest-reset-age { padding-inline: var(--sp-2) }
  .home-reset .hero-sub { font-size: var(--fs-1) }
  /* the time toggle sits on the left under the H1 here, so the reaction button starts at that edge too */
  .hero-reaction { justify-content: flex-start }
  .hero-reaction .plea-game { margin-left: 0 }
}
/* Hero figures on wider screens: one large, one small (home 1/3 + 2/3, forecast and tracker 2/3 + 1/3).
   Each data column is a size container, so a figure grows with its column and its longest text
   ("59 minutes ago", "100%") still fits; without container units the sizes above stay. */
@media (min-width: 801px) {
  .home-summary, .hero-odds, .hero-cols { flex: 1 1 100%; display: grid; gap: var(--sp-5); align-items: start }
  .home-summary { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) }
  .hero-odds, .hero-cols { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) }
  .home-forecast, .home-reset, .hero-odds .hero-figure-wrap, .hero-cols .meter { container-type: inline-size }
  .home-forecast .hero-figure, .hero-odds .hero-figure { padding: .09em .2em 0; font-size: clamp(4rem, 30cqi, 9.25rem) }
  /* tracker's figures take home's tight tracking, so "59 minutes ago" stays on one line in a 1/3 column at 820 px */
  .home-reset .latest-reset-age, .hero-cols .meter-n { padding: .13em .28em 0; font-size: clamp(1.75rem, 13cqi, 6rem); letter-spacing: -.025em }
  /* forecast: two tiles of one height that fill their columns, each number centered */
  .hero-odds { align-items: stretch }
  .hero-odds .hero-figure-wrap { grid-template-rows: auto 1fr }
  .hero-odds .hero-figure { display: grid; place-items: center; justify-self: stretch }
}

/* One-time, non-modal invitation beside the existing alert actions. */
/* busy while push.js checks: the label says so ("Checking alerts…"); no fade, the text keeps AA contrast */
[data-browser]:disabled { cursor: wait }
.push-invite { display: flex; align-items: stretch; gap: var(--sp-2); padding: var(--sp-2); border: var(--edge) solid var(--c-edge); border-radius: var(--round-ctl); background: var(--c-watch); color: var(--c-on-tint); box-shadow: var(--lift-sm); max-width: 100% }
.push-invite button { border: 0; background: transparent; color: inherit; cursor: pointer; font: 700 var(--fs-3)/1.4 var(--f-body); min-height: var(--ctl) }
.push-invite-action { flex: 1; text-align: left; padding: var(--sp-2) var(--sp-3) }
.push-invite-action:hover { text-decoration: underline }
.push-invite-close { flex: none; width: var(--ctl); font-size: var(--fs-6) !important }

.replica-status{max-width:1120px;margin:10px auto -14px;padding:0 24px;font:11px/1.5 system-ui;color:#737580}.replica-toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);background:#202024;color:white;padding:12px 20px;border-radius:6px;z-index:9999}form[data-email] .help{display:block} [data-browser]{opacity:.75}
