/* ════════════════════════════════════════════════════════════
   (four:three) — style.css
   Single shared stylesheet for all pages.
   Sections marked with dashed comment headers.
   ════════════════════════════════════════════════════════════ */


/* ── FONTS: NOHEMI (self-hosted) ── */
/* Used for: headings, nav, logo, labels, capabilities, footer CTA, tags */
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-Thin-BF6438cc577ef3b.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-Thin-BF6438cc5896c67.ttf') format('truetype');
  font-weight: 100;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-ExtraLight-BF6438cc581502c.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-ExtraLight-BF6438cc58a2634.ttf') format('truetype');
  font-weight: 200;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-Light-BF6438cc5702321.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-Light-BF6438cc5899919.ttf') format('truetype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-Regular-BF6438cc579d934.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-Regular-BF6438cc4d0e493.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-Medium-BF6438cc57ddecd.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-Medium-BF6438cc5883899.ttf') format('truetype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-SemiBold-BF6438cc57db2ff.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-SemiBold-BF6438cc588a48a.ttf') format('truetype');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-Bold-BF6438cc577b524.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-Bold-BF6438cc587b5b5.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-ExtraBold-BF6438cc5761ae2.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-ExtraBold-BF6438cc5881baf.ttf') format('truetype');
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Nohemi';
  src: url('assets/fonts/nohemi-font-family/Nohemi-Black-BF6438cc565e67b.woff') format('woff'),
       url('assets/fonts/nohemi-font-family/Nohemi-Black-BF6438cc58744d4.ttf') format('truetype');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

/* Variable axis (wght 100–900) — used for smooth capabilities distortion */
@font-face {
  font-family: 'Nohemi VF';
  src: url('assets/fonts/nohemi-font-family/Nohemi-VF-BF6438cc58ad63d.ttf') format('truetype');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}


/* ── ROOT VARIABLES ── */
:root {
  --bg: #0c0c0c;
  --fg: #f0f0f0;
  --fg-muted: #444444;
  --accent: #4ade80;
}


/* ── RESET ── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Anchor jumps (e.g. nav "connect" → footer #contact) glide instead of snap */
html { scroll-behavior: smooth; }


/* ── BASE / BODY ── */
body {
  font-family: 'Roboto', sans-serif;
  font-weight: 400;
  line-height: 1.7;
  background: var(--bg);
  color: var(--fg);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
}


/* ── CUSTOM CURSOR (Miffy arrow / Problem pointer) ── */
body {
  cursor: url('assets/cursors/miffy-cursor.png') 2 2, auto;
}

/* Links & buttons swap the arrow for the Miffy pointer hand — clear click affordance */
a,
button {
  cursor: url('assets/cursors/miffy-pointer.png') 8 2, pointer;
}


/* ── NAV ── */
nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 20px 28px;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 500;
  background: transparent;
}

.nav-left,
.nav-right,
.nav-link {
  transition: opacity 0.8s cubic-bezier(0.4, 0, 0.2, 1),
              transform 0.8s cubic-bezier(0.4, 0, 0.2, 1),
              color 0.35s;
}

/* Scroll: slide up + fade out */
.nav-scrolling .nav-left,
.nav-scrolling .nav-right,
.nav-scrolling .nav-link {
  opacity: 0;
  transform: translateY(-5px);
  pointer-events: none;
}

.nav-left {
  font-family: 'Nohemi', sans-serif;
  font-size: 11px;
  letter-spacing: 0.06em;
  font-weight: 400;
  color: var(--fg);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.nav-center {
  display: flex;
  align-items: center;
  gap: 52px;
}


/* ── NAV LINKS + ACTIVE STATE ── */
.nav-link {
  font-family: 'Nohemi', sans-serif;
  font-size: 13px;
  font-weight: 400;
  text-decoration: none;
  color: var(--fg);
  white-space: nowrap;
  letter-spacing: -0.01em;
}
.nav-link:hover { opacity: 0.35; }

/* Active page link — green accent (set via main.js on pathname match) */
.nav-link.active {
  color: var(--accent);
}
.nav-link.active:hover { opacity: 1; }


/* ── LOGO ((:) → (four:three) on hover) ── */
.nav-logo-wrap {
  width: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.logo {
  display: inline-flex;
  align-items: center;
  color: var(--fg);
  text-decoration: none;
}
.logo svg { display: block; }
.logo path { fill: var(--fg); transition: fill 0.35s; }
.logo-colon { flex-shrink: 0; }

.paren-l { flex-shrink: 0; transition: transform 0.85s cubic-bezier(0.4,0,0.2,1); }
.paren-r { flex-shrink: 0; transition: transform 0.85s cubic-bezier(0.4,0,0.2,1); }

.slide-l {
  overflow: hidden; width: 0; opacity: 0; flex-shrink: 0;
  transition: width 0.85s cubic-bezier(0.4,0,0.2,1), opacity 0.5s ease;
}
.slide-r {
  overflow: hidden; width: 0; opacity: 0; flex-shrink: 0;
  transition: width 0.85s cubic-bezier(0.4,0,0.2,1), opacity 0.5s ease;
}
.slide-l svg { transform: translateX(20px); transition: transform 0.85s cubic-bezier(0.4,0,0.2,1); }
.slide-r svg { transform: translateX(-20px); transition: transform 0.85s cubic-bezier(0.4,0,0.2,1); }

.logo:hover .slide-l { width: 38px; opacity: 1; }
.logo:hover .slide-r { width: 39px; opacity: 1; }
.logo:hover .slide-l svg { transform: translateX(0); }
.logo:hover .slide-r svg { transform: translateX(0); }
.logo:hover .paren-l { transform: translateX(2px); }
.logo:hover .paren-r { transform: translateX(-2px); }


.nav-right {
  display: flex;
  justify-content: flex-end;
  align-items: center;
}

/* "connect" lives in the top-right corner (desktop); scrolls to footer #contact.
   On mobile it swaps places with the redundant clock — see the @media block. */
.nav-connect {
  text-transform: lowercase;
  /* Match the logo's 25px box and flex-centre the glyph, so connect shares the
     exact vertical centre of the logo/hamburger regardless of font metrics. */
  display: flex;
  align-items: center;
  height: 25px;
  line-height: 1;
}
/* connect hovers green (not the default fade) */
.nav-connect:hover {
  opacity: 1;
  color: var(--accent);
}


/* ── MENU TRIGGER (2 lines → X) ──
   Desktop: fixed to the left edge, vertically centred.
   Mobile (≤768px): jumps to the top-right corner as a classic menu button. */
.menu-trigger {
  position: fixed;
  left: 22px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 820;
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
}
.menu-trigger .bars {
  position: relative;
  width: 26px;
  height: 12px;
}
.menu-trigger .bars span {
  position: absolute;
  left: 0;
  width: 26px;
  height: 2px;
  background: #fff;
  mix-blend-mode: difference;     /* always inverts the backdrop → visible on any bg */
  transition: transform 0.35s cubic-bezier(0.7, 0, 0.2, 1),
              top 0.35s cubic-bezier(0.7, 0, 0.2, 1);
}
.menu-trigger .bars span:nth-child(1) { top: 2px; }
.menu-trigger .bars span:nth-child(2) { top: 8px; }

/* Open → the 2 lines cross into an X */
body.menu-open .menu-trigger .bars span:nth-child(1) { top: 5px; transform: rotate(45deg); }
body.menu-open .menu-trigger .bars span:nth-child(2) { top: 5px; transform: rotate(-45deg); }


/* ── NAV DRAWER (slides from the left, #000) ── */
.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 780;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
}
.nav-scrim.open {
  opacity: 1;
  pointer-events: auto;
}

.nav-drawer {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 800;
  width: 30vw;
  min-width: 380px;
  background: #000;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 56px 0 100px;        /* extra left padding = breathing room from the X */
  transform: translateX(-100%);
  transition: transform 0.55s cubic-bezier(0.7, 0, 0.2, 1);
}
.nav-drawer.open { transform: translateX(0); }

.nav-drawer-head {
  position: absolute;
  top: 0;
  left: 100px;
  right: 56px;
  height: 65px;
  display: flex;
  align-items: center;
}
.nav-drawer-head .mark {
  font-family: 'Nohemi', sans-serif;
  font-size: 13px;
  letter-spacing: 0.06em;
  color: #555;
  text-transform: lowercase;
}

.nav-drawer-links {
  display: flex;
  flex-direction: column;
  gap: 6px;
  list-style: none;
}
.drawer-link {
  font-family: 'Nohemi', sans-serif;
  font-weight: 400;
  font-size: clamp(34px, 4vw, 52px);
  line-height: 1.12;
  text-transform: lowercase;
  letter-spacing: -0.01em;
  color: #f0f0f0;
  text-decoration: none;
  opacity: 0;
  transform: translateX(-14px);
  transition: color 0.18s ease, opacity 0.22s ease,
              transform 0.5s cubic-bezier(0.7, 0, 0.2, 1);
}
.nav-drawer.open .drawer-link {
  opacity: 1;
  transform: translateX(0);
}
/* Stagger the links in after the panel */
.nav-drawer.open .drawer-link:nth-child(1) { transition-delay: 0.12s; }
.nav-drawer.open .drawer-link:nth-child(2) { transition-delay: 0.18s; }
.nav-drawer.open .drawer-link:nth-child(3) { transition-delay: 0.24s; }
.nav-drawer.open .drawer-link:nth-child(4) { transition-delay: 0.30s; }

/* Hover: active link green, siblings fade (same as social-links / capabilities) */
.drawer-link:hover { color: var(--accent); }
.nav-drawer-links:has(.drawer-link:hover) .drawer-link:not(:hover) { opacity: 0.3; }

/* Active page link — green accent (set via main.js on pathname match) */
.drawer-link.active { color: var(--accent); }

.nav-drawer-foot {
  position: absolute;
  bottom: 40px;
  left: 100px;
  right: 56px;
  font-family: 'Nohemi', sans-serif;
  font-size: 12px;
  letter-spacing: 0.05em;
  color: #444;
  text-transform: uppercase;
}

@media (max-width: 768px) {
  .menu-trigger {
    left: auto;
    right: 28px;           /* match the nav's 28px side padding (symmetry with connect) */
    top: 0;
    height: 65px;          /* span the nav height so the bars centre on its row */
    transform: none;
  }
  /* Clock is redundant on mobile → drop it; "connect" takes the left slot,
     logo stays centred, hamburger sits top-right. */
  .nav-left { display: none; }
  .nav-center { grid-column: 2; }   /* keep logo centred once the clock is gone */
  /* connect mirrors the hamburger EXACTLY (same fixed box, opposite side) so the
     two can't sit at different heights. Logo stays centred in the grid. */
  .nav-connect {
    position: fixed;
    left: 28px;
    top: 0;
    height: 65px;
    z-index: 820;
  }
  .nav-drawer {
    width: 88vw;
    min-width: 0;
    padding: 0 36px;
  }
  .nav-drawer-head,
  .nav-drawer-foot { left: 36px; right: 36px; }
}


/* ── FILM GRAIN / NOISE OVERLAY ── */
.noise-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0.05;
  filter: url(#noise);
  background: transparent;
}

@keyframes grain {
  0%   { transform: translate(0, 0); }
  10%  { transform: translate(-2%, -3%); }
  20%  { transform: translate(3%, 2%); }
  30%  { transform: translate(-1%, 4%); }
  40%  { transform: translate(4%, -1%); }
  50%  { transform: translate(-3%, 1%); }
  60%  { transform: translate(1%, -4%); }
  70%  { transform: translate(-4%, 3%); }
  80%  { transform: translate(2%, -2%); }
  90%  { transform: translate(-2%, 4%); }
  100% { transform: translate(0, 0); }
}

.noise-overlay canvas {
  position: absolute;
  inset: -20%;
  width: 140%;
  height: 140%;
  animation: grain 0.8s steps(1) infinite;
}

/* Reduced motion → keep the grain texture but calm it: stop the jitter animation
   and lower opacity. (JS also slows the noise regeneration; see filmGrain.) */
@media (prefers-reduced-motion: reduce) {
  .noise-overlay { opacity: 0.045; }
  .noise-overlay canvas { animation: none; }
}


/* ════════════════════════════════════════════════════════════
   INDEX PAGE
   ════════════════════════════════════════════════════════════ */

/* ── LOADER (index — (:) pans out to (four:three)) ── */
/* The colon + parentheses are the (:) seed; the "four"/"three" panels expand
   their width to push the parens apart, revealing (four:three). Same mechanic
   as the nav logo's hover. Then the overlay fades into the hero. State driven
   by classes from index.js. */
#loader {
  position: fixed;
  inset: 0;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9000;
  transition: opacity 0.35s ease;
}
#loader.done { display: none; }

.loader-mark {
  display: flex;
  align-items: center;
  transition: opacity 0.2s ease;   /* crossfades to .lm-solid at morph start */
}

/* Consolidated wordmark (identical artwork to the hero logo). Hidden until the
   morph: the 5-piece mark crossfades to this, which then grows + glides down to
   land pixel-perfectly on the hero logo (5 pieces can't match its kerning). */
.lm-solid {
  position: absolute;
  inset: 0;
  margin: auto;
  height: 56px;
  width: auto;
  opacity: 0;
  transform-origin: center center;
  transition: transform 0.65s cubic-bezier(0.7, 0, 0.2, 1), opacity 0.2s ease;
  will-change: transform, opacity;
}
.lm-solid path { fill: var(--fg); }

#loader.morph .loader-mark { opacity: 0; }
#loader.morph .lm-solid   { opacity: 1; }
.loader-mark svg { display: block; height: 56px; width: auto; }
.loader-mark path { fill: var(--fg); }

/* Always-visible (:) seed */
.lm-paren-l, .lm-paren-r, .lm-colon { flex-shrink: 0; }

/* "four" / "three" start collapsed (width 0) and pan open */
.lm-four, .lm-three {
  overflow: hidden;
  width: 0;
  opacity: 0;
  flex-shrink: 0;
  transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease;
}
.lm-four svg  { transform: translateX(22px);  transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); }
.lm-three svg { transform: translateX(-22px); transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); }

#loader.assemble .lm-four  { width: 85px; opacity: 1; }
#loader.assemble .lm-three { width: 87px; opacity: 1; }
#loader.assemble .lm-four svg,
#loader.assemble .lm-three svg { transform: translateX(0); }

/* Exit — overlay fades into the hero */
#loader.exit { opacity: 0; }


/* ── HERO WRAPPER (index) ── */
.section-hero {
  height: 100dvh;          /* dvh = stable on mobile (no jump as the URL bar hides) */
  padding-top: 65px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  flex-shrink: 0;
  position: relative;
  z-index: 2;
  background: var(--bg);
}

.hero {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  position: relative;
  z-index: 200;
}

.hero-logo { width: 100%; line-height: 0; flex-shrink: 0; }
.hero-logo svg { width: 100%; height: auto; display: block; }
.hero-logo path { fill: var(--fg); transition: fill 0.35s; }

/* Hero bottom labels row */
.hero-bottom {
  width: 100%;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  padding: 0 28px 10px;
  flex-shrink: 0;
  position: relative;
}

.hero-bottom-left,
.hero-bottom-right {
  font-family: 'Nohemi', sans-serif;
  font-size: 13px;
  letter-spacing: 0.05em;
  color: var(--fg);
  font-weight: 400;
  transition: color 0.35s;
  white-space: nowrap;
  line-height: 1;
}

.hero-bottom-center {
  font-family: 'Nohemi', sans-serif;
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-muted);
  font-weight: 400;
  transition: color 0.35s;
  white-space: nowrap;
  line-height: 1;
  padding-bottom: 1px;
}


/* ── TRAIL IMAGES (index hero) ── */
.trail-img {
  position: absolute;
  pointer-events: none;
  z-index: 100;
  width: 180px;
  aspect-ratio: 4 / 5;        /* all trace_pics are 1080×1350 (4:5) */
  object-fit: cover;
  will-change: transform, opacity;
  transform: translate(-50%, -50%) scale(0) rotate(var(--rot));
  opacity: 0;
}
.trail-img.spawn {
  animation: stamp 0.95s cubic-bezier(0.2, 0, 0.2, 1) forwards;
}

@keyframes stamp {
  0%   { transform: translate(-50%, -50%) scale(0) rotate(var(--rot)); opacity: 0; }
  10%  { transform: translate(-50%, -50%) scale(1) rotate(var(--rot)); opacity: 1; }
  85%  { transform: translate(-50%, -50%) scale(1) rotate(var(--rot)); opacity: 1; }
  86%  { transform: translate(-50%, -50%) scale(1) rotate(var(--rot)); opacity: 0; }
  100% { transform: translate(-50%, -50%) scale(1) rotate(var(--rot)); opacity: 0; }
}


/* ── SCROLL STAGE: parallax scrolls above the sticky footer ── */
.scroll-stage {
  position: relative;
  z-index: 2;
  background: var(--bg);
}

/* ── PARALLAX SECTION (index) ── */
/* The columns are a fixed-height "window" pinned with position:sticky; content
   scrolls through via JS (virtual scroll) so mixed image aspect ratios never
   affect layout. The section's HEIGHT is computed in index.js from the actual
   content (so adding images needs no code change) — min-height is just a
   pre-JS fallback. */
.section-parallax {
  position: relative;
  z-index: 2;
  background: var(--bg);
  min-height: 100vh;
}

.cols-container {
  position: sticky;
  top: 0;
  height: 100dvh;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 4px;
  background: var(--bg);
  overflow: hidden;
}

.col-track {
  background: var(--bg);
  overflow: hidden;
  position: relative;
}

.col-inner {
  will-change: transform;
  transform: translateZ(0);
}

.col-item {
  position: relative;
  display: block;
  margin-bottom: 4px;
  line-height: 0;
  text-decoration: none;
  color: inherit;
}
.col-item:last-child { margin-bottom: 0; }

.col-item img,
.col-item video {
  width: 100%;
  display: block;
  object-fit: cover;
}

/* ── Project title overlay (top-left) ──
   Title + year as a hierarchy on a soft top scrim, so it stays legible over any
   image. OPTION 1 (default) = scrim + plain white text. OPTION 2 = add the class
   `carousel-diff` to <body> for mix-blend-mode:difference over a faint scrim. */
.col-item-title {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 12px 13px 26px;
  pointer-events: none;
}
/* The scrim itself — a top-down fade that grounds the text without a hard box. */
.col-item-title::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0) 100%);
}
.col-item-name {
  position: relative;          /* paint above ::before */
  font-family: 'Nohemi', sans-serif;
  line-height: 1.15;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 500;
  color: #fff;
}

/* Video play indicator overlay */
.col-item-play {
  position: absolute;
  bottom: 11px;
  right: 12px;
  font-size: 10px;
  color: #fff;
  pointer-events: none;
  line-height: 1;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.55);   /* legible on bright frames too */
}

/* ── OPTION 2: guarded mix-blend-mode difference ──
   Text inverts against the image (editorial/raw look) but a faint scrim keeps
   mid-tone photos from collapsing to unreadable grey. Toggle: body.carousel-diff. */
body.carousel-diff .col-item-title::before {
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.22) 0%, rgba(0, 0, 0, 0) 100%);
}
body.carousel-diff .col-item-name {
  mix-blend-mode: difference;
  color: #fff;
}


/* ════════════════════════════════════════════════════════════
   ABOUT PAGE
   ════════════════════════════════════════════════════════════ */

/* ── ABOUT SECTION ── */
.section-about {
  /* Extra left padding reserves a rail for the fixed menu trigger (left:22px,
     vertically centred) so scrolling content never runs under it. */
  padding: 120px 28px 80px 90px;
  max-width: 100%;
}

/* ── BLOCK 1: INTRO ── */
.about-intro {
  display: grid;
  grid-template-columns: 1.5fr 0.82fr;
  gap: 72px;
  align-items: center;
  margin-bottom: 100px;
}
.about-intro-text { min-width: 0; }

/* Portrait — the (four:three) magazine cover. Static image, no overlay. */
.about-portrait {
  position: relative;
  width: calc(100% - 64px);
  aspect-ratio: 1000 / 1144;
  overflow: hidden;
  border-radius: 4px;
}
.portrait-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

.about-intro-label {
  font-family: 'Nohemi', sans-serif;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: 24px;
}

.about-intro-headline {
  font-family: 'Nohemi VF', 'Nohemi', sans-serif;
  font-size: clamp(32px, 5vw, 64px);
  font-weight: 300;
  font-variation-settings: 'wght' 300;
  letter-spacing: -0.02em;
  line-height: 1.1;
  max-width: 800px;
  margin-bottom: 24px;
}

.about-intro-body {
  font-family: 'Roboto', sans-serif;
  font-size: 14px;
  line-height: 1.7;
  color: var(--fg-muted);
  max-width: 540px;
}

/* ── BLOCK 2: CAPABILITIES ── */
.capabilities-heading {
  font-family: 'Nohemi', sans-serif;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: 28px;
}
/* Shared per-letter behaviour for any .vf-heading (capabilities + coming-soon). */
.vf-heading .letter {
  display: inline-block;
  font-variation-settings: 'wght' 300;
  transition: font-variation-settings 0.15s ease;
}

.about-capabilities {
  margin-bottom: 100px;
}

.about-section-label {
  font-family: 'Nohemi', sans-serif;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: 20px;
}

.capability-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
  padding: 40px 0;
  border-top: 0.5px solid var(--fg-muted);
  transition: opacity 0.3s ease, border-color 0.35s;
  cursor: default;
}
.capability-row:last-child {
  border-bottom: 0.5px solid var(--fg-muted);
}

/* Row hover: active full opacity, siblings fade.
   Mouse-only — on touch :hover sticks after a tap, so the row would stay dimmed.
   Touch gets the equivalent via JS (.scroll-dim, see end of file). */
@media (hover: hover) {
  .about-capabilities:has(.capability-row:hover) .capability-row:not(:hover) {
    opacity: 0.25;
  }
}

.capability-name {
  font-family: 'Nohemi', sans-serif;
  font-size: clamp(28px, 4vw, 52px);
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.capability-items {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  padding-top: 4px;
}

.capability-item {
  font-family: 'Roboto', sans-serif;
  font-size: 14px;
  color: var(--fg);
  letter-spacing: 0.02em;
  transition: color 0.35s;
  position: relative;
  cursor: default;
}

/* Tooltip slides in from left */
.capability-item .tooltip {
  position: absolute;
  right: calc(100% + 14px);
  top: 50%;
  transform: translateY(-50%);
  background: var(--fg);
  color: var(--bg);
  font-family: 'Roboto', sans-serif;
  font-size: 11px;
  letter-spacing: 0.02em;
  line-height: 1.5;
  padding: 8px 12px;
  border-radius: 4px;
  white-space: normal;
  width: 240px;
  text-align: left;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  z-index: 10;
}
.capability-item:hover .tooltip {
  opacity: 1;
}

/* ── BLOCK 3: TOOLS ── */
.about-tools {
  margin-bottom: 80px;
}

.tools-category {
  margin-bottom: 36px;
}

.tools-category-name {
  font-family: 'Nohemi', sans-serif;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: 12px;
}

.tools-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tool-tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px 6px 8px;
  border: 0.5px solid var(--fg-muted);
  border-radius: 4px;
  font-family: 'Nohemi', sans-serif;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--fg);
  transition: border-color 0.2s, color 0.2s;
  cursor: default;
}
.tool-tag:hover {
  border-color: var(--accent);
}
.tool-tag img {
  width: 14px;
  height: 14px;
  object-fit: contain;
  border-radius: 2px;
  flex-shrink: 0;
}


/* ── BLOCK 4: PERSONAL (facts list + colleagues pills) ── */
.about-personal {
  margin-bottom: 80px;
}

.fact-row {
  display: grid;
  grid-template-columns: 1fr 1.6fr;
  align-items: start;
  padding: 34px 0;
  border-top: 0.5px solid var(--fg-muted);
  transition: opacity 0.3s ease;
}
.fact-row:last-of-type {
  border-bottom: 0.5px solid var(--fg-muted);
}
@media (hover: hover) {
  .about-facts:has(.fact-row:hover) .fact-row:not(:hover) {
    opacity: 0.25;
  }
}

.fact-label {
  font-family: 'Nohemi', sans-serif;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-muted);
  padding-top: 6px;
}
.fact-value {
  font-family: 'Nohemi', sans-serif;
  font-weight: 300;
  font-size: clamp(18px, 2.1vw, 24px);
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--fg);
  max-width: 34ch;
}

.colleagues {
  margin-top: 72px;
}
.colleagues-label {
  font-family: 'Nohemi', sans-serif;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-muted);
  margin-bottom: 24px;
}
.colleagues-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.colleague-tag {
  font-family: 'Nohemi', sans-serif;
  font-size: 14px;
  letter-spacing: 0.01em;
  color: var(--fg);
  border: 0.5px solid var(--fg-muted);
  border-radius: 999px;
  padding: 11px 22px;
  transition: border-color 0.2s, color 0.2s;
}
.colleague-tag:hover {
  border-color: var(--accent);
}

@media (max-width: 768px) {
  .fact-row {
    grid-template-columns: 1fr;
    gap: 10px;
    padding: 26px 0;
  }
  .fact-value { max-width: none; }
}


/* ════════════════════════════════════════════════════════════
   SHELL PAGES (work / visuals / connect)
   ════════════════════════════════════════════════════════════ */
.section-shell {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 120px 28px;
  min-height: calc(100dvh - 65px);
}
.shell-label {
  font-family: 'Nohemi', sans-serif;
  font-size: clamp(28px, 5vw, 64px);
  font-weight: 300;
  letter-spacing: -0.02em;
  color: var(--fg-muted);
}


/* ════════════════════════════════════════════════════════════
   COMING-SOON SHELL (work / visuals)
   ════════════════════════════════════════════════════════════ */
/* A zero-height anchor sitting at the main↦footer seam. Its absolutely
   positioned heading drops into the footer's blank top space, so the text
   reads as "inside" the empty footer area without being part of <footer>. */
.coming-stage {
  position: relative;
  height: 0;
  z-index: 1;
  pointer-events: none;
}
.coming-soon {
  position: absolute;
  left: 0;
  right: 0;
  top: 42dvh;
  transform: translateY(-50%);
  margin: 0;
  padding: 0 28px;
  pointer-events: auto;
  text-align: center;        /* centred — clears the menu trigger on its own */
  white-space: nowrap;       /* keep "coming soon" on a single line */
  font-family: 'Nohemi VF', 'Nohemi', sans-serif;
  font-size: clamp(40px, 11vw, 180px);
  font-weight: 300;
  font-variation-settings: 'wght' 300;
  letter-spacing: -0.03em;
  line-height: 1;
  text-transform: lowercase;
  color: var(--fg);
  cursor: default;
}
/* On shell pages the footer fills the rest of the viewport (no overflow scroll)
   and drops its top border so no stray line shows under the empty nav area. */
.coming-stage + .section-footer {
  height: calc(100dvh - 65px);
  border-top: none;
}


/* ════════════════════════════════════════════════════════════
   FOOTER (shared — always dark)
   ════════════════════════════════════════════════════════════ */
.section-footer {
  position: relative;
  bottom: auto;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  background: #0c0c0c;
  border-top: 0.5px solid #444;
  overflow: hidden;
}

/* index.html only → footer is sticky and revealed by parallax */
body.home .section-footer {
  position: sticky;
  bottom: 0;
  z-index: 0;
}

.footer-social {
  display: flex;
  gap: 28px;
  padding: 0 28px 20px;
}

.footer-social a {
  font-family: 'Nohemi', sans-serif;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #f0f0f0;
  text-decoration: none;
  font-weight: 400;
  transition: color 0.2s, opacity 0.2s;
  display: flex;
  align-items: center;
  gap: 5px;
}
.footer-social a:hover { color: var(--accent); }
.footer-social:has(a:hover) a:not(:hover) { opacity: 0.3; }

.footer-social a svg {
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.footer-social a:hover svg { transform: translate(3px, -3px) scale(1.25); }

.footer-divider {
  width: 100%;
  height: 0.5px;
  background: #444;
}

.footer-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 28px;
  height: 135px;
  flex-shrink: 0;
  text-decoration: none;
}
.footer-cta:hover { color: var(--accent); }
.footer-cta:hover .footer-cta-text { color: var(--accent); }
.footer-cta:hover .footer-cta-arrow svg path { fill: var(--accent); }

.footer-cta-text {
  font-family: 'Nohemi', sans-serif;
  font-weight: 400;
  font-size: clamp(63px, 9vw, 120px);
  line-height: 1;              /* hitbox hugs the glyphs, no bleed toward social */
  color: #f0f0f0;
  letter-spacing: -0.02em;
}

.footer-cta-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  flex-shrink: 0;
  transition: opacity 0.2s;
}
.footer-cta-arrow svg {
  width: 89px;
  height: 89px;
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.footer-cta:hover .footer-cta-arrow svg { transform: scale(1.12); }
.footer-cta-arrow svg path { fill: #f0f0f0; }

.footer-bottom {
  padding: 14px 28px;
  display: flex;
  justify-content: flex-start;
  font-family: 'Nohemi', sans-serif;
  font-size: 9px;
  letter-spacing: 0.08em;
  color: #444;
}


/* ── FOOTER (mobile) ──
   Placed at the END of the file ON PURPOSE: @media adds no specificity, so
   these must come AFTER the base .footer-cta rules to win on source order. */
@media (max-width: 768px) {
  .footer-social {
    gap: 18px;
    flex-wrap: wrap;
    padding-bottom: 0;       /* the 44px link box below already supplies the spacing */
  }
  .footer-social a {
    font-size: 13px;
    min-height: 44px;        /* comfortable finger tap target */
  }

  .footer-cta {
    height: auto;
    padding: 26px 28px;
    gap: 16px;
    align-items: center;
  }
  .footer-cta-text {
    font-size: clamp(34px, 10vw, 52px);
    line-height: 1.05;
  }
  .footer-cta-arrow svg { width: 40px; height: 40px; }
}


/* ── ABOUT (mobile) ──
   At the END so these win source-order over the base about rules above. */
@media (max-width: 768px) {
  .section-about { padding: 24px 22px 70px; }

  .about-intro {
    grid-template-columns: 1fr;
    gap: 32px;
    margin-bottom: 64px;
  }
  .about-portrait { width: 100%; max-width: 340px; }
  .about-capabilities { margin-bottom: 64px; }

  /* Stack the name above its items, both left-aligned. */
  .capability-row {
    grid-template-columns: 1fr;
    gap: 16px;
    padding: 28px 0;
  }
  .capability-items {
    align-items: flex-start;
    gap: 8px;
  }
}

/* Touch devices can't hover, so tooltips can never trigger → hide them (option A).
   Keyed on (hover: none) not width, so touch tablets at desktop widths get it too. */
@media (hover: none) {
  .capability-item .tooltip { display: none; }
}

/* Scroll-driven dim, set by capabilitiesScrollDim in main.js on touch / narrow
   screens: the row nearest the viewport centre keeps full opacity, the rest fade
   — mirrors the desktop hover dim. Gated by the .scroll-dim class (JS only adds it
   when active), so no media query is needed and it works at any width. */
.about-capabilities.scroll-dim .capability-row:not(.in-focus) { opacity: 0.25; }


/* ── CONNECT stays constant (mobile) ──
   connect is a .nav-link, so the default .nav-scrolling rule would fade it out
   on scroll. On mobile we keep it visible at all times — must sit AFTER the base
   .nav-scrolling rule to win on source order.
   IMPORTANT: also clear the transform on .nav-right (connect's parent). A
   transformed ancestor becomes the containing block for connect's position:fixed,
   which would yank it from the viewport to nav-right's box (jumping right/down). */
@media (max-width: 768px) {
  .nav-scrolling .nav-right {
    transform: none;
    opacity: 1;
  }
  .nav-scrolling .nav-connect {
    transform: none;
    opacity: 1;
    pointer-events: auto;
  }
}


/* ── HERO bottom labels (mobile) ──
   Tighten the row on phones; the centre tagline stays visible as long as it fits.
   Only on the very narrowest screens (≤360px) does it collide with the side cues,
   so it's dropped there (it also lives in the drawer footer). */
@media (max-width: 768px) {
  .hero-bottom { padding: 0 22px 14px; }
  .hero-bottom-left,
  .hero-bottom-right { font-size: 11px; }
}
@media (max-width: 360px) {
  .hero-bottom-center { display: none; }
}


/* ── PARALLAX CAROUSEL (mobile) ──
   Keep all 3 columns (the multi-speed parallax is the point) — just tighten the
   gap and shrink the title overlay so the narrower columns stay legible. */
@media (max-width: 768px) {
  .cols-container { gap: 3px; }
  .col-item { margin-bottom: 3px; }
  .col-item-title { padding: 8px 8px 20px; }
  .col-item-name { font-size: 9px; letter-spacing: 0.07em; }
  .col-item-play {
    bottom: 7px;
    right: 7px;
    font-size: 9px;
  }
}


/* ── LARGE SCREENS — cap text content width ──
   Hero, carousel and the "get in touch" bar stay full-bleed by design. The about
   page is reading content, so centre it and stop the 2-col rows from sprawling
   apart on very wide / 4K displays. */
@media (min-width: 1600px) {
  .section-about {
    max-width: 1440px;
    margin-inline: auto;
  }
}


/* ── KEYBOARD FOCUS RING ──
   Only shows for keyboard navigation (:focus-visible), never on mouse/touch
   clicks — so the visual design is untouched for pointer users while keyboard
   users get a clear, on-brand focus indicator. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 1px;
}
/* Drop the legacy outline for mouse users on browsers that support :focus-visible. */
:focus:not(:focus-visible) { outline: none; }


/* ── SHORT VIEWPORTS (phones in landscape) ──
   Landscape phones are often wider than 768px, so they get the desktop layout
   but with very little height. Compact the tall footer CTA so it doesn't clip
   inside the shell footer's (100dvh − 65px) box. Keyed on height, not width. */
@media (max-height: 520px) {
  .footer-cta {
    height: auto;
    padding: 20px 28px;
  }
  .footer-cta-text { font-size: clamp(34px, 8vh, 63px); }
  .footer-cta-arrow svg { width: 56px; height: 56px; }
}
