/* Glanopoly design tokens — Warm Monochrome (2026-10-20). Shared by the hub (hub.css) and the match (mono.css);
   every page links this file first. Light is the default; dark comes from the theme switch (data-theme="dark").
   Pink and turquoise are rare accents with a job (status cells, the chance card, the chromatic fringe), never
   surfaces. Player and industry colours come from the server and are re-toned in static/hub/tone.js. */

/* Glanopoly Display Bold (Codex; static/hub/fonts/GlanopolyDisplay-LICENSE.txt): only the name GLANOPOLY and the
   logo. The interface — money, prices, names, buttons, menus — is set in Inter or the system sans, 400–500. */
@font-face { font-family: 'Glanopoly Display'; src: url('/static/hub/fonts/GlanopolyDisplay-Bold.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap; }

:root {
  /* brand constants */
  --off-white: #F5F4F4; --soft-black: #211F1F; --pink: #EFAFC1; --teal: #39D0D8;

  /* light theme: a neutral soft white (no yellow: the owner turned down the cream #F6F3ED), soft-black text and rules */
  --bg: #F5F4F4;            /* page ground */
  --bg-2: #EEECEC;          /* sunken wells, track of a segmented control */
  --surface: #FDFCFC;       /* panels, rows, cards */
  --surface-2: #F1EFEF;     /* hover on a surface */
  --surface-3: #E7E4E4;     /* pressed, skeletons */
  --line: #DCD8D8;          /* hairlines */
  --line-2: #BFBABA;        /* stronger rules, empty-seat dashes */
  --ink: #211F1F;           /* text, rules, primary buttons */
  --ink-2: #393535;         /* primary button hover */
  --on-ink: #F5F4F4;        /* text on ink */
  --muted: #6B6666;         /* secondary text: 4.8:1 on --bg-2, 5.2:1 on --bg */
  --dim: #9C9797;           /* decoration only (dividers, inactive marks), never body text */

  /* states: one value per state in both themes (owner, 2026-10-22: chromatic colours never change with the theme;
     only neutrals do). Each sits at the luminance that reads on paper and on graphite alike, about 4:1. */
  --good: #35865D; --bad: #D14A33; --warn: #9F6D16; --gold: #C99A2E;
  --live: var(--pink); --open: var(--teal);

  /* depth: soft warm shadows with an offset; no glows */
  --shadow-1: 0 1px 2px rgba(33, 31, 31, .06);
  --shadow-2: 0 2px 4px rgba(33, 31, 31, .05), 0 12px 28px -14px rgba(33, 31, 31, .28);
  --shadow-pop: 0 4px 10px rgba(33, 31, 31, .06), 0 28px 60px -24px rgba(33, 31, 31, .42);
  --scrim: rgba(33, 31, 31, .42);

  /* chromatic fringe for the logo, the wordmark and large display type only */
  --fringe-a: rgba(239, 175, 193, .62);
  --fringe-b: rgba(57, 208, 216, .5);

  /* type */
  --ui: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --cond: var(--ui);
  --display: var(--ui);   /* former compact face: the interface uses one family now */
  --brand: 'Glanopoly Display', var(--ui);   /* the name and the logo only */

  /* geometry: 2 cells and chips, 4 controls, 8 panels and dialogs; circles only for avatars and tokens */
  --r-xs: 2px; --r-s: 4px; --r-l: 8px;

  /* motion */
  --ease-out: cubic-bezier(.23, 1, .32, 1);
  --ease-in-out: cubic-bezier(.77, 0, .175, 1);
  --ease-drawer: cubic-bezier(.32, .72, 0, 1);
  --t-press: 140ms; --t-ui: 200ms; --t-panel: 260ms;

  color-scheme: light;
}

/* dark theme: its own design, not an inversion — warm graphite ground, raised panels a step lighter */
:root[data-theme="dark"] {
  /* neutral graphite (R = G = B): no brown, no blue or violet (owner, 2026-10-20) */
  --bg: #0D0D0D; --bg-2: #080808; --surface: #161616; --surface-2: #202020; --surface-3: #2B2B2B;
  --line: #303030; --line-2: #505050;
  --ink: #F5F4F4; --ink-2: #E0E0E0; --on-ink: #1E1E1E;
  --muted: #A3A3A3; --dim: #6B6B6B;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow-2: 0 2px 4px rgba(0, 0, 0, .25), 0 14px 30px -14px rgba(0, 0, 0, .7);
  --shadow-pop: 0 4px 12px rgba(0, 0, 0, .3), 0 30px 70px -24px rgba(0, 0, 0, .8);
  --scrim: rgba(10, 10, 10, .62);
  color-scheme: dark;
}

/* ---------- base ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--ink); font: 400 15px/1.45 var(--ui); font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; -webkit-font-smoothing: antialiased; -webkit-tap-highlight-color: transparent; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; padding: 0; }
a { color: inherit; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
::selection { background: var(--pink); color: var(--soft-black); }
* { scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 10px; border: 3px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-track { background: transparent; }
input::placeholder { color: var(--muted); opacity: 1; }
.num { font-variant-numeric: tabular-nums; }
b, strong { font-weight: 500; }

/* ---------- the brand: G mark of track cells, the wordmark, the fringe and the hover lap ---------- */
.brand-mark { display: block; flex: none; fill: currentColor; stroke: none; overflow: visible; }
/* the fringe sits on the ink cells only: the turquoise start (1st rect) and the pink bar (5th) stay clean (owner,
   2026-10-22); #g-fringe is defined inside each inline mark by tools/make_brand_images.py */
.brand-mark rect:not(:nth-of-type(1)):not(:nth-of-type(5)) { filter: url(#g-fringe); }
/* the wordmark: GLANOPOLY set in Glanopoly Display Bold (caps forms), in the text colour */
.wordmark { display: inline-block; flex: none; font: 700 var(--wm, 24px)/1 var(--brand); font-synthesis: none; letter-spacing: .01em;
  text-transform: uppercase; white-space: nowrap; color: inherit; }
.wordmark b { font-weight: 700; }
.brand .wordmark { filter: drop-shadow(-.3px 0 0 var(--fringe-a)) drop-shadow(.3px 0 0 var(--fringe-b)); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.fringe { text-shadow: -.5px 0 var(--fringe-a), .5px 0 var(--fringe-b); }
/* Glanopoly only: hovering the mark runs one lap of the board. A pink token passes the ink cells clockwise from the
   turquoise start (each cell takes the pink for a moment and hands it on), then the start cell takes the token
   back with a small press in place. Nothing moves away: the start cell and the pink inner bar keep their places
   (owner, 2026-10-22). Hover-capable pointers only; nothing with reduced motion. */
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
  a.brand:hover .brand-mark rect:nth-of-type(6) { animation: track-pass 300ms linear 0ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(7) { animation: track-pass 300ms linear 42ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(8) { animation: track-pass 300ms linear 84ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(9) { animation: track-pass 300ms linear 126ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(10) { animation: track-pass 300ms linear 168ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(11) { animation: track-pass 300ms linear 210ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(4) { animation: track-pass 300ms linear 252ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(3) { animation: track-pass 300ms linear 294ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(2) { animation: track-pass 300ms linear 336ms 1 both; }
  a.brand:hover .brand-mark rect:nth-of-type(1) { transform-box: fill-box; transform-origin: center;
    animation: track-arrive 280ms var(--ease-out) 418ms 1 both; }
}
@keyframes track-pass { 0%, 100% { fill: currentColor; } 22%, 48% { fill: var(--pink); } }
@keyframes track-arrive { 45% { transform: scale(.78); } }


/* the background dot grid (ambient.js): fixed behind the page, never takes the pointer */
.ambient-cells { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }
.login-layout { position: relative; z-index: 1; }

/* the cell marker: a small filled square that marks the current or active thing (the signature move) */
.cell-mark { display: inline-block; width: 8px; height: 8px; border-radius: 1px; background: var(--c, var(--ink)); flex: none; }

/* ---------- theme switch: the new theme spreads from the switch as a circle (view transition) ---------- */
:root.theme-vt::view-transition-old(root), :root.theme-vt::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
:root.theme-vt::view-transition-new(root) { z-index: 2; }
.theme-btn .moon { display: none; }
:root[data-theme="dark"] .theme-btn .sun { display: none; }
:root[data-theme="dark"] .theme-btn .moon { display: inline; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}

/* ---------- avatars (static/hub/avatar.js), shared by the hub and the match ---------- */
.av { --c: var(--muted); position: relative; overflow: hidden; width: 28px; height: 28px; border-radius: var(--r-s); flex: none;
  display: grid; place-items: center; color: #211F1F; font: 500 14px/1 var(--ui); }
.av.empty { box-shadow: inset 0 0 0 1.5px var(--line-2); color: transparent; }
.av.out { filter: grayscale(1); opacity: .5; }
/* The plate is drawn, not painted on the box (static/hub/avatar.js): one even-odd path, so the account's cut-out is a
   real hole through which the page, a card or a hover tint shows, in both themes and at every size. */
.av-plate { position: absolute; inset: 0; width: 100%; height: 100%; fill: var(--c); stroke: none; pointer-events: none; }
.av-i { position: relative; }
/* An own picture: a plain rounded square, nothing cut out of it (owner, 2026-10-23: the cut-outs belong to the
   standard avatars only). */
.av.photo { background: none; }
.av.photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; user-select: none; }
.av:not(.photo):not(.empty) { background: none; }
