/* Heroic Discord panel, design tokens.

   Brand: heroic.gg, read off the live page on 2 September 2026. The site is
   black top and bottom with cream #f0eee4 sections, its red is #b21832 (the
   favicon's red, also its section blocks), its nav and labels are Geist Mono
   in uppercase, its body is Geist, and its titles are PP Nikkei Pacific
   Ultrabold, a commercial face this panel stands in for with Geist at 900.
   Buttons on the site are 4px corners, not pills. The rail here is the
   site's black header, the buttons are the site's red.

   The ramp, the type scale, the spacing and the geometry are the shared
   panel's, so the admin tools read as one house.
   Components read the semantic aliases only, never a ramp step, so a theme is a
   token swap and nothing else. */

/* --- webfonts -------------------------------------------------------------
   Geist and Geist Mono, the faces heroic.gg sets its body and labels in.
   Open source (SIL OFL, see fonts/OFL-Geist.txt beside this file), served from the repo
   so the panel keeps working with no outbound network. Variable files, one
   per family. */
@font-face {
  font-family: "Geist";
  src: url("/brand/fonts/Geist.ttf") format("truetype-variations");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/brand/fonts/GeistMono.ttf") format("truetype-variations");
  font-weight: 100 900;
  font-display: swap;
}

:root {
  /* Three names, one face. Kept as three so the type scale below still says
     which role it means, and so a future brand can move one of them alone. */
  --font-serif: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-sans: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Real code and nothing else. Discord sets a code block in monospace and so
     does this, but an id or a timestamp is not code and no longer pretends. */
  --font-mono: "Geist Mono", ui-monospace, "SFMono-Regular", Consolas, monospace;

  /* --- neutral ramp, night -----------------------------------------------
     Read off a live dark site rather than invented: their page is #0f0f0f, their
     surfaces are #131313 and #212121, their rules #272727. Neutral grey, no
     colour in the ground, which is what keeps the orange the only hue on the
     page that means anything. */
  --c-000: #0a0a0a; /* page */
  --c-050: #101010; /* hover on the page itself */
  --c-100: #171717; /* card, panel: the server icon's grey */
  --c-150: #222222; /* raised: input, hovered row */
  --c-200: #2a2a2a; /* hairline, table rule */
  --c-250: #383838; /* control edge, ghost button */
  --c-300: #4a4a4a; /* disabled edge */

  /* --- text --------------------------------------------------------------- */
  --fg-1: #f0eee4; /* titles, figures, values: the site's cream */
  --fg-2: #cfcdc4; /* body, prose, cells */
  --fg-3: #aaaaaa; /* labels, column heads, meta, their muted */
  --fg-4: #7a7a7a; /* placeholder, disabled, build stamp */

  /* --- accent: Heroic red ---------------------------------------------------
     The favicon's red, lifted a step for text on the black ground. */
  --brand-500: #d0213c;
  --brand-hover: #e0405a;
  --brand-press: #b21832;
  --brand-tint: rgba(208, 33, 60, 0.16);
  --on-brand: #ffffff;

  --sx-red: #b21832;
  --sx-red-lift: #d0213c;
  --sx-cream: #f0eee4;
  --sx-black: #0a0a0a;
  --sx-purple-lift: #d0213c;

  /* --- the rail: the site's black header, the same in both themes --------- */
  --rail-bg: var(--sx-black);
  --rail-fg: var(--sx-cream);
  --rail-fg-muted: rgba(240, 238, 228, 0.72);
  --rail-fg-faint: rgba(240, 238, 228, 0.5);
  --rail-hover: rgba(240, 238, 228, 0.1);
  --rail-active: rgba(240, 238, 228, 0.16);
  --rail-rule: rgba(240, 238, 228, 0.16);
  --rail-head: var(--sx-red-lift);

  /* --- status, each meaning exactly one thing -----------------------------
     green the machine is doing it, amber a person must act, red withdrawn or
     unreachable, grey switched off on purpose. A zero is never tinted: an empty
     queue is good news. */
  --live-500: #6fca92;
  --attend-500: #e8b451;
  --halt-500: #e8796b;
  --live-tint: rgba(111, 202, 146, 0.14);
  --attend-tint: rgba(232, 180, 81, 0.14);
  --halt-tint: rgba(232, 121, 107, 0.14);

  /* --- unknown -------------------------------------------------------------
     The one colour decision the whole product turns on. A leaderboard returns
     20 rows; below rank 20 a member's total is not zero, it is unreadable.
     Unknown is achromatic and hatched so it can never be mistaken for a status or
     for a number. Never render unknown as 0. */
  --unknown-fg: #9a9a9a;
  --unknown-base: #1b1b1b;
  --unknown-line: #2b2b2b;

  --grid-line: rgba(255, 255, 255, 0.025);
  --shadow-float: 0 18px 44px rgba(0, 0, 0, 0.5);

  /* --- semantic aliases: the only names the stylesheet may use ------------- */
  --surface-page: var(--c-000);
  --surface-chrome: var(--c-000);
  --surface-panel: var(--c-100);
  --surface-raised: var(--c-150);
  --surface-input: var(--c-150);
  --surface-input-focus: #2b2b2b;
  --surface-row-hover: var(--c-150);
  --surface-row-stripe: #121212;
  --surface-overlay: var(--c-100);

  --text-title: var(--fg-1);
  --text-body: var(--fg-2);
  --text-prose: var(--fg-2);
  --text-label: var(--fg-3);
  --text-meta: var(--fg-3);
  --text-faint: var(--fg-4);
  --text-link: var(--brand-500);
  --text-link-hover: var(--brand-hover);

  --border-hairline: var(--c-200);
  --border-soft: #242424;
  --border-strong: var(--c-250);
  --border-input: var(--c-250);

  --accent: var(--brand-500);
  --accent-hover: var(--brand-hover);
  --accent-press: var(--brand-press);
  --accent-ink: var(--on-brand);
  --accent-tint: var(--brand-tint);

  --status-live: var(--live-500);
  --status-attend: var(--attend-500);
  --status-halt: var(--halt-500);
  --status-off: var(--fg-4);
  --status-unknown: var(--unknown-fg);

  --focus-ring: var(--brand-500);
  /* heroic.gg draws 4px corners on buttons and cards, never pills. */
  --radius-btn: 4px;
  --dirty-mark: var(--attend-500);

  /* --- type scale ----------------------------------------------------------
     Set larger than an admin panel usually is, on purpose. Nothing here is read
     at a glance; it is read carefully by somebody deciding whether to change a
     number that pays 400 people. */
  --fs-micro: 13px;
  --fs-meta: 14px;
  --fs-small: 15px;
  --fs-base: 16px;
  --fs-lead: 17px;
  --fs-section: 22px;
  --fs-title-sm: 26px;
  --fs-title: 34px;
  --fs-figure: 40px;
  --fs-figure-lg: 56px;

  --lh-flat: 1;
  --lh-tight: 1.25;
  --lh-snug: 1.45;
  --lh-body: 1.65;
  --lh-prose: 1.7;

  --tr-title: 0.005em;
  --tr-figure: -0.01em;

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-heavy: 900;

  /* Composed roles. Serif for anything that names or counts something, sans for
     everything operational, mono for machine values only: snowflakes, ids,
     timestamps, Metapoints, multipliers, rule keys. Mono is a semantic here, not
     a decoration, because those are the values a moderator copies into Discord or
     compares down a column. */
  --type-title: var(--fw-heavy) var(--fs-title) / var(--lh-tight) var(--font-serif);
  --type-section: var(--fw-bold) var(--fs-section) / var(--lh-tight) var(--font-serif);
  --type-figure: var(--fw-heavy) var(--fs-figure) / var(--lh-flat) var(--font-serif);
  --type-card-title: var(--fw-medium) var(--fs-lead) / var(--lh-snug) var(--font-sans);
  --type-lede: var(--fw-regular) var(--fs-lead) / var(--lh-prose) var(--font-sans);
  --type-body: var(--fw-regular) var(--fs-base) / var(--lh-body) var(--font-sans);
  --type-cell: var(--fw-regular) var(--fs-base) / var(--lh-snug) var(--font-sans);
  --type-small: var(--fw-regular) var(--fs-small) / var(--lh-body) var(--font-sans);
  --type-meta: var(--fw-regular) var(--fs-meta) / var(--lh-snug) var(--font-sans);
  --type-label: var(--fw-medium) var(--fs-small) / var(--lh-snug) var(--font-sans);
  --type-colhead: var(--fw-medium) var(--fs-meta) / var(--lh-flat) var(--font-sans);
  --type-tag: var(--fw-medium) var(--fs-micro) / var(--lh-flat) var(--font-sans);
  --type-button: var(--fw-bold) var(--fs-base) / var(--lh-flat) var(--font-sans);
  /* Numbers, ids and timestamps. Roboto like everything else, at the medium
     weight, because a snowflake in a second typeface was the loudest thing on
     the page and none of it is code. */
  --type-data: var(--fw-medium) var(--fs-base) / var(--lh-snug) var(--font-sans);
  --type-data-sm: var(--fw-regular) var(--fs-meta) / var(--lh-snug) var(--font-sans);
  --type-state: var(--fw-medium) var(--fs-meta) / var(--lh-flat) var(--font-sans);

  /* --- spacing -------------------------------------------------------------
     Roomy. Rows are 56px because a moderator taps a decision on one, controls are
     42px because the type inside them is 16px, and the page breathes at 44px. */
  --sp-1: 2px;  --sp-2: 4px;  --sp-3: 6px;  --sp-4: 8px;
  --sp-5: 10px; --sp-6: 14px; --sp-7: 18px; --sp-8: 22px;
  --sp-9: 28px; --sp-10: 34px; --sp-11: 44px; --sp-12: 60px; --sp-13: 88px;

  --row-dense: 48px;
  --row: 56px;
  --row-roomy: 64px;
  --cell-pad-x: var(--sp-8);
  --cell-pad-x-tight: var(--sp-6);

  --ctl-sm: 34px;
  --ctl: 42px;
  --ctl-lg: 52px;
  --hit: 44px;
  --num-w: 104px;

  --bar-h: 76px;
  --rail-w: 248px;
  --page-max: 1140px;
  --page-gutter: 44px;
  --page-gutter-sm: 20px;
  --page-narrow: 460px;
  --stack: var(--sp-9);
  --stack-lg: var(--sp-11);

  /* --- geometry ----------------------------------------------------------- */
  --radius-sm: 10px;
  --radius-md: 14px;
  --radius: 20px;
  --radius-lg: 24px;
  --radius-pill: 999px;

  --border: 1px;
  --rule: var(--border) solid var(--border-hairline);
  --rule-soft: var(--border) solid var(--border-soft);
  --edge-control: var(--border) solid var(--border-input);

  --focus-w: 2px;
  --focus-offset: 3px;
  --focus: var(--focus-w) solid var(--focus-ring);

  /* The system's one texture. Wherever it appears it means the same thing:
     there is no reading here and we cannot get one. */
  --hatch: repeating-linear-gradient(135deg, var(--unknown-base) 0 4px, var(--unknown-line) 4px 5px);

  /* Faint 8px paper. Empty states and the signed-out screens only, never behind
     live data. */
  --grid-8: linear-gradient(to right, var(--grid-line) 0 1px, transparent 1px 8px),
            linear-gradient(to bottom, var(--grid-line) 0 1px, transparent 1px 8px);
  --grid-8-size: 8px 8px;

  /* --- motion --------------------------------------------------------------
     120ms on colour and nothing else. No entrance animations, no hover
     transforms, no decorative spinners. */
  --tr-color: color 120ms ease-out, background-color 120ms ease-out, border-color 120ms ease-out;
}

/* Dark is the default because the panel sits beside Discord on the same desk,
   often late. The stylesheet never branches on the theme; only these values move. */
:root { color-scheme: dark; }

/* --- daylight --------------------------------------------------------------
   The same idea lit from outside. The accent darkens, because the orange
   on paper has to carry text-level contrast, and the status hues follow it down. */
[data-theme="light"] {
  color-scheme: light;

  /* Neutral on paper too, so the two themes are the same product in different
     light rather than two palettes. */
  --c-000: #f0eee4;
  --c-050: #e8e6da;
  --c-100: #ffffff;
  --c-150: #f5f3eb;
  --c-200: #e3e1d6;
  --c-250: #cbc9bf;
  --c-300: #aeaca3;

  --fg-1: #0a0a0a;
  --fg-2: #222222;
  --fg-3: #5c5b57;
  --fg-4: #8a8983;

  --brand-500: #b21832;
  --brand-hover: #9a1329;
  --brand-press: #7f0f21;
  --brand-tint: rgba(178, 24, 50, 0.12);
  --on-brand: #ffffff;
  --text-link: var(--sx-red);
  --text-link-hover: var(--brand-press);

  --sx-purple-lift: #b21832;

  --live-500: #1f6b45;
  --attend-500: #8a6410;
  --halt-500: #b04034;
  --live-tint: rgba(31, 107, 69, 0.12);
  --attend-tint: rgba(138, 100, 16, 0.13);
  --halt-tint: rgba(176, 64, 52, 0.11);

  --unknown-fg: #6e6e6e;
  --unknown-base: #e8e8e8;
  --unknown-line: #d6d6d6;

  --grid-line: rgba(19, 19, 19, 0.05);
  --shadow-float: 0 18px 44px rgba(19, 19, 19, 0.14);

  --surface-input-focus: #ebe9df;
  --surface-row-stripe: #faf9f4;
  --border-soft: #ebe9df;
}
