/* ============================================================
   THOMAS MACHINGAIDZE, personal site
   Full 8-section build. Batcave LIGHT brand (light top to bottom
   EXCEPT the footer). Mobile-first; desktop is the enhancement.
   Tokens from design/brands/thomas-batcave.md.
   ============================================================ */

/* ---- Luna Obscura: the DISPLAY face (big headlines, name) ---- */
@font-face {
  font-family: 'Luna Obscura';
  src: url('assets/fonts/HS_LunaObscura.woff2') format('woff2'),
       url('assets/fonts/HS_LunaObscura.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---- Tokens ---- */
:root {
  /* light surfaces */
  --plane: #F4F5F6;          /* near-white concrete bright-plane */
  --plane-2: #ECEDEE;        /* faint light panel */
  --plane-seam: #C9CCCF;     /* machined hairline on light */
  --ink: #121316;            /* near-black text on plane */
  --ink-muted: #54585D;      /* secondary text on plane */
  --hair: rgba(0, 0, 0, 0.10);

  /* dark surfaces (footer + cinematic) */
  --black: #0B0B0C;
  --charcoal: #16181B;
  --concrete: #2A2D31;
  --ink-on-dark: #ECEDEE;
  --ink-on-dark-muted: #9A9EA3;
  --hair-on-dark: rgba(255, 255, 255, 0.10);

  /* the ONE cold accent */
  --accent: #4FB4FF;         /* holo-blue, one job per section */

  /* depth = deep SOFT shadow, never glow */
  --shadow-soft: 0 24px 60px rgba(0, 0, 0, 0.14);
  --shadow-card: 0 18px 48px rgba(0, 0, 0, 0.12);

  /* type */
  --font-display: 'Luna Obscura', 'Inter', sans-serif;
  --font-body: 'Inter', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;
  --font-sig: 'Sacramento', 'Brush Script MT', cursive; /* legible signature script */

  /* motion */
  --ease: cubic-bezier(0.75, 0, 0.25, 1);

  --nav-h: 64px;
}

/* ---- Reset ---- */
*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: auto; /* Lenis owns scrolling */
}
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  /* NOTE: no `overflow-x: hidden` here, it forces overflow-y:auto on <body>,
     which makes <body> a scroll container and breaks `position: sticky`
     (the manifesto reveal). Horizontal overflow is prevented by sizing every
     section to 100% / max-width instead; verified no-overflow in the harness. */
  max-width: 100%;
}
body {
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--ink);
  background: var(--plane);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  line-height: 1.4;
}
img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
h1, h2, h3, p, ul, li { margin: 0; padding: 0; }
ul { list-style: none; }

/* ---- Shared type helpers ---- */
.display {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 0.98;
}
.mono {
  font-family: var(--font-mono);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 0.66rem;
  color: var(--ink-muted);
}
.eyebrow {
  display: block;
  margin-bottom: 1.2rem;
}

.section--light { background: var(--plane); color: var(--ink); }
.section--dark { background: var(--black); color: var(--ink-on-dark); }

/* reveal-on-scroll baseline (GSAP toggles .is-in) */
[data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
}
[data-reveal].is-in {
  opacity: 1;
  transform: none;
}

/* ============================ NAV ============================ */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--nav-h);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 18px;
  color: var(--ink); /* hero is LIGHT top-to-bottom; dark links read over it */
  transition: background 0.5s var(--ease), color 0.5s var(--ease), border-color 0.5s var(--ease);
  border-bottom: 1px solid transparent;
}
/* when scrolled past the hero, the bar turns light */
.nav.is-solid {
  background: rgba(244, 245, 246, 0.86);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--ink);
  border-bottom: 1px solid var(--hair);
}
.nav__wordmark {
  font-family: var(--font-mono);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.7rem;
  white-space: nowrap;
}
.nav__links {
  display: none; /* mobile: hidden, use burger */
  gap: 28px;
}
.nav__link {
  position: relative;
  font-size: 0.82rem;
  font-weight: 400;
  padding: 4px 0;
}
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s var(--ease);
}
.nav__link:hover::after { transform: scaleX(1); }

.nav__cta {
  display: none;
  font-size: 0.8rem;
  font-weight: 500;
  color: #06121c;
  background: var(--accent);
  padding: 9px 18px;
  border-radius: 999px; /* the ONE accent pill */
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.nav__cta:hover {
  transform: translateY(-1px);
  /* deep SOFT neutral shadow on lift, never a holo-blue glow (brand: depth is
     shadow, not emitted light). */
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.16);
}

.nav__burger {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  /* hit area >= 44px tall (a11y tap-target guideline). The bars + gap are still
     8px of content; vertical padding lifts the touchable box to 44px without
     changing the visible icon geometry, so the .is-open X transform (tied to the
     5px gap + 1.5px bars) is unaffected. */
  padding: 11px 9px;
  min-height: 44px;
  min-width: 44px;
}
.nav__burger span {
  display: block;
  width: 22px;
  height: 1.5px;
  background: currentColor;
  transition: transform 0.3s var(--ease), opacity 0.3s var(--ease);
}
.nav.is-open .nav__burger span:first-child { transform: translateY(3.25px) rotate(45deg); }
.nav.is-open .nav__burger span:last-child { transform: translateY(-3.25px) rotate(-45deg); }

.navsheet {
  position: fixed;
  top: var(--nav-h); left: 0; right: 0;
  z-index: 999;
  background: rgba(11, 11, 12, 0.96);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  display: flex;
  flex-direction: column;
  padding: 16px 22px 28px;
  gap: 4px;
}
/* [hidden] must win over the display above (explicit display beats [hidden]) */
.navsheet[hidden] { display: none; }
.navsheet a {
  color: var(--ink-on-dark);
  font-size: 1.2rem;
  padding: 14px 0;
  border-bottom: 1px solid var(--hair-on-dark);
}

/* ===================== 1. HERO ===================== */
.hero {
  position: relative;
  height: 100vh;
  height: 100svh;
  width: 100%;
  overflow: hidden;
  background: #d9dbdc; /* fallback under the video */
}
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #c9cbcc;
}
/* frame-sequence canvas is the BOTTOM layer (revealed on scroll); main.js draws
   cover-fit frames. f001 (bunker) sits under the still at rest. */
.hero__frames {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  display: block;
}
/* solid plane fill, faded in over the final ~8% of the hero pin so the §2
   boundary always lands on the EXACT plane color (no seam). Sits just above the
   frame canvas, below the still layer. JS (gsap) owns its opacity. */
.hero__planefill {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--plane);
  opacity: 0;
  pointer-events: none;
}
/* TOP layer, the composited him-in-cave still + #142 distort. Full-bleed, sits
   over the frame canvas at rest; GSAP fades + recedes it on scroll to reveal the
   scrub underneath. Its own scale/recede happens here via transform. */
.hero__still {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: auto;
  transform-origin: center center;
  will-change: opacity, transform;
}
/* the #142 module appends a 100%/100% container; this inner box just fills the
   still layer so the distort canvas is full-bleed. */
.hero__still-inner {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* plain-still fallback (touch / WebGL unavailable): the same composited image,
   cover-fit, painted directly when the distort doesn't mount. */
.hero__still-inner.is-static {
  background-image: url('assets/hero-image.jpg');
  background-size: cover;
  background-position: center 42%;
  background-repeat: no-repeat;
}

.hero__label {
  position: absolute;
  z-index: 3;
  color: var(--ink);
}
/* hero is light, so corner labels read in dark ink */
.hero__label .mono { color: rgba(18, 19, 22, 0.78); }
.hero__label--tl { top: calc(var(--nav-h) + 14px); left: 18px; }
.hero__label--tr { top: calc(var(--nav-h) + 14px); right: 18px; text-align: right; }

.hero__scrollcue {
  position: absolute;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.hero__scrollcue .mono { color: rgba(18, 19, 22, 0.62); font-size: 0.6rem; }
.hero__scrollcue-line {
  width: 1px;
  height: 36px;
  background: linear-gradient(to bottom, rgba(18,19,22,0.6), transparent);
  animation: cuePulse 2.2s var(--ease) infinite;
}
@keyframes cuePulse {
  0%, 100% { transform: scaleY(0.4); opacity: 0.4; transform-origin: top; }
  50% { transform: scaleY(1); opacity: 1; transform-origin: top; }
}

/* ===================== 2. INTRO (white-suit arrival) ===================== */
.intro {
  position: relative;
  padding: 84px 20px 100px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.intro__eyebrow { margin-bottom: 1.2rem; }
.intro__line {
  max-width: 14ch;
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 13vw, 5rem);
  line-height: 1.0;
  color: var(--ink);
  margin: 0 auto;
}
/* the white-suit figure lands straight out of the hero white-out, materialising on
   the white plane. The cutout is transparent so it floats; a soft shadow grounds it. */
.intro__figure {
  margin: 30px 0 6px;
  width: 100%;
  display: flex;
  justify-content: center;
}
.intro__suit {
  width: min(80vw, 350px);
  height: auto;
  filter: drop-shadow(0 30px 66px rgba(0, 0, 0, 0.14));
}
.intro__sig {
  margin-top: 6px;
  display: flex;
  justify-content: center;
}

/* ---- Legible "Thomas" signature (§2 + footer) ----
   Sacramento script in holo-blue, drawn on left-to-right via a clip-path
   width reveal on scroll-enter. Reads clearly as "Thomas". */
.sig {
  font-family: var(--font-sig);
  color: var(--accent);
  line-height: 1;
  white-space: nowrap;
  /* draw-on: start fully clipped from the right, open to full on .is-drawn */
  clip-path: inset(0 100% 0 0);
  transition: clip-path 1.15s var(--ease);
  will-change: clip-path;
  -webkit-user-select: none;
  user-select: none;
}
.sig.is-drawn { clip-path: inset(0 0 0 0); }
.intro__sig .sig { font-size: clamp(3.4rem, 13vw, 6rem); }
@media (prefers-reduced-motion: reduce) {
  .sig { clip-path: inset(0 0 0 0); transition: none; }
}

/* ===================== 3b. FEATURED (press strip) ===================== */
.featured {
  position: relative;
  padding: 64px 20px 52px;
  text-align: center;
}
.featured__label { margin-bottom: 22px; }
.featured__strip { width: 100%; max-width: 1200px; margin: 0 auto; }
/* drive every logo to a uniform optical height regardless of aspect, and let the
   frame shrink-wrap; the tone filter equalizes them to one even monochrome band. */
.featured__strip > div,
.featured__strip [role="img"] {
  width: auto !important;
  height: auto !important;
  padding: 0 !important;
}
.featured__strip img {
  filter: grayscale(1) brightness(1.12) contrast(0.82) !important;
  -webkit-filter: grayscale(1) brightness(1.12) contrast(0.82) !important;
  opacity: 0.7;
  height: 30px !important;
  width: auto !important;
  max-width: 200px;
  object-fit: contain;
  transition: filter 0.3s ease, opacity 0.3s ease;
}
.featured__strip img[alt*="King"], .featured__strip img[src*="kings"] {
  height: 33px !important;
  filter: grayscale(1) brightness(1.28) contrast(0.78) !important;
  -webkit-filter: grayscale(1) brightness(1.28) contrast(0.78) !important;
  opacity: 0.66;
}
.featured__strip img[src*="apple"],
.featured__strip img[src*="isef"],
.featured__strip img[src*="iias"] {
  filter: grayscale(1) brightness(1.5) contrast(0.72) !important;
  -webkit-filter: grayscale(1) brightness(1.5) contrast(0.72) !important;
  opacity: 0.62;
}
.featured__strip img[src*="isef"] {
  filter: grayscale(1) brightness(1.32) contrast(0.78) !important;
  -webkit-filter: grayscale(1) brightness(1.32) contrast(0.78) !important;
  opacity: 0.66;
}
.featured__strip img[src*="iias"] {
  filter: grayscale(1) brightness(2.05) contrast(0.58) !important;
  -webkit-filter: grayscale(1) brightness(2.05) contrast(0.58) !important;
  opacity: 0.55;
}
.featured__strip:hover img { opacity: 0.85; }

/* ===================== 4. STORY ===================== */
.story {
  position: relative;
  padding: 30px 0 50px;
}
/* each beat gives the #139 sticky word-reveal room to pin (top:20vh) and run as
   you scroll through it; one beat occupies the view at a time. */
.story__beat {
  position: relative;
  min-height: 86vh;
  max-width: 1040px;
  margin: 0 auto;
  padding: 0 8vw;
}
/* the #139 module sets size/weight/colour inline but not the family; story prose
   reads in the body grotesk (Inter), large and editorial, not the display caps. */
.story__beat h2, .story__beat p, .story__beat [role="heading"] {
  font-family: var(--font-body);
}
/* oversized quote marquees (#091) scrolling full-width between beats, in the
   display face, UPPERCASE; the accent variant closes the section in holo-blue. */
.story__marquee {
  width: 100%;
  overflow: hidden;
  padding: 26px 0;
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.01em;
}

/* ===================== 4. EVIDENCE ===================== */
.evidence {
  position: relative;
  padding: 100px 0 110px;
}
.evidence__head {
  padding: 0 20px;
  max-width: 1200px;
  margin: 0 auto 40px;
}
.evidence__title {
  font-size: clamp(1.9rem, 7vw, 3.6rem);
  line-height: 1;
  letter-spacing: 0.01em;
}
.evidence__gallery {
  position: relative;
  width: 100%;
  height: 380px;
  margin-bottom: 56px;
}
.evidence__list {
  max-width: 760px;
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  flex-direction: column;
}
.evidence__item {
  display: grid;
  grid-template-columns: 56px 1fr;
  grid-template-areas:
    "year name"
    "year note";
  gap: 2px 16px;
  padding: 20px 0;
  border-top: 1px solid var(--hair);
  align-items: baseline;
}
.evidence__item:last-child { border-bottom: 1px solid var(--hair); }
.evidence__year { grid-area: year; align-self: center; }
.evidence__name {
  grid-area: name;
  font-size: clamp(1.05rem, 4vw, 1.45rem);
  font-weight: 500;
  letter-spacing: -0.01em;
}
.evidence__note { grid-area: note; color: var(--ink-muted); font-size: 0.86rem; }

/* ===================== 5. WORLDS (feature-flipper) ===================== */
.worlds {
  padding: 80px 16px 96px;
  max-width: 1320px;
  margin: 0 auto;
}
.worlds__head { margin-bottom: 30px; text-align: center; }
/* the #113 feature-flipper builds its own row/cards; the mount just owns width. */
.worlds__flipper { width: 100%; }

/* ===================== 6. BANNER (vision banner above socials) ===================== */
.banner {
  position: relative;
  width: 100%;
  height: 76vh;
  min-height: 460px;
  overflow: hidden;
  background: var(--black);
}
/* full-bleed cover image; Thomas's Afrofuturism shot swaps into the JS-set url. */
.banner__media {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.banner__overlay {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  padding: 0 20px 44px;
  pointer-events: none;
}
/* bottom scrim so the line keeps AA contrast over any shot dropped in (deep soft
   shadow for depth, brand-allowed, not an emitted glow). */
.banner__overlay::before {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 52%;
  background: linear-gradient(
    to top,
    rgba(11, 11, 12, 0.62) 0%,
    rgba(11, 11, 12, 0.30) 46%,
    rgba(11, 11, 12, 0) 100%
  );
  pointer-events: none;
  z-index: 0;
}
.banner__line {
  position: relative;
  z-index: 1;
  font-size: clamp(1.8rem, 7vw, 4rem);
  line-height: 1.0;
  color: var(--ink-on-dark);
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.5);
}

/* ===================== 7. SOCIALS ===================== */
.socials {
  position: relative;
  padding: 100px 20px 130px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.socials__head { margin-bottom: 56px; }
.socials__title { font-size: clamp(1.9rem, 7vw, 3.6rem); line-height: 1; }
.socials__deck {
  width: 100%;
  max-width: 900px;
  min-height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
}
.socials__note { margin-top: 40px; }

/* ===================== 8. FOOTER ===================== */
.footer {
  position: relative;
  background: var(--black);
  color: var(--ink-on-dark);
  padding: 96px 20px 40px;
  overflow: hidden;
}
.footer__hero {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.footer__big {
  font-size: clamp(2.4rem, 11vw, 6rem);
  line-height: 0.96;
  color: var(--ink-on-dark);
  /* keep the one dominant element off the edges, generous air both sides
     (brand: one dominant element per screen, vast space around it). */
  max-width: 14ch;
  margin: 0 auto;
}
.footer__sig { display: flex; justify-content: center; margin-top: 6px; }
.footer__sig .sig { font-size: clamp(3rem, 12vw, 5.4rem); }
/* the suit figure was removed from the footer 2026-06-19 (moved up to the §2
   white arrival, Thomas). The dark close now rests on the headline + signature. */
.footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 36px;
  max-width: 1100px;
  margin: 48px auto 0;
  padding-top: 40px;
  border-top: 1px solid var(--hair-on-dark);
}
.footer__col { display: flex; flex-direction: column; gap: 2px; }
.footer__coltitle { color: var(--ink-on-dark-muted); margin-bottom: 4px; }
/* mobile-first: each interactive footer link is a ~44px touch target (defect:
   footer tap targets). Vertical padding + min-height + flex-centering grows the
   hit area to guideline without changing the visible type size; the reduced
   .footer__col gap above keeps the column rhythm even with the taller rows. */
.footer__col a {
  color: var(--ink-on-dark);
  font-size: 0.95rem;
  width: max-content;
  min-height: 44px;
  display: flex;
  align-items: center;
  transition: color 0.3s var(--ease);
}
.footer__col a:hover { color: var(--accent); }
.footer__email {
  color: var(--ink-on-dark);
  font-size: 0.92rem;
  text-align: left;
  min-height: 44px;
  display: flex;
  align-items: center;
  padding: 0;
  word-break: break-all;
  transition: color 0.3s var(--ease);
}
.footer__email:hover { color: var(--accent); }
.footer__copytip { color: var(--accent); margin-top: 4px; }
.footer__base {
  max-width: 1100px;
  margin: 56px auto 0;
  padding-top: 22px;
  border-top: 1px solid var(--hair-on-dark);
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  text-align: center;
}
.footer__base .mono { color: var(--ink-on-dark-muted); font-size: 0.6rem; }

/* ============================================================
   DESKTOP ENHANCEMENT
   ============================================================ */
@media (min-width: 768px) {
  :root { --nav-h: 76px; }
  .nav { padding: 0 32px; }
  .nav__links { display: flex; }
  .nav__cta { display: inline-block; }
  .nav__burger { display: none; }
  .navsheet { display: none !important; }

  .hero__label--tl { left: 32px; }
  .hero__label--tr { right: 32px; }

  /* consistent desktop section rhythm: ~140px vertical on the light content
     sections so the page breathes evenly (brand: hard-aligned grid, generous
     even negative space). */
  .intro { padding: 130px 40px 140px; }
  .intro__suit { width: min(30vw, 440px); }

  .featured { padding: 90px 20px 70px; }

  .story__beat { padding: 0 10vw; }

  .evidence { padding: 140px 0 140px; }
  .evidence__gallery { height: 440px; }

  .worlds { padding: 120px 32px 140px; }

  .banner { height: 84vh; }
  .banner__overlay { padding: 0 48px 60px; }

  .socials { padding: 140px 20px 150px; }

  .footer { padding: 140px 48px 48px; }
  /* cap the footer hero line below 6rem on desktop and hold a comfortable
     margin on both sides so it never runs edge-to-edge at 1440 (defect 6). */
  .footer__big { font-size: clamp(2.4rem, 8.5vw, 5.2rem); max-width: 12ch; }
  .footer__grid {
    grid-template-columns: 1.4fr 1fr 1fr;
    gap: 48px;
  }
  .footer__base {
    flex-direction: row;
    justify-content: space-between;
  }
}

@media (min-width: 1100px) {
  .intro__line { font-size: clamp(3.4rem, 6vw, 6rem); max-width: 16ch; }
}

/* reduced motion */
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .hero__scrollcue-line { animation: none; }
}
