/* === TOKENS (supplement to critical inline CSS) === */
/* @font-face, reset, :root, body base are in inline <style> for FOUC prevention */

body {
    scrollbar-width: thin;
    scrollbar-color: var(--line) transparent;
}

body::-webkit-scrollbar {
    width: 4px;
}

body::-webkit-scrollbar-track {
    background: transparent;
}

body::-webkit-scrollbar-thumb {
    background: var(--line);
    border-radius: 2px;
}

body::-webkit-scrollbar-thumb:hover {
    background: var(--text-3);
}

::selection {
    background: var(--highlight-selection);
    color: var(--text-1);
}

/* === LAYOUT === */

/* --- CURSOR 3D --- */
@media (hover: hover) and (min-width: 769px) {
    /* The OS cursor is the fail-safe. js/cursor-boot.js adds .cursor-ready only
       once a custom pointer is confirmed visible (3D first frame, or the SVG
       fallback). If WebGL init throws, the GLB 404s, the CDN is blocked, or the
       module stalls, this class never lands and the OS cursor stays. */
    html.cursor-ready *,
    html.cursor-ready *::before,
    html.cursor-ready *::after {
        cursor: none !important;
    }

    #cursor3d,
    #cursor3d-fallback {
        position: fixed;
        top: 0;
        left: 0;
        width: 120px;
        height: 120px;
        pointer-events: none;
        z-index: 10000;
        /* mix-blend-mode removed, caused cursor to vanish over dark overlays like cookie banner */
        transform: translate(calc(var(--mx, -100px) - 60px), calc(var(--my, -100px) - 60px));
    }

    #cursor3d-fallback {
        width: 48px;
        height: 48px;
        transform: translate(calc(var(--mx, -100px) - 24px), calc(var(--my, -100px) - 24px));
    }
}
@media not all and (hover: hover), (max-width: 768px) {
    #cursor3d,
    #cursor3d-fallback { display: none; }
}

/* --- MOBILE CURSOR MARK (audit D3-4) ---
   Where the WebGL cursor doesn't run, cursor-boot.js drops a 28px frame of
   assets/cursor-strip.svg into the page header (or the home hero). Scroll turns it
   by sliding the strip one frame at a time. Transform only. */
.cursor-mark {
    display: inline-block;
    flex: none;
    width: 28px;
    height: 28px;
    overflow: hidden;
    opacity: 0.7;
    pointer-events: none;
}
.cursor-mark img {
    display: block;
    width: auto;
    max-width: none;
    height: 28px;
    will-change: transform;
}
#hero > .cursor-mark {
    position: absolute;
    top: 16px;
    right: 16px;
    z-index: 5;
}
@media (hover: hover) and (min-width: 769px) {
    .cursor-mark { display: none; }
}

/* Firefox keeps the OS cursor: cursor-boot.js returns before marking ready, so
   .cursor-ready never lands and the rule above never applies. The old
   @-moz-document override is redundant now and was removed. */

/* --- VIEW TRANSITIONS (audit D3-7) ---
   A card cover morphs into the detail-page cover that shares its
   view-transition-name (js/cards.mjs coverTransitionName). Nothing else animates.
   Browsers without support just navigate. */
@view-transition {
    navigation: auto;
}

::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
    animation-duration: 0.5s;
    animation-timing-function: var(--ease-expo);
}

/* No page cross-fade (2026-09-30, user). The old page snapshot is dropped and the
   new one is static, so the page swaps at once and body's own pageIn fade is the
   only page fade, same as a plain navigation. */
::view-transition-old(root) {
    display: none;
}
::view-transition-new(root) {
    animation: none;
    mix-blend-mode: normal;
}

/* --- LAYOUT --- */

.page {
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 30px;
}

section {
    border-bottom: 1px solid var(--line);
    padding: 80px 0;
}

section:last-of-type {
    border-bottom: none;
}

/* --- Responsive --- */

/* Tablet (769-1024px) */
@media (max-width: 1024px) {
    .page {
        padding: 0 24px;
    }

    section {
        padding: 60px 0;
    }
}

/* Mobile (<=768px) */
@media (max-width: 768px) {
    .page {
        padding: 0 16px;
    }

    section {
        padding: 48px 0;
    }
}

/* Small mobile (<=400px) */
@media (max-width: 400px) {
    .page {
        padding: 0 12px;
    }
}

/* === ACCESSIBILITY === */

/* Skip link (visible only on focus) */
.skip-link {
    position: fixed;
    top: 16px;
    left: 16px;
    /* Off-screen via transform, not top: layout properties never animate (audit DL-6). */
    transform: translateY(calc(-100% - 32px));
    transition: transform 0.2s var(--ease-quart);
    z-index: 999;
    padding: 8px 16px;
    background: var(--text-1);
    color: var(--bg);
    font-family: var(--mono);
    font-size: 12px;
    line-height: 1.3;
    text-decoration: none;
}

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

.skip-link:focus {
    transform: translateY(0);
}

/* Focus indicators for keyboard navigation */
:focus-visible {
    outline: 1px dashed var(--text-2);
    outline-offset: 3px;
}
