/* ============================================================
   SCROLL SYSTEM - Luc Sloots portfolio (shared by every page)
   Mode classes on <html> (set by boot.js):
     sx-full    desktop: pinned/sticky scenes, smooth scroll, 3D wheel
     sx-lite    < 768px or touch: simple scrubbed parallax, stacked sections
     sx-reduce  prefers-reduced-motion: static page, only the progress bar moves
   No class / no JS: the plain, fully visible static layout.
   Scenes only animate transform, opacity and stroke-dashoffset.
   ============================================================ */

:root { --stage-max: 1600px; }

/* Scenes slide things in from off-screen; clip (not hidden) keeps sticky working and prevents any sideways scroll. */
main { overflow-x: clip; }

html { scroll-behavior: auto; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis [data-lenis-prevent] { overscroll-behavior: contain; }
html.menu-open { overflow: hidden; }

/* ── Focus + skip link ── */
:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; border-radius: 4px; }
.skip-link {
  position: fixed; left: 1rem; top: 0; z-index: 1200;
  background: var(--red); color: #fff; padding: 0.6rem 1rem; border-radius: 8px; font-weight: 600;
  transform: translateY(-150%);
}
.skip-link:focus { transform: translateY(1rem); }

/* ── Progress bar ── */
.sx-progress {
  position: fixed; top: 0; left: 0; width: 100%; height: 3px; z-index: 1100;
  background: linear-gradient(90deg, var(--red-dark), var(--red));
  box-shadow: 0 0 10px var(--red-glow);
  transform: scaleX(0); transform-origin: 0 50%;
  pointer-events: none; view-transition-name: sx-progress;
}

/* ── Page transitions (View Transitions API, plain-fade fallback) ── */
::view-transition-old(root) { animation: sx-fade-out 0.22s ease both; }
::view-transition-new(root) { animation: sx-fade-in 0.3s ease both; }
::view-transition-group(sx-nav), ::view-transition-group(sx-progress) { animation-duration: 0s; }
@keyframes sx-fade-out { to { opacity: 0; } }
@keyframes sx-fade-in { from { opacity: 0; } }
html.sx-fade body { animation: sx-fade-in 0.35s ease both; }
html.sx-leaving body { opacity: 0; transition: opacity 0.18s ease; }

/* ============================================================
   NAVBAR - glass layer fades in + shrinks on scroll, sliding underline, slide-in menu
   ============================================================ */
.navbar {
  background: transparent; border-bottom: 0; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none; transition: none;
  view-transition-name: sx-nav;
}
.navbar::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: rgba(10, 10, 10, 0.82);
  -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.6);
  transform-origin: 50% 0;
  transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
html.js .navbar::before { opacity: 0; }
html.js .navbar.scrolled::before { opacity: 1; transform: scaleY(0.8); }
.navbar .nav-logo, .navbar .nav-links, .navbar .nav-hamburger {
  transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
.navbar .nav-logo { transform-origin: 0 50%; }
.navbar.scrolled .nav-links, .navbar.scrolled .nav-hamburger { transform: translateY(-7px); }
.navbar.scrolled .nav-logo { transform: translateY(-7px) scale(0.9); }

.nav-links { position: relative; }
.nav-links a.active::after { content: none; }
.nav-indicator {
  position: absolute; left: 0; bottom: 4px; width: 100px; height: 2px; border-radius: 2px;
  background: var(--red); box-shadow: 0 0 8px var(--red-glow);
  transform-origin: 0 50%; opacity: 0; pointer-events: none;
  transition: transform 0.55s cubic-bezier(0.65, 0, 0.35, 1), opacity 0.3s ease;
}
.nav-indicator.on { opacity: 1; }

/* Hamburger is a real <button> now */
.nav-hamburger { background: none; border: 0; color: inherit; }

/* Slide-in panel (replaces the old drop-down) */
.nav-mobile {
  display: flex; position: fixed; top: 0; right: 0; bottom: 0; left: auto;
  width: min(82vw, 320px); padding: 92px 1.5rem 2rem; gap: 0.3rem; flex-direction: column;
  background: rgba(10, 10, 10, 0.97);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  border-left: 1px solid var(--border); border-bottom: 0;
  transform: translateX(100%); visibility: hidden; z-index: 999;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), visibility 0s 0.45s;
}
.nav-mobile.open { transform: none; visibility: visible; transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), visibility 0s; }
.nav-mobile a { opacity: 0; transform: translateX(24px); transition: opacity 0.35s ease, transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), color var(--transition), background var(--transition); }
.nav-mobile.open a { opacity: 1; transform: none; }
.nav-mobile.open a:nth-child(1) { transition-delay: 0.08s; }
.nav-mobile.open a:nth-child(2) { transition-delay: 0.13s; }
.nav-mobile.open a:nth-child(3) { transition-delay: 0.18s; }
.nav-mobile.open a:nth-child(4) { transition-delay: 0.23s; }
.nav-mobile.open a:nth-child(5) { transition-delay: 0.28s; }
.nav-mobile.open a:nth-child(6) { transition-delay: 0.33s; }
.nav-scrim {
  position: fixed; inset: 0; z-index: 998; background: rgba(0, 0, 0, 0.55);
  opacity: 0; visibility: hidden; transition: opacity 0.35s ease, visibility 0s 0.35s;
}
.nav-scrim.open { opacity: 1; visibility: visible; transition: opacity 0.35s ease, visibility 0s; }
@media (min-width: 769px) { .nav-mobile, .nav-scrim { display: none; } }

/* ============================================================
   SHARED SCENE PRIMITIVES
   ============================================================ */
.sx-stage { width: 100%; max-width: var(--stage-max); margin-inline: auto; }
.sx-word { display: inline-block; white-space: nowrap; }
.sx-ch { display: inline-block; will-change: transform, opacity; }
.sx-ln { display: block; white-space: nowrap; }
.sx-ln-in { display: inline-block; will-change: transform, opacity; }

/* A "track" is a tall block; its .sx-sticky child stays on screen while the track scrolls by.
   Heights are plain CSS (no JS), so there is no layout shift when the engine starts. */
html.sx-full .sx-track { height: var(--len, 300vh); position: relative; }
html.sx-full .sx-track > .sx-sticky { position: sticky; top: 0; height: 100vh; overflow: hidden; }

.sx-stars { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.sx-stars canvas { position: absolute; left: 0; top: 0; width: 100%; height: 140%; transform-origin: 50% 35%; will-change: transform; }

.wheel-stage { display: none; }
.wheel-stage canvas { display: block; width: 100%; height: 100%; }

/* ============================================================
   INDEX - cinematic hero -> transition -> work teaser
   ============================================================ */
.cine-stage { position: relative; }
html.sx-full .cine { --len: 520vh; }
html.sx-full .cine-stage { display: block; }
html.sx-full .cine-stage .hero { position: absolute; inset: 0; min-height: 0; z-index: 2; }
html.sx-full .cine-stage .teaser { position: absolute; inset: 0; z-index: 3; display: flex; align-items: center; justify-content: center; }
.cine-stage .hero { z-index: 2; }
.cine-stage .hero::after { z-index: 1; }
.hero-content { will-change: transform, opacity; }

.hero-typed {
  display: none; font-family: var(--font-display); font-size: clamp(0.95rem, 2.2vw, 1.25rem);
  color: var(--red); letter-spacing: 0.16em; text-transform: uppercase;
  min-height: 1.6em; margin: 0 0 1.6rem;
}
html.sx-full .hero-typed, html.sx-lite .hero-typed { display: block; }
.hero-typed .caret {
  display: inline-block; width: 2px; height: 1.05em; margin-left: 3px; vertical-align: -0.15em;
  background: var(--red); animation: sx-blink 1s steps(2) infinite;
}
@keyframes sx-blink { 50% { opacity: 0; } }

html.sx-full .wheel-stage {
  display: block; position: fixed; left: 50%; top: 50%; z-index: 1;
  width: min(72vh, 640px); aspect-ratio: 1; pointer-events: none;
  opacity: 0; transition: opacity 0.8s ease;
}
html.sx-full .wheel-stage.ready { opacity: 1; }

/* Teaser: two project cards that lock together */
.teaser { padding: 90px 2.5rem 80px; position: relative; }
.teaser-inner { max-width: 1000px; margin: 0 auto; text-align: center; }
.teaser .red-line { margin-inline: auto; }
.teaser .section-subtitle { margin-inline: auto; margin-bottom: 2.5rem; }
.teaser-cards { position: relative; display: grid; grid-template-columns: 1fr 1fr; max-width: 900px; margin: 0 auto 2.5rem; text-align: left; }
.teaser-card {
  background: var(--bg-card); border: 1px solid var(--border); padding: 2rem;
  display: flex; flex-direction: column; gap: 1rem; will-change: transform;
}
.teaser-card--a { border-radius: var(--radius-lg) 0 0 var(--radius-lg); border-right-width: 0; }
.teaser-card--b { border-radius: 0 var(--radius-lg) var(--radius-lg) 0; }
.tc-head { display: flex; align-items: center; gap: 0.9rem; }
.tc-icon {
  width: 46px; height: 46px; border-radius: 12px; flex-shrink: 0; display: grid; place-items: center;
  background: var(--red-dim); border: 1px solid rgba(255, 51, 51, 0.3); color: var(--red);
}
.tc-icon svg { width: 22px; height: 22px; }
.tc-title { font-family: var(--font-display); font-size: 1.1rem; font-weight: 700; letter-spacing: 0.04em; }
.tc-type { font-size: 0.72rem; color: var(--grey); text-transform: uppercase; letter-spacing: 0.06em; }
.tc-desc { font-size: 0.9rem; color: var(--grey); line-height: 1.7; }
.teaser-card .badge { margin-left: auto; }
.badge-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; display: inline-block; }
.teaser-lock {
  position: absolute; left: 50%; top: 50%; width: 46px; height: 46px; margin: -23px 0 0 -23px; z-index: 2;
  border-radius: 50%; background: var(--red); color: #fff; display: grid; place-items: center;
  box-shadow: 0 0 26px var(--red-glow);
}
.teaser-lock svg { width: 20px; height: 20px; }
.teaser-cta { will-change: transform, opacity; }
@media (max-width: 640px) {
  .teaser { padding: 70px 1.5rem 60px; }
  .teaser-cards { grid-template-columns: 1fr; gap: 1rem; }
  .teaser-card--a, .teaser-card--b { border-radius: var(--radius-lg); border-right-width: 1px; }
  .teaser-lock { display: none; }
}

/* ============================================================
   ABOUT - zooming photo, drawn ring, line-by-line bio, flip cards, Nexus hexagon
   ============================================================ */
html.sx-full .about-track { --len: 330vh; }
html.sx-full .facts-track { --len: 380vh; }
html.sx-full .about-header { display: flex; align-items: center; padding-top: 70px; }
html.sx-full .about-header-inner { width: 100%; padding-top: 0; padding-bottom: 0; }

/* The red ring is drawn by scroll (stroke-dashoffset); it replaces the old spinning conic ring. */
.photo-wrapper::before { content: none; }
.photo-ring {
  position: absolute; left: -9px; top: -9px; width: calc(100% + 18px); height: calc(100% + 18px);
  z-index: 2; transform: rotate(-90deg); overflow: visible; pointer-events: none;
}
.photo-ring circle { fill: none; stroke-linecap: round; }
.photo-ring .ring-track { stroke: rgba(255, 51, 51, 0.16); stroke-width: 1.6; }
.photo-ring .ring-draw { stroke: var(--red); stroke-width: 2.6; stroke-dasharray: 1 1; stroke-dashoffset: 0; }
/* Blur is faked with a pre-blurred copy underneath; only opacity of the sharp image is animated. */
.photo-bg { position: relative; }
.photo-blur { display: none; }
html.sx-full .photo-blur, html.sx-lite .photo-blur {
  display: block; position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  filter: blur(16px); transform: scale(1.14); border-radius: 0;
}
.photo-bg img:not(.photo-blur) { position: relative; z-index: 1; }
.photo-wrapper { will-change: transform; }

.about-facts { padding: 0 2.5rem; }
html.sx-full .about-facts { display: flex; align-items: center; justify-content: center; padding-top: 70px; }
html.sx-full .facts-inner { padding: 0; }
.facts-inner { padding: 4rem 0 3rem; }
.facts-inner .section-subtitle { margin-bottom: 0; }
.about-work { max-width: 1200px; margin: 0 auto; padding: 3rem 2.5rem 5rem; }
.fun-facts-grid { perspective: 1400px; }
html.sx-full .fun-facts-grid { grid-template-columns: repeat(4, 1fr); gap: 1.4rem; margin-top: 2.5rem; }
.fact-card { transform-style: preserve-3d; position: relative; will-change: transform; }
html.js .fact-card { backface-visibility: hidden; -webkit-backface-visibility: hidden; transition: border-color var(--transition), box-shadow var(--transition); }
html.js .fact-card:hover { transform: none; }
html.js .fact-card > * { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
/* Card back (visible while flipped): subtle hex pattern in the brand red */
html.js .fact-card::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  background:
    radial-gradient(circle at 50% 50%, rgba(255, 51, 51, 0.22), transparent 62%),
    repeating-linear-gradient(60deg, rgba(255, 51, 51, 0.07) 0 2px, transparent 2px 22px),
    #140808;
  border: 1px solid rgba(255, 51, 51, 0.3);
  transform: rotateY(180deg); backface-visibility: hidden; -webkit-backface-visibility: hidden;
}

.working-on-card > :not(.nexus-hex) { position: relative; z-index: 1; }
.nexus-hex {
  position: absolute; right: -44px; top: -70px; width: 210px; height: 210px; z-index: 0;
  pointer-events: none; opacity: 0.55;
}
.nexus-hex svg { width: 100%; height: 100%; display: block; animation: sx-hex-idle 60s linear infinite; }
@keyframes sx-hex-idle { to { transform: rotate(360deg); } }
.woi-item-now { position: relative; }

/* ============================================================
   SKILLS - pinned horizontal scroll through the categories
   ============================================================ */
.skills-viewport { width: 100%; }
html.sx-full .skills-pin { height: 100vh; display: flex; flex-direction: column; overflow: hidden; }
html.sx-full .skills-pin .page-hero { flex: none; padding-top: 100px; padding-bottom: 0.5rem; max-width: var(--stage-max); width: 100%; }
html.sx-full .skills-pin .section-subtitle { margin-bottom: 0; }
html.sx-full .skills-viewport { flex: 1; min-height: 0; display: flex; align-items: center; perspective: 1600px; }
html.sx-full .skills-outer {
  --pw: min(1100px, calc(100vw - 5rem));
  display: flex; gap: 32px; width: max-content; max-width: none; margin: 0;
  padding: 0 calc((100vw - var(--pw)) / 2) 0;
  grid-template-columns: none;
}
html.sx-full .skill-category {
  flex: none; width: var(--pw); display: grid; grid-template-columns: 260px 1fr; column-gap: 3rem;
  row-gap: 0; align-content: center; min-height: 340px; will-change: transform, opacity;
}
html.sx-full .skill-category > .category-header { grid-column: 1; grid-row: 1 / span 8; flex-direction: column; align-items: flex-start; align-self: center; margin-bottom: 0; }
html.sx-full .skill-category > :not(.category-header) { grid-column: 2; }
html.sx-full .category-title { font-size: 1.5rem; }
html.sx-full .category-icon { width: 60px; height: 60px; font-size: 1.7rem; }
.skill-category { transform-style: preserve-3d; }
.tool-chip { will-change: transform, opacity; }

/* ============================================================
   PROJECTS - sticky stacked cards
   ============================================================ */
.badge-live, .badge-soon { position: relative; }
.project-card .badge::before, .working-on-item .badge::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; border: 1px solid currentColor;
  opacity: 0; animation: sx-pulse 2.2s ease-out infinite; pointer-events: none;
}
@keyframes sx-pulse { 0% { transform: scale(1); opacity: 0.6; } 100% { transform: scale(1.5, 1.9); opacity: 0; } }
html.sx-full .projects-grid {
  display: flex; flex-direction: column; gap: 24vh; max-width: 940px;
  grid-template-columns: none; padding-bottom: 28vh;
}
html.sx-full .project-card { position: sticky; min-height: 360px; transform-origin: 50% 0; will-change: transform, opacity; }
html.sx-full .project-card:nth-child(1) { top: 110px; }
html.sx-full .project-card:nth-child(2) { top: 134px; }
html.sx-full .project-card:nth-child(3) { top: 158px; }
.tag { will-change: transform, opacity; }
.stack-dim { position: absolute; inset: 0; background: #0a0a0a; opacity: 0; pointer-events: none; border-radius: inherit; z-index: 3; }

/* ============================================================
   SIM RACING - speed lines, speedometer, rig + 3D wheel, tracks
   ============================================================ */
.racing-hero { isolation: isolate; }
.racing-hero-inner { display: grid; grid-template-columns: 1fr; gap: 2.5rem; align-items: center; }
.speed-lines { position: absolute; inset: 0; z-index: 1; overflow: hidden; pointer-events: none; }
.speed-lines span {
  position: absolute; left: 0; top: var(--y); width: var(--w); height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, transparent, rgba(255, 51, 51, 0.85) 70%, #fff);
  opacity: 0; will-change: transform, opacity;
}
html:not(.sx-full):not(.sx-lite) .speed-lines { display: none; }
.gauge { position: relative; width: min(100%, 360px); margin: 0 auto; }
.gauge svg { display: block; width: 100%; height: auto; overflow: visible; }
.gauge .g-track, .gauge .g-fill { fill: none; stroke-width: 8; stroke-linecap: round; }
.gauge .g-track { stroke: rgba(255, 255, 255, 0.08); }
.gauge .g-fill { stroke: var(--red); stroke-dasharray: 1 1; stroke-dashoffset: 0; }
.gauge .t-major { stroke: rgba(255, 255, 255, 0.7); stroke-width: 2.4; }
.gauge .t-minor { stroke: rgba(255, 255, 255, 0.28); stroke-width: 1.4; }
.gauge .g-labels text { fill: var(--grey); font: 600 10px var(--font-display); text-anchor: middle; }
.gauge .needle line { stroke: var(--red); stroke-width: 4; stroke-linecap: round; }
.gauge .needle circle { fill: #1a1a1a; stroke: var(--red); stroke-width: 3; }
.gauge .needle .hub { fill: var(--red); stroke: none; }
.gauge-readout { position: absolute; left: 0; right: 0; bottom: 6%; text-align: center; font-family: var(--font-display); }
.gauge-readout span { display: block; font-size: 2.1rem; font-weight: 900; line-height: 1; font-variant-numeric: tabular-nums; }
.gauge-readout small { font-size: 0.7rem; letter-spacing: 0.2em; color: var(--grey); }
@media (min-width: 900px) { .racing-hero-inner { grid-template-columns: 1.2fr 0.8fr; } }

html.sx-full .race-track { --len: 300vh; }
html.sx-full .rig-track { --len: 360vh; }
html.sx-full .tracks-track { --len: 320vh; }
html.sx-full .racing-hero { padding-top: 70px; }
html.sx-full .rig-scene, html.sx-full .tracks-scene { display: flex; align-items: center; justify-content: center; padding-top: 70px; padding-bottom: 0; }
html.sx-full .rig-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; }
html.sx-full .rig-wheel { display: block; position: relative; width: min(100%, 520px); aspect-ratio: 1; margin: 0 auto; }
.rig-wheel canvas { display: block; width: 100%; height: 100%; }
.setup-item, .track-card { will-change: transform, opacity; }

/* ============================================================
   CONTACT - finale that zooms out from the previous theme
   ============================================================ */
.finale { position: relative; }
html:not(.sx-full) .finale { min-height: 62vh; padding: 70px 0 1rem; }
.finale { display: flex; align-items: center; justify-content: center; text-align: center; overflow: hidden; }
.finale .page-hero { position: relative; z-index: 2; padding-top: 0; padding-bottom: 0; }
.finale .red-line { margin-inline: auto; }
.finale .section-subtitle { margin-inline: auto; margin-bottom: 0; }
.finale-glow { position: absolute; inset: 0; z-index: 0; background: radial-gradient(circle at 50% 50%, rgba(255, 51, 51, 0.18), transparent 60%); }
.finale-bg { position: absolute; left: 50%; top: 50%; width: min(130vmin, 1100px); aspect-ratio: 1; margin: calc(min(130vmin, 1100px) / -2) 0 0 calc(min(130vmin, 1100px) / -2); z-index: 1; pointer-events: none; will-change: transform, opacity; }
.finale-bg svg { width: 100%; height: 100%; display: block; }
.finale-bg .f-ring { fill: none; stroke: rgba(255, 51, 51, 0.32); stroke-width: 2; }
.finale-bg .f-dash { stroke-dasharray: 3 14; stroke-width: 4; }
.finale-bg .f-hot { stroke: rgba(255, 51, 51, 0.6); stroke-width: 3; }
.finale-bg .f-ticks line { stroke: rgba(255, 255, 255, 0.35); stroke-width: 2; }
html.sx-full .finale-track { --len: 280vh; }
.contact-info .contact-card, .contact-info .open-for, .contact-form-wrapper { will-change: transform, opacity; }

/* ============================================================
   REDUCED MOTION - static page, no ongoing animation
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
  .nexus-hex svg, .hero-typed .caret, .project-card .badge::before, .working-on-item .badge::before { animation: none; }
  .racing-hero::before { animation: none; }
  html { scroll-behavior: auto; }
}
