/* ============================================================================
   OakTree Games — Master Stylesheet
   Retro pixel-art aesthetic + modern sleek interaction layer
   ============================================================================ */

/* ---------- TOKENS ---------- */
:root {
    /* Brand palette — deep cosmic + oak forest */
    --bg-void:        #04060d;
    --bg-deep:        #0a0e1a;
    --bg-panel:       #111a2e;
    --bg-panel-hi:    #1a2540;
    --bg-elev:        #1f2c4a;

    --line-faint:     rgba(124, 192, 134, 0.12);
    --line-soft:      rgba(124, 192, 134, 0.22);
    --line-strong:    rgba(124, 192, 134, 0.48);

    --text-pri:       #e6efe9;
    --text-sec:       #9fb1a4;
    --text-mute:      #5e7068;

    --accent-oak:     #7cc086;          /* Brand green (leaves) */
    --accent-oak-d:   #4f8a5b;
    --accent-bark:    #8b5a2b;          /* Bark brown */
    --accent-cosmic:  #ffd86b;          /* Sun gold */
    --accent-aurora:  #66e0c6;          /* Aria/quantum cyan */
    --accent-rose:    #ff6b8b;          /* Special/special tier */
    --accent-violet:  #a583ff;
    --accent-amber:   #ffa845;
    --accent-red:     #ff6b6b;

    /* Tier colors — match in-game tiers */
    --tier-0: #9fb1a4;
    --tier-1: #c4794a;   /* Copper */
    --tier-2: #b0b3b8;   /* Iron */
    --tier-3: #4f5a6b;   /* Steel */
    --tier-4: #66e0c6;   /* Electronics */
    --tier-5: #a583ff;   /* Quantum */
    --tier-6: #ffd86b;   /* Planetary */
    --tier-7: #ff6b8b;   /* Stellar */

    /* Spacing scale */
    --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;
    --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;
    --sp-7: 48px; --sp-8: 64px; --sp-9: 96px; --sp-10: 128px;

    --radius: 0;            /* Pixel-art = hard corners */
    --radius-soft: 4px;

    /* All visible copy uses one of two pixel fonts so the site reads as
       a cohesive retro-space artifact:
         --font-pixel   chunky 8-bit headline / label font (Press Start 2P)
         --font-display same chunky font for hero headlines
         --font-body    readable CRT-style pixel font for paragraphs (VT323)
                        — Press Start 2P is too dense for long copy, VT323
                        keeps the pixel feel without sacrificing legibility
         --font-mono    JetBrains Mono kept ONLY for inline `code` blocks
                        where it actually helps read snippets correctly. */
    --font-pixel:   'Press Start 2P', 'VT323', monospace;
    --font-display: 'Press Start 2P', 'VT323', monospace;
    --font-body:    'VT323', 'Press Start 2P', ui-monospace, monospace;
    --font-mono:    'JetBrains Mono', ui-monospace, monospace;

    --shadow-pixel-sm: 0 2px 0 0 rgba(0,0,0,0.35);
    --shadow-pixel-md: 0 4px 0 0 rgba(0,0,0,0.45);
    --shadow-pixel-lg: 0 8px 0 0 rgba(0,0,0,0.55), 0 0 0 1px var(--line-soft);

    --glow-oak:  0 0 24px rgba(124, 192, 134, 0.35);
    --glow-cosm: 0 0 32px rgba(255, 216, 107, 0.40);
}

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

html {
    scroll-behavior: smooth;
    /* anchor jumps (e.g. /game.html#endgame) land directly under the
       fixed nav instead of being hidden beneath it */
    scroll-padding-top: var(--nav-h, 68px);
    overflow-x: hidden;
    background: var(--bg-void);
}

body {
    font-family: var(--font-body);
    /* VT323 reads smaller than Inter at the same px, so we bump the base
       size to keep perceived text size comparable to the previous design.
       Headings and labels use their own pixel font + explicit sizes, so
       they're unaffected by this bump. */
    font-size: 19px;
    line-height: 1.5;
    letter-spacing: 0.01em;
    color: var(--text-pri);
    /* Body background MUST be transparent so the .cosmos-canvas (positioned
       at z-index:-1) is visible behind body content. The html element still
       paints `--bg-void` so the page never flashes white. */
    background: transparent;
    overflow-x: hidden;
    min-height: 100vh;
    image-rendering: pixelated;
    -webkit-font-smoothing: antialiased;
    /* Top offset so content doesn't slide under the fixed nav.
       Matches .nav height (14px padding × 2 + ~36px logo). Tuned by eye. */
    padding-top: var(--nav-h, 68px);
}

img {
    image-rendering: pixelated;
    image-rendering: crisp-edges;
    max-width: 100%;
    height: auto;
    display: block;
}

a {
    color: var(--accent-oak);
    text-decoration: none;
    transition: color 200ms ease;
}
a:hover { color: var(--accent-cosmic); }

button {
    font-family: inherit;
    cursor: pointer;
    border: none;
    background: none;
    color: inherit;
}

::selection {
    background: var(--accent-oak);
    color: var(--bg-void);
}

/* ---------- COSMIC BACKDROP ---------- */
.cosmos {
    position: fixed;
    inset: 0;
    z-index: -10;
    pointer-events: none;
    background:
        radial-gradient(ellipse at 25% 15%, rgba(124,192,134,0.10), transparent 50%),
        radial-gradient(ellipse at 80% 70%, rgba(165,131,255,0.10), transparent 55%),
        radial-gradient(ellipse at 50% 95%, rgba(255,216,107,0.06), transparent 60%),
        linear-gradient(180deg, #04060d 0%, #0a0e1a 60%, #04060d 100%);
}

.cosmos::before,
.cosmos::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image:
        radial-gradient(1px 1px at 23% 12%, #fff, transparent),
        radial-gradient(1px 1px at 67% 8%,  #c9e0ff, transparent),
        radial-gradient(1px 1px at 88% 33%, #fff, transparent),
        radial-gradient(2px 2px at 12% 47%, #fff8c4, transparent),
        radial-gradient(1px 1px at 41% 64%, #ffd86b, transparent),
        radial-gradient(1px 1px at 79% 81%, #fff, transparent),
        radial-gradient(1px 1px at 55% 25%, #b3e0ff, transparent),
        radial-gradient(1px 1px at 8% 78%,  #fff, transparent),
        radial-gradient(2px 2px at 91% 53%, #fff, transparent),
        radial-gradient(1px 1px at 33% 92%, #b1ffc6, transparent);
    background-size: 1100px 900px;
    animation: drift-stars 240s linear infinite;
    opacity: 0.85;
}
.cosmos::after {
    background-size: 700px 600px;
    animation-duration: 360s;
    animation-direction: reverse;
    opacity: 0.55;
}

@keyframes drift-stars {
    from { transform: translate3d(0,0,0); }
    to   { transform: translate3d(-800px,-600px,0); }
}

/* ---------- NAVIGATION ----------
   The body has overflow-x: hidden (and so does html) — and that combination
   silently disables `position: sticky` in every browser. Use `fixed` instead
   and offset the body with padding-top: var(--nav-h) so content starts below
   the locked bar. The nav is always reachable, even mid-page-scroll.
   !important on the position properties so a stale cached stylesheet (or any
   theme-level override) can't accidentally revert to a sticky/static layout. */
.nav,
html .nav,
header.nav {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    z-index: 100;
    background: rgba(4, 6, 13, 0.78);
    backdrop-filter: saturate(160%) blur(14px);
    -webkit-backdrop-filter: saturate(160%) blur(14px);
    border-bottom: 1px solid var(--line-faint);
    transition: border-color 300ms ease, background 300ms ease;
}
.nav.scrolled {
    background: rgba(4, 6, 13, 0.94);
    border-bottom-color: var(--line-soft);
}

.nav-inner {
    max-width: 1280px;
    margin: 0 auto;
    padding: 14px var(--sp-5);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-5);
}

.nav-brand {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    color: var(--text-pri);
    font-family: var(--font-display);
    letter-spacing: 0.02em;
    font-size: 16px;
    text-transform: uppercase;
}
.nav-brand img {
    width: 36px;
    height: 36px;
    border: 1px solid var(--line-soft);
    box-shadow: var(--shadow-pixel-sm);
}

.nav-links {
    display: flex;
    align-items: center;
    gap: 4px;
    list-style: none;
}
.nav-links a {
    display: inline-block;
    padding: 8px 14px;
    color: var(--text-sec);
    font-family: var(--font-pixel);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border: 1px solid transparent;
    transition: color 180ms ease, border-color 180ms ease, background 180ms ease;
}
.nav-links a:hover,
.nav-links a.active {
    color: var(--text-pri);
    border-color: var(--line-soft);
    background: rgba(124, 192, 134, 0.06);
}

.nav-cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    background: var(--accent-oak);
    color: var(--bg-void) !important;
    font-family: var(--font-pixel);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border: 1px solid var(--accent-oak);
    box-shadow: var(--shadow-pixel-sm);
    transition: transform 120ms ease, box-shadow 120ms ease, background 180ms ease;
}
.nav-cta:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-pixel-md);
    background: #8fd29a;
}
.nav-cta:active {
    transform: translateY(2px);
    box-shadow: none;
}

.nav-burger {
    display: none;
    width: 38px;
    height: 38px;
    padding: 8px;
    color: var(--text-pri);
    border: 1px solid var(--line-soft);
    background: rgba(255,255,255,0.02);
}
.nav-burger svg { width: 100%; height: 100%; }

@media (max-width: 880px) {
    /* Closed state: hide the desktop nav controls; show burger only */
    .nav-links, .nav-cta, .nav-tools { display: none; }
    .nav-burger { display: inline-flex; align-items: center; justify-content: center; }

    /* Open state: nav-inner flex-wraps so brand + burger stay in the
       top row, and links / cta / tools wrap below as a stacked drawer.
       Background extends the whole nav bar so the drawer reads as
       one continuous opaque panel. */
    .nav.is-open {
        background: rgba(4, 6, 13, 0.98);
        box-shadow: 0 16px 32px rgba(0, 0, 0, 0.55);
    }
    .nav.is-open .nav-inner {
        flex-wrap: wrap;
        padding-bottom: var(--sp-3);
    }
    .nav.is-open .nav-links,
    .nav.is-open .nav-cta,
    .nav.is-open .nav-tools {
        display: flex;
        flex: 1 1 100%;
        animation: drawer-down 220ms cubic-bezier(.21,.92,.32,1);
    }
    @keyframes drawer-down {
        from { transform: translateY(-6px); opacity: 0; }
        to   { transform: translateY(0);    opacity: 1; }
    }
    .nav.is-open .nav-links {
        flex-direction: column;
        gap: 2px;
        padding: var(--sp-3) 0;
        max-height: calc(100vh - var(--nav-h, 68px) - 120px);
        overflow-y: auto;
        border-top: 1px dashed var(--line-faint);
    }
    .nav.is-open .nav-links > li {
        width: 100%;
        list-style: none;
    }
    .nav.is-open .nav-tools {
        gap: 8px;
        justify-content: center;
        padding: var(--sp-3) 0;
        order: 99;            /* sink tools to the bottom of the drawer */
    }
    .nav.is-open .nav-cta {
        justify-content: center;
        margin: var(--sp-3) 0 0;
        order: 100;
    }
}

/* ---------- LAYOUT PRIMITIVES ---------- */
.container {
    max-width: 1280px;
    margin: 0 auto;
    padding: 0 var(--sp-5);
}
.container-narrow {
    max-width: 920px;
    margin: 0 auto;
    padding: 0 var(--sp-5);
}

.section {
    padding: var(--sp-9) 0;
    position: relative;
}
.section-tight { padding: var(--sp-7) 0; }

.section-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    font-family: var(--font-pixel);
    font-size: 9px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent-oak);
    background: rgba(124,192,134,0.10);
    border: 1px solid var(--line-soft);
    margin-bottom: var(--sp-4);
}
.section-eyebrow::before {
    content: "";
    width: 6px; height: 6px;
    background: var(--accent-oak);
    box-shadow: 0 0 8px var(--accent-oak);
}

h1, h2, h3, h4 {
    font-family: var(--font-display);
    color: var(--text-pri);
    line-height: 1.15;
    letter-spacing: 0.01em;
    text-transform: uppercase;
}
h1 { font-size: clamp(36px, 6vw, 72px); }
h2 { font-size: clamp(28px, 4vw, 48px); }
h3 { font-size: clamp(20px, 2.4vw, 28px); }
h4 { font-size: clamp(14px, 1.4vw, 18px); }

p {
    color: var(--text-sec);
    max-width: 65ch;
}
strong { color: var(--text-pri); font-weight: 600; }
em { color: var(--accent-aurora); font-style: normal; }

/* Mono inline */
code, kbd {
    font-family: var(--font-mono);
    font-size: 0.9em;
    padding: 1px 6px;
    background: var(--bg-panel);
    border: 1px solid var(--line-faint);
    color: var(--accent-aurora);
}

/* ---------- BUTTONS ---------- */
.btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 14px 22px;
    font-family: var(--font-pixel);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border: 1px solid var(--accent-oak);
    background: var(--accent-oak);
    color: var(--bg-void) !important;
    box-shadow: var(--shadow-pixel-md);
    transition: transform 120ms ease, box-shadow 120ms ease, background 180ms ease;
    cursor: pointer;
}
.btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 0 0 rgba(0,0,0,0.45), var(--glow-oak);
    background: #8fd29a;
}
.btn:active {
    transform: translateY(4px);
    box-shadow: none;
}
.btn-ghost {
    background: transparent;
    color: var(--text-pri) !important;
    border-color: var(--line-soft);
    box-shadow: var(--shadow-pixel-sm);
}
.btn-ghost:hover {
    background: rgba(124,192,134,0.08);
    border-color: var(--accent-oak);
    color: var(--accent-oak) !important;
}
.btn-gold {
    background: var(--accent-cosmic);
    color: var(--bg-void) !important;
    border-color: var(--accent-cosmic);
}
.btn-gold:hover { background: #ffe695; box-shadow: 0 6px 0 0 rgba(0,0,0,0.45), var(--glow-cosm); }

/* ---------- CARDS / PANELS ---------- */
.panel {
    background: var(--bg-panel);
    border: 1px solid var(--line-faint);
    padding: var(--sp-5);
    position: relative;
    /* snappier hover: transform reacts immediately, color/shadow are
       slightly more relaxed for a softer settle */
    transition: border-color 200ms ease,
                transform 120ms cubic-bezier(.16, 1, .32, 1),
                box-shadow 200ms ease;
}
.panel:hover {
    border-color: var(--line-soft);
    transform: translateY(-2px);
    box-shadow: var(--shadow-pixel-md);
}
.panel-flush { padding: 0; }
.panel-elev { background: var(--bg-panel-hi); }

.panel-corner-tape::before,
.panel-corner-tape::after {
    content: "";
    position: absolute;
    width: 14px; height: 14px;
    border: 2px solid var(--accent-oak);
}
.panel-corner-tape::before { top: -1px; left: -1px;  border-right: none;  border-bottom: none; }
.panel-corner-tape::after  { bottom: -1px; right: -1px; border-left: none; border-top: none; }

/* ---------- TAGS / CHIPS ---------- */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    font-family: var(--font-pixel);
    font-size: 9px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    background: rgba(124,192,134,0.10);
    border: 1px solid var(--line-soft);
    color: var(--accent-oak);
}
.chip[data-tier="0"] { background: rgba(159,177,164,0.12); border-color: rgba(159,177,164,0.4); color: var(--tier-0); }
.chip[data-tier="1"] { background: rgba(196,121,74,0.12);  border-color: rgba(196,121,74,0.4);  color: var(--tier-1); }
.chip[data-tier="2"] { background: rgba(176,179,184,0.14); border-color: rgba(176,179,184,0.4); color: var(--tier-2); }
.chip[data-tier="3"] { background: rgba(79,90,107,0.18);   border-color: rgba(79,90,107,0.5);   color: #a0b0c5; }
.chip[data-tier="4"] { background: rgba(102,224,198,0.10); border-color: rgba(102,224,198,0.4); color: var(--tier-4); }
.chip[data-tier="5"] { background: rgba(165,131,255,0.10); border-color: rgba(165,131,255,0.4); color: var(--tier-5); }
.chip[data-tier="6"] { background: rgba(255,216,107,0.10); border-color: rgba(255,216,107,0.4); color: var(--tier-6); }
.chip[data-tier="7"] { background: rgba(255,107,139,0.10); border-color: rgba(255,107,139,0.4); color: var(--tier-7); }

/* ---------- FOOTER ---------- */
.footer {
    margin-top: var(--sp-9);
    padding: var(--sp-8) 0 var(--sp-6);
    border-top: 1px solid var(--line-faint);
    background: linear-gradient(180deg, transparent, rgba(0,0,0,0.4));
}
.footer-grid {
    display: grid;
    grid-template-columns: 1.4fr 1fr 1fr 1fr;
    gap: var(--sp-6);
}
@media (max-width: 720px) {
    .footer-grid { grid-template-columns: 1fr 1fr; }
}
.footer h4 {
    font-family: var(--font-pixel);
    font-size: 10px;
    color: var(--text-pri);
    letter-spacing: 0.08em;
    margin-bottom: var(--sp-3);
}
.footer ul { list-style: none; }
.footer li { margin: 4px 0; }
.footer a { color: var(--text-sec); font-size: 14px; }
.footer a:hover { color: var(--accent-oak); }
.footer-bottom {
    margin-top: var(--sp-7);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--line-faint);
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-4);
    justify-content: space-between;
    align-items: center;
    color: var(--text-mute);
    font-size: 13px;
}
.footer-mark {
    display: flex; align-items: center; gap: 10px;
    font-family: var(--font-display);
    color: var(--text-pri);
    font-size: 14px;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}
.footer-mark img { width: 28px; height: 28px; }
.footer-blurb {
    color: var(--text-sec);
    margin: var(--sp-3) 0 var(--sp-4);
    font-size: 13px;
    max-width: 36ch;
}

/* ---------- SOCIAL ICONS ---------- */
.social-row {
    display: flex; gap: 8px; margin-top: var(--sp-3);
}
.social {
    width: 36px; height: 36px;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--bg-panel);
    border: 1px solid var(--line-soft);
    color: var(--text-sec);
    transition: transform 160ms ease, border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.social:hover {
    transform: translateY(-2px);
    background: rgba(124,192,134,0.12);
    border-color: var(--accent-oak);
    color: var(--accent-oak);
}
.social svg { width: 16px; height: 16px; fill: currentColor; }

/* ---------- SCROLL-IN ANIMATIONS ----------
   Timing tuned for a "discovery" feel: long enough to read as a deliberate
   reveal, gentle cubic-bezier ease-out so the motion settles instead of
   snapping. Per-type rules below override duration as needed.
   Tuned slower (≈1200ms) after user feedback that 900ms still felt rushed. */
.reveal {
    opacity: 0;
    transform: translateY(36px);
    transition: opacity 1200ms cubic-bezier(.21,.92,.32,1),
                transform 1200ms cubic-bezier(.21,.92,.32,1);
    will-change: opacity, transform;
}
.reveal.is-visible { opacity: 1; transform: translateY(0); }
.reveal[data-delay="100"].is-visible { transition-delay: 150ms; }
.reveal[data-delay="200"].is-visible { transition-delay: 300ms; }
.reveal[data-delay="300"].is-visible { transition-delay: 450ms; }
.reveal[data-delay="400"].is-visible { transition-delay: 600ms; }
.reveal[data-delay="500"].is-visible { transition-delay: 750ms; }

@media (prefers-reduced-motion: reduce) {
    .reveal { opacity: 1; transform: none; }
    /* Tier-stack segments use a translateX(-12px) initial state which
       is animated in by the IntersectionObserver. Reduced-motion users
       disable the observer animation, leaving segments shifted left.
       Force them to their visible state here so the layout is correct
       even without animation. Same belt-and-suspenders for cascade. */
    .tier-stack-segment,
    .reveal[data-anim-from="cascade"] > * {
        opacity: 1 !important;
        transform: none !important;
    }
    *, ::before, ::after { animation: none !important; transition: none !important; }
    .cosmos::before, .cosmos::after { animation: none !important; }
}

/* ---------- PIXEL DIVIDER ---------- */
.pixel-divider {
    height: 4px;
    margin: var(--sp-4) auto;
    width: 96px;
    background-image:
        linear-gradient(90deg,
            var(--accent-oak) 0 16px,
            transparent 16px 24px,
            var(--accent-oak) 24px 40px,
            transparent 40px 48px,
            var(--accent-oak) 48px 64px,
            transparent 64px 72px,
            var(--accent-oak) 72px 88px,
            transparent 88px);
}
.pixel-divider-gold { filter: hue-rotate(50deg) brightness(1.4) saturate(1.3); }

/* ---------- DISCOVERY-FEEL SECTION INTROS ----------
   When a centered section intro (.reveal.text-center) becomes visible,
   stagger the eyebrow → h2 → paragraph so the section reads as if it's
   building itself in front of the user rather than appearing all at once.
   Inner pixel-divider draws itself left-to-right via clip-path. */
.reveal.text-center .section-eyebrow,
.reveal.text-center > h2,
.reveal.text-center > p,
.reveal.text-center > .pixel-divider {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 900ms cubic-bezier(.16, 1, .32, 1),
                transform 900ms cubic-bezier(.16, 1, .32, 1),
                clip-path 900ms cubic-bezier(.16, 1, .32, 1);
}
.reveal.text-center.is-visible .section-eyebrow {
    opacity: 1; transform: none;
    transition-delay: 80ms;
}
.reveal.text-center.is-visible > h2 {
    opacity: 1; transform: none;
    transition-delay: 240ms;
}
.reveal.text-center.is-visible > p {
    opacity: 1; transform: none;
    transition-delay: 400ms;
}
.reveal.text-center > .pixel-divider {
    clip-path: inset(0 100% 0 0);
}
.reveal.text-center.is-visible > .pixel-divider {
    opacity: 1; transform: none;
    clip-path: inset(0 0 0 0);
    transition-delay: 320ms;
    transition-duration: 1100ms;
}
@media (prefers-reduced-motion: reduce) {
    .reveal.text-center .section-eyebrow,
    .reveal.text-center > h2,
    .reveal.text-center > p,
    .reveal.text-center > .pixel-divider {
        opacity: 1 !important;
        transform: none !important;
        clip-path: none !important;
    }
}

/* Section-eyebrow gains a subtle pulse on entrance — draws the eye to
   the start of a new section. Plays once after reveal completes. */
@keyframes section-eyebrow-flash {
    0%   { box-shadow: 0 0 0 0 rgba(102, 224, 198, 0); }
    20%  { box-shadow: 0 0 18px 0 rgba(102, 224, 198, 0.35); }
    100% { box-shadow: 0 0 0 0 rgba(102, 224, 198, 0); }
}
.reveal.text-center.is-visible .section-eyebrow {
    animation: section-eyebrow-flash 1600ms ease-out 600ms 1;
}
@media (prefers-reduced-motion: reduce) {
    .reveal.text-center.is-visible .section-eyebrow { animation: none; }
}

/* ---------- UTILITY ---------- */
.text-center { text-align: center; }
.text-mute { color: var(--text-mute); }
.text-sec  { color: var(--text-sec); }
.font-pixel { font-family: var(--font-pixel); letter-spacing: 0.04em; }
.font-mono  { font-family: var(--font-mono); }
.mt-0 { margin-top: 0; } .mt-3 { margin-top: var(--sp-3); } .mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); } .mt-6 { margin-top: var(--sp-6); } .mt-7 { margin-top: var(--sp-7); }
.mb-3 { margin-bottom: var(--sp-3); } .mb-4 { margin-bottom: var(--sp-4); }
.mb-5 { margin-bottom: var(--sp-5); } .mb-6 { margin-bottom: var(--sp-6); }
.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.items-center { align-items: center; }
.gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); }
.gap-4 { gap: var(--sp-4); }
.gap-5 { gap: var(--sp-5); }

/* ============================================================================
   EASTER EGG · BLUEPRINT MODE
   Triggered by the Konami code in js/easter-eggs.js. Recolors the page to an
   engineer's blueprint — cyan-on-deep-blue, with a faint grid overlay and a
   subtle scanline. Pure cosmetic; nothing about the layout changes.
   ============================================================================ */
html.blueprint-mode {
    filter: hue-rotate(165deg) saturate(1.4) contrast(1.05);
}
html.blueprint-mode body {
    position: relative;
}
html.blueprint-mode body::before {
    /* faint engineering grid overlay */
    content: "";
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 9990;
    background-image:
        linear-gradient(rgba(102,224,198,0.06) 1px, transparent 1px),
        linear-gradient(90deg, rgba(102,224,198,0.06) 1px, transparent 1px);
    background-size: 32px 32px;
    mix-blend-mode: lighten;
}
html.blueprint-mode body::after {
    /* corner stamp */
    content: "◆ BLUEPRINT MODE · KONAMI ⨯";
    position: fixed;
    top: 12px; right: 12px;
    font-family: var(--font-pixel);
    font-size: 9px;
    letter-spacing: 0.12em;
    color: rgba(102,224,198,0.7);
    background: rgba(4,6,13,0.85);
    padding: 6px 9px;
    border: 1px solid rgba(102,224,198,0.5);
    z-index: 9999;
    pointer-events: none;
}

/* ============================================================================
   ANIMATIONS — folded in 2026-05-14 (Cloudflare Pages rejects new files)
   Originally css/animations.css. Same content; inlined to deploy cleanly.
   ============================================================================ */
/* ============================================================================
   animations.css — Cosmic Scale website
   ----------------------------------------------------------------------------
   Adds opt-in scroll-triggered animations on top of the existing .reveal
   IntersectionObserver in js/main.js.

   USAGE:
     <div class="reveal" data-anim-from="left">…</div>
     <div class="reveal" data-anim-from="right">…</div>
     <div class="reveal" data-anim-from="up">…</div>          ← default if omitted
     <div class="reveal" data-anim-from="zoom">…</div>
     <div class="reveal" data-anim-from="cascade">…</div>     ← children stagger
     <div class="reveal" data-anim-from="pixel-pop">…</div>   ← stepped pixel scale-in

   PRINCIPLES:
     · Pixel-art aesthetic: stepped easing, no smooth cubic-bezier curves.
     · Performance: only transform + opacity, both GPU-cheap.
     · Respect prefers-reduced-motion (handled by base .reveal rule).
     · No layout shift on initial paint — animations only DELTA from final
       position, so the page reads correctly even pre-JS.

   The existing js/main.js applies .is-visible when an element scrolls into
   view; these rules pin the FROM state via data-anim-from and animate to
   the natural rest state when .is-visible flips on.
   ============================================================================ */

/* All directional reveals share the same easing & duration so they
   feel like one system. cubic-bezier(.16, 1, .32, 1) is the "expo
   ease-out" curve — fast start, slow settle, satisfying landing.
   Durations tuned after iterations: 1300ms reads as a deliberate
   reveal at scroll-reading pace without dragging.
   Steps-based opacity replaced with the same ease so the fade reads
   smoothly even on heavy-text blocks. */

/* ─── FROM-LEFT ─────────────────────────────────────────────────────── */
.reveal[data-anim-from="left"] {
    opacity: 0;
    transform: translateX(-64px);
    transition: opacity 1300ms cubic-bezier(.16, 1, .32, 1),
                transform 1300ms cubic-bezier(.16, 1, .32, 1);
}
.reveal[data-anim-from="left"].is-visible {
    opacity: 1;
    transform: translateX(0);
}

/* ─── FROM-RIGHT ────────────────────────────────────────────────────── */
.reveal[data-anim-from="right"] {
    opacity: 0;
    transform: translateX(64px);
    transition: opacity 1300ms cubic-bezier(.16, 1, .32, 1),
                transform 1300ms cubic-bezier(.16, 1, .32, 1);
}
.reveal[data-anim-from="right"].is-visible {
    opacity: 1;
    transform: translateX(0);
}

/* ─── FROM-UP (default) ─ overrides .reveal's existing translateY ──── */
.reveal[data-anim-from="up"] {
    opacity: 0;
    transform: translateY(48px);
    transition: opacity 1300ms cubic-bezier(.16, 1, .32, 1),
                transform 1300ms cubic-bezier(.16, 1, .32, 1);
}
.reveal[data-anim-from="up"].is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── FROM-DOWN (rare — for sticky-style descending elements) ─────── */
.reveal[data-anim-from="down"] {
    opacity: 0;
    transform: translateY(-48px);
    transition: opacity 1300ms cubic-bezier(.16, 1, .32, 1),
                transform 1300ms cubic-bezier(.16, 1, .32, 1);
}
.reveal[data-anim-from="down"].is-visible {
    opacity: 1;
    transform: translateY(0);
}

/* ─── ZOOM (smooth scale-in) ────────────────────────────────────────── */
.reveal[data-anim-from="zoom"] {
    opacity: 0;
    transform: scale(0.86);
    transition: opacity 1100ms cubic-bezier(.16, 1, .32, 1),
                transform 1100ms cubic-bezier(.16, 1, .32, 1);
}
.reveal[data-anim-from="zoom"].is-visible {
    opacity: 1;
    transform: scale(1);
}

/* ─── PIXEL-POP — discrete pixel-art snap, kept stepped on purpose ─── */
.reveal[data-anim-from="pixel-pop"] {
    opacity: 0;
    transform: scale(0.5) translateY(8px);
    transition: opacity 600ms steps(6, end),
                transform 600ms steps(6, end);
}
.reveal[data-anim-from="pixel-pop"].is-visible {
    opacity: 1;
    transform: scale(1) translateY(0);
}

/* ─── CASCADE — parent triggers, children stagger via :nth-child ───── */
/* Apply to a container; children animate in sequence (max 12 supported).
   Child elements should NOT have their own .reveal class. */
.reveal[data-anim-from="cascade"] {
    opacity: 1; /* parent itself doesn't animate */
    transform: none;
    transition: none;
}
.reveal[data-anim-from="cascade"] > * {
    opacity: 0;
    transform: translateY(32px);
    transition: opacity 1100ms cubic-bezier(.16, 1, .32, 1),
                transform 1100ms cubic-bezier(.16, 1, .32, 1);
}
.reveal[data-anim-from="cascade"].is-visible > * { opacity: 1; transform: translateY(0); }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(1)  { transition-delay:    0ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(2)  { transition-delay:  140ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(3)  { transition-delay:  280ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(4)  { transition-delay:  420ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(5)  { transition-delay:  560ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(6)  { transition-delay:  700ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(7)  { transition-delay:  840ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(8)  { transition-delay:  980ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(9)  { transition-delay: 1120ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(10) { transition-delay: 1260ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(11) { transition-delay: 1400ms; }
.reveal[data-anim-from="cascade"].is-visible > *:nth-child(12) { transition-delay: 1540ms; }

/* ─── PULSE — gentle scaling for "alive" elements ───────────────────── */
@keyframes pixel-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.04); }
}
.anim-pulse { animation: pixel-pulse 2.4s steps(8, end) infinite; }

/* ─── PRE-LAUNCH BADGE PULSE — cyan glow ─────────────────────────────── */
@keyframes prelaunch-glow {
    0%, 100% { box-shadow: 0 0 0 0 rgba(102, 224, 198, 0.0); }
    50%      { box-shadow: 0 0 16px 2px rgba(102, 224, 198, 0.4); }
}
.anim-prelaunch { animation: prelaunch-glow 3s ease-in-out infinite; }

/* ─── SCROLL-PROGRESS INDICATOR (left-side) ──────────────────────────── */
.scroll-progress {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    z-index: 50;
    pointer-events: none;
    background: linear-gradient(to bottom,
        rgba(102, 224, 198, 0.05) 0%,
        rgba(102, 224, 198, 0.05) 100%);
}
.scroll-progress::after {
    content: "";
    position: absolute;
    left: 0; top: 0; right: 0;
    height: var(--scroll-progress, 0%);
    background: linear-gradient(to bottom,
        var(--accent-aurora, #66e0c6),
        var(--accent-cosmic, #ffd86b));
    box-shadow: 0 0 12px rgba(102, 224, 198, 0.6);
    transition: height 80ms linear;
}

/* ─── HOVER-LIFT — applies to anything with .anim-lift ──────────────── */
.anim-lift {
    transition: transform 200ms steps(6, end),
                box-shadow 200ms steps(6, end),
                border-color 200ms ease;
}
.anim-lift:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 32px rgba(102, 224, 198, 0.15);
}

/* ─── TIER LADDER ────────────────────────────────────────────────────── */
/* A vertical 8-segment bar that fills as the section enters view.
   Used on the home page to visualize T0 → T7 progression. */
.tier-stack {
    display: flex;
    flex-direction: column-reverse;
    gap: 2px;
    width: 100%;
    max-width: 480px;
    margin: 0 auto;
    padding: 24px;
    background: rgba(12, 18, 32, 0.7);
    border: 1px solid var(--line-faint, #1f2940);
    box-shadow: 0 8px 24px rgba(0,0,0,0.4);
}
.tier-stack-segment {
    display: grid;
    grid-template-columns: 56px 1fr 80px;
    gap: 12px;
    align-items: center;
    padding: 14px 16px;
    background: var(--bg-deep, #04060d);
    border-left: 4px solid var(--tier-color, var(--accent-oak));
    opacity: 0;
    transform: translateX(-12px);
    transition: opacity 360ms steps(4, end),
                transform 360ms steps(4, end),
                background 200ms ease,
                box-shadow 200ms ease;
    cursor: pointer;
    position: relative;
}
.tier-stack.is-visible .tier-stack-segment {
    opacity: 1;
    transform: translateX(0);
}
.tier-stack.is-visible .tier-stack-segment:nth-child(1)  { transition-delay: 0ms;   }
.tier-stack.is-visible .tier-stack-segment:nth-child(2)  { transition-delay: 60ms;  }
.tier-stack.is-visible .tier-stack-segment:nth-child(3)  { transition-delay: 120ms; }
.tier-stack.is-visible .tier-stack-segment:nth-child(4)  { transition-delay: 180ms; }
.tier-stack.is-visible .tier-stack-segment:nth-child(5)  { transition-delay: 240ms; }
.tier-stack.is-visible .tier-stack-segment:nth-child(6)  { transition-delay: 300ms; }
.tier-stack.is-visible .tier-stack-segment:nth-child(7)  { transition-delay: 360ms; }
.tier-stack.is-visible .tier-stack-segment:nth-child(8)  { transition-delay: 420ms; }
.tier-stack-segment:hover {
    background: rgba(20, 29, 51, 0.95);
    box-shadow: 0 0 0 1px var(--tier-color, var(--accent-oak)),
                0 0 18px rgba(102, 224, 198, 0.15);
}
.tier-stack-tier {
    font-family: var(--font-pixel);
    font-size: 14px;
    color: var(--tier-color, var(--accent-oak));
    text-align: center;
}
.tier-stack-label {
    font-family: var(--font-pixel);
    font-size: 11px;
    color: var(--text-pri, #e6ecf5);
    letter-spacing: 0.06em;
}
.tier-stack-meta {
    font-size: 11px;
    color: var(--text-mute, #5e6a82);
    text-align: right;
    font-family: var(--font-mono);
}
.tier-stack-detail {
    grid-column: 1 / -1;
    margin-top: 12px;
    padding: 12px 0 4px;
    border-top: 1px dashed var(--line-faint, #1f2940);
    color: var(--text-sec, #9aa6bf);
    font-size: 13px;
    line-height: 1.5;
    display: none;
}
.tier-stack-segment.is-open .tier-stack-detail {
    display: block;
    animation: pixel-fade-in 240ms steps(4, end);
}
@keyframes pixel-fade-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* ─── BIOME WHEEL (mid-page rotating selector) ──────────────────────── */
.biome-wheel {
    position: relative;
    width: 100%;
    max-width: 520px;
    aspect-ratio: 1 / 1;
    margin: 24px auto;
}
.biome-wheel-rotor {
    position: absolute;
    inset: 0;
    border: 2px solid var(--line-faint, #1f2940);
    border-radius: 50%;
    background: radial-gradient(circle at center,
        rgba(12, 18, 32, 0.95) 0%,
        rgba(4, 6, 13, 0.9) 60%,
        rgba(102, 224, 198, 0.05) 100%);
    transition: transform 500ms cubic-bezier(.16, 1, .32, 1);
}
.biome-wheel-spoke {
    position: absolute;
    top: 50%; left: 50%;
    width: 88px;
    margin-top: -44px;
    margin-left: -44px;
    transform-origin: 50% 50%;
    cursor: pointer;
    will-change: transform;
    /* No CSS transition on .transform here — JS sets it 60×/sec from
       a constant-velocity orbit. A transition would fight the rAF
       updates and produce the jitter/easing-stutter the user reported. */
}
.biome-wheel-spoke-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 88px;
    height: 88px;
    background: var(--bg-panel, #0c1220);
    border: 2px solid var(--biome-color, var(--accent-aurora));
    border-radius: 50%;
    font-family: var(--font-pixel);
    font-size: 8px;
    letter-spacing: 0.06em;
    color: var(--text-pri, #e6ecf5);
    text-align: center;
    padding: 4px;
    line-height: 1.3;
    box-shadow: 0 0 12px rgba(102, 224, 198, 0.1);
}
.biome-wheel-spoke:hover .biome-wheel-spoke-inner {
    background: rgba(20, 29, 51, 0.98);
    transform: scale(1.10);
    box-shadow: 0 0 24px rgba(102, 224, 198, 0.55);
}
/* Active (clicked) spoke — pulsing cosmic glow */
.biome-wheel-spoke.is-active .biome-wheel-spoke-inner {
    background: rgba(20, 29, 51, 1);
    transform: scale(1.14);
    box-shadow: 0 0 0 2px var(--biome-color, var(--accent-aurora)),
                0 0 24px var(--biome-color, var(--accent-aurora)),
                0 0 48px rgba(102, 224, 198, 0.35);
    animation: biome-active-pulse 2.4s ease-in-out infinite;
}
@keyframes biome-active-pulse {
    0%, 100% {
        box-shadow: 0 0 0 2px var(--biome-color, var(--accent-aurora)),
                    0 0 24px var(--biome-color, var(--accent-aurora)),
                    0 0 48px rgba(102, 224, 198, 0.35);
    }
    50% {
        box-shadow: 0 0 0 2px var(--biome-color, var(--accent-aurora)),
                    0 0 36px var(--biome-color, var(--accent-aurora)),
                    0 0 72px rgba(102, 224, 198, 0.55);
    }
}
.biome-wheel-center {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 220px;
    height: 220px;
    background: radial-gradient(circle at center,
        rgba(4, 6, 13, 0.98) 0%,
        rgba(12, 18, 32, 0.96) 70%,
        rgba(4, 6, 13, 0.98) 100%);
    border: 1px solid var(--accent-aurora);
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 28px 22px;
    z-index: 5;
    box-shadow: 0 0 32px rgba(102, 224, 198, 0.15),
                inset 0 0 32px rgba(102, 224, 198, 0.08);
    animation: biome-center-breath 6s ease-in-out infinite;
}
@keyframes biome-center-breath {
    0%, 100% {
        box-shadow: 0 0 32px rgba(102, 224, 198, 0.15),
                    inset 0 0 32px rgba(102, 224, 198, 0.08);
    }
    50% {
        box-shadow: 0 0 48px rgba(102, 224, 198, 0.28),
                    inset 0 0 48px rgba(102, 224, 198, 0.12);
    }
}
.biome-wheel-center h4 {
    font-family: var(--font-pixel);
    font-size: 13px;
    letter-spacing: 0.05em;
    color: var(--accent-aurora);
    margin: 0 0 10px;
    line-height: 1.3;
    text-align: center;
    width: 100%;
}
.biome-wheel-center p {
    font-size: 11px;
    color: var(--text-sec, #9aa6bf);
    line-height: 1.55;
    margin: 0;
    text-align: center;
    /* Force narrow line wrapping so paragraph stays visually balanced */
    max-width: 160px;
    text-wrap: balance;
}
.biome-wheel-rotate-hint {
    margin-top: 14px;
    font-family: var(--font-pixel);
    font-size: 7px;
    color: var(--text-mute, #5e6a82);
    letter-spacing: 0.08em;
    text-align: center;
    width: 100%;
}

/* ============================================================================
   VISUAL WIDGETS — Phase B-2 (2026-05-15)
   Unique interactive visualizations per page. Same pixel-art aesthetic,
   same stepped easing.
   ============================================================================ */

/* ─── 1. DEVLOG SIDEBAR + LAYOUT ───────────────────────────────────
   DESKTOP: sidebar is position: fixed — it stays anchored to the
   viewport like the top nav, regardless of how far the user scrolls.
   The post list compensates with left padding so nothing overlaps.
   MOBILE (<980px): sidebar collapses to normal flow above the post
   list, with filter chips + week list rendered as horizontal scrollers
   so the page still reads on a phone. */
.devlog-layout {
    max-width: 1080px;
    margin: 0 auto;
    padding: 0 var(--sp-4);
    position: relative;
}
@media (min-width: 981px) {
    .devlog-layout {
        /* Two-column grid: sidebar (240px) + posts (rest). The sidebar
           uses position:sticky inside this grid so it naturally lines up
           next to the post list without overlapping the page-header
           above. It sticks under the nav only once the user scrolls
           past the page-header. Previously the sidebar was
           position:fixed at top:92px, which covered "The Devlog." title
           on first load. */
        display: grid;
        grid-template-columns: 240px 1fr;
        gap: var(--sp-5);
    }
}
.devlog-sidebar {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    z-index: 5;
}
@media (min-width: 981px) {
    .devlog-sidebar {
        position: sticky;
        top: calc(var(--nav-h, 68px) + 24px);
        align-self: start;        /* don't stretch to grid row height */
        max-height: calc(100vh - var(--nav-h, 68px) - 48px);
        overflow-y: auto;
        overflow-x: hidden;
        padding-right: 4px;
    }
}
@media (max-width: 980px) {
    .devlog-sidebar {
        position: static;
        max-height: none;
        overflow: visible;
        padding-right: 0;
        margin-bottom: var(--sp-4);
    }
}
/* Subtle scrollbar so the sidebar doesn't feel "stuck" when its
   content exceeds the viewport. */
.devlog-sidebar::-webkit-scrollbar { width: 6px; }
.devlog-sidebar::-webkit-scrollbar-thumb {
    background: var(--line-soft);
    border-radius: 3px;
}

.devlog-sidebar-card {
    background: var(--bg-panel);
    border: 1px solid var(--line-faint);
    padding: 14px 16px;
    border-left: 3px solid var(--accent-aurora);
}
.devlog-sidebar-heading {
    font-family: var(--font-pixel);
    font-size: 10px;
    letter-spacing: 0.12em;
    color: var(--text-mute);
    text-transform: uppercase;
    margin: 0 0 12px;
}

/* Filter buttons stack vertically inside the sidebar. Mobile shows
   them as a horizontal scrolling strip so all topics stay reachable
   without ballooning the page height. */
.devlog-filter-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0;
}
.devlog-filter-list .filter-tag {
    text-align: left;
    padding: 7px 10px;
    width: 100%;
}
@media (max-width: 980px) {
    .devlog-filter-list {
        flex-direction: row;
        flex-wrap: nowrap;
        overflow-x: auto;
        gap: 6px;
        scrollbar-width: thin;
        -webkit-overflow-scrolling: touch;
        padding-bottom: 4px;
    }
    .devlog-filter-list .filter-tag {
        width: auto;
        flex: 0 0 auto;
    }
}

/* Week jump-list: ordered list, no bullet marker, one row per week.
   Each row shows the week number + the post title; clicking smooth-
   scrolls to the post. The currently-viewed post gets .is-active
   which paints the row with the accent + a left bar. */
.devlog-week-nav {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 360px;
    overflow-y: auto;
    scrollbar-width: thin;
}
@media (max-width: 980px) {
    .devlog-week-nav {
        flex-direction: row;
        flex-wrap: nowrap;
        overflow-x: auto;
        gap: 6px;
        max-height: none;
        padding-bottom: 4px;
        -webkit-overflow-scrolling: touch;
    }
}
.devlog-week-nav li { margin: 0; padding: 0; }
.devlog-week-nav a {
    display: grid;
    grid-template-columns: 30px 1fr;
    gap: 8px;
    align-items: baseline;
    padding: 7px 10px 7px 9px;
    border-left: 3px solid transparent;
    background: transparent;
    color: var(--text-mute);
    font-family: var(--font-mono);
    font-size: 11.5px;
    line-height: 1.35;
    text-decoration: none;
    transition: background 140ms ease,
                color 140ms ease,
                border-left-color 140ms ease;
}
.devlog-week-nav a:hover {
    background: rgba(102, 224, 198, 0.06);
    color: var(--text-pri);
    border-left-color: var(--accent-aurora);
}
.devlog-week-nav .devlog-week-num {
    font-family: var(--font-pixel);
    font-size: 9px;
    letter-spacing: 0.08em;
    color: var(--accent-aurora);
}
.devlog-week-nav .devlog-week-title {
    color: inherit;
    /* clamp long titles to two lines so the sidebar doesn't blow up */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
}
.devlog-week-nav li.is-active a {
    background: linear-gradient(90deg,
        rgba(102, 224, 198, 0.10),
        transparent 80%);
    color: var(--text-pri);
    border-left-color: var(--accent-aurora);
    box-shadow: 0 0 16px rgba(102, 224, 198, 0.10) inset;
}
.devlog-week-nav li.is-active .devlog-week-num {
    color: var(--accent-cosmic);
}
@media (max-width: 980px) {
    .devlog-week-nav a {
        grid-template-columns: auto auto;
        white-space: nowrap;
        border-left: none;
        border-bottom: 2px solid transparent;
        padding: 6px 12px;
    }
    .devlog-week-nav li.is-active a {
        border-bottom-color: var(--accent-aurora);
        background: rgba(102, 224, 198, 0.08);
    }
    .devlog-week-nav .devlog-week-title {
        -webkit-line-clamp: 1;
        max-width: 240px;
    }
}

.devlog-content { min-width: 0; }

/* ─── 2. TIER DISTRIBUTION PYRAMID ──────────────────────────────────
   Rewritten 2026-05-15 for bulletproof rendering. Uses flexbox (better
   compatibility than grid for this use case) with explicit widths so
   labels, bars, and counts never collapse. The bar fill always shows a
   visible color even before JS lands (15% default + 8px min-width).
   IMPORTANT: this widget DOES NOT use the global .reveal scroll-fade
   system. In testing it would sometimes stick at opacity 0 mid-
   transition, hiding all the visual elements (labels, bars, sweep
   highlight) while only the bright text counts remained visible.
   The bars have their own width transition for entrance animation. */
.tier-pyramid {
    display: flex !important;
    flex-direction: column;
    gap: 10px;
    max-width: 720px;
    margin: 32px auto;
    background: rgba(12, 18, 32, 0.7);
    border: 1px solid var(--line-soft);
    padding: 24px;
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45);
    /* Belt-and-suspenders: in case any HTML accidentally adds .reveal
       back, force the pyramid to its visible state immediately. */
    opacity: 1 !important;
    transform: none !important;
}
.tier-pyramid-row {
    display: flex !important;
    flex-direction: row;
    align-items: center;
    gap: 14px;
    position: relative;
    width: 100%;
    min-height: 28px;
}
.tier-pyramid-label {
    flex: 0 0 52px;
    display: inline-block;
    font-family: var(--font-pixel);
    font-size: 12px;
    color: var(--tier-color, var(--accent-aurora));
    text-align: right;
    letter-spacing: 0.06em;
    text-shadow: 0 0 8px color-mix(in srgb, var(--tier-color, var(--accent-aurora)) 40%, transparent);
}
.tier-pyramid-bar {
    flex: 1 1 auto;
    height: 26px;
    background: var(--bg-deep);
    border: 1px solid var(--line-faint);
    overflow: hidden;
    position: relative;
    min-width: 60px;
}
.tier-pyramid-bar-fill {
    display: block;
    position: relative;
    height: 100%;
    /* Default 15% visible so the bar is never empty before JS lands. */
    width: var(--bar-width, 15%);
    min-width: 8px;
    /* Solid tier color is the always-rendered base layer. The gradient
       above adds a glassy highlight. background-color paints first so
       even if the gradient fails to parse on a browser, the solid color
       still shows. */
    background-color: var(--tier-color, var(--accent-aurora));
    background-image:
        linear-gradient(180deg,
            rgba(255, 255, 255, 0.28) 0%,
            rgba(255, 255, 255, 0.06) 48%,
            rgba(0, 0, 0, 0.22) 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.30),
        inset 0 -1px 0 rgba(0, 0, 0, 0.30),
        0 0 14px color-mix(in srgb, var(--tier-color, var(--accent-aurora)) 45%, transparent);
    transition: width 1200ms cubic-bezier(.16, 1, .32, 1);
}
/* Browsers WITHOUT color-mix() support fall back to a simple aurora
   glow that always renders. Older Safari, etc. */
@supports not (background: color-mix(in srgb, red, blue)) {
    .tier-pyramid-bar-fill {
        box-shadow:
            inset 0 1px 0 rgba(255, 255, 255, 0.30),
            inset 0 -1px 0 rgba(0, 0, 0, 0.30),
            0 0 14px rgba(102, 224, 198, 0.35);
    }
    .tier-pyramid-label { text-shadow: none; }
}
/* Live-data shimmer — a real child element (JS injects it) so it never
   has the pseudo-element rendering quirks. */
.tier-pyramid-bar-shimmer {
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255, 255, 255, 0.30) 50%,
        transparent 100%);
    transform: translateX(-100%);
    animation: tier-pyramid-shimmer 4.5s ease-in-out infinite;
    pointer-events: none;
}
@keyframes tier-pyramid-shimmer {
    0%   { transform: translateX(-100%); }
    55%  { transform: translateX(100%); }
    100% { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
    .tier-pyramid-bar-shimmer { animation: none; }
}
.tier-pyramid-count {
    flex: 0 0 72px;
    display: inline-block;
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-pri);
    text-align: left;
    white-space: nowrap;
}
@media (max-width: 540px) {
    .tier-pyramid { padding: 18px 14px; }
    .tier-pyramid-row { gap: 10px; }
    .tier-pyramid-label { flex-basis: 36px; font-size: 10px; }
    .tier-pyramid-count { flex-basis: 56px; font-size: 11px; }
}

/* ─── 3. BUILDING CATEGORY RADIAL — space-themed star cluster ──────
   Replaces the old donut chart. The chart now consists of 6 "star
   systems" orbiting a central core, with constellation lines linking
   them. Continuous animation drives the orbital motion. */
.building-radial {
    max-width: 360px;
    margin: 32px auto;
    text-align: center;
    position: relative;
}
.building-radial-svg {
    width: 100%;
    height: auto;
    display: block;
    background:
        radial-gradient(ellipse at center, rgba(102, 224, 198, 0.04), transparent 70%);
}
/* Star halo softly pulses on each system — staggered via inline delay */
.br-halo {
    animation: br-halo-pulse 4.5s ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: center;
}
@keyframes br-halo-pulse {
    0%, 100% { opacity: 0.18; }
    50%      { opacity: 0.45; }
}
/* Star body has a soft drop-shadow in its own color */
.br-star {
    filter: drop-shadow(0 0 4px var(--cluster-color, #fff));
    animation: br-star-pulse 3s ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: center;
}
@keyframes br-star-pulse {
    0%, 100% { filter: drop-shadow(0 0 4px var(--cluster-color, #fff)); }
    50%      { filter: drop-shadow(0 0 9px var(--cluster-color, #fff)); }
}
/* Background dust twinkle */
.br-dust circle {
    animation: br-dust-twinkle 4s ease-in-out infinite;
}
@keyframes br-dust-twinkle {
    0%, 100% { opacity: 0.25; }
    50%      { opacity: 0.95; }
}
/* Central core — bright pulsing star, the gravity well */
.br-core {
    transform-box: fill-box;
    transform-origin: center;
    animation: br-core-beat 2.6s ease-in-out infinite;
}
@keyframes br-core-beat {
    0%, 100% { transform: scale(1);    opacity: 1;   }
    50%      { transform: scale(1.18); opacity: 0.9; }
}
.br-core-halo {
    transform-box: fill-box;
    transform-origin: center;
    animation: br-core-halo-pulse 4s ease-in-out infinite;
}
@keyframes br-core-halo-pulse {
    0%, 100% { opacity: 0.7; transform: scale(1);    }
    50%      { opacity: 1;   transform: scale(1.25); }
}
@media (prefers-reduced-motion: reduce) {
    .br-halo, .br-star, .br-dust circle,
    .br-core, .br-core-halo { animation: none; }
}

.building-radial-legend {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
    margin-top: 20px;
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-sec);
    text-align: left;
}
.building-radial-legend-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    background: rgba(12, 18, 32, 0.4);
    border: 1px solid var(--line-faint);
    border-left: 3px solid var(--swatch-color, var(--line-faint));
    transition: border-color 200ms ease, background 200ms ease;
}
.building-radial-legend-item:hover {
    background: rgba(12, 18, 32, 0.7);
}
.building-radial-legend-swatch {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    box-shadow: 0 0 8px currentColor;
    flex-shrink: 0;
}

/* ─── 4. ACHIEVEMENT PROGRESS WHEEL ───────────────────────────────── */
.achievement-wheel {
    max-width: 380px;
    margin: 32px auto;
    text-align: center;
    /* No position:relative here — that put the absolutely-positioned
       center label at 50% of the WHOLE widget (SVG + legend). The ring-wrap
       below now owns the positioning context for just the SVG. */
}
.achievement-wheel-ring-wrap {
    position: relative;
    width: 100%;
}
.achievement-wheel-svg { width: 100%; height: auto; image-rendering: pixelated; display: block; }
/* Each ring fills proportionally to its data-percent on entry, then
   gently rotates forever at its own speed. The result reads as a live
   radial dashboard rather than a one-shot reveal. */
.achievement-wheel-ring {
    fill: none;
    stroke-width: 8;
    transform-origin: center;
    transform: rotate(-90deg);
    stroke-dasharray: var(--ring-circumference, 1000);
    stroke-dashoffset: var(--ring-circumference, 1000);
    /* the initial fill transition still fires once on .is-visible */
    transition: stroke-dashoffset 1400ms steps(28, end);
    will-change: transform;
}
.achievement-wheel.is-visible .achievement-wheel-ring {
    stroke-dashoffset: var(--ring-offset-target, 1000);
    /* After the fill, kick off a continuous spin at the per-ring speed
       set inline. Six rings × six different durations = gentle parallax
       between layers. */
    animation: ach-ring-spin var(--ring-duration, 24s) linear infinite;
    animation-delay: 1.4s;
}
@keyframes ach-ring-spin {
    from { transform: rotate(-90deg); }
    to   { transform: rotate(270deg); }
}
@media (prefers-reduced-motion: reduce) {
    .achievement-wheel.is-visible .achievement-wheel-ring { animation: none; }
}
.achievement-wheel-center {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
}
.achievement-wheel-center-count {
    font-family: var(--font-pixel);
    font-size: 24px;
    color: var(--accent-aurora);
    display: block;
    line-height: 1;
}
.achievement-wheel-center-label {
    font-family: var(--font-pixel);
    font-size: 8px;
    letter-spacing: 0.1em;
    color: var(--text-mute);
    text-transform: uppercase;
    display: block;
    margin-top: 6px;
}
.achievement-wheel-legend {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
    margin-top: 24px;
    font-family: var(--font-mono);
    font-size: 12px;
    text-align: left;
    color: var(--text-sec);
}
.achievement-wheel-legend-item {
    display: grid;
    grid-template-columns: 14px 1fr auto;
    align-items: center;
    gap: 8px;
}
.achievement-wheel-legend-swatch {
    width: 12px;
    height: 12px;
    border: 1px solid var(--line-faint);
    background: var(--swatch-color, var(--accent-oak));
}

/* ─── 5. PRODUCTION CHAIN FLOW ────────────────────────────────────── */
.prod-chain-flow {
    margin: 32px 0;
    padding: 24px;
    background: rgba(12, 18, 32, 0.7);
    border: 1px solid var(--line-faint);
    overflow-x: auto;
    position: relative;
    /* fade-out right edge hints horizontal scroll on small viewports */
    -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent 100%);
            mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent 100%);
}
@media (min-width: 800px) {
    .prod-chain-flow { -webkit-mask-image: none; mask-image: none; }
}
.prod-chain-flow svg {
    width: 100%;
    min-width: 720px;
    height: 240px;
    display: block;
    image-rendering: pixelated;
}
.prod-chain-flow-caption {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--text-mute);
    margin-top: 12px;
    text-align: center;
}
/* Box + label styling. Without these, SVG <rect>/<text> default to a
   black fill — invisible on the dark panel. The labels also need
   text-anchor:middle so they center on the box-center x coordinate
   instead of left-anchoring and overflowing to the right. Per-box
   accent colors are set inline in the markup so each label matches
   its box's stroke colour. */
.prod-chain-box {
    fill: #141d33;
    stroke: #66e0c6;
    stroke-width: 1.5;
}
.prod-chain-box-label {
    fill: #e6ecf5;
    font-family: 'Press Start 2P', 'JetBrains Mono', monospace;
    font-size: 9px;
    text-anchor: middle;
    dominant-baseline: middle;
    letter-spacing: 0.5px;
}
.prod-chain-arrow {
    fill: none;
    stroke-width: 2.5;
    stroke-linecap: square;
}

/* ─── 6. DYSON RINGS ──────────────────────────────────────────────── */
/* dyson 5-stage rings — animated star + 5 orbiting satellites + legend
   container-type: inline-size lets satellite radii use cqi units so the
   dots scale together with the SVG orbits at any container width. */
.dyson-rings {
    position: relative;
    width: min(460px, 100%);
    aspect-ratio: 1 / 1;
    margin: 0 auto;
    user-select: none;
    container-type: inline-size;
}
.dyson-rings-svg {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    pointer-events: none;
}
.dyson-rings-sun {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 56px; height: 56px;
    z-index: 2;
    pointer-events: none;
}
.dyson-rings-sun-core {
    position: absolute; inset: 0;
    background: radial-gradient(circle at 40% 35%, #fff5d3 0%, #ffd86b 35%, #ff9c33 70%, #cc4d2d 100%);
    border-radius: 50%;
    box-shadow:
        0 0 30px rgba(255, 216, 107, 0.55),
        0 0 80px rgba(255, 156, 51, 0.30),
        inset 0 0 12px rgba(255, 255, 255, 0.25);
    animation: dyson-sun-pulse 4s ease-in-out infinite;
}
.dyson-rings-sun-flare {
    position: absolute; inset: -28px;
    background: radial-gradient(circle, rgba(255, 216, 107, 0.20) 0%, transparent 70%);
    border-radius: 50%;
    animation: dyson-sun-flare 6s ease-in-out infinite;
}
@keyframes dyson-sun-pulse {
    0%, 100% { filter: brightness(1); }
    50%      { filter: brightness(1.18); }
}
@keyframes dyson-sun-flare {
    0%, 100% { transform: scale(1);   opacity: 0.7; }
    50%      { transform: scale(1.18); opacity: 1; }
}

/* each satellite is a 0×0 box at center; its ::before is the dot offset
   to --r, then the parent rotates → dot traces a perfect orbit */
.dyson-rings-sat {
    position: absolute;
    top: 50%; left: 50%;
    width: 0; height: 0;
    transform-origin: center;
    animation: dyson-sat-orbit var(--dur, 20s) linear infinite;
    pointer-events: none;
    z-index: 1;
}
.dyson-rings-sat::before {
    content: '';
    position: absolute;
    top: -3px;
    left: calc(var(--r, 100px) - 3px);
    width: 6px; height: 6px;
    background: var(--col, #66e0c6);
    border-radius: 50%;
    box-shadow: 0 0 8px var(--col, #66e0c6);
}
.dyson-rings-sat::after {
    content: '';
    position: absolute;
    top: -1px;
    left: calc(var(--r, 100px) - 22px);
    width: 20px; height: 2px;
    background: linear-gradient(90deg, transparent, var(--col, #66e0c6));
    opacity: 0.55;
    filter: blur(0.5px);
}
@keyframes dyson-sat-orbit {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .dyson-rings-sat, .dyson-rings-sun-core, .dyson-rings-sun-flare { animation: none; }
}

/* transparent ring-shaped hover targets on top of each orbit */
.dyson-rings-pick {
    position: absolute;
    top: 50%; left: 50%;
    width: calc(var(--r) * 2 + 24px);
    height: calc(var(--r) * 2 + 24px);
    transform: translate(-50%, -50%);
    background: transparent;
    border: 14px solid transparent;
    border-radius: 50%;
    cursor: crosshair;
    padding: 0;
    z-index: 3;
    transition: border-color 200ms ease;
}
.dyson-rings-pick:hover,
.dyson-rings-pick:focus-visible {
    border-color: rgba(255, 216, 107, 0.16);
    outline: none;
}

/* legend cards under the diagram */
.dyson-rings-legend {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 12px;
    max-width: 1080px;
    margin: var(--sp-6) auto 0;
}
.dyson-rings-legend-card {
    padding: 14px 16px;
    background: var(--bg-panel);
    border: 1px solid var(--line-faint);
    border-left: 3px solid var(--line-faint);
    transition: border-color 200ms ease, transform 200ms steps(4, end), background 200ms ease;
}
.dyson-rings-legend-card:hover,
.dyson-rings-legend-card.is-active {
    transform: translateY(-2px);
    background: rgba(255, 216, 107, 0.04);
}
.dyson-rings-legend-card[data-ring="1"].is-active,
.dyson-rings-legend-card[data-ring="1"]:hover { border-left-color: #66e0c6; }
.dyson-rings-legend-card[data-ring="2"].is-active,
.dyson-rings-legend-card[data-ring="2"]:hover { border-left-color: #7cc086; }
.dyson-rings-legend-card[data-ring="3"].is-active,
.dyson-rings-legend-card[data-ring="3"]:hover { border-left-color: #ffd86b; }
.dyson-rings-legend-card[data-ring="4"].is-active,
.dyson-rings-legend-card[data-ring="4"]:hover { border-left-color: #ff8f6b; }
.dyson-rings-legend-card[data-ring="5"].is-active,
.dyson-rings-legend-card[data-ring="5"]:hover { border-left-color: #a583ff; }
.dyson-rings-legend-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--text-pri);
}
.dyson-rings-legend-head .dot {
    width: 8px; height: 8px;
    border-radius: 50%;
    flex: 0 0 8px;
}
.dyson-rings-legend-head .badge {
    margin-left: auto;
    padding: 2px 8px;
    background: var(--bg-deep);
    border: 1px solid var(--line-faint);
    font-family: var(--font-pixel);
    font-size: 8px;
    letter-spacing: 0.06em;
    color: var(--text-sec);
}
.dyson-rings-legend-card p {
    margin: 0;
    font-size: 12px;
    color: var(--text-sec);
    line-height: 1.5;
}

/* highlight orbit that matches hovered ring */
.dyson-rings[data-stage="1"] .dyson-rings-orbit[data-ring="1"],
.dyson-rings[data-stage="2"] .dyson-rings-orbit[data-ring="2"],
.dyson-rings[data-stage="3"] .dyson-rings-orbit[data-ring="3"],
.dyson-rings[data-stage="4"] .dyson-rings-orbit[data-ring="4"],
.dyson-rings[data-stage="5"] .dyson-rings-orbit[data-ring="5"] {
    stroke-opacity: 1;
    stroke-width: 2;
    stroke-dasharray: none;
    filter: drop-shadow(0 0 4px currentColor);
}

/* ─── 7. ORBITAL ANIMATION ────────────────────────────────────────── */
.orbital-map {
    position: relative;
    width: 100%;
    max-width: 560px;
    aspect-ratio: 1 / 1;
    margin: 32px auto;
    background: radial-gradient(circle at center,
        rgba(255, 216, 107, 0.04) 0%,
        rgba(4, 6, 13, 0.95) 70%);
    border: 1px solid var(--line-faint);
}
.orbital-star {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 36px;
    height: 36px;
    background: radial-gradient(circle, #ffd86b 0%, #ff9c33 80%);
    box-shadow: 0 0 40px rgba(255, 216, 107, 0.6),
                0 0 80px rgba(255, 156, 51, 0.3);
    border-radius: 50%;
    z-index: 2;
}
.orbital-ring {
    position: absolute;
    top: 50%; left: 50%;
    border: 1px dashed var(--line-faint);
    border-radius: 50%;
    transform: translate(-50%, -50%);
    pointer-events: none;
}
.orbital-planet {
    position: absolute;
    top: 50%; left: 50%;
    width: 16px;
    height: 16px;
    margin-top: -8px;
    margin-left: -8px;
    transform-origin: center;
    animation: orbit-spin var(--orbit-duration, 24s) linear infinite;
}
.orbital-planet-dot {
    position: absolute;
    top: 50%;
    left: var(--orbit-radius, 80px);
    width: 14px;
    height: 14px;
    margin-top: -7px;
    background: var(--planet-color, var(--accent-aurora));
    border: 1px solid rgba(255, 255, 255, 0.3);
    box-shadow: 0 0 10px var(--planet-color, var(--accent-aurora));
    cursor: pointer;
    transition: transform 200ms steps(4, end);
    border-radius: 50%;
}
.orbital-planet-dot:hover { transform: scale(1.6); }
.orbital-planet-label {
    position: absolute;
    top: 50%;
    left: calc(var(--orbit-radius, 80px) + 18px);
    transform: translateY(-50%);
    font-family: var(--font-pixel);
    font-size: 8px;
    color: var(--text-sec);
    pointer-events: none;
    white-space: nowrap;
    text-shadow: 0 0 4px rgba(4, 6, 13, 0.8);
    opacity: 0.7;
}
@keyframes orbit-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .orbital-planet { animation: none; }
}
.orbital-map:hover .orbital-planet { animation-play-state: paused; }

/* ─── 8. STUDIO STATS STRIP ───────────────────────────────────────── */
.studio-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 14px;
    margin: 0 0 var(--sp-2);
}
.studio-stat {
    position: relative;
    padding: 22px 16px 18px;
    background: var(--bg-panel);
    border: 1px solid var(--line-faint);
    border-left: 3px solid var(--accent-oak);
    text-align: center;
    transition: transform 220ms steps(4, end), border-color 220ms ease, background 220ms ease;
    overflow: hidden;
}
.studio-stat::before {
    /* subtle starfield glow that grows on hover */
    content: "";
    position: absolute; inset: 0;
    background: radial-gradient(120px 80px at 50% 100%,
                rgba(124, 192, 134, 0.10),
                transparent 70%);
    opacity: 0;
    transition: opacity 240ms ease;
    pointer-events: none;
}
.studio-stat:hover {
    transform: translateY(-3px);
    border-color: var(--accent-aurora);
    border-left-color: var(--accent-aurora);
}
.studio-stat:hover::before { opacity: 1; }
.studio-stat-value {
    font-family: var(--font-pixel);
    font-size: 28px;
    color: var(--accent-aurora);
    display: block;
    line-height: 1;
    text-shadow: 0 0 12px rgba(102, 224, 198, 0.35);
}
.studio-stat-label {
    font-family: var(--font-pixel);
    font-size: 8px;
    letter-spacing: 0.12em;
    color: var(--text-pri);
    text-transform: uppercase;
    display: block;
    margin-top: 12px;
}
.studio-stat-sub {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--text-mute);
    display: block;
    margin-top: 6px;
    letter-spacing: 0.02em;
}

/* ─── 9. TECH TREE CONSTELLATION (research page) ────────────────────────── */
.tech-tree {
    position: relative;
    max-width: 980px;
    margin: 0 auto;
    padding: 0 var(--sp-3);
}
.tech-tree-svg {
    width: 100%;
    height: auto;
    display: block;
    background:
        radial-gradient(ellipse 400px 200px at 80% 15%, rgba(165, 131, 255, 0.08), transparent 70%),
        radial-gradient(ellipse 300px 200px at 20% 90%, rgba(102, 224, 198, 0.06), transparent 70%);
    border: 1px solid var(--line-soft);
}
/* on narrow screens, allow horizontal scroll on JUST the SVG so the
   detail card below stays inside the viewport. */
.tech-tree-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    position: relative;
}
.tech-tree-scroll::-webkit-scrollbar { height: 6px; }
.tech-tree-scroll::-webkit-scrollbar-thumb { background: var(--line-soft); border-radius: 3px; }
@media (max-width: 720px) {
    .tech-tree-svg { min-width: 640px; }
    /* fade-edge hint so users see they can scroll horizontally */
    .tech-tree-scroll {
        -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent 100%);
                mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent 100%);
    }
}

/* path dash animation: draw in left-to-right when section enters viewport */
.tech-tree .tt-path {
    stroke-dasharray: 200;
    stroke-dashoffset: 200;
    transition: stroke-dashoffset 1400ms ease, stroke-opacity 240ms ease, stroke-width 240ms ease;
    transition-delay: calc(var(--seq, 0) * 140ms);
}
.tech-tree.is-visible .tt-path { stroke-dashoffset: 0; }
.tech-tree .tt-path[data-from="0"] { --seq: 0; }
.tech-tree .tt-path[data-from="1"] { --seq: 1; }
.tech-tree .tt-path[data-from="2"] { --seq: 2; }
.tech-tree .tt-path[data-from="3"] { --seq: 3; }
.tech-tree .tt-path[data-from="4"] { --seq: 4; }
.tech-tree .tt-path[data-from="5"] { --seq: 5; }
.tech-tree .tt-path[data-from="6"] { --seq: 6; }

/* node interaction */
.tech-tree .tt-node {
    cursor: pointer;
    transition: transform 240ms cubic-bezier(.16,1,.3,1);
    transform-box: fill-box;
    transform-origin: center;
}
.tech-tree .tt-node:hover,
.tech-tree .tt-node:focus-visible,
.tech-tree .tt-node.is-active {
    /* SVG translate is already on the group; scale via nested */
}
.tech-tree .tt-node-ring {
    transition: stroke-width 220ms ease, filter 220ms ease;
}
.tech-tree .tt-node:hover .tt-node-ring,
.tech-tree .tt-node.is-active .tt-node-ring {
    stroke-width: 2.5;
    filter: drop-shadow(0 0 8px currentColor);
}

/* twinkle the star dust */
.tech-tree-dust circle {
    animation: tt-twinkle 4s ease-in-out infinite;
}
.tech-tree-dust circle:nth-child(2n)  { animation-delay: -0.8s; }
.tech-tree-dust circle:nth-child(3n)  { animation-delay: -1.6s; }
.tech-tree-dust circle:nth-child(5n)  { animation-delay: -2.4s; }
@keyframes tt-twinkle {
    0%, 100% { opacity: 0.3; }
    50%      { opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) {
    .tech-tree-dust circle { animation: none; }
    .tech-tree .tt-path { transition: none; stroke-dashoffset: 0; }
}

/* dim non-selected paths/nodes when a tier is active */
.tech-tree[data-tier="0"] .tt-path,
.tech-tree[data-tier="1"] .tt-path,
.tech-tree[data-tier="2"] .tt-path,
.tech-tree[data-tier="3"] .tt-path,
.tech-tree[data-tier="4"] .tt-path,
.tech-tree[data-tier="5"] .tt-path,
.tech-tree[data-tier="6"] .tt-path,
.tech-tree[data-tier="7"] .tt-path { stroke-opacity: 0.18; }

.tech-tree[data-tier="1"] .tt-path[data-to="1"],
.tech-tree[data-tier="2"] .tt-path[data-to="1"],
.tech-tree[data-tier="2"] .tt-path[data-to="2"],
.tech-tree[data-tier="3"] .tt-path[data-to="1"],
.tech-tree[data-tier="3"] .tt-path[data-to="2"],
.tech-tree[data-tier="3"] .tt-path[data-to="3"],
.tech-tree[data-tier="4"] .tt-path[data-to="1"],
.tech-tree[data-tier="4"] .tt-path[data-to="2"],
.tech-tree[data-tier="4"] .tt-path[data-to="3"],
.tech-tree[data-tier="4"] .tt-path[data-to="4"],
.tech-tree[data-tier="5"] .tt-path[data-to="1"],
.tech-tree[data-tier="5"] .tt-path[data-to="2"],
.tech-tree[data-tier="5"] .tt-path[data-to="3"],
.tech-tree[data-tier="5"] .tt-path[data-to="4"],
.tech-tree[data-tier="5"] .tt-path[data-to="5"],
.tech-tree[data-tier="6"] .tt-path[data-to="1"],
.tech-tree[data-tier="6"] .tt-path[data-to="2"],
.tech-tree[data-tier="6"] .tt-path[data-to="3"],
.tech-tree[data-tier="6"] .tt-path[data-to="4"],
.tech-tree[data-tier="6"] .tt-path[data-to="5"],
.tech-tree[data-tier="6"] .tt-path[data-to="6"],
.tech-tree[data-tier="7"] .tt-path { stroke-opacity: 1; stroke-width: 1.8; }

/* keep all paths bright when no tier is selected (data-tier="0" = default state) */
.tech-tree[data-tier="0"] .tt-path { stroke-opacity: 0.55; }

/* detail card below the SVG */
.tech-tree-detail {
    margin-top: var(--sp-4);
    padding: 18px 22px;
    background: var(--bg-panel);
    border: 1px solid var(--line-faint);
    border-left: 3px solid var(--accent-cosmic);
    transition: border-left-color 240ms ease;
}
.tech-tree-detail-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 6px;
    flex-wrap: wrap;
    gap: 8px;
}
.tech-tree-detail-tier {
    font-family: var(--font-pixel);
    font-size: 11px;
    letter-spacing: 0.12em;
    color: var(--accent-cosmic);
    transition: color 240ms ease;
}
.tech-tree-detail-time {
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--text-mute);
}
.tech-tree-detail-body {
    margin: 0;
    font-size: 13px;
    color: var(--text-sec);
    line-height: 1.55;
}

/* ============================================================================
   DONATION GOAL TRACKER (/support page)
   Visual representation of community funding progress toward the $10,000
   Year-One goal, with milestone tiers laid out along a rocket-trail rail.
   Data + tiers are CMS-editable in /admin/ under Support Page → Goal Tracker.
   ============================================================================ */
.goal-tracker {
    position: relative;
    max-width: 920px;
    margin: 0 auto;
    padding: 32px 28px;
    background:
        radial-gradient(ellipse 700px 240px at 50% 0%,
            rgba(102, 224, 198, 0.08), transparent 70%),
        rgba(12, 18, 32, 0.7);
    border: 1px solid var(--line-soft);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
    overflow: hidden;
}
.goal-tracker::before {
    /* faint star-field texture so it ties into the cosmic theme */
    content: "";
    position: absolute; inset: 0;
    background-image:
        radial-gradient(1px 1px at 14% 22%, rgba(255,255,255,0.5), transparent),
        radial-gradient(1px 1px at 78% 64%, rgba(255,216,107,0.5), transparent),
        radial-gradient(1px 1px at 38% 84%, rgba(165,131,255,0.4), transparent),
        radial-gradient(1px 1px at 92% 18%, rgba(102,224,198,0.5), transparent);
    background-size: 320px 240px;
    pointer-events: none;
    opacity: 0.6;
}

/* Live amount header */
.goal-tracker-head {
    position: relative;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 14px;
    padding-bottom: 18px;
    margin-bottom: 22px;
    border-bottom: 1px dashed var(--line-faint);
    z-index: 1;
}
.goal-tracker-amount {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 10px;
}
.goal-tracker-current {
    font-family: var(--font-pixel);
    font-size: 32px;
    color: var(--accent-aurora);
    text-shadow: 0 0 14px rgba(102, 224, 198, 0.45);
    letter-spacing: 0.02em;
    white-space: nowrap;
}
@media (max-width: 540px) {
    .goal-tracker-current { font-size: 24px; }
}
.goal-tracker-of {
    font-family: var(--font-mono);
    font-size: 13px;
    color: var(--text-mute);
}
.goal-tracker-target {
    font-family: var(--font-pixel);
    font-size: 16px;
    color: var(--text-pri);
    letter-spacing: 0.04em;
}
.goal-tracker-meta {
    display: flex;
    gap: 18px;
    align-items: baseline;
    font-family: var(--font-pixel);
    font-size: 10px;
    letter-spacing: 0.08em;
    color: var(--text-mute);
}
.goal-tracker-pct {
    color: var(--accent-cosmic);
    font-size: 12px;
    letter-spacing: 0.06em;
}
.goal-tracker-supporters {
    color: var(--text-sec);
}

/* The rocket-trail rail */
.goal-tracker-rail-wrap {
    position: relative;
    z-index: 1;
    margin: 22px auto 50px;
    padding: 28px 0 22px;
}
.goal-tracker-rail {
    position: relative;
    height: 12px;
    background: transparent;
    border-radius: 6px;
}
.goal-tracker-rail-track {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(90deg,
            rgba(102, 224, 198, 0.10) 0%,
            rgba(165, 131, 255, 0.10) 50%,
            rgba(255, 216, 107, 0.10) 100%);
    border: 1px solid var(--line-faint);
    border-radius: 6px;
    overflow: hidden;
}
.goal-tracker-rail-fill {
    position: absolute;
    top: 1px; bottom: 1px; left: 1px;
    width: var(--goal-progress, 0%);
    border-radius: 5px;
    background:
        linear-gradient(90deg,
            var(--accent-aurora) 0%,
            var(--accent-cosmic) 50%,
            #ff8f6b 100%);
    background-size: 200% 100%;
    background-position: 0% 0%;
    box-shadow:
        0 0 16px rgba(102, 224, 198, 0.45),
        inset 0 1px 0 rgba(255, 255, 255, 0.25);
    transition: width 1600ms cubic-bezier(.16, 1, .32, 1);
    animation: goal-shimmer 5s ease-in-out infinite;
}
@keyframes goal-shimmer {
    0%, 100% { background-position: 0% 0%; }
    50%      { background-position: 100% 0%; }
}
@media (prefers-reduced-motion: reduce) {
    .goal-tracker-rail-fill { animation: none; transition: none; }
}

/* Rocket icon rides on the leading edge of the fill */
.goal-tracker-rocket {
    position: absolute;
    top: 50%;
    left: var(--goal-progress, 0%);
    transform: translate(-50%, -50%) rotate(90deg);
    width: 28px; height: 28px;
    display: flex; align-items: center; justify-content: center;
    font-size: 14px;
    color: var(--accent-cosmic);
    background: var(--bg-deep);
    border: 2px solid var(--accent-cosmic);
    border-radius: 50%;
    box-shadow:
        0 0 16px var(--accent-cosmic),
        0 0 32px rgba(255, 216, 107, 0.4);
    z-index: 3;
    transition: left 1600ms cubic-bezier(.16, 1, .32, 1);
    animation: goal-rocket-pulse 2.4s ease-in-out infinite;
}
@keyframes goal-rocket-pulse {
    0%, 100% { box-shadow: 0 0 16px var(--accent-cosmic), 0 0 32px rgba(255, 216, 107, 0.4); }
    50%      { box-shadow: 0 0 24px var(--accent-cosmic), 0 0 48px rgba(255, 216, 107, 0.6); }
}
@media (prefers-reduced-motion: reduce) {
    .goal-tracker-rocket { animation: none; transition: none; }
}

/* Tier markers along the rail */
.goal-tracker-tier-marker {
    position: absolute;
    top: 50%;
    left: var(--tier-pct, 0%);
    transform: translate(-50%, -50%);
    width: 16px; height: 16px;
    background: var(--bg-panel);
    border: 2px solid var(--line-soft);
    border-radius: 50%;
    z-index: 2;
    transition: border-color 400ms ease, background 400ms ease, box-shadow 400ms ease;
    cursor: help;
}
.goal-tracker-tier-marker[data-status="reached"] {
    background: var(--accent-aurora);
    border-color: var(--accent-cosmic);
    box-shadow: 0 0 12px rgba(102, 224, 198, 0.6);
}
.goal-tracker-tier-marker[data-status="in-progress"] {
    background: var(--accent-cosmic);
    border-color: var(--accent-cosmic);
    box-shadow: 0 0 16px rgba(255, 216, 107, 0.7);
    animation: goal-tier-active 1.6s ease-in-out infinite;
}
@keyframes goal-tier-active {
    0%, 100% { transform: translate(-50%, -50%) scale(1); }
    50%      { transform: translate(-50%, -50%) scale(1.25); }
}
.goal-tracker-tier-marker::after {
    content: attr(data-label);
    position: absolute;
    top: calc(100% + 8px);
    left: 50%;
    transform: translateX(-50%);
    font-family: var(--font-pixel);
    font-size: 8px;
    letter-spacing: 0.08em;
    color: var(--text-mute);
    white-space: nowrap;
}
.goal-tracker-tier-marker[data-status="reached"]::after {
    color: var(--accent-aurora);
}
.goal-tracker-tier-marker[data-status="in-progress"]::after {
    color: var(--accent-cosmic);
}

/* Tier description cards under the rail */
.goal-tracker-tiers {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 12px;
    position: relative;
    z-index: 1;
}
.goal-tracker-tier-card {
    padding: 14px 16px;
    background: var(--bg-panel);
    border: 1px solid var(--line-faint);
    border-left: 3px solid var(--line-faint);
    position: relative;
    transition: border-color 280ms ease, background 280ms ease, transform 180ms cubic-bezier(.16, 1, .32, 1);
}
.goal-tracker-tier-card:hover {
    transform: translateY(-2px);
}
.goal-tracker-tier-card[data-status="reached"] {
    border-left-color: var(--accent-aurora);
    background: linear-gradient(180deg, rgba(102, 224, 198, 0.06), transparent 60%), var(--bg-panel);
}
.goal-tracker-tier-card[data-status="in-progress"] {
    border-left-color: var(--accent-cosmic);
    background: linear-gradient(180deg, rgba(255, 216, 107, 0.08), transparent 60%), var(--bg-panel);
    box-shadow: 0 0 0 1px rgba(255, 216, 107, 0.18);
}
.goal-tracker-tier-card[data-status="locked"] {
    opacity: 0.78;
}
.goal-tracker-tier-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 4px;
}
.goal-tracker-tier-amount {
    font-family: var(--font-pixel);
    font-size: 13px;
    color: var(--text-pri);
    letter-spacing: 0.04em;
}
.goal-tracker-tier-card[data-status="reached"] .goal-tracker-tier-amount {
    color: var(--accent-aurora);
}
.goal-tracker-tier-card[data-status="in-progress"] .goal-tracker-tier-amount {
    color: var(--accent-cosmic);
}
.goal-tracker-tier-status {
    font-family: var(--font-pixel);
    font-size: 8px;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    padding: 2px 6px;
    background: var(--bg-deep);
    border: 1px solid var(--line-faint);
    color: var(--text-mute);
}
.goal-tracker-tier-card[data-status="reached"] .goal-tracker-tier-status {
    color: var(--accent-aurora);
    border-color: var(--accent-aurora);
}
.goal-tracker-tier-card[data-status="in-progress"] .goal-tracker-tier-status {
    color: var(--accent-cosmic);
    border-color: var(--accent-cosmic);
}
.goal-tracker-tier-title {
    font-family: var(--font-pixel);
    font-size: 11px;
    letter-spacing: 0.04em;
    color: var(--text-pri);
    line-height: 1.4;
    margin-bottom: 6px;
}
.goal-tracker-tier-body {
    font-size: 13px;
    color: var(--text-sec);
    line-height: 1.55;
    margin: 0;
}

.goal-tracker-footnote {
    margin-top: 22px;
    text-align: center;
    font-size: 12px;
    color: var(--text-mute);
    line-height: 1.5;
    position: relative;
    z-index: 1;
}
