/* ════════════════════════════════════════════════════════════════
   DualLife Chess — site styles
   Design system: "Classical" (imported from Claude Design)

   Cormorant Garamond over Lora, gold as a stroke rather than a fill,
   hairlines instead of cards, paper rather than a dark dashboard.

   Two token vocabularies live here on purpose:
     · --color-*, --font-*, --space-*, --radius-*  — the imported system,
       kept under its own names so a retune can be pasted straight in;
     · --bg, --text, --accent, --border, --sq …    — this app's original
       names, now re-pointed at the system above. Seven JS files and a
       dozen views already speak that vocabulary, so keeping it intact is
       what lets the whole visual language change without touching them.
   ════════════════════════════════════════════════════════════════ */

:root {
  /* ── Imported system: Classical ─────────────────────────────── */
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-text: #201f1d;
  --color-accent: #b68235;
  --color-accent-2: #ac803e;
  --color-divider: color-mix(in srgb, #201f1d 16%, transparent);

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f8f4f4;
  --color-neutral-200: #eae7e7;
  --color-neutral-300: #d7d3d3;
  --color-neutral-400: #bab6b6;
  --color-neutral-500: #9b9797;
  --color-neutral-600: #7d7979;
  --color-neutral-700: #605d5d;
  --color-neutral-800: #444141;
  --color-neutral-900: #2d2b2b;

  --color-accent-100: #fff3e4;
  --color-accent-200: #ffe3bf;
  --color-accent-300: #facb8d;
  --color-accent-400: #e1ad66;
  --color-accent-500: #c28d41;
  --color-accent-600: #a06f24;
  --color-accent-700: #7d5411;
  --color-accent-800: #5a3b0a;
  --color-accent-900: #3a270d;

  --font-heading: "Cormorant Garamond", Georgia, serif;
  --font-heading-weight: 600;
  --font-body: "Lora", Georgia, serif;

  /* Figures, and the readouts made of them.
     Neither of the two serifs can set data. Cormorant ships OLD-STYLE figures, where 3, 4,
     7 and 9 drop below the baseline and 0, 1, 2 sit at x-height — beautiful inside a
     sentence and unreadable in a column of node counts, which is what the engine's status
     bar had become. Lora's figures are lining but its proportional widths still wander.
     IBM Plex Mono is a humanist mono drawn to sit beside serif text: lining, tabular, one
     width per glyph, so an eval that ticks from -0.15 to -1.05 does not reflow the row.
     It reads as an instrument rather than as prose, which is what these numbers are. */
  --font-figure: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;

  --space-1: 4.6px;
  --space-2: 9.2px;
  --space-3: 13.8px;
  --space-4: 18.4px;
  --space-6: 27.6px;
  --space-8: 36.8px;

  --radius-sm: 2px;
  --radius-md: 4px;
  --radius-lg: 7px;

  --shadow-sm: 0 1px 2px color-mix(in srgb, #2d2b2b 14%, transparent);
  --shadow-md: 0 3px 10px color-mix(in srgb, #2d2b2b 16%, transparent);
  --shadow-lg: 0 12px 32px color-mix(in srgb, #2d2b2b 22%, transparent);

  /* ── App vocabulary, mapped onto the system ─────────────────── */
  --bg:        var(--color-bg);
  --bg-2:      var(--color-neutral-100);
  --surface:   var(--color-surface);
  --surface-2: var(--color-neutral-200);
  --border:    var(--color-divider);
  --accent:    var(--color-accent);
  --accent-down: var(--color-accent-700);
  --accent-2:  var(--color-accent-400);
  --accent-ink: var(--color-accent-700);   /* gold as TEXT, where #b68235 is too light */
  --green:     #4b7d3f;
  --red:       #a02418;
  --text:      var(--color-text);
  --muted:     var(--color-neutral-700);

  /* Board square size: fills viewport width minus labels/padding, capped.
     The cap is raised on wide screens by the 3-column game layout below. */
  --sq: clamp(32px, calc((100vw - 56px) / 8), 68px);

  /* Boxwood — the default board, shared with the phone app. */
  --light-sq:  #f0d9b5;
  --dark-sq:   #b58863;
  --frame:     #8a6747;

  /* Squares the board wants to point at are washed, never outlined. An inset ring draws a
     box around a square that already has edges, and at board scale it reads as a border on
     the square rather than as a mark on the game. A translucent wash tints the square it
     is on and leaves the grid alone, which is what Lichess does and why its board stays
     quiet with four squares lit at once.

     Two different colours, because they say different things: gold is the move that was
     just played, green is the piece you are holding right now. Both are laid over the
     square's own colour rather than replacing it, so the light/dark chequer still reads
     through the highlight on every palette.

     These three are literal colours rather than tokens from the palette above, which is
     deliberate. A wash has to stay legible against the BOARD, and the board has six
     palettes of its own; the interface gold is the same hue as Boxwood's brown squares, so
     washing a brown square with it moved the colour by almost nothing. Measured over every
     square colour the six palettes can produce, the gold washes bottomed out around 15-26
     units of RGB distance — invisible — where amber reaches 40 and a deep green 59. The
     numbers, not the eye, chose these.

     Amber for the move just played, deep green for the piece being moved: one warm and
     light, one cool and dark, so they are told apart by two channels at once rather than
     by hue alone. */
  --wash-last: rgba(240, 165,  0, .42);
  --wash-sel:  rgba( 31,  92, 46, .45);
  --wash-drop: rgba( 32,  32, 29, .17);

  /* A wounded piece bleeds. The one colour in the system that is not gold. */
  --wound:     200, 40, 30;

  --radius:    var(--radius-md);
  --shadow:    var(--shadow-md);
  --nav-bg:    color-mix(in srgb, var(--color-bg) 88%, transparent);
}

/* ── Night paper ─────────────────────────────────────────────────
   The imported system ships one ground. Night is derived from it rather
   than invented: the same hues carried to a low lightness, so the gold
   still reads as the same gold and the neutrals stay warm rather than
   sliding to the blue-grey every dark theme defaults to. */
[data-theme="dark"] {
  --color-bg: #1a1917;
  --color-surface: #24221f;
  --color-text: #ece9e4;
  --color-accent: #c9964a;
  --color-divider: color-mix(in srgb, #ece9e4 18%, transparent);

  --color-neutral-100: #2d2b28;
  --color-neutral-200: #35322e;
  --color-neutral-300: #46423d;
  --color-neutral-400: #5d5850;
  --color-neutral-500: #7a746b;
  --color-neutral-600: #979086;
  --color-neutral-700: #b3aca1;
  --color-neutral-800: #cec8bf;
  --color-neutral-900: #e6e1d9;

  --color-accent-100: #2e2416;
  --color-accent-200: #3f301b;
  --color-accent-300: #5a4423;
  --color-accent-400: #7d5f2e;
  --color-accent-500: #a37c3c;
  --color-accent-600: #c2954c;
  --color-accent-700: #dcb268;
  --color-accent-800: #ecc98f;
  --color-accent-900: #f7e0b8;

  --accent-ink: var(--color-accent-700);
  --green: #7fae6b;
  --red:   #d8695a;

  --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --shadow-md: 0 3px 10px rgba(0,0,0,.45);
  --shadow-lg: 0 12px 32px rgba(0,0,0,.55);
}

/* Explicit "Paper" keeps working if it is stored from an earlier build. */
[data-theme="light"] { color-scheme: light; }
[data-theme="dark"]  { color-scheme: dark; }

/* ── Board palettes — applied via <html data-board="…"> ────────── */
[data-board="boxwood"]  { --light-sq: #f0d9b5; --dark-sq: #b58863; --frame: #8a6747; }
[data-board="buff"]     { --light-sq: #f8f4f4; --dark-sq: #dbaf70; --frame: #7d5411; }
[data-board="ivory"]    { --light-sq: #f8f4f4; --dark-sq: #d7d3d3; --frame: #605d5d; }
[data-board="baize"]    { --light-sq: #eaf1ed; --dark-sq: #64b988; --frame: #40825b; }
[data-board="legacy"]   { --light-sq: #e8edf4; --dark-sq: #7692bd; --frame: #4c618a; }
[data-board="slate"]    { --light-sq: #e7e8ec; --dark-sq: #8a8f9c; --frame: #5f636f; }
/* Palettes no longer offered in the picker, kept so a saved choice still resolves
   rather than silently reverting to the default. */
[data-board="colophon"] { --light-sq: #4a4643; --dark-sq: #26241f; --frame: #e1ad66; }
[data-board="classic"]  { --light-sq: #f0d9b5; --dark-sq: #b58863; --frame: #8a6747; }
[data-board="blue"]     { --light-sq: #e8edf4; --dark-sq: #7692bd; --frame: #4c618a; }
[data-board="forest"]   { --light-sq: #ebecd0; --dark-sq: #6f9b55; --frame: #4f7340; }
[data-board="ocean"]    { --light-sq: #d6e0ea; --dark-sq: #5b7fa6; --frame: #3f5d7d; }
[data-board="coral"]    { --light-sq: #f6dcdc; --dark-sq: #c87f7f; --frame: #9c5d5d; }
[data-board="midnight"] { --light-sq: #6b7392; --dark-sq: #353a4d; --frame: #11141d; }

/* ════════════════════════════════════════════════════════════════
   Base
   ════════════════════════════════════════════════════════════════ */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.55;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

/* Components cross-fade when the paper changes.
   body is deliberately NOT in this list: transitioning its background-color
   when the value comes from a var() chain (--bg → --color-bg) leaves the old
   colour latched, so switching Paper↔Night only took effect after a reload.
   The ground repaints instantly instead, which is what a paper change should
   look like anyway. */
.navbar, .toolbar, .status-bar, .history-card, .create-panel,
.players-bar, .auth-card, .feature-card, .offer-item, .modal-card,
.board-wrap, .field input, .tog, .theme-toggle {
  transition: background-color .25s ease, border-color .25s ease, color .15s ease;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  line-height: 1.12;
  letter-spacing: -.015em;
}

a { color: var(--accent-ink); text-decoration: none; text-underline-offset: 3px; }
a:hover { text-decoration: underline; }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* Every figure in the app is tabular: clocks, ratings, records, evaluations. */
.clock, .stat-val, .h-row, .pc-stats, .profile-rating, .m-delta, .m-meta,
.offer-color, .slider-scale, .live-meta, .conn-pill, .badge {
  font-variant-numeric: tabular-nums;
}

/* The readouts that are mostly figures are SET in the figure face, not merely given tabular
   numerals. The rest of the list above — the connection pill, the mode badge, the slider's
   "Easier"/"Stronger" — are words that happen to sit near numbers, and they stay in Lora. */
.pc-stats, .profile-rating, .m-delta, .m-meta, .live-meta {
  font-family: var(--font-figure);
}

/* An uppercase, letterspaced Lora micro-label. The system's one recurring tic. */
.kicker,
.hist-title, .ctrl-label, .setup-label, .setting-kicker, .stat-lbl {
  font-family: var(--font-body);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--accent-ink);
}

.hr, .rule { height: 1px; border: 0; background: var(--color-divider); }

/* ════════════════════════════════════════════════════════════════
   Navbar
   ════════════════════════════════════════════════════════════════ */
.navbar {
  position: sticky;
  top: 0;
  z-index: 30;
  background: var(--nav-bg);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--color-divider);
}
.nav-inner {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 44px;
  height: 66px;
  display: flex;
  align-items: center;
  gap: 34px;
}
.brand {
  display: flex; align-items: baseline; gap: 9px;
  font-family: var(--font-heading);
  font-size: 21px; font-weight: 600; letter-spacing: .01em;
  color: var(--text);
}
.brand:hover { text-decoration: none; }
.brand-logo { width: 22px; height: 22px; object-fit: contain; align-self: center; }
.brand-accent { color: inherit; }   /* the wordmark is one colour; gold is spent elsewhere */

/* Uppercase Lora, gold rule under the current page. */
.nav-links { display: flex; gap: 26px; margin-inline-start: 14px; }
.nav-links a {
  font-family: var(--font-body);
  font-size: 11px; font-weight: 400;
  letter-spacing: .13em; text-transform: uppercase;
  color: var(--muted);
  padding-bottom: 3px;
  border-bottom: 1px solid transparent;
}
.nav-links a:hover { color: var(--text); text-decoration: none; }
.nav-links a.active, .nav-links a[aria-current="page"] {
  color: var(--text); border-bottom-color: var(--color-accent);
}

.nav-auth { margin-inline-start: auto; display: flex; align-items: center; gap: 14px; }
.nav-user {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--font-body); font-size: 12px; color: var(--muted);
}
.nav-user:hover { text-decoration: none; color: var(--text); }
.nav-avatar {
  width: 32px; height: 32px; border-radius: 50%;
  display: inline-grid; place-items: center;
  font-family: var(--font-heading); font-size: 13px; font-weight: 600;
  color: var(--accent-ink);
  background: transparent;
  border: 1px solid var(--color-accent);
}
.inline-form { display: inline; }

.nav-collapse { display: flex; align-items: center; gap: 26px; flex: 1; min-width: 0; }

.nav-toggle {
  display: none;
  flex-direction: column; justify-content: center; gap: 4px;
  width: 38px; height: 34px; margin-inline-start: auto; padding: 0 9px;
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  cursor: pointer;
}
.nav-toggle:hover { border-color: var(--color-accent); }
.nav-toggle-bar {
  display: block; width: 100%; height: 1px;
  background: var(--text); transition: transform .2s ease, opacity .2s ease;
}
.nav-inner.open .nav-toggle-bar:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav-inner.open .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-inner.open .nav-toggle-bar:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

/* ── Layout shell ───────────────────────────────────────────── */
.site-main {
  flex: 1;
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: 34px 44px 56px;
}
/* The home page is an editorial spread: it manages its own gutters. */
.site-main:has(> .home-page) { padding: 0; max-width: 1400px; }

.site-footer {
  display: flex; align-items: baseline; gap: 24px;
  max-width: 1400px; margin: 0 auto; width: 100%;
  border-top: 1px solid var(--color-divider);
  color: var(--muted);
  font-size: 11px;
  padding: 26px 44px 40px;
}
.site-footer .foot-links { margin-inline-start: auto; display: flex; gap: 24px; }

/* ════════════════════════════════════════════════════════════════
   Buttons — gold is a stroke, never a fill
   ════════════════════════════════════════════════════════════════ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: var(--font-heading);
  font-size: 14px; font-weight: var(--font-heading-weight); line-height: 1.2;
  color: var(--text);
  background: transparent;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color .14s ease, border-color .14s ease, color .14s ease;
}
.btn:hover { text-decoration: none; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn svg { display: block; }
.btn-lg { padding: 14px 28px; font-size: 15px; }
.btn-sm { padding: 7px 14px; font-size: 12px; }
.btn-block { width: 100%; }

.btn-primary { color: var(--accent-ink); border-color: var(--color-accent); }
.btn-primary:hover  { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.btn-primary:active { background: color-mix(in srgb, var(--color-accent) 22%, transparent); }

.btn-ghost { border-color: var(--color-divider); }
.btn-ghost:hover  { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }

/* Game actions: the same two weights, named for their jobs. */
.btn-new { color: var(--accent-ink); border-color: var(--color-accent); }
.btn-new:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.btn-step, .btn-auto, .btn-run { border-color: var(--color-divider); }
.btn-step:hover:not(:disabled),
.btn-auto:hover:not(:disabled),
.btn-run:hover:not(:disabled) { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-auto.on { color: var(--accent-ink); border-color: var(--color-accent); }

/* The language control shows the language you would switch TO, set in that
   language's own script — the one label a visitor who cannot read the current
   one will still recognise. */
.lang-switch {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--muted);
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
}
.lang-switch:hover { color: var(--accent-ink); border-bottom-color: var(--color-accent); text-decoration: none; }

.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: var(--radius-md);
  background: transparent; border: 1px solid var(--color-divider);
  color: var(--muted); cursor: pointer; line-height: 1;
}
.theme-toggle:hover { border-color: var(--color-accent); color: var(--accent-ink); }
.ti-light { display: none; }
[data-theme="dark"] .ti-dark  { display: none; }
[data-theme="dark"] .ti-light { display: inline; }

/* ── Icons (inline SVG sprite) ──────────────────────────────── */
.icon {
  width: 1.05em; height: 1.05em;
  flex: 0 0 auto;
  vertical-align: -0.16em;
  fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.icon.fill { fill: currentColor; stroke: none; }

/* ════════════════════════════════════════════════════════════════
   Home — an editorial opening, not a stack of tiles
   ════════════════════════════════════════════════════════════════ */
.home-page { display: block; }

.home-open {
  display: grid; grid-template-columns: 1fr 560px;
  gap: 56px; padding: 64px 44px 0; align-items: start;
}
.home-eyebrow {
  font-family: var(--font-body);
  font-size: 10.5px; font-weight: 600;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--accent-ink);
}
.home-rule { height: 1px; background: var(--color-divider); margin: 16px 0 26px; }
.home-title {
  font-family: var(--font-heading); font-weight: 400;
  font-size: clamp(40px, 5.3vw, 76px); line-height: .98;
  letter-spacing: -.025em;
  margin: 0 0 26px;
}
.home-cols {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 30px; column-gap: 34px;
}
.home-cols p {
  font-size: 14px; line-height: 1.75;
  text-align: justify; hyphens: auto;
  margin: 0;
  color: color-mix(in srgb, var(--color-text) 82%, transparent);
}
.home-cta { display: flex; gap: 12px; margin-top: 34px; flex-wrap: wrap; }

/* The board tipped in as a plate. */
.home-plate { margin: 0; }
.home-plate .plate-frame {
  border: 8px solid var(--color-surface);
  outline: 1px solid var(--color-divider);
  width: fit-content;
}
.home-board {
  display: grid;
  grid-template-columns: repeat(8, var(--home-sq, 68px));
  grid-template-rows: repeat(8, var(--home-sq, 68px));
}
.home-plate figcaption {
  font-size: 11px; line-height: 1.6; color: var(--muted); margin-top: 9px;
}

/* Three propositions, parted by vertical hairlines rather than boxed. */
.features {
  display: grid; grid-template-columns: repeat(3, 1fr);
  margin: 64px 44px 0;
  border-top: 1px solid var(--color-divider);
  border-bottom: 1px solid var(--color-divider);
  gap: 0;
}
.feature-card {
  padding: 30px 34px 30px 34px;
  border-inline-start: 1px solid var(--color-divider);
  background: transparent; border-radius: 0;
}
.feature-card:first-child { padding-inline-start: 0; border-inline-start: 0; }
.feature-card:last-child  { padding-inline-end: 0; }
.feature-icon {
  color: var(--accent-ink); margin-bottom: 14px;
  width: auto; height: auto; background: none; border: 0; display: block;
}
.feature-icon .icon { width: 22px; height: 22px; }
.feature-card h3 { font-size: 22px; line-height: 1.15; margin: 0 0 8px; }
.feature-card p {
  font-size: 13px; line-height: 1.7; margin: 0;
  text-align: justify; hyphens: auto;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}

/* Legacy hero classes — kept so any cached markup still lands somewhere sane. */
.hero { padding: 56px 0 40px; }
.hero-glow { display: none; }
.hero-content { max-width: 760px; }
.hero-eyebrow {
  display: inline-block; font-family: var(--font-body);
  font-size: 10.5px; font-weight: 600; letter-spacing: .22em; text-transform: uppercase;
  color: var(--accent-ink); margin-bottom: 18px;
}
.hero-title { font-family: var(--font-heading); font-weight: 400; font-size: clamp(38px, 6vw, 72px); line-height: 1; letter-spacing: -.025em; margin-bottom: 18px; }
.grad { color: inherit; font-style: italic; }
.hero-sub { color: var(--muted); font-size: 14px; line-height: 1.75; max-width: 620px; margin: 0 0 28px; }
.hero-cta { display: flex; gap: 12px; flex-wrap: wrap; }

/* ════════════════════════════════════════════════════════════════
   Auth
   ════════════════════════════════════════════════════════════════ */
.auth-wrap { display: flex; justify-content: center; padding: 40px 8px 56px; }
.auth-card {
  width: 100%; max-width: 420px;
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  padding: 34px 32px;
}
.auth-title { font-family: var(--font-heading); font-weight: 400; font-size: 34px; letter-spacing: -.02em; }
.auth-sub { color: var(--muted); font-size: 12.5px; line-height: 1.7; margin: 6px 0 24px; }
.auth-form { display: flex; flex-direction: column; gap: 14px; }

.field { display: flex; flex-direction: column; gap: 5px; }
.field > span { font-size: 12px; color: color-mix(in srgb, var(--color-text) 70%, transparent); }
.field > span small { color: var(--muted); }
.field input {
  width: 100%; min-height: 38px; padding: 8px 11px;
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  color: var(--text);
  caret-color: var(--color-accent);
  font-family: var(--font-body); font-size: 14px;
}
.field input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.field input:focus { outline: none; border-color: var(--color-accent); }
.field input::placeholder { color: var(--color-neutral-500); }
.field-error { color: var(--red); font-size: 11.5px; }

.val-summary { color: var(--red); font-size: 12.5px; }
.val-summary ul { list-style: none; }
.val-summary:empty { display: none; }

.divider-or {
  display: flex; align-items: center; gap: 12px;
  color: var(--muted); font-size: 10.5px;
  letter-spacing: .14em; text-transform: uppercase;
  margin: 22px 0 16px;
}
.divider-or::before, .divider-or::after { content: ''; flex: 1; height: 1px; background: var(--color-divider); }

.g-btn-center { display: flex; justify-content: center; }
.muted-note { color: var(--muted); font-size: 11.5px; line-height: 1.6; text-align: center; }
.muted-note code {
  background: color-mix(in srgb, var(--color-text) 7%, transparent);
  padding: 1px 5px; border-radius: var(--radius-sm); font-size: .92em;
}
.auth-switch { text-align: center; color: var(--muted); font-size: 12.5px; margin-top: 22px; }

/* ════════════════════════════════════════════════════════════════
   Game page — board, controls, status, ledger
   ════════════════════════════════════════════════════════════════ */
.game-page {
  max-width: 700px;
  margin: 0 auto;
  display: flex; flex-direction: column; gap: 16px;
}
.game-layout { display: flex; flex-direction: column; gap: 16px; }
.game-col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.game-col-center { align-items: center; }

/* Where the desktop earns its width: roster left, board centre, ledger right —
   all three readable without scrolling, parted by hairlines rather than gaps. */
@media (min-width: 1100px) {
  .game-page { max-width: 1400px; --sq: 64px; }
  .game-layout {
    display: grid;
    grid-template-columns: 296px minmax(0, 1fr) 336px;
    align-items: start;
    justify-content: center;
    gap: 0;
  }
  .game-col-left  { border-inline-end: 1px solid var(--color-divider); padding: 4px 24px 26px 0; }
  .game-col-right { border-inline-start:  1px solid var(--color-divider); padding: 4px 0 26px 24px; }
  .game-col-center { padding: 0 26px; }
  .game-col-left .players-bar,
  .game-col-left .legend,
  .game-col-right .status-bar { align-self: stretch; }
  .game-col-right .hist-scroll { max-height: clamp(260px, 52vh, 560px); }
}

.game-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px 14px; }

/* Title and its badges on the left, the action on the right.
   Scoped to a head that actually has a title, so the profile's back-nav pair — two
   buttons and no heading — stays packed left where it belongs. The reset keeps a second
   button beside the first rather than flung to the opposite edge. */
.game-head .page-title ~ .btn { margin-inline-start: auto; }
.game-head .page-title ~ .btn ~ .btn { margin-inline-start: 0; }

/* The heading tracks whatever is actually on screen.
   .game-page is sized for the in-game grid — 700px, and 1400px once there is room for
   roster | board | ledger. Before a game starts the only thing in it is the 460px setup
   card, so a heading spanning the container floats off to the left of the one element it
   is meant to label, by 120px at 700 and by nearly 500 at 1400. Matching the card's own
   width and centring keeps the two in one column at every width.

   Opt IN, deliberately. Keying this on :not(.in-game) instead caught every page built on
   .game-page — the replay page has no setup step, never sets that class, and had its
   heading narrowed for a card it does not have. */
.game-page.setup .game-head {
  width: 100%; max-width: 460px; align-self: center;
}
.page-title {
  font-family: var(--font-heading); font-weight: 400;
  font-size: 42px; letter-spacing: -.02em; line-height: 1;
}
.badge {
  font-family: var(--font-body);
  font-size: 9.5px; font-weight: 600; letter-spacing: .2em; text-transform: uppercase;
  padding: 0; color: var(--accent-ink); background: transparent; border-radius: 0;
}

.toolbar {
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 10px;
}
.ctrl-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.ctrl-label { white-space: nowrap; }
.divider { width: 1px; height: 18px; background: var(--color-divider); margin: 0 4px; }

.tog {
  padding: 7px 12px;
  border: 1px solid var(--color-divider);
  background: transparent;
  color: var(--muted);
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: var(--font-body); font-size: 12px;
}
/* Selected is a filled state, not an outlined one.
   A border colour and a slightly darker label were the only difference between chosen and
   unchosen, and on the Night ground the gold border sits close in value to the plain
   divider — the point where it stops being readable at a glance.

   These are the same three declarations .seg.on already uses for Mode and Bot speed on the
   engine page. The site had two answers to "this option is selected"; now it has one. */
.tog.on {
  background: color-mix(in srgb, var(--color-accent) 13%, var(--color-bg));
  border-color: var(--color-accent);
  color: var(--accent-ink);
}
.tog:hover:not(.on) { color: var(--text); }
.toolbar .btn { padding: 7px 12px; font-size: 13px; }

/* ── Setup card ─────────────────────────────────────────────── */
.setup-card {
  width: 100%; max-width: 460px; align-self: center;
  background: transparent;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  padding: 24px 22px;
  display: flex; flex-direction: column; gap: 22px;
}
.setup-title { font-family: var(--font-heading); font-weight: 400; font-size: 26px; line-height: 1.1; }
.setup-row { display: flex; flex-direction: column; gap: 10px; }
.setup-val { color: var(--accent-ink); font-family: var(--font-figure); font-weight: 500; font-size: 16px; }

/* Segmented control — hairline-divided cells, no pill, no fill. */
.segmented {
  display: flex; gap: 1px; padding: 0;
  background: var(--color-divider);
  border: 1px solid var(--color-divider);
  border-radius: 0;
}
.seg {
  flex: 1; padding: 11px 10px; border: none;
  background: var(--color-bg);
  color: var(--muted);
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 13.5px;
  cursor: pointer; white-space: nowrap;
  transition: background-color .14s, color .14s;
}
.seg:hover:not(.on) { color: var(--text); }
.seg.on {
  background: color-mix(in srgb, var(--color-accent) 13%, var(--color-bg));
  color: var(--accent-ink);
}

/* Difficulty slider */
.slider {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 3px; border-radius: 0;
  background: var(--color-neutral-300); outline: none; cursor: pointer;
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--color-bg); border: 1px solid var(--color-accent);
  cursor: pointer;
}
.slider::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--color-bg); border: 1px solid var(--color-accent);
  cursor: pointer;
}
.slider-scale { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--muted); }

.live-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  padding: 10px 14px;
}
.live-meta { font-size: 12px; color: var(--muted); }

/* ── Board ──────────────────────────────────────────────────── */
/* The plate: a mount, not a card. No radius, no shadow — the frame is the
   surface tone and a single hairline, exactly as in the design. */
.board-wrap {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  width: calc(24px + 8 * var(--sq));
  align-self: center;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.coord-row-h { display: grid; grid-template-columns: 24px repeat(8, var(--sq)); width: 100%; }
.coord-row-h span {
  height: 16px; display: flex; align-items: center; justify-content: center;
  font-family: var(--font-body); font-size: 10.5px; color: var(--muted);
}
.board-inner { display: flex; gap: 6px; width: 100%; }
.rank-labels { display: flex; flex-direction: column; width: 18px; }
.rank-labels span {
  height: var(--sq); display: flex; align-items: center; justify-content: center;
  font-family: var(--font-body); font-size: 10.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
#board {
  display: grid;
  grid-template-columns: repeat(8, var(--sq));
  grid-template-rows:    repeat(8, var(--sq));
  border: 8px solid var(--color-surface);
  outline: 1px solid var(--color-divider);
  border-radius: 0;
  flex-shrink: 0;
}
.sq { position: relative; display: flex; align-items: center; justify-content: center; }
.sq.light { background: var(--light-sq); }
.sq.dark  { background: var(--dark-sq); }
/* linear-gradient rather than background-color: the square's own colour is already in
   background-color from .sq.light/.dark, and a gradient layer composites over it. Setting
   background-color here would replace the chequer instead of tinting it. */
.sq.hi-from,
.sq.hi-to { background-image: linear-gradient(var(--wash-last), var(--wash-last)); }

/* Only a piece you can actually move offers to be picked up. Putting the pointer cursor
   on every square claimed the whole board was interactive, including the empty half. */
#board .sq.movable { cursor: grab; }
/* After the last-move rule, so holding a piece on a square that was just played shows the
   selection — the thing you are doing now outranks the thing that already happened. */
.sq.sel { background-image: linear-gradient(var(--wash-sel), var(--wash-sel)); }

/* ── Dragging ────────────────────────────────────────────────────
   touch-action has to sit on the element the gesture starts in, and it is deliberately
   only on squares you can pick a piece up from. On the whole board it would also cover
   the replay board, which shares this id and cannot be dragged at all — a finger there
   would stop scrolling the page for no reason. This way a touch on your own piece drags
   it, and a touch anywhere else still scrolls. */
.sq.movable { touch-action: none; }

/* The piece is still on its square while it is in the air, so it is faded rather than
   hidden — the square keeps its occupant and the board does not appear to lose a piece. */
.sq.dragging .pc { opacity: .26; }

/* Where the piece would land. Reads the same as the last-move ring, because it is the
   same statement about the same square. */
/* Where the piece would land. Neutral on purpose: it appears on top of squares that may
   already be washed gold or green, and a fourth colour competing with those two would make
   a board mid-drag harder to read rather than easier. */
.sq.drag-over { background-image: linear-gradient(var(--wash-drop), var(--wash-drop)); }

.pc-drag {
  position: fixed; top: 0; left: 0;
  z-index: 60; pointer-events: none;
  will-change: transform;
  filter: drop-shadow(0 4px 7px rgba(0,0,0,.34));
}
/* The cursor has to be forced across every element the pointer crosses mid-drag,
   including the ghost's own neighbours, or it flickers back on each square boundary. */
body.dragging-piece, body.dragging-piece * { cursor: grabbing !important; }

.move-target {
  position: absolute; width: 23%; height: 23%; border-radius: 50%;
  background: color-mix(in srgb, var(--color-accent) 70%, transparent);
  z-index: 2; pointer-events: none;
}
.move-target.cap {
  width: 88%; height: 88%; background: transparent;
  border: clamp(3px, calc(var(--sq) * .06), 4px) solid color-mix(in srgb, var(--color-accent) 80%, transparent);
}

.pc { position: relative; font-size: calc(var(--sq) * 0.72); line-height: 1; user-select: none; z-index: 1; }

.pc-img {
  width: 84%; height: 84%;
  object-fit: contain;
  -webkit-user-drag: none;
  pointer-events: none;
}
.pc-img.w { filter: drop-shadow(0 1px 1.5px rgba(0,0,0,.30)); }
.pc-img.b { filter: drop-shadow(0 0 1px rgba(255,255,255,.45)) drop-shadow(0 1px 1.5px rgba(0,0,0,.3)); }


/* A wounded piece: the halo. The default wounded state in the design. */
.dmg-glow {
  position: absolute; inset: 0;
  /* No border-radius, and closest-side rather than the default farthest-corner.
     Together those were cutting the halo off mid-fade: the gradient's 100% reached the
     CORNER of the box (0.707w from centre) while border-radius:50% clipped everything past
     the inscribed circle (0.5w) — 70.7% of the way along the gradient, where the alpha was
     still 0.163. The glow ended on a hard circular edge, and the two stops meant to fade it
     out never rendered at all. closest-side puts 100% exactly on the square's edge, so the
     curve below is drawn in full.

     The falloff is a(r) = 0.934 * (1 - r^3.68)^2, which reaches zero AT the square's edge
     and reaches it with zero slope — the halo stops mattering before it stops existing, so
     there is no boundary to see. Both constants are fitted rather than chosen: measured
     against every square colour the six palettes produce, this curve moves the worst-case
     square by 95 units of RGB distance at half radius and 60 at seven-tenths. Raising the
     exponent alongside the peak is what keeps the tail soft while the body gets stronger —
     a plain multiplier would have brightened the edge too and put the hard rim back. */
  background: radial-gradient(circle closest-side at center,
              rgba(var(--wound), .934) 0%,
              rgba(var(--wound), .933) 12%,
              rgba(var(--wound), .924) 24%,
              rgba(var(--wound), .899) 34%,
              rgba(var(--wound), .845) 44%,
              rgba(var(--wound), .773) 52%,
              rgba(var(--wound), .671) 60%,
              rgba(var(--wound), .555) 67%,
              rgba(var(--wound), .439) 73%,
              rgba(var(--wound), .314) 79%,
              rgba(var(--wound), .209) 84%,
              rgba(var(--wound), .114) 89%,
              rgba(var(--wound), .051) 93%,
              rgba(var(--wound), .018) 96%,
              rgba(var(--wound), .005) 98%,
              rgba(var(--wound), 0)    100%);
  z-index: 0; pointer-events: none;
  /* Static. A pulsing halo on every wounded piece meant several things breathing at once
     on a board that is meant to be read, and motion attracts the eye continuously rather
     than once. The keyframes stay for the engine's thinking dot, which is a single mark
     that genuinely is in progress. */
}
@keyframes dmgpulse {
  0%,100% { opacity: .72; transform: scale(1); }
  50%     { opacity: 1;   transform: scale(1.1); }
}
@media (prefers-reduced-motion: reduce) {
  .dmg-glow { animation: none; opacity: .9; }
}

/* ── Legend ─────────────────────────────────────────────────── */
.legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 11px; color: var(--muted); align-self: center; }
.leg { display: flex; align-items: center; gap: 6px; }
.leg-glow {
  width: 14px; height: 14px;
  /* Same curve as the board, same reason it is not clipped to a circle. */
  background: radial-gradient(circle closest-side at center,
              rgba(var(--wound), .934) 0%,  rgba(var(--wound), .899) 34%,
              rgba(var(--wound), .773) 52%, rgba(var(--wound), .555) 67%,
              rgba(var(--wound), .314) 79%, rgba(var(--wound), .114) 89%,
              rgba(var(--wound), 0) 100%);
}
/* The legend shows the real thing: a board square carrying the real last-move wash, so
   the key and the board cannot drift apart. */
.leg-sq {
  width: 14px; height: 14px;
  background-color: var(--light-sq);
  background-image: linear-gradient(var(--wash-last), var(--wash-last));
}

/* ── Turn hint ──────────────────────────────────────────────── */
.hint { font-size: 13px; color: var(--muted); }
.hint b { color: var(--accent-ink); font-weight: 400; font-family: var(--font-heading); font-size: 16px; }
.hint .thinking { color: var(--muted); }
.hint .thinking::after {
  content: ''; display: inline-block; width: 6px; height: 6px; margin-inline-start: 7px;
  border-radius: 50%; background: var(--color-accent); animation: dmgpulse 1s ease-in-out infinite;
}

/* ── Promotion modal ────────────────────────────────────────── */
.modal {
  display: none; position: fixed; inset: 0;
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
  z-index: 50; align-items: center; justify-content: center; padding: var(--space-4);
}
.modal.show { display: flex; }
.modal-card {
  background: var(--color-surface);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 20px 22px; text-align: center;
}
.modal-card h3 { font-family: var(--font-heading); font-weight: 400; font-size: 20px; margin-bottom: 14px; }
.promo-row { display: flex; gap: 10px; }
.promo-pc {
  width: 56px; height: 56px;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
  background: transparent; font-size: 2rem; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .12s;
}
.promo-pc:hover { border-color: var(--color-accent); }
.promo-pc.w { color: #f6f2ea; text-shadow: 0 0 2px #26241f, 1px 1px 0 #3a362f, -1px -1px 0 #3a362f; }
.promo-pc.b { color: #26241f; text-shadow: 0 0 3px rgba(255,255,255,.5); }
.modal-cancel { margin-top: 14px; background: none; border: none; color: var(--muted); font-family: var(--font-body); font-size: 11.5px; cursor: pointer; }
.modal-cancel:hover { color: var(--text); }

/* ── Status bar ─────────────────────────────────────────────── */
.status-bar {
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center; font-size: 12.5px;
}
.stat-item { display: flex; align-items: center; gap: 6px; }
.stat-key { color: var(--muted); font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; }
.stat-val { font-family: var(--font-figure); font-weight: 500; }
.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; }
.dot.w { background: #f6f2ea; border: 1px solid var(--color-divider); }
.dot.b { background: #26241f; border: 1px solid var(--color-divider); }

.result-pill {
  display: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 13px;
  padding: 4px 11px; border-radius: var(--radius-md); border: 1px solid var(--color-divider);
}
.result-pill.show  { display: inline-block; }
.result-pill.white { color: var(--text); }
.result-pill.black { color: var(--text); }
.result-pill.draw  { color: var(--muted); }

/* ── The ledger (move history) ──────────────────────────────── */
.history-card {
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  padding: 14px 16px;
}
.hist-title { margin-bottom: 10px; }
.hist-scroll { max-height: 180px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--color-divider) transparent; }
.h-row {
  display: grid; grid-template-columns: 30px 1fr 1fr; gap: 2px;
  padding: 6px 6px; margin: 0 -6px;
  border-top: 1px solid var(--color-divider);
  font-family: var(--font-figure); font-size: 12.5px; line-height: 1.45;
}
.h-row:first-child { border-top: 0; }
.h-row:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
.h-num { color: var(--color-neutral-800); }
.h-w   { color: var(--text); }
.h-b   { color: var(--color-neutral-800); }
.h-row.cur { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.h-row.cur .h-w, .h-row.cur .h-b { color: var(--color-accent-900); }

/* Replay: each half-move is a scrubber handle, so the ledger doubles as navigation. */
/* Fills its grid cell so the target is the whole half of the row. As an inline span it
   was only as wide as "e2e4", leaving most of the visible cell dead — a click that looked
   like it landed on the move did nothing, which reads as the list simply not working. */
.h-move { cursor: pointer; padding: 0 3px; display: block; border-radius: var(--radius-sm); }
.h-move:hover { color: var(--accent-ink); }
.h-move.cur-ply {
  background: color-mix(in srgb, var(--color-accent) 22%, transparent);
  color: var(--color-accent-900);
}

/* A whole history row is a link on the games page; it must not look like body copy. */
a.match-row { text-decoration: none; color: inherit; }
a.match-row:hover { text-decoration: none; }

/* ════════════════════════════════════════════════════════════════
   Lobby + live human-vs-human game
   ════════════════════════════════════════════════════════════════ */
.lobby-page { max-width: 1000px; margin: 0 auto; display: flex; flex-direction: column; gap: 18px; }

.conn-pill {
  font-family: var(--font-body);
  font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
  padding: 5px 11px; border-radius: 999px;
  background: transparent; color: var(--muted);
  border: 1px solid var(--color-divider);
}
.conn-pill.on { color: var(--accent-ink); border-color: var(--color-accent-300); }

.create-panel {
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  padding: 18px;
  display: flex; flex-direction: column; gap: 10px;
}

.quick-panel {
  background: transparent;
  border: 1px solid var(--color-accent);
  border-radius: var(--radius-md);
  padding: 20px;
}
.quick-idle { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.quick-text { min-width: 0; }
.quick-title { font-family: var(--font-heading); font-weight: 400; font-size: 26px; line-height: 1.1; }
.quick-title .icon { color: var(--accent-ink); }
.quick-searching { display: flex; align-items: center; gap: 12px; }
.quick-searching .btn { margin-inline-start: auto; }
.search-spinner {
  flex: 0 0 auto; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--color-divider); border-top-color: var(--color-accent);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.lobby-or {
  display: flex; align-items: center; gap: 12px; color: var(--muted);
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
}
.lobby-or::before, .lobby-or::after { content: ''; flex: 1; height: 1px; background: var(--color-divider); }

/* Open games read as a table: hairline rows, no boxes. */
.offer-list { display: flex; flex-direction: column; gap: 0; }
.offer-empty { color: var(--muted); font-size: 13px; padding: 18px 4px; text-align: center; }
.offer-item {
  display: flex; align-items: center; gap: 14px;
  background: transparent;
  border: 0; border-bottom: 1px solid var(--color-divider);
  border-radius: 0; padding: 14px 6px; margin: 0 -6px;
}
.offer-item:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
.offer-item.mine { background: color-mix(in srgb, var(--color-accent) 6%, transparent); }
.offer-info { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.offer-name { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 17px; line-height: 1.2; }
.offer-color { color: var(--muted); font-size: 12.5px; }
.offer-item .btn { padding: 7px 14px; font-size: 12px; }

/* Live game roster — one row per player, name left, clock right. */
.players-bar {
  display: flex; flex-direction: column; gap: 0;
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  padding: 4px;
  align-self: center; min-width: 250px;
}
.players-bar .player {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 17px;
  padding: 11px 10px;
}
.players-bar .player > span:not(.dot):not(.clock):not(.rating) {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.players-bar .player .clock { margin-inline-start: auto; }

/* A finished game's rating — NOT a clock.
   The replay page put "1200 → 1216" in .clock, which is 22px inside a bordered box
   because during a live game it renders "3:02". Two four-digit numbers and an arrow at
   that size wrapped to two lines and took so much of the row that the player's name was
   cut to an ellipsis on a narrow screen. This is the figure the games list and the
   profile already use for the same fact, at the size they use. */
.players-bar .player .rating {
  margin-inline-start: auto;
  display: flex; align-items: baseline; gap: 6px;
  font-family: var(--font-figure); font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.players-bar .player .rating-val { font-size: 14px; color: var(--muted); }
/* tabular-nums equalises the digits but not the sign, so "+16" and "-16" come out a
   couple of pixels apart and the two ratings above them stop lining up. A fixed column
   for the delta puts both rows' figures on the same edge. */
.players-bar .player .rating .m-delta { min-width: 3ch; text-align: end; }
/* Whose move it is: a wash the weight of a highlight, not a filled panel. */
.players-bar .player.active { background: color-mix(in srgb, var(--color-accent) 8%, transparent); }
.players-bar .vs {
  color: var(--muted); font-family: var(--font-body);
  font-size: 10.5px; letter-spacing: .2em; text-transform: uppercase;
  text-align: center; padding: 2px 0;
}

.clock {
  font-family: var(--font-figure);
  font-size: 22px; line-height: 1;
  padding: 4px 9px; border-radius: var(--radius-md);
  background: transparent; color: var(--muted);
  border: 1px solid var(--color-divider);
}
.clock.ticking { color: var(--text); border-color: var(--color-accent); }
.clock.low { color: var(--red); border-color: color-mix(in srgb, var(--red) 55%, transparent); }

.flash {
  align-self: center;
  min-height: 0; max-height: 0; overflow: hidden;
  font-size: 12.5px; color: var(--red);
  opacity: 0; transition: opacity .15s, max-height .15s;
}
.flash.show { opacity: 1; max-height: 40px; min-height: 18px; }

/* ════════════════════════════════════════════════════════════════
   Players / Friends / Profile — directories as real tables
   ════════════════════════════════════════════════════════════════ */
.players-page, .friends-page, .profile-page {
  max-width: 1000px; margin: 0 auto;
  display: flex; flex-direction: column; gap: 20px;
}

.search-panel { display: flex; }
.search-input {
  width: 100%; max-width: 340px; padding: 9px 12px;
  font-family: var(--font-body); font-size: 13px;
  background: transparent; color: var(--text);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
  outline: none;
}
.search-input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.search-input:focus { border-color: var(--color-accent); }

/* A hairline-ruled list that reads as a table without needing <table>. */
.player-list, .friend-list { display: flex; flex-direction: column; gap: 0; }
.player-list::before, .friend-list::before {
  content: ''; display: block; height: 1px; background: var(--color-text);
}
.player-card, .friend-item {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 13px 6px; margin: 0 -6px;
  background: transparent;
  border: 0; border-bottom: 1px solid var(--color-divider);
  border-radius: 0;
  transition: background-color .14s;
}
.player-card:hover, .friend-item:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

.pc-main { display: flex; align-items: center; gap: 14px; flex: 1; min-width: 0; color: var(--text); }
.pc-main:hover { text-decoration: none; }
.pc-avatar {
  flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--font-heading); font-weight: 600; font-size: 13px;
  color: var(--accent-ink);
  background: transparent;
  border: 1px solid var(--color-divider);
}
.pc-info { display: flex; flex-direction: column; min-width: 0; }
.pc-name { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 17px; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pc-stats { font-size: 12.5px; color: var(--muted); }
.pc-action { display: flex; gap: 8px; flex: 0 0 auto; }

.rel-badge {
  font-family: var(--font-body); font-size: 11px;
  letter-spacing: .1em; text-transform: uppercase;
  padding: 5px 10px; border-radius: var(--radius-md);
  border: 1px solid var(--color-divider); color: var(--muted);
}
.rel-badge.is-friend  { color: var(--accent-ink); border-color: var(--color-accent-300); }
.rel-badge.is-pending { color: var(--muted); }
.rel-badge.is-self    { color: var(--accent-ink); }

/* "(you)" annotates the name, it is not part of it — lighter and in the body face so it
   reads as an aside rather than as a surname. */
.pc-you { font-family: var(--font-body); font-size: 11.5px; color: var(--muted); }

.pager { display: flex; align-items: center; justify-content: center; gap: 18px; font-size: 11.5px; color: var(--muted); }

.friend-section { display: flex; flex-direction: column; gap: 10px; }

/* ── Profile ────────────────────────────────────────────────── */
.profile-card {
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  padding: 26px;
}
.profile-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.profile-avatar {
  width: 58px; height: 58px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center;
  font-family: var(--font-heading); font-weight: 400; font-size: 24px;
  color: var(--accent-ink);
  background: transparent;
  border: 1px solid var(--color-accent);
}
.profile-name { font-family: var(--font-heading); font-weight: 400; font-size: 30px; line-height: 1; margin: 0; }
/* font-family comes from the figure-face rule above; re-declaring it here overrode it. */
.profile-rating { color: var(--muted); font-size: 12px; }
.profile-action { margin-inline-start: auto; }
.respond-group { display: flex; gap: 8px; }

/* Match history */
.match-list { display: flex; flex-direction: column; gap: 0; }
.match-row {
  display: flex; align-items: center; gap: 11px;
  padding: 11px 6px; margin: 0 -6px;
  border-bottom: 1px solid var(--color-divider);
  font-size: 13px;
}
.match-row:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
.m-outcome {
  flex: 0 0 auto; width: 22px; text-align: center;
  border: 1px solid var(--color-divider); border-radius: var(--radius-sm);
  padding: 3px 0;
  font-family: var(--font-heading); font-weight: 600; font-size: 11px;
  color: var(--muted); background: transparent;
}
.m-outcome.win  { color: var(--accent-ink); border-color: var(--color-accent); }
.m-outcome.loss { color: var(--muted); }
.m-outcome.draw { color: var(--muted); }
.m-dot { flex: 0 0 auto; width: 10px; height: 10px; border-radius: 50%; border: 1px solid var(--color-divider); }
.m-dot.w { background: #f6f2ea; }
.m-dot.b { background: #26241f; }
.m-opp { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 15px; color: var(--text); flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.m-opp:hover { color: var(--accent-ink); text-decoration: none; }
.m-delta { font-size: 12.5px; color: var(--muted); }
.m-delta.up   { color: var(--accent-ink); }
.m-delta.down { color: var(--muted); }
.m-meta { color: var(--muted); font-size: 11.5px; white-space: nowrap; }

/* A hairline grid of figures — the design's profile readout. */
.stat-grid {
  display: grid; grid-template-columns: repeat(5, 1fr);
  gap: 1px; background: var(--color-divider);
  border: 1px solid var(--color-divider);
  margin-top: 22px;
}
.stat { background: var(--color-bg); padding: 14px 6px; text-align: center; border-radius: 0; }
/* Scoped to the profile grid. Unscoped it also caught the game's status bar, which has its
   own .stat-val, and set those readouts in 24px Cormorant — the old-style figures the
   status bar was never meant to have. */
.stat .stat-val { font-family: var(--font-figure); font-weight: 500; font-size: 21px; line-height: 1; }
.stat-lbl { margin-top: 5px; letter-spacing: .1em; color: var(--muted); }

/* ════════════════════════════════════════════════════════════════
   Settings — choices left, a board at playing size right
   ════════════════════════════════════════════════════════════════ */
.settings-page { max-width: 1400px; margin: 0 auto; display: flex; flex-direction: column; gap: 26px; }

@media (min-width: 1100px) {
  .settings-page { display: grid; grid-template-columns: 520px 1fr; gap: 0; align-items: start; }
  /* The header spans both columns and needs its own space below.
     gap is 0 here so the setting groups stack flush and their inline-end borders form one
     continuous hairline down the left column — a row-gap would chop that line into
     segments. But .page-title is 42px Cormorant at line-height 1, so its box is 42px while
     the glyphs need 51: the descenders of "Appearance" hang 4px below the box and, with
     nothing between the rows, landed on top of the "PAPER" kicker. This matches the 26px
     the flex layout below 1100px already gets from its gap. */
  .settings-page > .game-head { grid-column: 1 / -1; margin-block-end: 26px; }
  .settings-page > .setting-group { border-inline-end: 1px solid var(--color-divider); padding-inline-end: 40px; }
  /* The span tracks how many choosers sit in the left column (Paper, Board), so the
     preview stands beside all of them. Add a chooser, widen the span. */
  .settings-page > .setting-group.preview-group {
    grid-column: 2; grid-row: 2 / span 2;
    border-inline-end: 0; padding-inline-start: 44px; padding-inline-end: 0;
  }
}

.setting-group { background: transparent; border: 0; border-radius: 0; padding: 0 0 8px; }
.setting-group h2 {
  font-family: var(--font-body);
  font-size: 9.5px; font-weight: 600; letter-spacing: .2em; text-transform: uppercase;
  color: var(--accent-ink);
}
.setting-desc { color: var(--muted); font-size: 11.5px; line-height: 1.6; margin: 5px 0 12px; }

.swatch-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }

.swatch {
  cursor: pointer; display: flex; flex-direction: column; gap: 7px; align-items: center;
  padding: 0; border: 0; border-radius: 0;
  background: transparent;
}
.swatch:hover .swatch-name { color: var(--text); }
.swatch.active .swatch-name { color: var(--accent-ink); }
.swatch-name { font-family: var(--font-body); font-size: 11.5px; color: var(--muted); }

/* Mini board preview inside a board swatch (4×2 checker). */
.swatch-board {
  width: 100%; aspect-ratio: 2 / 1; border-radius: 0; overflow: hidden;
  display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(2, 1fr);
  border: 1px solid var(--frame);
  outline: none;
}
.swatch.active .swatch-board { outline: 2px solid var(--color-accent); }

/* Every other setting group puts a .setting-desc between its heading and its control,
   which is where their spacing comes from. This one has no description, so the board was
   sitting directly under the heading; the margin stands in for the missing paragraph. */
.preview-group h2 { margin-block-end: 22px; }
.settings-preview { display: flex; flex-direction: column; align-items: center; --sq: clamp(30px, 7vw, 68px); }
#preview-board {
  display: grid;
  grid-template-columns: repeat(8, var(--sq));
  grid-template-rows: repeat(8, var(--sq));
  border: 8px solid var(--color-surface);
  outline: 1px solid var(--color-divider);
  border-radius: 0;
  box-shadow: none;
}

/* ════════════════════════════════════════════════════════════════
   Responsive
   ════════════════════════════════════════════════════════════════ */
@media (max-width: 1099px) {
  .home-open { grid-template-columns: 1fr; gap: 40px; padding: 44px 24px 0; }
  .home-plate { --home-sq: clamp(34px, 10vw, 62px); }
  .features { grid-template-columns: 1fr; margin: 44px 24px 0; }
  .feature-card { padding: 26px 0; border-inline-start: 0; border-top: 1px solid var(--color-divider); }
  .feature-card:first-child { border-top: 0; }
  .nav-inner, .site-main, .site-footer { padding-inline-start: 24px; padding-inline-end: 24px; }
}

@media (max-width: 760px) {
  .nav-inner { flex-wrap: wrap; height: auto; padding: 12px 18px; gap: 8px 10px; }
  .nav-toggle { display: flex; }

  .nav-collapse {
    order: 3; flex: 0 0 100%;
    display: none;
    flex-direction: column; align-items: stretch; gap: 12px;
    margin-top: 4px; padding-top: 12px;
    border-top: 1px solid var(--color-divider);
  }
  .nav-inner.open .nav-collapse { display: flex; }

  .nav-links { flex-direction: column; gap: 12px; margin-inline-start: 0; }
  .nav-links a { padding-bottom: 0; border-bottom: 0; }
  .nav-links a.active { color: var(--accent-ink); }

  .nav-auth { margin-inline-start: 0; flex-wrap: wrap; gap: 12px; }

  .home-cols { grid-template-columns: 1fr; gap: 18px; }
  .home-title { font-size: clamp(34px, 11vw, 52px); }
  .site-main { padding: 22px 18px 40px; }
  .site-footer { flex-wrap: wrap; gap: 12px; padding: 22px 18px 32px; }
  .site-footer .foot-links { margin-inline-start: 0; }
  .page-title { font-size: 32px; }
  .profile-action { margin-inline-start: 0; width: 100%; }
  .respond-group { width: 100%; }
  .respond-group .btn { flex: 1; }
  .profile-card { padding: 18px; }
  .swatch-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
  .stat-grid { grid-template-columns: repeat(3, 1fr); }
  .m-meta { display: none; }
}

@media (max-width: 360px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
}

/* Language switcher. Each language is labelled in its own script, so the labels
   are the one thing a visitor who cannot read the current language can still use. */
.lang-switch-group { display: inline-flex; align-items: center; gap: 10px; }

/* ════════════════════════════════════════════════════════════════
   Learn — the prose pages (rules, strategy, engine, about)

   A single measured column. These are the only pages on the site
   meant to be read rather than operated, so the width is set by the
   line length that is comfortable to read (~70 characters) and not
   by the viewport. Everything else here is the home page's editorial
   type at a smaller step, so an article looks like the same
   publication as the front page.
   ════════════════════════════════════════════════════════════════ */
.learn-page { max-width: 748px; margin: 0 auto; padding: 64px 44px 84px; }

.learn-head { margin-bottom: 8px; }
.learn-title {
  font-family: var(--font-heading); font-weight: 400;
  font-size: clamp(34px, 4.4vw, 56px); line-height: 1.02;
  letter-spacing: -.022em;
  margin: 0 0 22px;
}
.learn-lede {
  font-size: 17px; line-height: 1.62; margin: 0;
  color: color-mix(in srgb, var(--color-text) 88%, transparent);
}

.learn-section { margin-top: 42px; }
.learn-section h2 {
  font-family: var(--font-heading); font-weight: 400;
  font-size: 27px; line-height: 1.15; letter-spacing: -.012em;
  margin: 0 0 12px;
}
.learn-section p {
  font-size: 15px; line-height: 1.78; margin: 0 0 14px;
  color: color-mix(in srgb, var(--color-text) 82%, transparent);
}
.learn-section p:last-child { margin-bottom: 0; }

.learn-more { margin-top: 68px; }
.learn-more ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 12px 28px;
}
.learn-more a {
  font-family: var(--font-heading); font-size: 20px;
  color: var(--color-text); text-decoration: none;
  border-bottom: 1px solid var(--color-divider); padding-bottom: 2px;
}
.learn-more a:hover { color: var(--accent-ink); border-bottom-color: var(--accent-ink); }

@media (max-width: 720px) {
  .learn-page { padding: 40px 20px 60px; }
  .learn-lede { font-size: 16px; }
}
