/* ============================================================
   DOUBLE SKUNK — Brand tokens
   ------------------------------------------------------------
   This file holds the BRAND-LEVEL system: skunk colors, type,
   spacing, radii, shadows, and SEMANTIC SURFACE TOKENS bound to
   brand defaults.

   The brand surfaces are intentionally NEUTRAL — a near-black
   "ink" with a chalk-cream foreground and a brass accent. The
   wooden parlor look is NOT the brand; it is one theme.

   Themes live in `themes/` and override the semantic surface
   tokens for in-game boards. Apply with a class on a wrapper:
       <div class="theme-parlor">...the match...</div>
   ============================================================ */

/* The webfonts (Bowlby One SC, Big Shoulders Display, Space Grotesk,
   JetBrains Mono, and Caudex on the learn pages) are self-hosted out of
   priv/static/doubleskunk/fonts and declared by the ds_fonts component,
   which inlines the @font-face rules into each page's head. Pulling them
   in from here instead would hide every font URL behind this file. */

:root {
  /* ===========================================================
     BRAND CORE — skunk-ink, chalk, brass.
     These are the three colors that define the brand at every
     touchpoint regardless of which board you're on.
     =========================================================== */

  --skunk-ink:        #0d0c10;   /* near-black, hint of plum — never navy, never brown */
  --skunk-ink-2:      #14131a;
  --skunk-ink-3:      #1d1c24;
  --skunk-ink-4:      #2b2932;
  --skunk-ink-5:      #3a3742;

  --chalk:            #f1ead0;   /* the skunk stripe — primary text on dark */
  --chalk-2:          #e6dcba;
  --chalk-3:          #ada48a;
  --chalk-4:          #7a7263;

  /* --brass stays the brand hex because it is a SURFACE as well as an accent:
     it is the mid stop of the .cta.pop gradient and the fill behind the learn
     toggles, all of which carry --chalk text. Lifting it for legibility as
     text would darken that text's contrast in exchange. Accent TEXT reads
     --fg-accent instead; see the note there. */
  --brass:            #d24b3a;   /* BRAND accent (ruby). Parlor overrides this to actual brass-gold. */
  --brass-bright:     #e9624f;
  --brass-deep:       #8e2418;
  --brass-glow:       #f4a190;

  /* secondary brand accents — used for variety, progress, mystery.
     --pop-ruby is only ever text (guide badges, section kickers), so unlike
     --brass it can take the lifted value outright. It was #d24b3a, which was
     4.23:1 on --skunk-ink-2 and 3.87:1 on the --surface-raised badges. */
  --pop-ruby:         #e25947;
  --pop-mint:         #58c08e;
  --pop-violet:       #7a52c4;

  /* ===========================================================
     GAME COLORS — rarity, currency, HP, suits. These belong to
     the GAME, not to any single theme. They render on top of
     whatever surface the active theme provides.
     =========================================================== */

  /* Rarity (the roguelite layer) — desaturated to feel hand-painted */
  --rarity-common:    #9a9082;
  --rarity-uncommon:  #4c9a72;
  --rarity-rare:      #4a82c4;
  --rarity-legendary: #b562d4;
  --rarity-mythic:    #e25a36;

  /* Currency & state */
  --gold:             #e6b94e;
  --gold-deep:        #a07e1f;
  --seal-blue:        #6a9bd8;
  --seal-purple:      #9170c4;
  --seal-jade:        #5cb693;
  --hp-red:           #c0392b;
  --xp-jade:          #5cb693;
  --ok:               #5cb693;
  --warn:             #e6b94e;
  --danger:           #c0392b;

  /* Playing card stock — these stay constant across themes
     (cards are world objects, not chrome) */
  --card-face:        #f1ead0;
  --card-back:        #2b2932;   /* default — themes override */
  --card-red:         #c8412c;   /* the game's red ink (parlor CardSkin); the card SVGs hard-code the same value for parity */
  --card-black:       #16110f;   /* the game's black ink */
  --card-cut-frame:   #a56a22;   /* the game's ember starter frame, worn by the cut card */
  --card-select:      #36c2b4;   /* halo on a card the reader has picked */

  /* ===========================================================
     SEMANTIC SURFACE TOKENS — bind these in your components.
     Defaults below are the BRAND surfaces (neutral skunk-ink).
     Themes override these. Never write to --walnut-* etc.
     directly from a component — go through these.
     =========================================================== */

  /* layers from back to front */
  --surface-page:        var(--skunk-ink);     /* whole-viewport bg */
  --surface-base:        var(--skunk-ink-2);   /* default panel bg */
  --surface-raised:      var(--skunk-ink-3);   /* button, row, list cell */
  --surface-row-hover:   var(--skunk-ink-4);
  --surface-panel:       var(--skunk-ink-2);   /* major dialog / menu panel */

  /* the table — where the match happens. Themes change this most. */
  --surface-table:       var(--skunk-ink);
  --surface-board:       var(--skunk-ink-3);   /* the pegboard plank itself */

  /* foreground tiers */
  --fg-1:                var(--chalk);
  --fg-2:                oklch(85% 0.02 90);
  --fg-3:                oklch(70% 0.02 90);
  /* The quietest tier still has to be readable: it carries the kb-bar
     breadcrumb, the footer byline, the footer fine print, the learn stop-card
     kickers and the stat labels on --surface-raised. At 55% it was 4.01:1 on
     --skunk-ink and failed all of them. Still the dimmest tier, now past
     4.5:1 on every surface it is painted on. */
  --fg-4:                oklch(62% 0.02 90);
  /* Brass as TEXT. Was var(--brass) = #d24b3a, which is 4.23:1 on
     --skunk-ink-2 and accounted for five of the eight Lighthouse contrast
     failures on the landing page (.fnum, the kickers, the cast flourish).
     Lifted at the same hue and chroma until it clears 4.5:1 on every
     surface it lands on, --surface-raised included. Kept separate from
     --brass so the button fills underneath --chalk text do not move with
     it: that is the trade this split exists to avoid. */
  --fg-accent:           #e25947;

  /* borders — chalk-tinted at brand level (neutral). Themes override to warm tints. */
  --border-hair:         oklch(95% 0.02 90 / 0.12);
  --border-soft:         oklch(95% 0.02 90 / 0.06);
  --border-strong:       var(--brass);

  /* vignette + texture — themes override.
     Brand default: very subtle, no candle (that's the parlor) */
  --vignette:            none;
  --texture-overlay:     none;
  --texture-board:       none;    /* pegboard background image */

  /* ===========================================================
     TYPE SYSTEM — brand-level. Themes do not change type.
     =========================================================== */

  /* The *Fallback families are declared by the ds_fonts component, not here:
     they are local Arial (Roboto on Android) with size-adjust and vertical
     metrics overridden to match the real face. They sit ahead of the plain
     local names so headings keep their measurements while the webfont is
     still in flight, which is what stops the swap re-wrapping the page. */
  --font-display: 'Bowlby One SC', 'Bowlby One SC Fallback', 'Bowlby One', 'Anton', 'Impact', sans-serif;
  --font-poster:  'Bowlby One SC', 'Bowlby One SC Fallback', 'Bowlby One', 'Anton', 'Impact', sans-serif;
  --font-sign:    'Big Shoulders Display', 'Big Shoulders Fallback', 'Oswald', 'Impact', sans-serif;
  --font-body:    'Space Grotesk', 'Space Grotesk Fallback', 'Inter', 'Helvetica Neue', system-ui, sans-serif;
  --font-mono:    'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace;

  --t-display-1-size: 72px;   --t-display-1-lh: 1.0;   --t-display-1-tracking: -0.02em;
  --t-display-2-size: 48px;   --t-display-2-lh: 1.05;  --t-display-2-tracking: -0.015em;
  --t-h1-size:        36px;   --t-h1-lh: 1.1;          --t-h1-tracking: -0.01em;
  --t-h2-size:        28px;   --t-h2-lh: 1.15;         --t-h2-tracking: -0.005em;
  --t-h3-size:        22px;   --t-h3-lh: 1.2;          --t-h3-tracking: 0;
  --t-body-size:      17px;   --t-body-lh: 1.5;        --t-body-tracking: 0;
  --t-small-size:     14px;   --t-small-lh: 1.45;      --t-small-tracking: 0;
  --t-sign-size:      13px;   --t-sign-lh: 1.0;        --t-sign-tracking: 0.14em;
  --t-mono-size:      13px;   --t-mono-lh: 1.0;        --t-mono-tracking: 0.05em;

  /* ===========================================================
     RADII + SPACING — brand-level, never themed.
     =========================================================== */

  --r-card: 2px;
  --r-chip: 6px;
  --r-inset: 10px;
  --r-panel: 18px;
  --r-pill: 999px;

  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-5: 20px; --s-6: 24px; --s-8: 32px; --s-10: 40px;
  --s-14: 56px; --s-20: 80px;

  /* ===========================================================
     SHADOWS / GLOWS — brand-level.
     =========================================================== */

  --shadow-candle:
    inset 0 1px 0 oklch(95% 0.04 80 / 0.06),
    0 24px 60px -16px oklch(8% 0 0 / 0.7),
    0 4px 12px -4px oklch(8% 0 0 / 0.4);

  --shadow-card:
    0 1px 1px oklch(8% 0 0 / 0.5),
    0 8px 16px -4px oklch(8% 0 0 / 0.4);

  --shadow-engrave:
    inset 0 1px 0 oklch(95% 0.04 80 / 0.12),
    inset 0 -1px 0 oklch(8% 0 0 / 0.6);

  --shadow-button:
    inset 0 1px 0 oklch(95% 0.04 80 / 0.18),
    inset 0 -1px 0 oklch(8% 0 0 / 0.5),
    0 2px 6px -2px oklch(8% 0 0 / 0.6);

  --glow-brass:
    0 0 0 1px var(--brass),
    0 0 24px -4px color-mix(in srgb, var(--brass) 55%, transparent);

  --glow-mythic: 0 0 22px -2px var(--rarity-mythic);

  /* ===========================================================
     BRAND TEXTURES — cribbage-hole pattern (universal, says
     "this is cribbage" without saying "this is wood"). Used as
     a subtle background overlay at low opacity.
     =========================================================== */

  --cribbage-holes: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40'><circle cx='8' cy='8' r='1.4' fill='%23f1ead0' opacity='0.10'/><circle cx='24' cy='8' r='1.4' fill='%23f1ead0' opacity='0.10'/><circle cx='8' cy='24' r='1.4' fill='%23f1ead0' opacity='0.10'/><circle cx='24' cy='24' r='1.4' fill='%23f1ead0' opacity='0.10'/></svg>");

  --grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.6  0 0 0 0 0.45  0 0 0 0 0.25  0 0 0 0.5 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

/* ============================================================
   SEMANTIC ELEMENT STYLES
   ============================================================ */

body {
  margin: 0;
  background: var(--surface-page);
  color: var(--fg-1);
  font-family: var(--font-body);
  font-size: var(--t-body-size);
  line-height: var(--t-body-lh);
  font-feature-settings: 'liga', 'kern', 'onum';
  -webkit-font-smoothing: antialiased;
}

h1, .display-1 {
  font-family: var(--font-display);
  font-size: var(--t-display-1-size);
  line-height: var(--t-display-1-lh);
  letter-spacing: var(--t-display-1-tracking);
  font-weight: 400;
  color: var(--fg-1);
  margin: 0;
  text-transform: none;
}
.display-2 {
  font-family: var(--font-display);
  font-size: var(--t-display-2-size);
  line-height: var(--t-display-2-lh);
  letter-spacing: var(--t-display-2-tracking);
  font-weight: 400; color: var(--fg-1);
}
h2 {
  font-family: var(--font-display);
  font-size: var(--t-h1-size);
  line-height: var(--t-h1-lh);
  letter-spacing: var(--t-h1-tracking);
  font-weight: 400; color: var(--fg-1); margin: 0;
}
h3 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--t-h2-size); line-height: var(--t-h2-lh);
  letter-spacing: var(--t-h2-tracking);
  color: var(--fg-1); margin: 0;
}
h4 {
  font-family: var(--font-body);
  font-size: var(--t-h3-size); line-height: var(--t-h3-lh);
  font-weight: 600; color: var(--fg-1); margin: 0;
}
p { margin: 0; color: var(--fg-2); text-wrap: pretty; }

.sign, .sublabel, .section-label {
  font-family: var(--font-sign);
  font-size: var(--t-sign-size); line-height: var(--t-sign-lh);
  letter-spacing: var(--t-sign-tracking);
  font-weight: 600; text-transform: uppercase;
  color: var(--fg-3);
}
.sign-strong {
  font-family: var(--font-sign);
  font-size: var(--t-sign-size); letter-spacing: var(--t-sign-tracking);
  font-weight: 800; text-transform: uppercase;
  color: var(--fg-accent);
}

.mono, .readout, .keybind {
  font-family: var(--font-mono);
  font-size: var(--t-mono-size); letter-spacing: var(--t-mono-tracking);
  font-weight: 500; color: var(--fg-2);
}
.readout-large {
  font-family: var(--font-mono); font-size: 22px;
  letter-spacing: 0.04em; font-weight: 700; color: var(--fg-accent);
  font-variant-numeric: tabular-nums;
}

a, .link {
  color: var(--fg-accent); text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--brass) 40%, transparent);
  transition: border-color 180ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
a:hover, .link:hover { border-bottom-color: var(--brass); }

em, .italic { font-style: normal; font-weight: 600; }
.italic-display {
  font-family: var(--font-display); font-weight: 400;
}

/* ============================================================
   BRAND PAGE CHROME — apply to the root of a brand-level
   surface (title screen, main menu, settings, achievements).
   Themes (theme-parlor etc.) layer ON TOP of this.
   ============================================================ */

.brand-room {
  background: var(--surface-page);
  background-image: var(--cribbage-holes);
  background-repeat: repeat;
  min-height: 100vh;
  position: relative;
}

/* PAGE CHROME BOUNDARY */

/* ============================================================
   SHARED DOUBLE SKUNK PAGE CHROME
   ------------------------------------------------------------
   Shared Double Skunk page chrome (kb-bar, nav, CTA buttons, footer).
   Dresses the ds_kb_bar / ds_nav components, so it only matters to the
   pages that render them: the guides, the learn chapters, the dev log
   and the updates feed.

   This used to be chrome.css, a second render-blocking request on every
   one of those pages. The tokens above and these rules always shipped
   together, so they are one file and one request now.

   The landing page is the exception. It renders its own <html> with its
   own hand-written, localized chrome, so it inlines everything ABOVE the
   boundary marker and none of this. `ds_tokens/1` does that split, on the
   marker line above, and raises at compile time if the line is gone.
   Moving a rule across that line changes what the landing page gets.
   ============================================================ */

* { box-sizing: border-box; }
/* Beats any component rule that sets display, so `hidden` always hides. */
[hidden] { display: none !important; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background: var(--skunk-ink);
  background-image: var(--cribbage-holes);
  background-size: 40px 40px;
  color: var(--fg-1);
  font-family: var(--font-body);
  min-height: 100vh;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
.wrap { max-width: 1040px; margin: 0 auto; padding: 0 32px; }

/* ---- Kerrberry domain bar ---- */
.kb-bar { background: #08070a; border-bottom: 1px solid var(--border-hair);
  font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.02em; color: var(--fg-4); }
.kb-bar-inner { max-width: 1040px; margin: 0 auto; padding: 8px 32px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.kb-sep { color: var(--fg-4); opacity: 0.5; }
.kb-here { color: var(--brass-glow); }
.kb-spacer { flex: 1; }
.kb-bar a { color: var(--fg-3); text-decoration: none; border-bottom: 1px dotted var(--fg-4); transition: color 160ms, border-color 160ms; }
.kb-bar a:hover { color: var(--chalk); border-bottom-color: var(--chalk-4); }

/* ---- Nav ---- */
.nav { position: sticky; top: 0; z-index: 50;
  background: color-mix(in oklch, var(--skunk-ink) 92%, transparent);
  backdrop-filter: blur(10px); border-bottom: 1px solid var(--border-hair); }
.nav-inner { max-width: 1040px; margin: 0 auto; padding: 12px 32px;
  display: flex; align-items: center; gap: 18px; position: relative; }
.nav-brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; }
.nav-brand img { width: 38px; height: 38px; display: block; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.6)); }
.nav-brand .nb-name { font-family: var(--font-display); font-size: 17px; color: var(--chalk); line-height: 1; }
.nav-spacer { flex: 1; }
.nav-link { font-family: var(--font-sign); font-weight: 800; font-size: 12px;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--fg-3);
  text-decoration: none; border-bottom: 1px dotted var(--fg-4); transition: color 160ms, border-color 160ms; }
.nav-link:hover { color: var(--chalk); border-bottom-color: var(--chalk-4); }
.nav-link[aria-current="page"] { color: var(--chalk); border-bottom: 2px solid var(--brass); }
.nav-cta { display: inline-flex; align-items: center; gap: 8px; padding: 10px 16px;
  border-radius: 10px; font-family: var(--font-sign); font-weight: 800; font-size: 12px;
  letter-spacing: 0.18em; text-transform: uppercase; text-decoration: none; border: 0; cursor: pointer;
  transition: transform 80ms, box-shadow 160ms, background 160ms, color 160ms; }
.nav-cta.pop { color: var(--chalk);
  background: linear-gradient(180deg, var(--brass-bright), var(--brass) 65%, var(--brass-deep));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.25), inset 0 -2px 0 rgba(0,0,0,0.30), 0 6px 14px -6px color-mix(in srgb, var(--brass) 55%, transparent); }
.nav-cta.pop:hover { transform: translateY(-1px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.30), inset 0 -2px 0 rgba(0,0,0,0.30), 0 10px 22px -6px color-mix(in srgb, var(--brass) 70%, transparent); }
.nav-cta:active { transform: translateY(1px); }
.nav-cta .star { color: var(--chalk); }

/* ---- Mobile menu ----
   Only ever visible under 720px, where .nav-link is hidden. The <details>
   element owns the open state, the keyboard, and the expanded/collapsed
   announcement, so the whole menu costs no script. */
.nav-menu { display: none; }
.nav-menu-toggle { display: inline-flex; align-items: center; gap: 9px; list-style: none;
  padding: 9px 13px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--chalk-4); color: var(--chalk);
  font-family: var(--font-sign); font-weight: 800; font-size: 12px;
  letter-spacing: 0.16em; text-transform: uppercase; }
.nav-menu-toggle::-webkit-details-marker { display: none; }
.nav-menu-toggle:focus-visible { outline: 2px solid var(--brass); outline-offset: 2px; }
.nav-menu[open] .nav-menu-toggle { border-color: var(--chalk); }
.nav-menu-glyph { width: 15px; height: 2px; background: currentColor;
  box-shadow: 0 -5px 0 currentColor, 0 5px 0 currentColor; }
.nav-menu-panel { position: absolute; right: 32px; top: calc(100% + 6px); z-index: 60;
  display: flex; flex-direction: column; min-width: 200px; padding: 8px;
  border-radius: 12px; background: var(--surface-base);
  border: 1px solid var(--border-hair); box-shadow: 0 18px 34px -12px rgba(0,0,0,0.8); }
.nav-menu-link { padding: 11px 12px; border-radius: 8px; border: 0; text-decoration: none; color: var(--fg-2);
  font-family: var(--font-sign); font-weight: 800; font-size: 13px;
  letter-spacing: 0.16em; text-transform: uppercase; }
.nav-menu-link:hover { background: var(--surface-raised); color: var(--chalk); }
.nav-menu-link[aria-current="page"] { color: var(--chalk); box-shadow: inset 2px 0 0 var(--brass); }

/* ---- CTA buttons ---- */
.cta { display: inline-flex; align-items: center; gap: 12px; padding: 16px 22px; border-radius: 12px;
  font-family: var(--font-sign); font-weight: 800; font-size: 13px; letter-spacing: 0.18em;
  text-transform: uppercase; text-decoration: none; border: 0; cursor: pointer; transition: transform 80ms, box-shadow 160ms; }
.cta.pop { color: var(--chalk);
  background: linear-gradient(180deg, var(--brass-bright), var(--brass) 60%, var(--brass-deep));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.30), inset 0 -2px 0 rgba(0,0,0,0.35), 0 10px 24px -8px color-mix(in srgb, var(--brass) 65%, transparent); }
.cta.pop:hover { transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.35), inset 0 -2px 0 rgba(0,0,0,0.35), 0 16px 32px -8px color-mix(in srgb, var(--brass) 75%, transparent); }
.cta:active { transform: translateY(1px); }
.cta .glyph { font-size: 16px; line-height: 1; }

/* ---- Footer ---- */
.foot { background: #08070a; border-top: 1px solid var(--border-hair); padding: 36px 0 32px; margin-top: 24px; }
.foot-inner { display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.foot-brand { display: inline-flex; align-items: center; gap: 12px; }
.foot-brand img { width: 32px; height: 32px; }
.foot-brand .fb-name { font-family: var(--font-display); font-size: 15px; color: var(--chalk); line-height: 1; }
.foot-brand .fb-by { font-family: var(--font-sign); font-weight: 800; font-size: 10px; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--fg-4); margin-top: 4px; display: block; line-height: 1; }
.foot-brand .fb-by a { color: var(--fg-3); text-decoration: none; border-bottom: 1px dotted var(--fg-4); }
.foot-brand .fb-by a:hover { color: var(--chalk); }
.foot-fine { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em; color: var(--fg-4); }

/* ---- Responsive ---- */
@media (max-width: 720px) {
  .nav-link { display: none; }
  .nav-menu { display: block; }
  /* backdrop-filter repaints a blurred copy of the page under the bar on
     every scroll frame, which a cheap Android feels. The header is opaque
     at this width, so there is nothing left to blur. */
  .nav { background: color-mix(in oklch, var(--skunk-ink) 92%, var(--skunk-ink-3));
    backdrop-filter: none; }
  /* Brand, menu and CTA have to share a 320px row. The medallion holds
     the brand on its own here; the wordmark would cost the menu its
     place, and on the landing page it is repeated three times the size
     in the hero directly below. Gutters stay at 32px so the header
     still lines up with the body content under it. */
  .nav-inner { padding: 10px 32px; gap: 12px; }
  .nav-brand img { width: 32px; height: 32px; }
  .nav-brand .nb-name { display: none; }
  .nav-cta { padding: 9px 12px; letter-spacing: 0.12em; }
}

/* The brand, the menu and the CTA still have to fit a 320px phone with a
   32px gutter, and `body { overflow-x: hidden }` would clip the CTA
   rather than let you scroll to it. This buys the last few pixels
   without touching 375px and up. */
@media (max-width: 360px) {
  .nav-inner { gap: 10px; }
  .nav-menu-toggle { padding: 9px 10px; gap: 7px; letter-spacing: 0.08em; }
  .nav-cta { padding: 9px 10px; gap: 6px; letter-spacing: 0.06em; }
}
