:root {
    --color-bg: #050505;
    --color-surface: #101010;
    --color-contrast: #ffffff;
    --color-muted: #9d9d9d;
    --color-line: rgba(255, 255, 255, 0.12);
    --color-glow: rgba(255, 255, 255, 0.08);
    --color-invert-bg: #fafafa;
    --color-invert-text: #0a0a0a;
    --max-width: 1080px;
    --spacing: clamp(1.25rem, 2vw + 1rem, 2.5rem);
    --radius: 18px;
    --shadow-hard: 0 24px 48px rgba(0, 0, 0, 0.45);
    --shadow-soft: 0 20px 40px rgba(0, 0, 0, 0.3);
    --font-sans: "Inter", "Helvetica Neue", Arial, sans-serif;
    --font-display: "Space Grotesk", "Inter", "Helvetica Neue", Arial, sans-serif;
    --motion-duration: 0.85s;
    --motion-ease: cubic-bezier(0.16, 1, 0.3, 1);
    --body-background: radial-gradient(circle at top, rgba(255, 255, 255, 0.06), transparent 60%), var(--color-bg);
    --nav-background: linear-gradient(180deg, rgba(6, 12, 22, 0.74) 0%, rgba(6, 12, 22, 0.48) 60%, rgba(6, 12, 22, 0.12) 100%);
    --nav-background-solid: linear-gradient(180deg, rgba(6, 12, 22, 0.94) 0%, rgba(6, 12, 22, 0.82) 60%, rgba(6, 12, 22, 0.68) 100%);
    --hero-overlay: linear-gradient(120deg, rgba(5, 5, 5, 0.9) 10%, rgba(5, 5, 5, 0.4) 60%, rgba(5, 5, 5, 0.85) 100%);
    --page-hero-background: var(--nav-background);
    --section-cta-background: linear-gradient(160deg, rgba(255, 255, 255, 0.05), transparent 60%);
    --card-background: rgba(255, 255, 255, 0.03);
    --card-border: var(--color-line);
    --card-ghost-bg: rgba(255, 255, 255, 0.02);
    --list-chip-bg: rgba(255, 255, 255, 0.04);
    --contrast-list-border: rgba(10, 10, 10, 0.15);
    --button-bg: rgba(255, 255, 255, 0.08);
    --button-border: rgba(255, 255, 255, 0.45);
    --button-text: var(--color-contrast);
    --button-shadow: 0 16px 28px rgba(0, 0, 0, 0.35);
    --button-hover-bg: rgba(255, 255, 255, 0.14);
    --button-inverted-bg: var(--color-contrast);
    --button-inverted-text: var(--color-invert-text);
    --footer-bg: rgba(5, 5, 5, 0.9);
    --footer-text: var(--color-muted);
    --footer-link: var(--color-contrast);
    --toggle-track: rgba(255, 255, 255, 0.18);
    --toggle-thumb: #ffffff;
    --toggle-thumb-shadow: 0 6px 14px rgba(0, 0, 0, 0.2);
    --profile-border: rgba(255, 255, 255, 0.4);
    --profile-shadow: 0 18px 46px rgba(0, 0, 0, 0.45);
    --link-underline: rgba(255, 255, 255, 0.45);
}

.theme-light {
    --color-bg: #f5f7fa;
    --color-surface: #ffffff;
    --color-contrast: #10121a;
    --color-muted: #47505f;
    --color-line: rgba(16, 18, 26, 0.08);
    --color-glow: rgba(16, 18, 26, 0.05);
    --color-invert-bg: #0b1523;
    --color-invert-text: #f2f6ff;
    --shadow-hard: 0 24px 48px rgba(16, 18, 26, 0.12);
    --shadow-soft: 0 18px 32px rgba(16, 18, 26, 0.08);
    --body-background: var(--color-bg);
    --nav-background: linear-gradient(180deg, rgba(246, 248, 255, 0.85) 0%, rgba(232, 238, 248, 0.58) 60%, rgba(232, 238, 248, 0.16) 100%);
    --nav-background-solid: linear-gradient(180deg, rgba(246, 248, 255, 0.98) 0%, rgba(232, 238, 248, 0.86) 60%, rgba(232, 238, 248, 0.72) 100%);
    --hero-overlay: linear-gradient(120deg, rgba(255, 255, 255, 0.95) 10%, rgba(255, 255, 255, 0.65) 60%, rgba(255, 255, 255, 0.9) 100%);
    --page-hero-background: linear-gradient(180deg, rgba(246, 248, 255, 0.5), rgba(232, 238, 248, 0));
    --section-cta-background: linear-gradient(160deg, rgba(16, 18, 26, 0.08), transparent 60%);
    --card-background: rgba(226, 239, 255, 0.86);
    --card-border: rgba(112, 146, 210, 0.24);
    --card-ghost-bg: rgba(226, 239, 255, 0.42);
    --list-chip-bg: rgba(16, 18, 26, 0.06);
    --contrast-list-border: rgba(255, 255, 255, 0.35);
    --button-bg: rgba(16, 18, 26, 0.08);
    --button-border: rgba(16, 18, 26, 0.16);
    --button-text: var(--color-contrast);
    --button-shadow: 0 16px 28px rgba(16, 18, 26, 0.15);
    --button-hover-bg: rgba(16, 18, 26, 0.12);
    --button-inverted-bg: var(--color-contrast);
    --button-inverted-text: #f5f7fa;
    --footer-bg: rgba(255, 255, 255, 0.92);
    --footer-text: rgba(16, 18, 26, 0.72);
    --footer-link: var(--color-contrast);
    --toggle-track: rgba(16, 18, 26, 0.12);
    --toggle-thumb: #10121a;
    --toggle-thumb-shadow: 0 6px 14px rgba(16, 18, 26, 0.12);
    --profile-border: rgba(16, 18, 26, 0.25);
    --profile-shadow: 0 18px 46px rgba(16, 18, 26, 0.18);
    --link-underline: rgba(16, 18, 26, 0.35);
}

* {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    position: relative;
    z-index: 0;
    margin: 0;
    font-family: var(--font-sans);
    color: var(--color-contrast);
    background: var(--body-background);
    line-height: 1.65;
    font-feature-settings: "ss01" on, "liga" on;
    text-rendering: optimizeLegibility;
}

.skip-link {
    position: fixed;
    left: 16px;
    top: 12px;
    z-index: 10000;
    padding: 10px 14px;
    border-radius: 8px;
    background: var(--color-contrast);
    color: var(--color-bg);
    font-weight: 700;
    text-decoration: none;
    transform: translateY(-160%);
    transition: transform 0.2s ease;
}
.skip-link:focus { transform: translateY(0); }

:where(a, button, input, textarea, select, [role="button"], [tabindex]):focus-visible {
    outline: 3px solid #ff9a3d;
    outline-offset: 4px;
}

.theme-light :where(a, button, input, textarea, select, [role="button"], [tabindex]):focus-visible {
    outline-color: #8f3505;
}

.error-stage {
    width: min(760px, calc(100% - 40px));
    min-height: calc(100vh - 80px);
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    position: relative;
    z-index: 2;
}
.error-stage__code {
    margin: 0 0 -0.25em;
    font-family: var(--font-display);
    font-size: clamp(5rem, 18vw, 12rem);
    font-weight: 700;
    line-height: 0.9;
    color: rgba(180,230,255,0.12);
}
.error-stage h1 { margin: 0.2rem 0 0.6rem; font-size: clamp(2rem, 6vw, 4.5rem); }
.error-stage > p:not(.error-stage__code):not(.eyebrow) { max-width: 560px; color: var(--color-muted); }
.error-stage__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 1.4rem; }



@media (pointer: coarse) {
    .cursor-dot, .cursor-ring { display: none; }
}

.site-backdrop {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: radial-gradient(circle at top 20% left 35%, rgba(42, 76, 120, 0.38), rgba(4, 6, 12, 0.85) 65%),
        radial-gradient(circle at bottom right, rgba(78, 42, 120, 0.3), transparent 70%),
        var(--body-background);
    overflow: hidden;
}

.site-backdrop__canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    mix-blend-mode: screen;
    /* A modest lift on top of the saturated palettes in the *-3d.js files. `screen`
       pulls bright values toward white, so the thickest, brightest parts of a root are
       exactly where hue drains away; this puts some of it back without touching the
       geometry or the alpha. Kept low — past ~125% the trunks start to look tinted
       rather than lit. */
    filter: saturate(118%);
    opacity: 0.68;
    transform-origin: 50% 50%;
    will-change: transform, filter, opacity;
}

[data-page-shell] {
    position: relative;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    /* This one line is what stops the scrollbar flashing on every page change.
       The entrance translates the content down 22px, and a transform counts toward
       the SCROLLABLE overflow region — so for the length of the transition the
       document was 22px taller than the window and the browser grew a real 15px
       scrollbar, measured present for 64 frames. The 15px it took shifted the whole
       layout sideways, which is what read as flicker.
       `clip`, not `hidden`: clip does not create a scroll container, so it cannot
       trap or swallow scrolling. It clips nothing real either — this box is sized by
       its content, so a page that genuinely overflows still makes the shell taller
       and still scrolls; only the transform's overflow, which is 22px of empty space
       below the content, stops counting. The root canvases are unaffected: every
       backdrop lives outside this element (base.html line 82, before the shell) and
       the rail is appended to <body>.
       Clipping the ROOT for the duration of `page-is-loading` was tried first and is
       not enough — the transform animates back over 420ms AFTER that class is
       removed, and it overflows for every frame of that animation. */
    overflow: clip;
}

[data-page-shell-content] {
    flex: 1 0 auto;
    display: flex;
    flex-direction: column;
    transform: translateY(0);
    opacity: 1;
    will-change: transform, opacity;
    transition: transform 420ms cubic-bezier(0.22, 0.61, 0.36, 1), opacity 360ms ease;
}

[data-page-shell-content] > main {
    flex: 1 0 auto;
}

/* ── the scrollbar that flashed on every page change ──
   Clipping the root for the length of the transition is the whole fix. Two things
   were tried first and are recorded so they are not tried again:
   `scrollbar-gutter: stable` does nothing here — Chrome did not reserve the gutter
   at rest even with the root made an explicit scroll container (`overflow-y: auto`),
   and it DID reserve it while the clip below was applied, which simply moved the
   15px jump from 64 frames to 20 rather than removing it. And `overflow-y: scroll`
   would hold the width constant only by showing a permanent scrollbar, which is the
   bar we are removing. */
html.page-is-loading [data-page-shell-content] {
    transform: translateY(22px);
    opacity: 0;
    /* FAIL-SAFE: the content must never need JS to become visible.
       `page-is-loading` is removed by page-transitions.js on `pageshow`, and if that
       event never arrives — a browser that skips it, a JS error earlier in the page,
       an embedded webview — the whole page stays at opacity 0 and reads as blank. This
       was found in the in-app browser pane, which fires no `pageshow`: every page sat
       invisible with its content 22px low. The animation reveals it anyway after
       1.2s, well behind the normal 420ms transition, so it only ever fires when the
       normal path did not. */
    animation: shell-fail-safe 600ms 1200ms forwards;
}

@keyframes shell-fail-safe {
    to { transform: none; opacity: 1; }
}

html.page-is-exiting [data-page-shell-content] > :not(main),
html.page-is-exiting [data-page-shell-content] main > * {
    animation: page-section-exit 360ms var(--motion-ease) forwards;
    animation-delay: calc(var(--exit-i, 0) * 38ms);
}

@keyframes page-section-exit {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-14px); }
}

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

    html.page-is-loading [data-page-shell-content] {
        transform: none;
        opacity: 1;
    }

    html.page-is-exiting [data-page-shell-content] > :not(main),
    html.page-is-exiting [data-page-shell-content] main > * {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
    }
}

.page-transition {
    position: fixed;
    inset: 0;
    z-index: 120;
    pointer-events: none;
    background: transparent;
    opacity: 0;
    transition: opacity 0.36s ease;
}


.theme-light .site-backdrop {
    background: transparent;
}

/* ── room for the side rail on a phone ──
   The rail is the only navigation on an inner page, so it stays put on mobile as a
   44px strip of tappable dots (see side-nav.js). Its dots sit on top of whatever is
   underneath, and the stacked lists run the full width — measured at 440x956, all six
   of Home's mark rows passed under it. This gives the content the strip's width back.
   The fixed root canvases are unaffected: they are not in this box. */
@media (max-width: 768px) {
    [data-page-shell-content] {
        padding-right: 46px;
    }
}

.theme-light .site-backdrop__canvas {
    /* 0.68, not 0.55. The dark theme's `screen` blend does the heavy lifting there —
       the lines only have to out-glow black. Light theme blends `normal` over a
       near-white page (#f5f7fa), so what reaches the eye is material opacity TIMES
       this: at 0.58 * 0.55 = 0.32 effective alpha the roots were barely there, which
       is exactly how they looked; 0.62 * 0.68 = 0.42 is roughly a third more ink, and
       the deepened _L palettes in the *-3d.js files do the rest.
       NOT higher than this. Measured on Team: a dense terminal tuft carries only 1.27x
       a lone twig's alpha, so there is no setting that shows the twigs and hides the
       tufts — past ~0.75 the tufts stop reading as foliage and start reading as solid
       speckled discs. `multiply` was the other candidate and is wrong
       here: the line materials blend additively inside the canvas, so the dense inner
       mass saturates toward white and would have multiplied to nothing — the thickest
       part of the root would have been the most invisible.
       0.74, raised from 0.68 after the roots were still reported as barely there on the
       light theme. This is the ceiling: past ~0.75 a dense terminal tuft stops reading as
       foliage and becomes a solid speckled disc (measured on Team — a tuft carries only
       1.27x a lone twig's alpha, so there is no setting that shows one and hides the
       other). */
    opacity: 0.74;
    mix-blend-mode: normal;
    filter: saturate(150%);
}


.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

a {
    color: inherit;
}

img {
    max-width: 100%;
    display: block;
}

.container {
    width: min(100% - 2 * var(--spacing), var(--max-width));
    margin: 0 auto;
}

.site-main,
.footer {
    position: relative;
    z-index: 1;
}

.site-header {
    position: relative;
    z-index: 1;
    position: sticky;
    top: 0;
    z-index: 100;
    backdrop-filter: blur(14px);
    background: var(--nav-background);
    box-shadow: 0 18px 32px rgba(0, 0, 0, 0.28);
    transform: translateY(0);
    opacity: 1;
    transition: transform 420ms var(--motion-ease), opacity 320ms ease;
}

.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 1rem 0;
}

.site-header.site-header--solid {
    background: var(--nav-background-solid);
}

.theme-light .site-header {
    box-shadow: 0 18px 32px rgba(68, 108, 160, 0.18);
}

.theme-light .site-header.site-header--solid {
    background: var(--nav-background-solid);
}

.site-header__actions {
    display: flex;
    align-items: center;
    gap: 1.5rem;
}

.header-controls {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.brand {
    font-weight: 700;
    font-size: 1.25rem;
    letter-spacing: 0.2em;
    text-transform: none;
    text-decoration: none;
    color: var(--color-contrast);
}

.nav {
    display: flex;
    gap: 1rem;
}

.nav__link {
    position: relative;
    padding: 0.35rem 0.6rem;
    text-decoration: none;
    text-transform: uppercase;
    font-size: 0.75rem;
    letter-spacing: 0.18em;
    color: var(--color-muted);
    transition: color 0.2s ease;
}

.nav__link::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    bottom: -0.35rem;
    height: 2px;
    background: var(--color-contrast);
    opacity: 0;
    transform: scaleX(0.25);
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.nav__link:hover,
.nav__link--active {
    color: var(--color-contrast);
}

.nav__link--active::after,
.nav__link:hover::after {
    opacity: 1;
    transform: scaleX(1);
}

@media (max-width: 1200px) {
    .nav-toggle {
        display: inline-flex;
        z-index: 110;
    }

    .site-header__actions {
        position: fixed;
        inset: 0;
        width: 100vw;
        min-height: 100vh;
        padding: clamp(4rem, 9vw, 5.5rem) clamp(1.8rem, 6vw, 2.8rem) clamp(3.5rem, 9vw, 5.5rem);
        background: var(--color-bg);
        display: flex;
        flex-direction: column;
        align-items: stretch;
        justify-content: space-between;
        gap: clamp(1.8rem, 6vw, 2.6rem);
        z-index: 105;
        overflow-y: auto;
        transform: translateX(100%);
        transition: transform 0.45s var(--motion-ease);
        pointer-events: none;
    }

    .nav-open .site-header__actions {
        transform: translateX(0);
        pointer-events: auto;
    }

    .nav {
        display: flex;
        flex-direction: column;
        gap: clamp(1.4rem, 5.5vw, 2.2rem);
        width: 100%;
        text-align: left;
    }

    .nav__link {
        font-size: clamp(1.3rem, 5.2vw, 1.7rem);
        letter-spacing: 0.2em;
        padding: 0;
        color: var(--color-contrast);
        opacity: 0;
        transform: translateX(18px);
        transition: opacity 0.35s var(--motion-ease), transform 0.35s var(--motion-ease);
    }

    .nav__link:nth-child(1) { transition-delay: 0.22s; }
    .nav__link:nth-child(2) { transition-delay: 0.30s; }
    .nav__link:nth-child(3) { transition-delay: 0.38s; }
    .nav__link:nth-child(4) { transition-delay: 0.46s; }
    .nav__link:nth-child(5) { transition-delay: 0.54s; }

    .nav-open .nav__link {
        opacity: 1;
        transform: translateX(0);
    }

    .header-controls {
        flex-direction: column;
        align-items: stretch;
        gap: 1rem;
        width: 100%;
    }

}

.nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 58px;
    height: 58px;
    border-radius: 20px;
    border: 1px solid rgba(255, 255, 255, 0.65);
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.05));
    box-shadow: 0 20px 36px rgba(0, 0, 0, 0.45);
    cursor: pointer;
    transition: transform 0.2s ease, border-color 0.2s ease, background 0.2s ease;
    margin-left: auto;
    position: relative;
    z-index: 110;
}

.nav-toggle:hover {
    border-color: var(--color-contrast);
    background: linear-gradient(135deg, rgba(255, 255, 255, 0.28), rgba(255, 255, 255, 0.08));
    transform: translateY(-1px) scale(1.02);
}

.nav-toggle__icon {
    position: relative;
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

.nav-toggle__icon::before,
.nav-toggle__icon::after {
    content: "";
    position: absolute;
    left: 0;
    width: 100%;
    height: 3px;
    border-radius: 999px;
    background: var(--color-contrast);
    transform-origin: 18% 50%;
    transition: transform 0.35s var(--motion-ease), opacity 0.3s ease;
}

.nav-toggle__icon::before {
    transform: translateY(-6px);
}

.nav-toggle__icon::after {
    transform: translateY(6px);
}

.nav-open .nav-toggle__icon::before {
    transform: translateY(0) rotate(45deg);
}

.nav-open .nav-toggle__icon::after {
    transform: translateY(0) rotate(-45deg);
}

.theme-light .nav-toggle {
    background: linear-gradient(135deg, rgba(16, 18, 26, 0.12), rgba(16, 18, 26, 0.06));
    border-color: rgba(16, 18, 26, 0.22);
    box-shadow: 0 18px 30px rgba(16, 18, 26, 0.2);
}

.theme-light .nav-toggle:hover {
    background: linear-gradient(135deg, rgba(16, 18, 26, 0.22), rgba(16, 18, 26, 0.08));
}

@media (min-width: 1201px) {
    .nav-toggle {
        display: none;
    }

    .site-header__actions {
        display: flex;
    }
}

.nav-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(5, 5, 5, 0.55);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
    z-index: 95;
}

.theme-light .nav-backdrop {
    background: rgba(16, 18, 26, 0.4);
}

.theme-toggle {
    position: relative;
    width: 58px;
    height: 30px;
    border-radius: 999px;
    border: 1px solid var(--button-border);
    background: var(--toggle-track);
    cursor: pointer;
    padding: 0;
    transition: background 0.3s ease, border-color 0.3s ease;
}

.theme-toggle:hover {
    border-color: var(--color-contrast);
}

/* ── Seed node toggle ── */
.seed-toggle {
    position: relative;
    width: 32px;
    height: 32px;
    border: none;
    background: transparent;
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.seed-toggle__canvas {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 9999;
}

.seed-toggle__node {
    display: block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: rgba(220, 155, 35, 0.9);
    box-shadow: 0 0 10px rgba(220,155,35,0.7), 0 0 28px rgba(220,155,35,0.35);
    transition: transform 0.2s ease, box-shadow 0.3s ease, background 0.3s ease;
    animation: seed-pulse 2.8s ease-in-out infinite;
}

.seed-toggle:hover .seed-toggle__node {
    transform: scale(1.45);
    box-shadow: 0 0 18px rgba(220,155,35,1), 0 0 44px rgba(220,155,35,0.5);
}

/* light theme: dormant/dimmed */
.theme-light .seed-toggle__node {
    background: rgba(150, 90, 10, 0.55);
    box-shadow: 0 0 6px rgba(150,90,10,0.3), 0 0 14px rgba(150,90,10,0.15);
    animation: none;
}

.theme-light .seed-toggle:hover .seed-toggle__node {
    background: rgba(150, 90, 10, 0.85);
    box-shadow: 0 0 12px rgba(150,90,10,0.6), 0 0 28px rgba(150,90,10,0.3);
    transform: scale(1.35);
}

/* burst state: briefly scales up on click */
.seed-toggle--burst .seed-toggle__node {
    animation: none;
    transform: scale(2.2);
    box-shadow: 0 0 32px rgba(220,155,35,1), 0 0 80px rgba(220,155,35,0.6);
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}

@keyframes seed-pulse {
    0%, 100% {
        transform: scale(1);
        box-shadow: 0 0 10px rgba(220,155,35,0.7), 0 0 28px rgba(220,155,35,0.35);
    }
    50% {
        transform: scale(1.22);
        box-shadow: 0 0 18px rgba(220,155,35,1), 0 0 44px rgba(220,155,35,0.5);
    }
}

/* ── Option 2: signal / radial-wipe toggle ── */
.signal-toggle {
    position: relative;
    width: 62px;
    height: 34px;
    border: none;
    background: transparent;
    cursor: pointer;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* canvas is appended to body via JS — the liquid-glass wipe (theme-wipe.js) and
   the flat-ring fallback it replaces share these rules */
.theme-wipe__canvas,
.signal-toggle__wipe-canvas {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 9998;
}

/* tooltip */
.signal-toggle[data-tip]::after {
    content: attr(data-tip);
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    background: var(--color-surface);
    color: var(--color-muted);
    border: 1px solid var(--color-line);
    font-family: var(--font-sans);
    font-size: 0.68rem;
    letter-spacing: 0.04em;
    white-space: nowrap;
    padding: 4px 9px;
    border-radius: 6px;
    pointer-events: none;
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 0.18s ease, transform 0.18s ease;
    z-index: 1000;
}

.signal-toggle[data-tip]:hover::after {
    opacity: 1;
    transform: translateY(0);
}

/* ── soft-UI body: a recessed socket, a raised face, a glow behind it ──
   Dark is the lit state: the pill sinks into the page and the moon blooms.
   Light is the resting state: the pill is a pale button and the moon is a
   small dark crescent. The face TRAVELS the length of the socket between the
   two states — that slide is the movement, everything else (fill, glow, moon)
   just rides along with it, so the switch reads as one object moving rather
   than two icons swapping.
   Travel = 62 - 2*4 padding - 26 face = 28px. */
.signal-toggle__socket {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    height: 100%;
    padding: 4px;
    box-sizing: border-box;
    border-radius: 999px;
    /* light: pale key-light from top-left, shadow bottom-right */
    background: linear-gradient(145deg, #e9edf3, #f7f9fc);
    box-shadow:
        inset 0.09em 0.12em 0.22em rgba(16, 24, 38, 0.13),
        inset -0.07em -0.09em 0.18em rgba(255, 255, 255, 0.95),
        0 0.05em 0.12em rgba(16, 24, 38, 0.07);
    transition: background 0.42s ease, box-shadow 0.42s ease;
}

.theme-dark .signal-toggle__socket {
    background: linear-gradient(145deg, #0a0f17, #10161f);
    box-shadow:
        inset 0.09em 0.12em 0.26em rgba(0, 0, 0, 0.85),
        inset -0.06em -0.08em 0.18em rgba(255, 255, 255, 0.05),
        0 0.04em 0.1em rgba(0, 0, 0, 0.5);
}

.signal-toggle__face {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: linear-gradient(150deg, #ffffff, #dfe5ee);
    box-shadow:
        0 0.1em 0.18em rgba(16, 24, 38, 0.2),
        inset 0 0.05em 0.08em rgba(255, 255, 255, 0.9);
    transform: translateX(0) scale(1);
    /* slight overshoot at the end of the travel — the knob settles rather than
       stopping dead. Fill and glow are slower than the slide so the colour
       change trails the movement instead of racing it. */
    transition: transform 0.46s cubic-bezier(0.34, 1.28, 0.52, 1),
                background 0.5s ease,
                box-shadow 0.5s ease;
}

.theme-dark .signal-toggle__face {
    transform: translateX(28px) scale(1);
    background: radial-gradient(circle at 34% 28%, #1c2634, #0b1017 78%);
    box-shadow:
        0 0.08em 0.16em rgba(0, 0, 0, 0.6),
        inset 0 0.05em 0.08em rgba(255, 255, 255, 0.07);
}

.signal-toggle__moon {
    width: 13px;
    height: 13px;
    display: block;
    overflow: visible;
    fill: rgba(44, 58, 80, 0.88);
    stroke: none;
    transform: rotate(0deg);
    /* the crescent turns a little as the knob travels, so the face reads as
       rolling across the socket rather than being carried flat */
    transition: fill 0.5s ease, filter 0.5s ease,
                transform 0.46s cubic-bezier(0.34, 1.28, 0.52, 1);
    filter: none;
}

.theme-dark .signal-toggle__moon {
    transform: rotate(-28deg);
    fill: #f2f7ff;
    filter: drop-shadow(0 0 3px rgba(190, 220, 255, 0.85))
            drop-shadow(0 0 7px rgba(120, 170, 255, 0.4));
}

/* the bloom: off in light, lit in dark — this is what the reel's `.glow` does */
.signal-toggle__glow {
    position: absolute;
    top: 50%;
    left: 4px;                 /* socket padding — aligns with the face at rest */
    width: 34px;
    height: 34px;
    margin: -17px 0 0 -4px;    /* centres the 34px bloom on the 26px face */
    border-radius: 50%;
    pointer-events: none;
    background: radial-gradient(circle,
        rgba(198, 224, 255, 0.5) 0%,
        rgba(140, 185, 255, 0.22) 45%,
        rgba(140, 185, 255, 0) 72%);
    opacity: 0;
    transform: translateX(0);
    /* same curve as the face, so the bloom stays welded to the knob */
    transition: opacity 0.42s cubic-bezier(0.32, 0.72, 0, 1),
                transform 0.46s cubic-bezier(0.34, 1.28, 0.52, 1);
}

.theme-dark .signal-toggle__glow {
    opacity: 1;
    transform: translateX(28px);
}

/* status LED under the pill: dim amber in light, lit amber in dark */
.signal-toggle__led {
    position: absolute;
    bottom: -1px;
    left: 15.5px;              /* 4px padding + half the 26px face - 1.5px */
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: rgba(150, 90, 10, 0.3);
    transform: translateX(0);
    transition: background 0.5s ease, box-shadow 0.5s ease,
                transform 0.46s cubic-bezier(0.34, 1.28, 0.52, 1);
}

.theme-dark .signal-toggle__led {
    transform: translateX(28px);
    background: rgba(220, 155, 35, 0.95);
    box-shadow: 0 0 4px rgba(220, 155, 35, 0.8);
}

.signal-toggle:hover .signal-toggle__face { box-shadow: 0 0.12em 0.22em rgba(16, 24, 38, 0.26), inset 0 0.05em 0.08em rgba(255, 255, 255, 0.9); }
.theme-dark .signal-toggle:hover .signal-toggle__face { box-shadow: 0 0.1em 0.2em rgba(0, 0, 0, 0.65), inset 0 0.05em 0.1em rgba(255, 255, 255, 0.12); }
.theme-dark .signal-toggle:hover .signal-toggle__glow { opacity: 1; transform: translateX(28px) scale(1.12); }

/* press: the knob squashes into the socket without losing its place on the
   track — every :active transform has to restate the travel, or the knob
   snaps back to the left while held. The socket's rim light is the reel's
   own rule. */
.signal-toggle:active .signal-toggle__face { transform: translateX(0) scale(0.94); }
.theme-dark .signal-toggle:active .signal-toggle__face { transform: translateX(28px) scale(0.94); }
.signal-toggle:active .signal-toggle__socket {
    box-shadow:
        inset 0.11em 0.15em 0.26em rgba(16, 24, 38, 0.18),
        -0.045em 0.1em 0.2em -0.15em rgba(255, 255, 255, 0.9);
}
.theme-dark .signal-toggle:active .signal-toggle__socket {
    box-shadow:
        inset 0.11em 0.15em 0.3em rgba(0, 0, 0, 0.9),
        -0.045em 0.1em 0.2em -0.15em rgba(255, 255, 255, 0.35);
}
.signal-toggle:active .signal-toggle__glow { opacity: 0; }

.signal-toggle:focus-visible {
    outline: none;
}
.signal-toggle:focus-visible .signal-toggle__socket {
    box-shadow:
        0 0 0 2px rgba(220, 155, 35, 0.85),
        inset 0.09em 0.12em 0.22em rgba(16, 24, 38, 0.13);
}

@media (prefers-reduced-motion: reduce) {
    .signal-toggle__socket,
    .signal-toggle__face,
    .signal-toggle__moon,
    .signal-toggle__glow,
    .signal-toggle__led { transition: none; }
}

/* ── copyright in header ── */
.header-copyright {
    font-size: 0.62rem;
    letter-spacing: 0.08em;
    color: var(--color-muted);
    opacity: 0.5;
    flex: 1;
    text-align: center;
    pointer-events: none;
    user-select: none;
}

/* ── floating LinkedIn icon ── */
.linkedin-float {
    position: fixed;
    bottom: 20px;
    left: 20px;
    z-index: 800;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255, 255, 255, 0.28);
    transition: color 0.25s ease, filter 0.25s ease, transform 0.25s ease;
}

.linkedin-float svg {
    width: 18px;
    height: 18px;
    fill: currentColor;
}

.linkedin-float:hover {
    color: rgba(220, 155, 35, 0.9);
    filter: drop-shadow(0 0 6px rgba(220,155,35,0.6)) drop-shadow(0 0 14px rgba(220,155,35,0.3));
    transform: scale(1.15);
}

.theme-light .linkedin-float {
    color: rgba(16, 18, 26, 0.30);
}

.theme-light .linkedin-float:hover {
    color: rgba(150, 90, 10, 0.9);
    filter: drop-shadow(0 0 5px rgba(150,90,10,0.4));
}

.nav-open body {
    position: relative;
    z-index: 0;
    overflow: hidden;
}

.nav-open .nav-backdrop {
    opacity: 1;
    pointer-events: auto;
}

.theme-toggle::before,
.theme-toggle::after {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.7rem;
    pointer-events: none;
}

.theme-toggle::before {
    content: "☾";
    left: 10px;
    opacity: 0.65;
}

.theme-toggle::after {
    content: "☀";
    right: 10px;
    opacity: 0.35;
}

.theme-toggle[data-theme="theme-light"]::before {
    opacity: 0.25;
}

.theme-toggle[data-theme="theme-light"]::after {
    opacity: 0.75;
}

.theme-toggle__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.theme-toggle__knob {
    position: absolute;
    top: 4px;
    left: 4px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--toggle-thumb);
    box-shadow: var(--toggle-thumb-shadow);
    transition: transform 0.3s ease, background 0.3s ease, box-shadow 0.3s ease;
}

.theme-toggle[data-theme="theme-light"] .theme-toggle__knob {
    transform: translateX(26px);
}

/* Mobile browser chrome changes the visible viewport while scrolling. Dynamic
   viewport units keep full-screen compositions inside the actually visible area;
   their existing 100vh rules remain the fallback for older browsers. */
@supports (height: 100dvh) {
    @media (max-width: 768px) {
        html,
        body,
        .site-shell {
            min-height: 100dvh;
        }

        .identity-hero {
            height: 100dvh;
            min-height: 100dvh;
        }

        .about-stage {
            min-height: calc(100dvh - 80px);
        }
    }
}
