/* ============================================================
   repio.dev hub — 3D/motion prototype (stops 1-3: hero, Macro,
   meeting room / Scribe)
   Design tokens copied verbatim from repio-scribe's assets/css/style.css
   (commented there as "shared with repio.dev") so the hub and its
   product landings read as one family.
   ============================================================ */
:root {
    --bg-dark: #0a0e1a;
    --bg-darker: #060912;
    --bg-card: rgba(20, 24, 38, 0.62);
    --bg-card-solid: #161b2a;
    --bg-card-hover: #1d2438;
    --primary: #4f46e5;
    --primary-light: #6366f1;
    --secondary: #06b6d4;
    --accent: #10b981;
    --accent-dark: #059669;
    --violet: #7c3aed;
    --text-primary: #f1f5f9;
    --text-secondary: #9aa7bd;
    --text-muted: #64748b;
    --gradient-hero: linear-gradient(135deg, #4f46e5 0%, #06b6d4 100%);
    --gradient-cta: linear-gradient(135deg, #10b981 0%, #059669 100%);
    --gradient-pro: linear-gradient(135deg, #4f46e5 0%, #7c3aed 50%, #06b6d4 100%);
    --border-subtle: rgba(255, 255, 255, 0.07);
    --border-glow: rgba(99, 102, 241, 0.45);
    --shadow-lg: 0 25px 60px -12px rgba(0, 0, 0, 0.6);
    --radius: 16px;
    --radius-sm: 8px;
    --radius-full: 9999px;
    --transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { font-size: 16px; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    background: var(--bg-dark);
    color: var(--text-primary);
    overflow-x: hidden;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    position: relative;
}

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }
ul { list-style: none; }
::selection { background: rgba(99, 102, 241, 0.35); color: #fff; }

.container { max-width: 1200px; margin: 0 auto; padding: 0 2rem; position: relative; z-index: 2; }
.mono { font-family: 'JetBrains Mono', monospace; }

/* ============================================================
   WORLD LAYER — fixed full-viewport canvas behind everything.
   Content scrolls normally over it (native document scroll,
   no sticky blocks — see scroll-world-pitfalls §4).
   ============================================================ */
#world {
    position: fixed;
    inset: 0;
    z-index: 0;
    display: block;
    width: 100vw;
    height: 100vh;
    outline: none;
    cursor: grab;
}

/* Free-look drag affordance — set on <body> because the drag listener
   lives on window (see scene.js free-look section) and can keep firing
   while the pointer strays over a card mid-drag; forcing the cursor
   everywhere while dragging reads better than letting it flicker back to
   a text/pointer cursor over content. No persistent on-screen label —
   the grab cursor alone is the hint, discovered on hover/drag. */
body.is-free-looking,
body.is-free-looking * {
    cursor: grabbing !important;
}

.world-fallback {
    position: fixed;
    inset: 0;
    z-index: 0;
    background:
        radial-gradient(ellipse 900px 620px at 18% 8%, rgba(79,70,229,0.20) 0%, transparent 60%),
        radial-gradient(ellipse 900px 620px at 84% 18%, rgba(6,182,212,0.14) 0%, transparent 60%),
        radial-gradient(ellipse 700px 700px at 50% 100%, rgba(16,185,129,0.08) 0%, transparent 60%),
        var(--bg-dark);
    opacity: 1;
    transition: opacity 0.6s ease;
}
.world-ready .world-fallback { opacity: 0; }
.no-webgl .world-fallback { opacity: 1 !important; }
.no-webgl #world { display: none; }

.world-vignette {
    position: fixed; inset: 0; z-index: 1; pointer-events: none;
    background:
        radial-gradient(ellipse 1400px 900px at 50% 0%, transparent 40%, rgba(6,9,18,0.55) 100%),
        linear-gradient(180deg, rgba(6,9,18,0.15) 0%, transparent 12%, transparent 88%, rgba(6,9,18,0.45) 100%);
}

main { position: relative; z-index: 2; }

.section-label {
    display: inline-block; font-size: 0.78rem; font-weight: 600; text-transform: uppercase;
    letter-spacing: 2px; color: var(--secondary); margin-bottom: 1rem;
    padding: 0.4rem 1rem; border: 1px solid rgba(6, 182, 212, 0.3);
    border-radius: var(--radius-full); background: rgba(6, 182, 212, 0.10);
    backdrop-filter: blur(6px);
}
.section-title {
    font-size: clamp(2rem, 5vw, 3rem); font-weight: 800; line-height: 1.16;
    margin-bottom: 1.25rem; letter-spacing: -0.5px;
    text-shadow: 0 8px 40px rgba(6,9,18,0.85);
}
.section-sub {
    font-size: 1.05rem; color: var(--text-secondary); max-width: 560px;
    margin-bottom: 1.5rem; line-height: 1.7;
    text-shadow: 0 4px 24px rgba(6,9,18,0.8);
}
.gradient-text {
    background: var(--gradient-hero); -webkit-background-clip: text;
    -webkit-text-fill-color: transparent; background-clip: text;
}

.reveal { opacity: 0; transform: translateY(28px); transition: opacity 0.7s ease, transform 0.7s ease; }
.reveal.visible { opacity: 1; transform: translateY(0); }
.reveal-delay-1 { transition-delay: 0.06s; }
.reveal-delay-2 { transition-delay: 0.12s; }
.reveal-delay-3 { transition-delay: 0.18s; }

@media (prefers-reduced-motion: reduce) {
    .reveal { transition: opacity 0.25s ease; transform: none !important; }
}

/* progress rail — tiny fixed indicator tied to the scroll conductor */
.chapter-rail {
    position: fixed; right: 1.1rem; top: 50%; transform: translateY(-50%);
    z-index: 900; display: flex; flex-direction: column; gap: 0.55rem;
    pointer-events: none;
}
.chapter-rail span {
    width: 6px; height: 6px; border-radius: 50%; background: rgba(255,255,255,0.18);
    transition: background 0.35s ease, transform 0.35s ease, box-shadow 0.35s ease;
}
.chapter-rail span.active {
    background: var(--secondary); transform: scale(1.5);
    box-shadow: 0 0 10px rgba(6,182,212,0.7);
}
@media (max-width: 900px) { .chapter-rail { display: none; } }

/* ============================================================
   HEADER
   NOTE: backdrop-filter here creates a containing block for
   position:fixed descendants — the mobile nav overlay below is
   sized with 100vw/100vh, not inset:0, to survive that. See
   scroll-world-pitfalls §1-2.
   ============================================================ */
.header {
    position: fixed; top: 0; left: 0; right: 0; z-index: 1000;
    background: rgba(9, 12, 22, 0.55); backdrop-filter: blur(18px) saturate(160%);
    border-bottom: 1px solid var(--border-subtle);
    transition: background var(--transition), box-shadow var(--transition);
}
.header.scrolled { background: rgba(8, 11, 20, 0.9); box-shadow: 0 4px 30px rgba(0,0,0,0.35); }
.nav { display: flex; justify-content: space-between; align-items: center; padding: 1rem 0; }
.logo-link { display: flex; align-items: center; gap: 0.5rem; }
.logo {
    font-size: 1.4rem; font-weight: 900; letter-spacing: -0.5px;
    background: var(--gradient-hero); -webkit-background-clip: text;
    -webkit-text-fill-color: transparent; background-clip: text;
}
.nav-links { display: flex; gap: 2rem; align-items: center; }
.nav-links a {
    font-size: 0.9rem; font-weight: 500; color: var(--text-secondary);
    transition: color var(--transition); position: relative;
}
.nav-links a:hover { color: var(--text-primary); }
.nav-links a::after {
    content: ''; position: absolute; bottom: -4px; left: 0; width: 0; height: 2px;
    background: var(--gradient-hero); transition: width var(--transition);
}
.nav-links a:hover::after { width: 100%; }
.nav-controls { display: flex; gap: 0.75rem; align-items: center; }
.btn-nav-cta {
    padding: 0.5rem 1.25rem; border-radius: var(--radius-sm);
    background: var(--gradient-cta); color: white; font-size: 0.85rem;
    font-weight: 600; transition: all var(--transition);
    box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
}
.btn-nav-cta:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4); }
.mobile-toggle { display: none; background: none; color: var(--text-primary); font-size: 1.5rem; padding: 0.25rem; }

/* ============================================================
   HERO
   Two-column framing, same mechanism as .station below: the card owns
   a dedicated column so it never sits on top of the 3D subject behind
   it. Hero puts the card on the RIGHT and leaves the LEFT column open —
   that's where scene.js frames the brighter of the two establishing
   monitor glows (leftGlow), so the open zone still reads as "something
   is there", not empty space. Chosen deliberately over card-left so the
   more prominent glow is the one left uncovered.
   ============================================================ */
.hero {
    position: relative; min-height: 100svh;
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(360px, 620px);
    align-items: center; gap: clamp(2rem, 5vw, 5rem);
    max-width: 1680px; margin: 0 auto;
    padding: 8.5rem clamp(1.25rem, 5vw, 4rem) 5rem;
}
.hero-content {
    grid-column: 2; position: relative; z-index: 1; text-align: left;
}
.hero-badge {
    display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.78rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: 1.5px; color: var(--accent);
    padding: 0.4rem 0.9rem; border: 1px solid rgba(16,185,129,0.3);
    border-radius: var(--radius-full); background: rgba(16,185,129,0.10);
    backdrop-filter: blur(6px); margin-bottom: 1.5rem;
}
.hero-badge .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px var(--accent); animation: pulse-dot 2.2s ease-in-out infinite; }
@keyframes pulse-dot { 0%,100%{opacity:1} 50%{opacity:.35} }
.hero h1 {
    font-size: clamp(2.3rem, 3.6vw, 3.4rem); font-weight: 900; line-height: 1.1;
    margin-bottom: 1.25rem; letter-spacing: -1px;
    text-shadow: 0 10px 50px rgba(6,9,18,0.9);
}
.hero h1 span {
    background: var(--gradient-cta); -webkit-background-clip: text;
    -webkit-text-fill-color: transparent; background-clip: text;
}
.hero-sub {
    font-size: 1.1rem; color: var(--text-secondary); max-width: 540px;
    margin: 0 0 2.25rem; line-height: 1.7;
    text-shadow: 0 6px 30px rgba(6,9,18,0.85);
}
.hero-buttons { display: flex; gap: 1rem; flex-wrap: wrap; justify-content: flex-start; }
.btn-primary {
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 1rem 2rem; border-radius: var(--radius-full);
    background: var(--gradient-cta); color: white; font-size: 1rem;
    font-weight: 600; transition: all var(--transition);
    box-shadow: 0 8px 30px rgba(16, 185, 129, 0.35);
}
.btn-primary:hover { transform: translateY(-3px); box-shadow: 0 12px 40px rgba(16, 185, 129, 0.45); }
.btn-outline {
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 1rem 2rem; border-radius: var(--radius-full);
    background: rgba(10,14,26,0.35); color: var(--text-primary); font-size: 1rem;
    font-weight: 600; border: 1px solid rgba(255,255,255,0.18);
    transition: all var(--transition); backdrop-filter: blur(6px);
}
.btn-outline:hover { border-color: var(--primary); background: rgba(79,70,229,0.15); transform: translateY(-3px); }
.hero-scroll-hint {
    margin-top: 3rem; font-size: 0.78rem; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: 2px;
}

/* ============================================================
   PRODUCT STATIONS — Macro's desk, meeting room / Scribe.

   Two dedicated columns, not a floating box positioned by margin auto.
   station-left puts the card in column 1 and leaves column 2 open;
   station-right mirrors it. The camera (scene.js CAM_TARGET_OFF +
   FRAME_BIAS_X) is framed per station to land the 3D subject inside
   whichever column is left open, so card and subject never share space.

   Previous version wrapped .station-content in a .container div and
   alternated with margin-left/right:auto on the card. That looked
   right in isolation but .container ITSELF is a flex item of .station
   (display:flex), and .container's own `margin: 0 auto` auto-centers
   *it* within .station's flex row — auto margins on a flex item always
   win over the parent, so both the "left" and "right" variants ended
   up centered near the middle of the viewport, on top of the 3D
   subject the camera was also centering. Removing the extra wrapper
   and switching to grid-column placement on .station-content directly
   fixes that at the source instead of patching the symptom.
   ============================================================ */
.station {
    position: relative; min-height: 100vh;
    display: grid; grid-template-columns: minmax(360px, 640px) minmax(0, 1fr);
    align-items: center; gap: clamp(2rem, 5vw, 5rem);
    max-width: 1680px; margin: 0 auto;
    padding: 7rem clamp(1.25rem, 5vw, 4rem);
}
.station-right { grid-template-columns: minmax(0, 1fr) minmax(360px, 640px); }
.station-content { grid-column: 1; }
.station-right .station-content { grid-column: 2; }
.station-content {
    background: var(--bg-card); border: 1px solid var(--border-subtle);
    border-radius: var(--radius); padding: 3rem 2.75rem; backdrop-filter: blur(14px);
    box-shadow: var(--shadow-lg);
}
.station-content p { color: var(--text-secondary); font-size: 1.05rem; line-height: 1.75; margin-bottom: 1.85rem; }
.station-cta {
    display: inline-flex; align-items: center; gap: 0.6rem;
    padding: 0.85rem 1.6rem; border-radius: var(--radius-full);
    background: var(--gradient-hero); color: white; font-size: 0.92rem;
    font-weight: 600; transition: all var(--transition);
    box-shadow: 0 8px 26px rgba(79,70,229,0.35);
}
.station-cta:hover { transform: translateY(-2px); box-shadow: 0 12px 32px rgba(79,70,229,0.45); }
.station-cta .arrow { transition: transform var(--transition); }
.station-cta:hover .arrow { transform: translateX(4px); }
.station-badge {
    font-family: 'JetBrains Mono', monospace; font-size: 0.72rem; font-weight: 700;
    letter-spacing: 1px; color: var(--text-muted); margin-top: 1.25rem; display: block;
}

/* ============================================================
   "DUO" STATIONS — aiclaw's desk + korfix.app's desk. The one place
   --gradient-pro (violet-leaning, unused until now) gets used: these two
   share it so they read as a connected pair, distinct from Macro/Scribe's
   indigo/cyan (--gradient-hero) and Switcher's dimmed grey.
   ============================================================ */
.station-pro .section-label {
    color: #a78bfa;
    border-color: rgba(124, 58, 237, 0.32);
    background: rgba(124, 58, 237, 0.10);
}
.station-pro .station-cta {
    background: var(--gradient-pro);
    box-shadow: 0 8px 26px rgba(124, 58, 237, 0.35);
}
.station-pro .station-cta:hover { box-shadow: 0 12px 32px rgba(124, 58, 237, 0.45); }

/* ============================================================
   "COMING SOON" STATION — Switcher's desk. Dashed outline + lower
   opacity instead of the solid card + glow the two live desks get, so
   it reads as "not yet" rather than a broken/missing CTA. No station-cta
   link and no station-badge URL — nothing here should look clickable.
   ============================================================ */
.station-soon {
    background: rgba(20, 24, 38, 0.4);
    border: 1px dashed rgba(255, 255, 255, 0.22);
    box-shadow: none;
}
.station-soon .section-title,
.station-soon p { opacity: 0.88; }
.soon-pill {
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 0.7rem 1.5rem; border-radius: var(--radius-full);
    border: 1px dashed rgba(255, 255, 255, 0.32); color: var(--text-muted);
    font-size: 0.85rem; font-weight: 600; letter-spacing: 0.5px;
    text-transform: uppercase;
}
.footer-soon {
    display: block; font-size: 0.85rem; color: var(--text-muted);
    padding: 0.3rem 0; opacity: 0.65;
}

/* ============================================================
   LANGUAGE SWITCHER — lives in the header (.nav-controls), reachable from
   any scroll position, not just the exit station. Toggle overrides the
   navigator.language default set by main.js initI18n().
   ============================================================ */
.lang-toggle {
    display: inline-flex; gap: 0.2rem;
    border: 1px solid var(--border-subtle); border-radius: var(--radius-full);
    padding: 0.2rem; background: rgba(10, 14, 26, 0.4);
}
.lang-toggle button {
    padding: 0.3rem 0.7rem; border-radius: var(--radius-full);
    font-size: 0.72rem; font-weight: 700; letter-spacing: 0.5px;
    color: var(--text-muted); transition: all var(--transition);
}
.lang-toggle button.active { background: var(--gradient-hero); color: #fff; }
.lang-toggle button:not(.active):hover { color: var(--text-primary); }

/* ============================================================
   FOOTER
   ============================================================ */
.footer { position: relative; padding: 3rem 0 2rem; border-top: 1px solid var(--border-subtle); background: rgba(6,9,18,0.55); backdrop-filter: blur(12px); }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr; gap: 3rem; margin-bottom: 2rem; }
.footer-brand .logo { margin-bottom: 1rem; display: inline-block; }
.footer-brand p { font-size: 0.85rem; color: var(--text-muted); max-width: 320px; line-height: 1.6; }
.footer-col h4 { font-size: 0.85rem; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 1rem; color: var(--text-secondary); }
.footer-col a { display: block; font-size: 0.85rem; color: var(--text-muted); padding: 0.3rem 0; transition: color var(--transition); }
.footer-col a:hover { color: var(--primary-light); }
.footer-bottom {
    text-align: center; padding-top: 2rem; border-top: 1px solid var(--border-subtle);
    font-size: 0.8rem; color: var(--text-muted);
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 900px) {
    .station-content { max-width: 420px; }
}
@media (max-width: 768px) {
    .nav { position: relative; }
    .nav-links { display: none; }
    /* Fullscreen overlay sized in viewport units, not inset:0 — the
       .header above has backdrop-filter, which makes it a containing
       block for fixed descendants, so inset:0 would shrink this menu
       to the header's own box instead of covering the screen. See
       scroll-world-pitfalls §1. */
    .nav-links.open {
        display: flex; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;
        z-index: 1100; flex-direction: column; justify-content: center; align-items: stretch;
        background: rgba(6,9,18,0.98); backdrop-filter: blur(20px) saturate(160%);
        padding: 6rem 2rem 3rem; gap: 0.6rem;
    }
    .nav-links.open a {
        padding: 1.35rem 0.25rem; width: 100%; font-size: 1.55rem; font-weight: 700;
        border-bottom: 1px solid var(--border-subtle); color: var(--text-primary);
    }
    .nav-links.open a:last-child { border-bottom: none; }
    body.nav-open { overflow: hidden; }
    .mobile-toggle {
        display: flex; align-items: center; justify-content: center;
        position: relative; z-index: 1101; width: 40px; height: 40px;
    }
    .logo { font-size: 1.15rem; }
    .nav-controls { gap: 0.4rem; }
    .btn-nav-cta { padding: 0.45rem 0.9rem; font-size: 0.78rem; }
    .lang-toggle button { padding: 0.28rem 0.55rem; font-size: 0.68rem; }
    /* Narrow screens: card-beside-object doesn't work — there's no spare
       width to give either one a real column, splitting them side by side
       would leave both squeezed. Stack instead: card anchored to the top
       of the section, object framed lower (scene.js MOBILE_TARGET_Y_BIAS)
       so it's visible in the space below the card rather than centered
       behind it. */
    .hero {
        display: block; padding: 7.5rem 1.25rem 3rem; min-height: auto;
    }
    .hero-content { text-align: center; }
    .hero-sub, .hero-badge { margin-left: auto; margin-right: auto; }
    .hero-buttons { flex-direction: column; align-items: stretch; justify-content: center; }
    .station, .station-right {
        grid-template-columns: 1fr; align-items: start;
        padding: 6.5rem 1.25rem 3rem; min-height: 94vh; gap: 1.5rem;
    }
    .station-content, .station-right .station-content { grid-column: 1; max-width: 100%; padding: 2rem; }
    .footer-grid { grid-template-columns: 1fr; gap: 2rem; }
    .container { padding: 0 1.25rem; }
}
