/* ==========================================================================
   Broken Branch — tokens.css · the shared spine
   --------------------------------------------------------------------------
   The house style in one file: palette, type law, the ambient layer (grain,
   lamplight, motes), and the shared chrome (skip-link, crumb, eyebrow,
   focus, reduced-motion). Link this FIRST in any page's <head> and the page
   inherits the whole Brokenbranch Lab look. Page-specific <style> blocks load
   after and override freely — this file is the floor, not the ceiling.

   One palette, two vocabularies: the canonical --color-* names (homepage, 404,
   the-ground) and the short --bark/--parchment/--ember names (the lab pages)
   are aliases over the SAME values. Either vocabulary works; nothing to rewrite.

   This file is also the seed of "Portfolio in a Box" — swap the values in
   :root and the voice stays while the identity becomes yours.
   ========================================================================== */

/* The two faces: serif = human voice, mono = machine voice.
   Self-hosted at /fonts/ (no third-party round-trip, no FOUT on the Fraunces
   hero). Google serves ONE variable woff2 per family/style/subset, so the
   weight RANGE (300 900 / 300 700) and the optical-size axis live inside each
   file. The 2 critical Fraunces latin weights are <link rel=preload>'d in the
   homepage <head>. Self-contained pages (aquarium, windowsill) repeat these
   @font-face rules inline since they don't link this file. */
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url('/fonts/fraunces-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url('/fonts/fraunces-italic-latinext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('/fonts/fraunces-normal-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('/fonts/fraunces-normal-latinext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/fonts/jetbrainsmono-normal-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('/fonts/jetbrainsmono-normal-latinext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url('/fonts/jetbrainsmono-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url('/fonts/jetbrainsmono-italic-latinext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   Design tokens
   -------------------------------------------------------------------------- */
:root {
    /* ground — bark & lamplight */
    --color-bg: #1c1510;
    --color-bg-elevated: #241b13;
    --color-bg-hover: #2b2117;
    --color-surface: #332719;
    --color-border: #3a2f26;
    --color-border-hover: #4a3b28;

    /* ink — parchment */
    --color-text: #ece1cc;
    --color-text-secondary: #b8a98c;
    --color-text-muted: #a0926f;   /* AA 4.5:1+ on all bark surfaces (was #847660, ~3.3:1) */

    /* alive / safe — moss (the brand green; tank plants, LIVE pills, the dial) */
    --color-primary: #8aa86b;
    --color-primary-hover: #9fbd80;
    --color-primary-muted: rgba(138, 168, 107, 0.15);

    /* "this matters" — gold (night fish, wordmark glints) */
    --color-accent: #d9a441;
    --color-accent-hover: #e3b341;

    /* workshop semantics */
    --color-ember: #e8833a;        /* load-bearing accent: links, CTAs, stats, the lit word */
    --color-ember-bright: #f09048;
    --color-brass: #c9a86a;        /* pins, eyebrows, section numbers, chrome */
    --color-clay: #c4744a;         /* warm warning */
    --color-wax: #a84b3a;          /* the stamp */
    --color-slate: #8fa3ad;        /* cool / quiet / info */
    --color-ash: #6f6557;          /* dormant */

    /* organic colors — warm beachhead, kept */
    --color-bark: #1a1410;
    --color-bark-light: #2a1f14;
    --color-moss: #4a6741;
    --color-canopy: rgba(138, 168, 107, 0.04);
    --color-fog: rgba(236, 225, 204, 0.03);
    --color-warmth: rgba(42, 31, 20, 0.15);

    /* typography */
    --font-sans: 'Fraunces', Georgia, serif;
    --font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
    --font-serif: 'Fraunces', Georgia, serif;

    /* spacing */
    --space-xs: 0.25rem;
    --space-sm: 0.5rem;
    --space-md: 1rem;
    --space-lg: 1.5rem;
    --space-xl: 2rem;
    --space-2xl: 3rem;
    --space-3xl: 4rem;
    --space-4xl: 6rem;

    /* border radius */
    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 10px;
    --radius-xl: 12px;

    /* transitions — organic cubic-bezier for natural feel */
    --ease-organic: cubic-bezier(0.25, 0.46, 0.45, 0.94);
    --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
    --transition-fast: 150ms var(--ease-organic);
    --transition-base: 250ms var(--ease-organic);
    --transition-slow: 500ms var(--ease-organic);

    /* layout */
    --max-width: 1000px;
    --header-height: 72px;

    /* ----- short aliases: the lab-page vocabulary, same values ----- */
    --bark: var(--color-bg);
    --bark-2: var(--color-bg-elevated);
    --panel: var(--color-bg-hover);
    --panel-2: var(--color-surface);
    --line: var(--color-border-hover);
    --parchment: var(--color-text);
    --parchment-dim: var(--color-text-secondary);
    --faint: var(--color-text-muted);
    --ember: var(--color-ember);
    --gold: var(--color-accent);
    --moss: var(--color-primary);
    --clay: var(--color-clay);
    --wax: var(--color-wax);
    --brass: var(--color-brass);
    --slate: var(--color-slate);
    --ash: var(--color-ash);
    --serif: var(--font-serif);
    --mono: var(--font-mono);
}

/* --------------------------------------------------------------------------
   Reset & base
   -------------------------------------------------------------------------- */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html {
    scroll-behavior: smooth;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

body {
    font-family: var(--font-sans);
    font-size: 17px;
    font-weight: 360;
    line-height: 1.58;
    color: var(--color-text);
    background-color: var(--color-bg);
    min-height: 100vh;
    overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
ul { list-style: none; }
img { max-width: 100%; height: auto; }

/* --------------------------------------------------------------------------
   Ambient layer — grain, lamplight, motes
   -------------------------------------------------------------------------- */

/* SVG fractal-noise grain — patina over the whole workshop */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 9999;
    opacity: 0.35;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
    background-repeat: repeat;
    background-size: 160px 160px;
}

/* Lamplight — radial washes anchored top + corner. The work lamp over the bench.
   Add <div class="lamplight"></div> as the first child of <body>. */
.lamplight {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background:
        radial-gradient(ellipse 70% 38% at 50% -6%, rgba(232, 166, 74, 0.13), transparent 70%),
        radial-gradient(ellipse 45% 30% at 12% 110%, rgba(138, 168, 107, 0.05), transparent 70%);
}

/* Dust motes — the bench air. Namespaced (.motes i) so they can never collide
   with the aquarium's runtime-generated .mote tank particles.
   Add <div class="motes"><i></i>... ×8</div> to opt in. */
.motes i {
    position: fixed;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: rgba(232, 166, 74, 0.45);
    filter: blur(1.5px);
    pointer-events: none;
    z-index: 1;
    animation: moteDrift 16s ease-in-out infinite alternate;
}
.motes i:nth-child(1) { top: 18%; left: 12%; }
.motes i:nth-child(2) { top: 34%; left: 78%; animation-delay: -4s; }
.motes i:nth-child(3) { top: 55%; left: 28%; animation-delay: -8s; }
.motes i:nth-child(4) { top: 70%; left: 64%; animation-delay: -2s; }
.motes i:nth-child(5) { top: 26%; left: 46%; animation-delay: -11s; }
.motes i:nth-child(6) { top: 82%; left: 14%; animation-delay: -6s; }
.motes i:nth-child(7) { top: 44%; left: 90%; animation-delay: -9s; }
.motes i:nth-child(8) { top: 64%; left: 6%; animation-delay: -13s; }
@keyframes moteDrift {
    from { transform: translate(0, 0); }
    to { transform: translate(14px, -22px); }
}

/* --------------------------------------------------------------------------
   Shared chrome — skip-link, crumb, eyebrow, focus
   -------------------------------------------------------------------------- */

/* Skip-to-content link — visible only when focused via keyboard.
   Add <a href="#main-content" class="skip-link">Skip to content</a> as the
   first focusable element, and id="main-content" on the main landmark. */
.skip-link {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1000;
    transform: translateY(-120%);
    padding: 0.6rem 1rem;
    background: var(--color-primary);
    color: var(--color-bg);
    font-family: var(--font-mono);
    font-size: 0.85rem;
    font-weight: 600;
    text-decoration: none;
    border-bottom-right-radius: 6px;
    transition: transform 0.15s ease-out;
}
.skip-link:focus {
    transform: translateY(0);
    outline: 2px solid var(--color-bg);
    outline-offset: -4px;
}

/* Breadcrumb — the way back. Lab pages: "← the lab · brokenbranch.dev".
   Top-level docs: "← brokenbranch.dev". */
.crumb {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: .22em;
    text-transform: uppercase;
}
.crumb a { color: var(--color-text-muted); text-decoration: none; }
.crumb a:hover { color: var(--color-brass); }

/* Eyebrow — the brass section rule. */
.eyebrow {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: .42em;
    text-transform: uppercase;
    color: var(--color-brass);
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 34px;
}
.eyebrow::before, .eyebrow::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--color-border-hover);
}

/* Focus-visible — keyboard navigation accessibility */
:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}
a:focus-visible,
button:focus-visible,
.btn:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   Reduced-motion baseline — honor the OS preference everywhere
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .motes i { animation: none; }
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* Hide motes on small screens — they're bench atmosphere, not content. */
@media (max-width: 720px) {
    .motes i { display: none; }
}
