@import url('https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400;0,500;1,400;1,500&family=Space+Mono:wght@400;700&display=swap');

:root {
  --bg:        #f1ebdd;
  --ink:       #2b2b2b;
  --ink-dim:   rgba(43,43,43,.5);
  --ink-faint: rgba(43,43,43,.14);

  --soccer:    #6f8f5e;
  --basket:    #cf8542;
  --guitar:    #7d5f86;

  --font-serif: 'EB Garamond', Georgia, serif;
  --font-mono:  'Space Mono', 'Courier New', monospace;

  --ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: auto; }
body { margin: 0; background: var(--bg); color: var(--ink); font-family: var(--font-serif); }

/* ── Grain overlay ─────────────────────────────── */
.grain {
  position: fixed; inset: 0; pointer-events: none; z-index: 60;
  opacity: .055; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ── Left nav ──────────────────────────────────── */
.nav {
  position: fixed; left: 24px; top: 50%; transform: translateY(-50%);
  z-index: 40; display: flex; gap: 16px; align-items: flex-start;
}
.nav__track {
  position: relative; width: 2px; height: 200px; background: var(--ink-faint);
}
.nav__dot {
  position: absolute; left: -3px; top: 0; width: 8px; height: 8px;
  border-radius: 50%; background: var(--soccer);
  transform: translateY(9px);
  transition: transform .35s var(--ease-out), background .35s ease;
}
.nav__labels {
  display: flex; flex-direction: column; gap: 24px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .14em;
  color: var(--ink-dim); line-height: 1.15;
}

/* ── Hero ──────────────────────────────────────── */
.hero {
  min-height: 100vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center; padding: 48px 24px; position: relative;
}
.hero__eyebrow {
  font-family: var(--font-mono); font-size: 12px;
  letter-spacing: .34em; text-transform: uppercase; color: var(--ink-dim);
  clip-path: inset(0 0 100% 0);
  transition: clip-path .7s var(--ease-out);
}
.hero__h1 {
  font-family: var(--font-serif); font-weight: 500;
  font-size: clamp(46px, 8.5vw, 108px); line-height: .98; margin: 6px 0;
}
.hero__sub {
  font-size: clamp(17px, 2.4vw, 22px); max-width: 520px;
  color: rgba(43,43,43,.68); margin: 14px auto 0; font-style: italic;
  clip-path: inset(0 0 100% 0);
  transition: clip-path .8s .2s var(--ease-out);
}
.hero.is-loaded .hero__eyebrow,
.hero.is-loaded .hero__sub { clip-path: inset(0 0 0% 0); }

.hero__figure { width: 188px; height: auto; margin-top: 28px; overflow: visible; }
.hero__scroll-cue {
  position: absolute; bottom: 28px; left: 50%; transform: translateX(-50%);
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .22em;
  color: var(--ink-dim); display: flex; flex-direction: column; align-items: center; gap: 4px;
}

/* ── Sections (natural scroll) ────────────────── */
.section {
  position: relative;
  min-height: 90vh;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  overflow: hidden;
}

.section__anim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
}

.section__content {
  position: relative;
  z-index: 1;
  max-width: 880px;
  margin: 0 auto;
  padding: 80px 24px 0;
  width: 100%;
}

.section__header { display: flex; align-items: baseline; gap: 14px; }

.section__num {
  font-family: var(--font-mono); font-size: clamp(18px, 3vw, 28px);
  clip-path: inset(0 0 100% 0);
}
.section__title {
  font-family: var(--font-serif); font-weight: 500;
  font-size: clamp(40px, 7vw, 88px); letter-spacing: -.01em; margin: 0;
  clip-path: inset(0 0 100% 0);
}
.section__caption {
  font-family: var(--font-mono); font-size: 13px; letter-spacing: .1em;
  color: var(--ink-dim); max-width: 420px; margin: 10px 0 2px; line-height: 1.6;
  clip-path: inset(0 0 100% 0);
}

/* ── Pinned scroll-scrub sections (soccer + basketball decorative accents) ────
   A taller-than-viewport section whose .section__pin wrapper goes
   position:sticky top:0 height:100vh, so .section__anim and
   .section__content overlay inside that single sticky box, the same
   way they overlay inside the plain .section box everywhere else,
   while the section's own extra height supplies the scroll range the
   scrub is driven against - see setupSoccer() / setupBasket(). ── */
.section--pinned {
  min-height: 240vh;
  /* position:sticky below is inert if any ancestor (including .section's own
     base overflow:hidden) has overflow other than visible - .section__anim's
     own overflow:hidden still contains the scene inside its 100vh box. */
  overflow: visible;
  /* Native CSS scroll-driven timeline for the decorative scroll-scrub. The
     section is the view-timeline subject; because it is taller than the
     viewport, the timeline's `contain` phase spans exactly the CSS-sticky pin
     window (.section__pin is stuck while the section covers the viewport).
     scrub-vignette.js's buildScrubStylesheet() generates @keyframes bound to
     this timeline from the section's pose data / hermiteSpline / releaseT, so
     the compositor advances every element 1:1 with scroll offset - no
     ScrollTrigger scrub catch-up smoothing, which was the laggy-scroll /
     stop-motion root cause (see AGENTS.md). Each section keeps only a
     scrub-free ScrollTrigger for its one-shot contact accents. Unlike
     position:sticky, view-timeline name lookup is NOT broken by an
     intermediate ancestor's overflow, so .section__anim's overflow:hidden is
     fine here. Each pinned section declares its own timeline name below. */
  view-timeline-axis: block;
}
#sec-soccer { view-timeline-name: --soccer-tl; }
#sec-basket { view-timeline-name: --basket-tl; }
#sec-guitar { view-timeline-name: --guitar-tl; }
.section--pinned .section__pin {
  position: sticky;
  top: 0;
  height: 100vh;
}
.soccer-scene,
.basket-scene,
.guitar-scene {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* No static will-change for the scrub: Chrome auto-promotes the elements whose
   scroll-driven CSS animations are running, and dropping back afterwards is
   cheaper than a dozen permanently-promoted SVG layers (see AGENTS.md on layer
   cost). The JS rAF fallback sets will-change:transform on just the ball and
   figure joints while it drives them. */

/* ── Hero chars ─────────────────────────────────── */
.hero__word { display: inline-block; margin-right: 0.28em; }
em.hero__word { margin-right: 0; font-style: italic; }
.hero__char { display: inline-block; will-change: transform, opacity; }

/* ── Projects ──────────────────────────────────── */
.projects { padding: 80px 24px 100px; max-width: 1000px; margin: 0 auto; }
.projects__eyebrow {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .3em;
  text-transform: uppercase; color: var(--ink-dim); margin-bottom: 40px;
}
.projects__grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 24px;
}
.project-card {
  padding: 28px; position: relative;
  clip-path: inset(0 0 100% 0);
}
.project-card__border {
  position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;
}
.project-card__border rect { fill: none; stroke: var(--ink); stroke-width: 1.6; opacity: .5; }
.project-card__label {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-dim); margin-bottom: 8px;
}
.project-card__title {
  font-family: var(--font-serif); font-size: 26px; font-weight: 500;
  line-height: 1.2; margin: 0 0 10px;
}
.project-card__desc {
  font-size: 16px; color: rgba(43,43,43,.72); line-height: 1.55; margin: 0; font-style: italic;
}
.project-card__link {
  display: inline-block; margin-top: 14px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .16em;
  color: var(--ink); text-decoration: none; opacity: .5;
  transition: opacity .2s ease;
}
.project-card__link:hover { opacity: 1; }

/* ── Footer ────────────────────────────────────── */
.footer {
  min-height: 60vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 12px; padding: 64px 24px; text-align: center;
}
.footer__eyebrow {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .3em;
  text-transform: uppercase; color: var(--ink-dim);
}
.footer__email {
  font-family: var(--font-serif); font-style: italic;
  font-size: clamp(28px, 5vw, 56px); color: var(--ink);
  text-decoration: none; border-bottom: 2px solid rgba(43,43,43,.28); padding-bottom: 3px;
  transition: border-color .2s ease;
}
.footer__email:hover { border-color: var(--ink); }
.footer__links {
  display: flex; gap: 24px; margin-top: 8px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .18em; color: var(--ink-dim);
}
.footer__links a { color: inherit; text-decoration: none; opacity: .6; transition: opacity .2s; }
.footer__links a:hover { opacity: 1; }
.footer__tagline {
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: .1em; color: rgba(43,43,43,.35); margin-top: 24px;
}

/* ── Hero animations (off main thread) ─────────── */
@keyframes bobx { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
@keyframes cuef { 0%,100% { transform: translateY(0); opacity: .45; } 50% { transform: translateY(7px); opacity: 1; } }
.hero__figure     { animation: bobx 4s ease-in-out infinite; }
.hero__scroll-arrow { display: inline-block; animation: cuef 1.7s ease-in-out infinite; }

/* ── Skip link ─────────────────────────────────── */
.skip-link {
  position: absolute; top: -40px; left: 0; background: var(--bg); color: var(--ink);
  padding: 8px 16px; font-family: var(--font-mono); font-size: 12px;
  text-decoration: none; z-index: 100; transition: top .2s;
}
.skip-link:focus { top: 0; }

/* ── Reduced motion ────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .hero__figure, .hero__scroll-arrow { animation: none; }

  .hero__eyebrow, .hero__h1, .hero__sub,
  .section__num, .section__title, .section__caption,
  .project-card { clip-path: none !important; }

  .hero__char { opacity: 1 !important; transform: none !important; }

  /* Hide all decoration and interactive layers */
  .section__anim { display: none; }

  /* Collapse the pinned sections back to normal-height static sections instead
     of leaving their scrub scroll-range (240vh) empty once the animation
     driving it is hidden above. */
  .section--pinned { min-height: 90vh; }
  .section--pinned .section__pin { position: relative; height: auto; }

  /* Basketball and guitar each keep a single static frame in reduced motion (a
     natural resting composition - the ball at rest in the net; a guitarist stood
     playing - that soccer's mid-flight ball doesn't have). setupBasket() /
     setupGuitar() draw it with no rAF and no scrub stylesheet; these overrides
     give the scene a box to sit in. */
  #sec-basket .section__anim,
  #sec-guitar .section__anim { display: block; }
  #sec-basket.section--pinned,
  #sec-guitar.section--pinned { min-height: 100vh; }
  #sec-basket .section__pin,
  #sec-guitar .section__pin { position: relative; height: 78vh; }

  * { transition-duration: 0.01ms !important; }
}
