/* ============================================================
   Benjamin Jeffries - Portfolio Homepage
   Stylesheet for index.html
   Modernist editorial aesthetic · white · ink · Akzidenz Grotesk
   ============================================================ */

/* ---------- Fonts ----------
   UntitledSansWeb (Klim Type Foundry) - local woff2 files already in the
   project root. Falls back to Helvetica Neue / system grotesques. */

@font-face {
  font-family: 'UntitledSansWeb';
  src: url('UntitledSansWeb-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'UntitledSansWeb';
  src: url('UntitledSansWeb-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  /* Color - strict 2-color palette + neutrals */
  --paper: #ffffff;
  --paper-alt: #fafafa;
  --ink: #1a1a1a;
  --ink-soft: #333333;
  --ink-mute: #777777;
  --ink-faint: #c4c4c4;
  --rule: rgba(26, 26, 26, 0.14);
  --rule-soft: rgba(26, 26, 26, 0.06);

  /* Type */
  --font-sans: 'UntitledSansWeb', 'Helvetica Neue';

  --type-display:  clamp(3.5rem, 9.5vw, 11rem);
  --type-h2:       clamp(2rem, 4.5vw, 4.25rem);
  --type-h3:       clamp(1.25rem, 1.8vw, 1.75rem);
  --type-lede:     clamp(1.125rem, 1.35vw, 1.5rem);
  --type-body:     1.0625rem;
  --type-small:    0.9375rem;
  --type-caption:  0.75rem;

  --lh-display: 0.94;
  --lh-tight:   1.1;
  --lh-body:    1.55;

  /* Space */
  --pad-x:  clamp(1rem, 3.5vw, 4rem);
  --pad-y:  clamp(3rem, 7vw, 6rem);
  --max-w:  100%;          /* outer containers go fluid; inner grids set their own caps */
  --max-w-grid: 2000px;    /* sane max for visual grids (work-list) on ultra-wide */

  /* Motion */
  --ease:   cubic-bezier(0.22, 0.61, 0.36, 1);
  --t-fast: 220ms;
  --t-med:  450ms;
  --t-slow: 800ms;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html {
  scroll-behavior: smooth;
  /* Opt out of iOS Safari's automatic text inflation - without this,
     rotating a phone to landscape "boosts" body text well past the
     authored clamp() sizes. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Kill iOS Safari's default tap-highlight: a dark rectangle that flashes
     over the tapped element's box (ignoring border-radius) and fades out.
     Inherited, so this clears it site-wide. Focus/active states are separate
     and unaffected. */
  -webkit-tap-highlight-color: transparent;
}
body {
  font-family: var(--font-sans);
  font-size: var(--type-body);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-feature-settings: 'kern' 1, 'liga' 1;
  /* Typography rule: no single-word last lines. text-wrap: pretty asks
     the browser's slow-but-smart line breaker to avoid widows/orphans. */
  text-wrap: pretty;
}

/* Headings: balance line lengths instead of orphan-avoiding (shorter text). */
h1, h2, h3, h4,
.hero-title,
.section-title,
.section-caption,
.contact-statement,
.work-name,
.press-title,
.practice-name {
  text-wrap: balance;
}
img { display: block; max-width: 100%; height: auto; }
ul, ol { list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

::selection { background: var(--ink); color: var(--paper); }

/* Visually hidden but available to screen readers and search engines. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Preloader ----------
   First visit of a session: the wordmark reveals (GSAP SplitText) above a line
   that grows, then the overlay slides up. Driven by GSAP (vendor/) with a vanilla
   fallback. An inline head script adds .bj-skip-loader on return visits. */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--paper);
  display: flex;
  align-items: center;
  justify-content: center;
  will-change: transform;
}
.preloader-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.1rem, 2.2vw, 1.75rem);
}
.preloader-name {
  font-weight: 500;
  font-size: 0.9375rem;       /* match the nav wordmark exactly */
  line-height: 1; letter-spacing: -0.005em;
  color: var(--ink);
  white-space: nowrap;
  opacity: 0;                 /* GSAP reveals it; prevents a flash before JS runs */
}
.preloader-line {
  position: relative;
  width: 120px;               /* proportionate to the smaller wordmark */
  height: 2px;
  background: var(--rule);
  overflow: hidden;
}
.preloader-line-fill {
  position: absolute;
  inset: 0;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left center;
}
.bj-skip-loader .preloader { display: none; }
html.bj-loading, html.bj-loading body { overflow: hidden; }
/* Fallback exit if GSAP is unavailable. */
.preloader.is-revealing { transform: translateY(-100%); transition: transform 850ms var(--ease); }
@media (prefers-reduced-motion: reduce) {
  .preloader-name { opacity: 1; }
  .preloader-line-fill { transform: scaleX(1); }
}

/* ---------- Layout primitives ---------- */
.rule { border: 0; height: 1px; background: var(--rule); margin: 0; }
.rule--soft { background: var(--rule-soft); }

/* ---------- Navigation / Masthead ---------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in oklab, var(--paper) 94%, transparent);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--rule-soft);
}
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.25rem var(--pad-x);
  max-width: var(--max-w);
  margin: 0 auto;
}
.nav-wordmark {
  font-weight: 500;
  font-size: 0.9375rem;
  letter-spacing: -0.005em;
}
.nav-links {
  display: flex;
  gap: 2rem;
  align-items: center;
}
.nav-links a {
  font-size: 0.9375rem;
  color: var(--ink-soft);
  position: relative;
  padding: 0.25rem 0;
  transition: color var(--t-fast) var(--ease);
}
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 1px;
  background: var(--ink);
  transition: right var(--t-med) var(--ease);
}
.nav-links a:hover { color: var(--ink); }
.nav-links a:hover::after { right: 0; }

@media (max-width: 640px) {
  .nav-links { gap: 1.25rem; }
}

/* ---------- Hero ---------- */
.hero {
  /* Pinned to the viewport at z:1. Post-hero content sits at z:2 and scrolls
     over the top, "uncovering" itself. */
  position: fixed;
  inset: 0 0 auto 0;
  height: 100vh;
  height: 100svh;          /* mobile dynamic UI fallback */
  z-index: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: flex-start; /* anchor content to the left gutter */
  justify-content: center; /* vertically center within the hero */
  padding-inline: var(--pad-x);
  background: #000;
  color: #fff;
}

/* Background image stack - layers fade between each other every 5s via JS */
.hero-bg-stack {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 1.5s ease-in-out;
  will-change: opacity;
}
.hero-bg.is-active { opacity: 1; }

.hero-bg-overlay {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: rgba(0, 0, 0, 0.55);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .hero-bg { transition: none; }
}

/* Content block - fills the section gutters so title and description match */
.hero-content {
  position: relative;
  z-index: 1;
  width: 100%;
  text-align: left;
}

.hero-title {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: clamp(2.5rem, 6.5vw, 5rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: #ffffff;
  text-wrap: balance;
}
.hero-title span { display: block; }
.hero-title-soft { color: rgba(255, 255, 255, 0.7); }

/* ---------- Hero entrance (homepage) ----------
   Text, CTAs and nav ease up + fade in on load instead of snapping in. Held
   behind the preloader curtain on first visit (html.bj-loading), released when
   it lifts; on reloads it simply plays on load. Scoped to the homepage hero. */
@keyframes bjHeroIn {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: translateY(0); }
}
body:has(.hero) .nav-inner,
body:has(.hero) .hero-title span,
body:has(.hero) .hero-description,
body:has(.hero) .hero-cta {
  animation: bjHeroIn 1.4s var(--ease) both;
}
body:has(.hero) .nav-inner { animation-delay: 0.1s; }
body:has(.hero) .hero-title span:nth-child(1) { animation-delay: 0.25s; }
body:has(.hero) .hero-title span:nth-child(2) { animation-delay: 0.5s; }
body:has(.hero) .hero-description { animation-delay: 0.78s; }
body:has(.hero) .hero-cta { animation-delay: 1s; }

html.bj-loading body:has(.hero) .nav-inner,
html.bj-loading body:has(.hero) .hero-title span,
html.bj-loading body:has(.hero) .hero-description,
html.bj-loading body:has(.hero) .hero-cta {
  animation: none;
  opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
  body:has(.hero) .nav-inner,
  body:has(.hero) .hero-title span,
  body:has(.hero) .hero-description,
  body:has(.hero) .hero-cta { animation: none; opacity: 1; }
}

.hero-description {
  margin-top: 1.5rem;
  /* Constrain to roughly the visual width of the H1 above it so the
     description wraps into two lines instead of stretching edge to edge.
     32em is sized in the description's own font so the constraint scales
     proportionally with .hero-description's font-size. */
  max-width: 32em;
  text-wrap: balance;            /* split the two lines evenly */
  /* calc() preferred value scales the description in lockstep with the
     title across the same viewport range (615px floor, 1230px ceiling). */
  font-size: clamp(1rem, calc(0.75rem + 0.65vw), 1.25rem);
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.82);
  letter-spacing: -0.005em;
}

.hero-cta {
  margin-top: clamp(2rem, 4vw, 2.75rem);
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
}

/* Short viewports (landscape phones): the vertically-centered hero stack is
   taller than the visible area and clips at the top behind the nav. Compact
   the type so the whole stack fits. Height-based - deliberately NOT part of
   the single 800px width breakpoint model. Must sit AFTER the base
   .hero-description/.hero-cta rules (equal specificity - order decides). */
@media (max-height: 560px) {
  /* The flex-centering ignores the fixed nav, so the stack reads crammed
     against it (~32px above vs ~104px below). Padding the hero by the nav
     height re-centers the stack within the space the nav actually leaves. */
  .hero { padding-top: 4.5rem; }
  .hero-title { font-size: clamp(1.75rem, 6vh, 2.75rem); }
  .hero-description {
    margin-top: 0.75rem;
    font-size: 0.9375rem;
    line-height: 1.4;
  }
  .hero-cta { margin-top: 1.25rem; }
}

/* Liquid-glass buttons - vanilla port of the shadcn GlassButton component.
   Two-layer pill: an empty .btn-liquid-lens span owns the backdrop-filter
   (so text never gets ghosted by the blur), and a .btn-liquid-text span
   sits on top. Chrome/Edge route the backdrop through the SVG filter
   #liquid-glass (see <svg> at the top of body) for a real refraction
   effect; Safari/Firefox fall back to plain blur via the
   -webkit-backdrop-filter override. */
.btn-liquid {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.875rem 1.75rem;
  border: 0;
  border-radius: 9999px;
  background: transparent;
  color: rgba(255, 255, 255, 0.95);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  text-decoration: none;
  cursor: pointer;
  transition: transform 300ms cubic-bezier(0.22, 0.61, 0.36, 1);
  /* Lower --glass-reflex-light to soften the white-edge reflections;
     raise back toward 1 for a glossier, more aggressive bevel. */
  --glass-reflex-light: 0.3;
  --glass-reflex-dark: 1;
}

.btn-liquid-lens {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
  background-color: rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(8px) url(#liquid-glass) saturate(150%);
  -webkit-backdrop-filter: blur(8px) saturate(150%);
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, white calc(var(--glass-reflex-light) * 10%), transparent),
    inset 1.8px 3px 0 -2px color-mix(in srgb, white calc(var(--glass-reflex-light) * 90%), transparent),
    inset -2px -2px 0 -2px color-mix(in srgb, white calc(var(--glass-reflex-light) * 80%), transparent),
    inset -3px -8px 1px -6px color-mix(in srgb, white calc(var(--glass-reflex-light) * 60%), transparent),
    inset -0.3px -1px 4px 0 color-mix(in srgb, black calc(var(--glass-reflex-dark) * 12%), transparent),
    inset -1.5px 2.5px 0 -2px color-mix(in srgb, black calc(var(--glass-reflex-dark) * 20%), transparent),
    inset 0 3px 4px -2px color-mix(in srgb, black calc(var(--glass-reflex-dark) * 20%), transparent),
    inset 2px -6.5px 1px -4px color-mix(in srgb, black calc(var(--glass-reflex-dark) * 10%), transparent),
    0 1px 5px 0 color-mix(in srgb, black calc(var(--glass-reflex-dark) * 10%), transparent),
    0 6px 16px 0 color-mix(in srgb, black calc(var(--glass-reflex-dark) * 8%), transparent);
  transition: background-color 400ms cubic-bezier(1, 0, 0.4, 1),
              box-shadow 400ms cubic-bezier(1, 0, 0.4, 1);
}

.btn-liquid-text {
  position: relative;
  z-index: 1;
  user-select: none;
  -webkit-user-select: none;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  transition: color 400ms cubic-bezier(1, 0, 0.4, 1);
}

@media (hover: hover) {
  .btn-liquid:hover {
    transform: scale(1.03);
  }
  .btn-liquid:hover .btn-liquid-lens {
    background-color: rgba(255, 255, 255, 0.13);
  }
}
.btn-liquid:active {
  transform: scale(0.96);
}
.btn-liquid:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.5);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .btn-liquid { transition: none; }
  .btn-liquid:hover, .btn-liquid:active { transform: none; }
}

@keyframes heroFadeUp {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}

/* Nav adapts to dark hero while hero is in view. JS toggles .nav--over-hero. */
.nav { transition: background-color var(--t-med) var(--ease), border-color var(--t-med) var(--ease); }
.nav.nav--over-hero {
  background: rgba(0, 0, 0, 0.18);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
  border-bottom-color: rgba(255, 255, 255, 0.08);
}
.nav.nav--over-hero .nav-wordmark,
.nav.nav--over-hero .nav-links a { color: #ffffff; }
.nav.nav--over-hero .nav-links a::after { background: #ffffff; }

@media (prefers-reduced-motion: reduce) {
  .hero-title, .hero-description, .hero-cta {
    opacity: 1;
    animation: none;
  }
}

/* All post-hero content sits above the fixed hero and has an opaque
   background so the hero is occluded as content covers it. Scoped with
   :has(.hero) so these rules only apply to the homepage. */
body:has(.hero) > section,
body:has(.hero) > footer {
  position: relative;
  z-index: 2;
  background: var(--paper);
}

/* First section is pushed one viewport down so the hero is the only thing
   visible on initial load. Scrolling pulls everything up over the hero. */
body:has(.hero) > section:first-of-type {
  margin-top: 100vh;
  margin-top: 100svh;
}

/* Paper-gradient bottom fade removed - would clash with the dark hero.
   The fixed-hero reveal (content scrolling over the hero) handles the
   transition on its own. */
/* .hero-eyebrow - retired (no longer in the markup) */
/* Old .hero-title / .hero-lede / .hero-eyebrow rules retired - replaced by
   the dark-hero rules above (.hero-title now sized differently, .hero-
   description replaces .hero-lede, .hero-meta no longer rendered). */

/* ---------- Section structure ---------- */
.section {
  padding-block: var(--pad-y);
  padding-inline: var(--pad-x);
  max-width: var(--max-w);
  margin: 0 auto;
}
.section-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.75rem;
  margin-bottom: clamp(3rem, 6vw, 5rem);
  padding-bottom: clamp(2rem, 4vw, 3rem);
  border-bottom: 1px solid var(--rule);
}
.section-caption {
  font-size: var(--type-caption);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
}
.section-title {
  /* Descriptive sentence, sized like .hero-lede; sits above the section caption */
  font-weight: 500;
  font-size: var(--type-lede);
  line-height: 1.4;
  letter-spacing: -0.005em;
  color: var(--ink);
  max-width: 50ch;
}

/* Tighten the gap between Clients -> Brands and Brands -> Work (Index) */
#clients { padding-bottom: clamp(2rem, 5vw, 4rem); }
#brands  {
  padding-top:    clamp(1rem, 3vw, 3rem);
  padding-bottom: clamp(2rem, 5vw, 4rem);
}
#index   { padding-top:    clamp(1rem, 3vw, 3rem); }

/* ---------- Logo marquee (Clients + Brands) - JS-driven, draggable ---------- */
.marquee {
  position: relative;
  overflow: hidden;
  margin-inline: calc(-1 * var(--pad-x));
  padding-block: 1.5rem;
  cursor: grab;
  touch-action: pan-y; /* allow vertical page scroll, capture horizontal drag */
  user-select: none;
  -webkit-user-select: none;
  -webkit-mask-image: linear-gradient(to right,
              transparent 0%,
              #000 7%,
              #000 93%,
              transparent 100%);
          mask-image: linear-gradient(to right,
              transparent 0%,
              #000 7%,
              #000 93%,
              transparent 100%);
}
.marquee.is-dragging { cursor: grabbing; }
.marquee + .marquee { margin-top: clamp(1.5rem, 3vw, 2.5rem); }

.marquee-track {
  display: flex;
  width: max-content;
  /* CSS fallback animation. JS overrides on init via track.style.animation = 'none' */
  animation: marquee 80s linear infinite;
}
.marquee--reverse .marquee-track { animation-name: marqueeReverse; }

.marquee-list {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  padding-right: clamp(2.5rem, 5vw, 4.5rem);
}
.marquee-item {
  /* Fixed-width cell for true equal spacing - logos centered inside */
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: clamp(120px, 12vw, 160px);
  height: 48px;
}
.marquee-item img {
  max-height: 44px;
  max-width: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  filter: grayscale(1) brightness(0.92) contrast(1.02);
  opacity: 0.82;
  border: 0;
  /* Let the parent marquee element receive pointer events; no native image drag */
  pointer-events: none;
  -webkit-user-drag: none;
  user-drag: none;
}

@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes marqueeReverse {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
}

/* ---------- Work index ---------- */
.work-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(4rem, 8vw, 7rem) clamp(2rem, 4vw, 4rem);
}
@media (min-width: 900px) {
  .work-list { grid-template-columns: 1fr 1fr; }
  .work-list .work-item:first-child { grid-column: 1 / -1; }
  .work-list .work-item:first-child .work-figure { aspect-ratio: 16 / 9; }
}
.work-item { position: relative; }
.work-link { display: block; color: inherit; }
.work-num {
  font-size: var(--type-caption);
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  display: inline-block;
  margin-bottom: 1rem;
  text-transform: uppercase;
}
.work-figure {
  position: relative;
  overflow: hidden;
  background: var(--paper-alt);
  aspect-ratio: 4 / 3;
  margin-bottom: 1.5rem;
  border: 1px solid var(--rule-soft);
}
.work-figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow) var(--ease), filter var(--t-med) var(--ease);
  filter: saturate(0.98);
}
.work-link:hover .work-figure img {
  transform: scale(1.025);
  filter: saturate(1.05);
}
.work-meta {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
}
@media (min-width: 700px) {
  .work-meta {
    grid-template-columns: 1.4fr 1fr;
    gap: 2rem;
    align-items: start;
  }
}
.work-name {
  font-weight: 500;
  font-size: var(--type-h3);
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--ink);
}
.work-disc {
  color: var(--ink-soft);
  font-size: 1rem;
  max-width: 45ch;
  line-height: 1.55;
}
.work-tags {
  margin-top: 0.75rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
}

.work-foot {
  margin-top: clamp(4rem, 8vw, 6rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--rule);
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 1rem;
}
.work-foot a {
  font-weight: 500;
  font-size: 1.125rem;
  letter-spacing: -0.005em;
  position: relative;
  padding-bottom: 0.3rem;
  transition: color var(--t-fast) var(--ease);
}
/* Slide-in underline on hover — same pattern as .nav-links a::after */
.work-foot a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 1px;
  background: var(--ink);
  transition: right var(--t-med) var(--ease);
}
.work-foot a:hover::after { right: 0; }
.work-foot a .arrow {
  display: inline-block;
  margin-left: 0.5em;
  transition: transform var(--t-med) var(--ease);
}
.work-foot a:hover .arrow { transform: translateX(4px); }

/* ---------- Work spotlights (replaces .work-list grid) ----------
   Each item: fixed-width text column on the left, image fills the rest.
   All hover effects driven by :hover on .work-spot-link — no JS needed. */
.work-spots {
  display: flex;
  flex-direction: column;
  gap: clamp(4rem, 9vw, 9rem);
}
.work-spot { position: relative; }

.work-spot-link {
  /* Wrapper only — clickability lives on .work-spot-image (the <a>). */
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  color: inherit;
}
/* Image is the only clickable element. The <a> default cursor handles it. */
.work-spot-image { color: inherit; }
@media (min-width: 800px) {
  .work-spot-link {
    grid-template-columns: 280px 1fr;
    gap: clamp(2rem, 4vw, 4rem);
    align-items: start;
  }
}
@media (min-width: 1200px) {
  .work-spot-link { grid-template-columns: 320px 1fr; }
}

/* Easing reused everywhere on the spotlight */
.work-spot * { transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); }

/* ----- Text column ----- */
.work-spot-text { padding-top: 0.5rem; }
@media (min-width: 800px) { .work-spot-text { padding-top: 1.5rem; } }

.work-spot-label {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: clamp(1.5rem, 3vw, 2rem);
}
.work-spot-line {
  display: inline-block;
  width: 32px;
  height: 1px;
  background: var(--ink-mute);
  transition: width 0.7s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-line { width: 48px; }

.work-spot-eyebrow {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  transition: letter-spacing 0.7s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-eyebrow { letter-spacing: 0.06em; }

.work-spot-title {
  /* Matches the .section-title (e.g. 'Work'): size, weight, color */
  font-weight: 500;
  font-size: var(--type-lede);
  line-height: 1.4;
  letter-spacing: -0.005em;
  color: var(--ink);
  transition: transform 0.7s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-title { transform: translateY(-2px); }

.work-spot-desc {
  margin-top: clamp(1.5rem, 3vw, 2rem);
  max-width: 36ch;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: rgba(119, 119, 119, 0.6);
  transition: color 0.7s, transform 0.7s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-desc {
  color: var(--ink-mute);
  transform: translateY(-4px);
}

.work-spot-cta {
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  display: flex;
  align-items: center;
  gap: 1rem;
}
/* Stretch the CTA link across the whole card so clicking anywhere - the
   airline name, the description, or empty space - opens the project page.
   .work-spot-cta is unpositioned and none of its ancestors take a hover
   transform, so this ::after stays pinned to .work-spot (position: relative). */
.work-spot-cta::after {
  content: "";
  position: absolute;
  inset: 0;
}
.work-spot-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: 1px solid rgba(119, 119, 119, 0.3);
  background: transparent;
  color: var(--ink);
  transition: background-color 0.5s, border-color 0.5s, color 0.5s,
              transform 0.5s, box-shadow 0.5s;
}
.work-spot-arrow svg {
  width: 0.9375rem;
  height: 0.9375rem;
  transition: transform 0.5s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-arrow {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
  transform: scale(1.05);
  box-shadow: 0 8px 32px rgba(26, 26, 26, 0.15);
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-arrow svg { transform: rotate(45deg); }

.work-spot-explore {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink);
  opacity: 0.5;
  transform: translateX(-8px);
  transition: opacity 0.7s, transform 0.7s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-explore {
  opacity: 1;
  transform: translateX(0);
  transition-delay: 100ms;
}

/* ----- Image column ----- */
.work-spot-image {
  position: relative;
  transition: transform 0.7s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-image { transform: translate(4px, -4px); }

.work-spot-frame {
  position: absolute;
  inset: clamp(-1rem, -1.5vw, -0.75rem);
  border: 1px solid transparent;
  pointer-events: none;
  transition: border-color 0.7s, transform 0.7s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-frame {
  border-color: rgba(26, 26, 26, 0.15);
  transform: scale(1.01);
}

.work-spot-figure {
  position: relative;
  overflow: hidden;
  margin: 0;
  background: var(--paper-alt);
  aspect-ratio: 4 / 3;
  width: 100%;
}
.work-spot-figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border: 0;
  transition: transform 1s;
}
.work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-figure img { transform: scale(1.03); }


@media (prefers-reduced-motion: reduce) {
  .work-spot *,
  .work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-image,
  .work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-arrow,
  .work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-title,
  .work-spot-link:has(.work-spot-text:hover, .work-spot-image:hover) .work-spot-desc { transform: none !important; transition: none !important; }
}

/* ---------- Practice (3 text-only cards with pill tag) ---------- */
.practice-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin-top: 1rem;
}
@media (min-width: 800px) {
  .practice-cards { grid-template-columns: repeat(3, 1fr); }
}

.practice-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 1.75rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 0.75rem;
  transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
@media (hover: hover) {
  .practice-card:hover { transform: scale(0.99); }
}

.practice-card-num {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
}

.practice-card-name {
  margin-top: 0.5rem;
  font-size: 1.375rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink);
  line-height: 1.2;
}

.practice-card-disc {
  margin-top: 1.5rem;        /* fixed gap from title, so descriptions always start at the same height */
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--ink-mute);
}

@media (prefers-reduced-motion: reduce) {
  .practice-card { transition: none; }
}

/* ---------- Press ---------- */
.press-list {
  display: flex;
  flex-direction: column;
  /* No border-top — the section-head already has a border-bottom directly above. */
}
.press-row { border-bottom: 1px solid var(--rule); }
.press-link {
  display: grid;
  grid-template-columns: 90px 1fr auto;
  align-items: baseline;
  gap: 1.5rem;
  padding: 1.5rem 0;
  position: relative;
  transition: padding var(--t-med) var(--ease);
}
@media (min-width: 800px) {
  .press-link {
    grid-template-columns: 110px 1fr 200px auto;
    padding: 2rem 0;
  }
}
.press-link:hover { padding-inline: 1.25rem; }
.press-date {
  font-size: var(--type-caption);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  white-space: nowrap;
}
.press-title {
  font-weight: 500;
  font-size: clamp(1.0625rem, 1.4vw, 1.375rem);
  letter-spacing: -0.01em;
  color: var(--ink);
  line-height: 1.3;
}
.press-source {
  font-size: 0.9375rem;
  color: var(--ink-mute);
  font-style: italic;
}
@media (max-width: 799px) {
  .press-source { grid-column: 2; }
}
.press-arrow {
  color: var(--ink-mute);
  transition: transform var(--t-med) var(--ease), color var(--t-fast) var(--ease);
  font-size: 1.125rem;
}
.press-link:hover .press-arrow {
  transform: translate(4px, -4px);
  color: var(--ink);
}

/* ---------- Contact (homepage teaser: huge statement + side blurb/CTA) ---------- */
.contact {
  padding-block: var(--pad-y);
  padding-inline: var(--pad-x);
  max-width: var(--max-w);
  margin: 0 auto;
}
.contact-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2.5rem, 6vw, 4rem);
  align-items: start;        /* both sides start at the same top */
}
@media (min-width: 900px) {
  .contact-grid {
    grid-template-columns: 1.7fr 1fr;
    gap: clamp(2rem, 5vw, 5rem);
  }
}
.contact-statement {
  /* Matches .hero-title exactly */
  font-weight: 500;
  font-size: clamp(2.5rem, 6.5vw, 5rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
}
.contact-statement .ink-mute { color: var(--ink-faint); }
.contact-side {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
.contact-blurb {
  font-size: clamp(1rem, 1.2vw, 1.25rem);
  line-height: 1.5;
  color: var(--ink);
  max-width: 36ch;
}
.contact-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink);
  align-self: flex-start;
  position: relative;
  padding-bottom: 0.4rem;
}
.contact-cta::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 1px;
  background: var(--ink);
  transition: right var(--t-med) var(--ease);
}
.contact-cta:hover::after { right: 0; }
.contact-cta .arrow {
  display: inline-block;
  transition: transform var(--t-med) var(--ease);
}
.contact-cta:hover .arrow { transform: translateX(4px); }

/* ---------- Footer (3-column site map) ---------- */
.footer {
  padding: clamp(3rem, 6vw, 5rem) var(--pad-x) clamp(2rem, 4vw, 3rem);
  max-width: var(--max-w);
  margin: 0 auto;
  border-top: 1px solid var(--rule);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
}
@media (min-width: 800px) {
  .footer-grid {
    grid-template-columns: 1fr 1fr 1.8fr;
    gap: clamp(2rem, 4vw, 4rem);
  }
}
.footer-col {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.footer-label {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  margin-bottom: 0.25rem;
}
.footer-col ul {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  list-style: none;
}
.footer-col a {
  font-size: 0.8125rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink);
  position: relative;
  padding-bottom: 2px;
  display: inline-block;
}
.footer-col a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 1px;
  background: var(--ink);
  transition: right var(--t-med) var(--ease);
}
.footer-col a:hover::after { right: 0; }
.footer-col--meta {
  text-align: right;          /* push copyright to the right page margin */
}
.footer-col--meta p {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  line-height: 1.7;
}

/* ---------- /contact page (form layout) ---------- */
.page-contact-form {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 80vh;
  gap: clamp(4rem, 9vw, 7rem);
  padding-block: clamp(5rem, 11vw, 9rem) clamp(3rem, 6vw, 5rem);
  padding-inline: var(--pad-x);
  max-width: var(--max-w);
  margin: 0 auto;
}
.page-contact-form-head { /* anchored to the top via parent justify-content */ }

.contact-form {
  display: flex;
  flex-direction: column;
}
.contact-form-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.4rem;
  padding: 1.1rem 0;
  border-top: 1px solid var(--rule);
}
@media (min-width: 700px) {
  .contact-form-row {
    grid-template-columns: 110px 1fr;
    gap: 2rem;
    align-items: center;
  }
}

.contact-form-label {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  align-self: center;
}

.contact-form-input {
  font: inherit;
  font-family: var(--font-sans);
  font-size: 0.9375rem;               /* 15px - readable, but quieter than body type */
  letter-spacing: -0.005em;
  color: var(--ink);
  background: transparent;
  border: 0;
  outline: none;
  padding: 0;
  width: 100%;
  line-height: 1.5;
}
.contact-form-input::placeholder { color: var(--ink-faint); }
.contact-form-input:focus { outline: none; }
.contact-form-textarea {
  resize: vertical;
  min-height: 2.4em;
  padding-block: 0.2rem;
}

/* Pill chips for the Interest row */
.contact-form-row--chips { align-items: center; }
.contact-form-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.contact-form-chip {
  position: relative;
  cursor: pointer;
  user-select: none;
}
.contact-form-chip input {
  position: absolute;
  width: 1px; height: 1px;
  margin: 0; padding: 0;
  opacity: 0;
  pointer-events: none;
}
.contact-form-chip > span {
  display: inline-flex;
  align-items: center;
  padding: 0.4rem 0.95rem;
  border: 1px solid var(--rule);
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  background: var(--paper);
  transition: background-color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
.contact-form-chip:hover > span {
  border-color: var(--ink);
  color: var(--ink);
}
.contact-form-chip input:checked + span {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}
.contact-form-chip input:focus-visible + span {
  /* box-shadow, not outline: iOS Safari draws `outline` as a rectangle that
     ignores border-radius, so a tap flashed a black box around the rounded
     pill. A double box-shadow (paper gap + ink ring) follows the pill radius
     on every browser. */
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--ink);
}

/* Bottom row: status text left, send button right. Top border closes
   the divider chain that runs above each form row. */
.contact-form-foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 1rem 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}
.contact-form-status {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  max-width: 36ch;
  min-height: 1em;
  margin: 0;
}
.contact-form-status.is-success { color: var(--ink); }
.contact-form-status.is-error   { color: #b04a3a; }

.contact-form-submit {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.95rem 1.6rem;
  background: var(--ink);
  color: var(--paper);
  border: 0;
  border-radius: 9999px;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: transform var(--t-fast) var(--ease),
              background-color var(--t-fast) var(--ease);
}
.contact-form-submit:hover:not(:disabled) { background: var(--ink-soft); }
.contact-form-submit:active:not(:disabled) { transform: scale(0.97); }
.contact-form-submit:disabled { opacity: 0.6; cursor: wait; }
.contact-form-submit .arrow {
  display: inline-block;
  transition: transform var(--t-med) var(--ease);
}
.contact-form-submit:hover:not(:disabled) .arrow { transform: translateX(4px); }

@media (prefers-reduced-motion: reduce) {
  .contact-form-chip > span,
  .contact-form-submit,
  .contact-form-submit .arrow { transition: none; }
}

/* ---------- /work page (filterable grid + list) ---------- */
.page-work {
  /* Less breathing room above the title — was clamp(5rem, 11vw, 9rem) */
  padding-block: clamp(2rem, 5vw, 4rem) clamp(3rem, 6vw, 5rem);
  padding-inline: var(--pad-x);
  max-width: var(--max-w);
  margin: 0 auto;
}
.page-work-head {
  /* Title stacks above the filter row at every breakpoint. The pill
     stretches to the left margin (where the title sits) and the Grid/List
     toggle stays anchored to the right margin. */
  display: flex;
  flex-direction: column;
  gap: clamp(2rem, 5vw, 3rem);
  margin-bottom: clamp(3rem, 6vw, 5rem);
  /* Stacks above sibling grid/list so the filter popover isn't covered. */
  position: relative;
  z-index: 20;
}
.page-work-title {
  font-weight: 500;
  font-size: 5rem;             /* fixed at desktop; reduced below 800px */
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0;
}

/* ----- Filter bar -----
   Wide pill on the left, view toggle on the right at every breakpoint. */
.work-filterbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
}
.work-filter {
  position: relative;
  /* basis 18rem (not 0) so once the row is too narrow to fit pill + toggle,
     the Grid/List toggle wraps to its own line beneath the pill (the parent
     is flex-wrap:wrap), giving the label its full width instead of truncating. */
  flex: 1 1 18rem;
  min-width: 0;
  height: 48px;         /* row keeps pill height so the toggle stays put */
}

/* Shell wraps pill + popover into ONE element. border-radius stays a
   constant 1.5rem (24px); at pill height it caps at half-height (perfect
   pill); at expanded height it reads as a rounded rectangle. */
.work-filter-shell {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  background: #f2f2f2;
  border-radius: 1.5rem;        /* constant, never changes */
  overflow: hidden;
  z-index: 30;
}

.work-filter-pill {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  width: 100%;       /* fills shell so pill content spans full width */
  padding: 0.5rem 0.5rem 0.5rem 1.25rem;      /* 32px + 16px = 48px */
  background: transparent;                    /* shell carries the bg */
  border: 0;
  border-radius: 9999px;                      /* unchanged (shell handles outer shape) */
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  letter-spacing: -0.005em;
  cursor: pointer;
  text-align: left;
  transition: background-color var(--t-fast) var(--ease);
}
/* Replace the browser's default (orange) focus ring: none for mouse,
   a subtle inset ink ring for keyboard users. Inset so the shell's
   overflow:hidden doesn't clip it. */
.work-filter-pill:focus { outline: none; }
.work-filter-pill:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
/* When the popover is open the focus state is already obvious, so drop the
   ring (it otherwise shows in screenshots/keyboard focus of the open pill). */
.work-filter-pill[aria-expanded="true"]:focus-visible { outline: none; }
/* No bg change on hover — feedback comes from the + icon rotating.
   (Switching to var(--paper) made the pill blend into the white page.) */
/* Pill stays fully rounded and fully visible when open. The popover
   extends *from below* the pill — it does not duplicate the pill's content. */
.work-filter-icon {
  display: inline-flex;
  width: 18px; height: 18px;
  color: var(--ink-mute);
  flex-shrink: 0;
}
.work-filter-icon svg { width: 100%; height: 100%; }
.work-filter-label {
  color: var(--ink);
  white-space: nowrap;
  /* Truncate an over-long label instead of pushing the +/count out of the
     pill (min-width:0 lets it shrink in the flex row). */
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.work-filter-count { color: var(--ink-mute); }
.work-filter-plus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  margin-left: auto;               /* pinned to the right edge of the pill */
  border: 0;                       /* no border, just bg + icon */
  border-radius: 9999px;
  color: var(--ink);
  background: var(--paper);
  flex-shrink: 0;
  /* Hover transform lives on the parent so it doesn't fight with the
     SVG's own rotation when the pill opens/closes. */
  transform: scale(1);
  transition: transform var(--t-med) var(--ease);
}
.work-filter-pill:hover .work-filter-plus {
  transform: scale(1.1);
}
.work-filter-plus svg {
  width: 18px;
  height: 18px;
  transition: transform var(--t-med) var(--ease);
}
/* When open: rotate 45° clockwise → becomes ×.
   When closed (aria-expanded toggles back to false), the SVG animates
   from rotate(45deg) → rotate(0deg) — i.e. counter-clockwise back to +.
   The hover rotation was removed because it caused the close to detour
   through 90deg (clockwise) before returning, instead of going
   counter-clockwise immediately. */
.work-filter-pill[aria-expanded="true"] .work-filter-plus svg {
  transform: rotate(45deg);
}

/* Popover sits below the pill inside the shell. max-height animates
   smoothly from 0 to a generous value, while the body fades in. */
.work-filter-popover {
  max-height: 0;
  overflow: hidden;
  transition: max-height 620ms cubic-bezier(0.4, 0, 0.2, 1);
}
.work-filter-popover[hidden] { display: block; }   /* override UA hidden */

.work-filter:has([aria-expanded="true"]) .work-filter-popover {
  /* Fits the list; caps to the viewport so nothing is clipped on short/narrow
     screens (where the groups stack to one column), and scrolls if taller. */
  max-height: min(760px, 85vh);
  overflow-y: auto;
}

.work-filter-popover-body {
  /* padding-left = pill padding-left (1.25rem) + icon (18px) + gap (0.85rem)
     so dropdown items align under the pill's "All works" label. */
  padding: 0.25rem 1.4rem 1.4rem calc(1.25rem + 18px + 0.85rem);
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  /* Fade text in as the box opens. Delay on open so the box starts
     unfolding first; on close, fade fast (no delay) to hide quickly. */
  opacity: 0;
  transition: opacity 360ms ease;
}
.work-filter:has([aria-expanded="true"]) .work-filter-popover-body {
  opacity: 1;
  transition: opacity 420ms ease 180ms;   /* delayed fade-in */
}

/* Groups: 2 columns at wider viewports (BY TYPE | BY SERVICE on row 1,
   ACADEMIC drops to row 2), 1 column once the pill gets narrow enough
   that item names would wrap. */
.work-filter-groups {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}
@media (min-width: 800px) {
  .work-filter-groups {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem 2rem;
    align-content: start;
  }
  /* Layout: BY TYPE on top-left, ACADEMIC under it, BY SERVICE spanning both
     rows on the right. Prevents BY SERVICE's longer column from inflating
     the gap between BY TYPE and ACADEMIC. */
  .work-filter-group:nth-child(1) { grid-area: 1 / 1; }       /* By Type */
  .work-filter-group:nth-child(2) { grid-area: 1 / 2 / 3 / 3; }/* By Service */
  .work-filter-group:nth-child(3) { grid-area: 2 / 1; }       /* Academic */
}

.work-filter-group {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.work-filter-group-title {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;       /* gentle positive tracking for caps */
  color: var(--ink-mute);
}

.work-filter-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
}
.work-filter-item label {
  /* inline-block (not inline-flex) so the count flows inline right after the
     label text and wraps WITH it - otherwise a two-line label pins the count
     to the first line's right edge. */
  display: inline-block;
  font-size: 1.0625rem;
  letter-spacing: -0.005em;
  color: var(--ink);
  cursor: pointer;
  user-select: none;
  /* underline spans the whole label (name + count) */
  position: relative;
  padding-bottom: 2px;
}
.work-filter-item label::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 1px;
  background: var(--ink);
  transition: right var(--t-med) var(--ease);
}
.work-filter-item:hover label::after { right: 0; }
.work-filter-item.is-active label::after { right: 0; }

.work-filter-item input {
  position: absolute;
  width: 1px; height: 1px;
  margin: 0; padding: 0;
  opacity: 0;
  pointer-events: none;
}
.work-filter-item-count {
  margin-left: 0.4rem;   /* replaces the former flex gap; keeps "(N)" glued to the label */
  white-space: nowrap;
  color: var(--ink-mute);
  font-size: 0.9375rem;
}

/* ----- Grid / List view toggle (sliding indicator) -----
   Heights matched to the filter pill (48px) so the row is visually flush. */
.work-view-toggle {
  position: relative;
  display: inline-flex;
  padding: 0.5rem;              /* matches pill padding */
  background: #f2f2f2;
  border: 0;                    /* no border, matches pill */
  border-radius: 9999px;
  /* indicator props (set by JS): --view-x, --view-w */
  --view-x: 0px;
  --view-w: 50%;
}
.work-view-toggle::before {
  content: "";
  position: absolute;
  top: 0.5rem;
  left: 0;
  height: calc(100% - 1rem);
  width: var(--view-w);
  background: var(--paper);
  border-radius: 9999px;
  box-shadow: 0 1px 4px rgba(26, 26, 26, 0.08);
  transform: translateX(var(--view-x));
  transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1),
              width 0.45s cubic-bezier(0.16, 1, 0.3, 1);
  pointer-events: none;
}
.work-view-btn {
  position: relative;
  z-index: 1;
  font: inherit;
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1;                /* explicit so total height is predictable */
  padding: 0 1.5rem;
  height: 32px;                  /* matches the pill's inner + circle */
  background: transparent;
  border: 0;
  border-radius: 9999px;
  color: var(--ink-mute);
  cursor: pointer;
  transition: color var(--t-fast) var(--ease);
}
.work-view-btn:hover { color: var(--ink); }
.work-view-btn.is-active { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .work-view-toggle::before,
  .work-filter-pill { transition: none; }
}

/* ---------- Narrow viewport (<800px): subtle scale-down ----------
   Step is small so the breakpoint isn't a jarring jump, and pill +
   Grid/List toggle share identical sizing so they read as a matched pair.
   Placed AFTER the regular toggle/pill rules so it actually wins. */
@media (max-width: 799px) {
  .page-work-title { font-size: 4rem; }       /* was 5rem — small step */

  .work-filter { height: 44px; }              /* match smaller pill */

  /* Pill: 28px + circle + 0.5rem padding each side = 44px tall */
  .work-filter-pill {
    font-size: 0.9375rem;
    padding: 0.5rem 0.5rem 0.5rem 1.25rem;
  }
  .work-filter-icon { width: 17px; height: 17px; }
  .work-filter-plus { width: 28px; height: 28px; }
  .work-filter-plus svg { width: 17px; height: 17px; }

  /* Toggle matches pill exactly: same padding, same inner button height */
  .work-view-toggle { padding: 0.5rem; }
  .work-view-toggle::before {
    top: 0.5rem;
    height: calc(100% - 1rem);
  }
  .work-view-btn {
    font-size: 0.9375rem;
    height: 28px;
    padding: 0 1.25rem;
  }
}

/* ----- Grid view ----- */
.work-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(3rem, 5vw, 4.5rem) clamp(1.5rem, 3vw, 2.5rem);
}
@media (min-width: 800px) {
  .work-grid { grid-template-columns: 1fr 1fr; }
}
.work-grid[hidden] { display: none; }

.work-card { position: relative; }
.work-card[hidden] { display: none; }
.work-card-link {
  display: block;
  color: inherit;
}
.work-card-image {
  position: relative;
  overflow: hidden;
  background: var(--paper-alt);
  aspect-ratio: 16 / 10;
  border: 1px solid var(--rule-soft);
  border-radius: 0.5rem;
}
.work-card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--t-slow) var(--ease);
}
.work-card-link:hover .work-card-image img { transform: scale(1.03); }

.work-card-title {
  margin-top: 1.25rem;
  font-weight: 500;
  font-size: clamp(1.125rem, 1.4vw, 1.375rem);
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--ink);
}
.work-card-meta {
  margin-top: 0.5rem;
  font-size: 0.9375rem;
  color: var(--ink-mute);
  line-height: 1.4;
}

/* ----- List view ----- */
.work-list-view {
  display: flex;
  flex-direction: column;
}
.work-list-view[hidden] { display: none; }

.work-list-head,
.work-list-row {
  display: grid;
  grid-template-columns: minmax(0, 2.2fr) minmax(0, 1.3fr) minmax(0, 1.5fr) 5rem;
  gap: 1.5rem;
  padding: 1.5rem 0;
  align-items: center;
  border-top: 1px solid var(--rule-soft);
}
.work-list-head {
  border-top: 0;
  border-bottom: 1px solid var(--rule);
  padding-block: 0.75rem 1.25rem;
}
.work-list-row {
  color: inherit;
  text-decoration: none;
  position: relative;
}
/* Own the transition at higher specificity than `.reveal` / `.reveal-delay-N`
   so two things hold:
   1. Animate transform, not padding - padding re-flows the fr grid every frame
      and re-wraps the multi-line category cells, which made the hover jump.
   2. transition-delay stays 0 - the reveal stagger (40-160ms) would otherwise
      bleed into the hover, so sweeping across rows quickly felt laggy.
   opacity is kept in the transition so the scroll-reveal still fades in. */
.work-list-view .work-list-row {
  transition: opacity var(--t-med) var(--ease), transform var(--t-med) var(--ease);
}
/* Scoped under .work-list-view so this beats `.reveal.is-in { transform:
   translateY(0) }` (equal specificity would otherwise let the reveal rule,
   which comes later in the file, cancel the hover). */
.work-list-view .work-list-row:hover { transform: translateX(1.25rem); }
.work-list-row[hidden] { display: none; }
.work-list-row:last-child { border-bottom: 1px solid var(--rule-soft); }

.work-list-cell {
  font-size: 0.9375rem;
  color: var(--ink);
  min-width: 0;
}
.work-list-head .work-list-cell {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
}
.work-list-cell--project {
  font-weight: 500;
  font-size: 1rem;
  letter-spacing: -0.005em;
}
.work-list-cell--cat { color: var(--ink-mute); }
.work-list-cell--right { text-align: right; }

@media (max-width: 799px) {
  .work-list-head { display: none; }
  .work-list-row {
    grid-template-columns: 1fr auto;
    gap: 0.4rem 1rem;
    padding: 1.25rem 0;
  }
  .work-list-cell--project { grid-column: 1; grid-row: 1; }
  .work-list-cell--right   { grid-column: 2; grid-row: 1; color: var(--ink-mute); font-size: 0.8125rem; }
  .work-list-row > .work-list-cell:nth-of-type(2) { grid-column: 1 / -1; grid-row: 2; color: var(--ink-mute); font-size: 0.875rem; }
  .work-list-cell--cat { grid-column: 1 / -1; grid-row: 3; font-size: 0.8125rem; }
}

.work-empty {
  margin-top: clamp(3rem, 6vw, 4rem);
  text-align: center;
  font-size: 0.9375rem;
  color: var(--ink-mute);
}
.work-empty[hidden] { display: none; }

/* ---------- Reveal on scroll ---------- */
.reveal {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
.reveal.is-in {
  opacity: 1;
  transform: translateY(0);
}
.reveal-delay-1 { transition-delay: 40ms; }
.reveal-delay-2 { transition-delay: 80ms; }
.reveal-delay-3 { transition-delay: 120ms; }
.reveal-delay-4 { transition-delay: 160ms; }

/* Project page: same snappy, low-travel reveal as the rest of the site. */
.project .reveal {
  transform: translateY(10px);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
/* Higher specificity than `.project .reveal` so the revealed state still
   settles to translateY(0) — otherwise revealed elements stay 16px low and
   throw off the section spacing. */
.project .reveal.is-in { transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
}

@media print {
  .nav, .reveal { all: revert; opacity: 1; }
  body { background: white; color: black; }
}

/* ============================================================
   Project / Case study page (e.g. united-dinnerware.html)
   Editorial long-form: dark hero, meta block, alternating
   text columns and full-bleed imagery. Reuses global tokens.
   ============================================================ */
.project { display: block; }

/* ----- Hero: smooth scroll clip-path reveal -----
   A sticky full-viewport image. As the page scrolls through the tall
   .hero-scroll spacer, JS (initSmoothScrollHero in bj.js) expands the
   clip-path from a centred window to full-bleed and eases the zoom from
   170% to 100%. No text overlay — Work lives in the nav, project info
   in the meta block below. */
.hero-scroll {
  position: relative;
  width: 100%;
  height: 100vh;            /* full-screen hero; the reveal opens to full-bleed on load */
  background: var(--paper);
}
.hero-scroll-sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  width: 100%;
  overflow: hidden;
  background: #000;
  /* Full-bleed at rest; JS plays a clip-open reveal to this from a window. */
  clip-path: none;
  will-change: clip-path, opacity;
  /* Hidden until the preloaded image is decoded, then JS plays the reveal. */
  opacity: 0;
}
.hero-scroll.hero-revealed .hero-scroll-sticky {
  opacity: 1;
  transition: opacity 700ms var(--ease);
}
.hero-scroll-bg {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
  /* Always covers the frame; JS scales from 1.7 -> 1 for the zoom-out so
     the image never reveals bands on tall/narrow viewports. */
  background-size: cover;
  transform: none;          /* full cover at rest; JS scales 1.7 -> 1 during the reveal */
  transform-origin: center;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .hero-scroll { height: 100vh; }
  .hero-scroll-sticky { clip-path: none; }
  .hero-scroll-bg { transform: none; }
}

/* ----- Meta block (4-col row) ----- */
.project-meta {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.5rem, 3vw, 2.75rem);
  padding: clamp(3rem, 7vw, 6rem) var(--pad-x);
}
.project-meta dt {
  font-size: var(--type-caption);
  text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ink-mute);
  margin-bottom: 0.85rem;
}
.project-meta dd {
  font-size: var(--type-small);
  line-height: 1.5;
  color: var(--ink-soft);
}
.project-meta-services {
  display: flex; flex-direction: column; gap: 0.4rem;
}

/* ----- Big headline statement (after meta) ----- */
.project-statement {
  padding: clamp(3rem, 7vw, 6rem) var(--pad-x);
  border-top: 1px solid var(--rule);
}
.project-statement p {
  font-weight: 500;
  font-size: clamp(1.6rem, 3.4vw, 3rem);
  line-height: 1.14; letter-spacing: -0.025em;
  color: var(--ink);
  max-width: none;
  text-align: center;
}

/* ----- Figures: uniform full-bleed bands, all cropped to one ratio -----
   No vertical margin — spacing around every figure comes from the even
   top/bottom padding of the adjacent text sections, so the rhythm stays
   identical across the whole page. */
.project-figure {
  margin: 0;
  /* Matches the rule the following section draws under the image, so each
     full-bleed image is framed by an identical hairline top and bottom. */
  border-top: 1px solid var(--rule);
}
.project-figure img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  object-position: center;
}

/* ----- Document-page sliders (e.g. Birchden Wood publications) -----
   An auto-scrolling, draggable band of publication pages, driven by the
   shared marquee engine (.marquee + bj.js). Pages keep a common height and
   their natural width, so portrait pages and landscape spreads sit together.
   The section supplies the --pad-x padding the .marquee full-bleeds out of. */
.doc-slider {
  padding: clamp(3rem, 7vw, 6rem) var(--pad-x);
  border-top: 1px solid var(--rule);
}
.doc-slider-label {
  font-size: .75rem;
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.doc-marquee .marquee-list {
  gap: clamp(0.9rem, 1.8vw, 1.75rem);
  padding-right: clamp(0.9rem, 1.8vw, 1.75rem);
  align-items: center;
}
.doc-page {
  position: relative;
  flex: 0 0 auto;
  height: clamp(240px, 44vh, 460px);
}
.doc-page img {
  height: 100%;
  width: auto;
  display: block;
  background: #fff;
  box-shadow: 0 12px 34px rgba(26, 26, 26, 0.12);
}
/* Optional per-page label chip, overlaid top-left on the page image
   (e.g. the emotion name on each Emotion Recognition study/chart). */
.doc-page-tag {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  padding: 0.38rem 0.6rem;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--paper);
  background: rgba(26, 26, 26, 0.82);
  pointer-events: none;
}
/* Labelled variant (e.g. Aegean "The Four Collections"): the name sits
   UNDER each image (like the Selected Works cards) and the drop shadow is
   dropped. Height moves from the page to the image so the caption has room. */
.doc-slider--labeled .doc-page { height: auto; }
.doc-slider--labeled .doc-page img {
  height: clamp(240px, 44vh, 460px);
  box-shadow: none;
}
.doc-page-cap {
  display: block;
  margin-top: 0.9rem;
  font-weight: 500;
  font-size: clamp(1rem, 1.4vw, 1.2rem);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* ----- Video poster (full-bleed 16:9 band; click opens a modal player) ----- */
.video-player {
  position: relative;
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  border-top: 1px solid var(--rule);
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #000;
  color: var(--paper);
  text-align: left;
  cursor: pointer;
  font: inherit;
}
/* Breathing room between stacked video posters. */
.video-player + .video-player { margin-top: clamp(1.5rem, 4vw, 3.5rem); }
.video-player-thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--t-slow) var(--ease);
}
.video-player:hover .video-player-thumb,
.video-player:focus-visible .video-player-thumb { transform: scale(1.04); }
.video-player-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0) 55%);
}
.video-player-play {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: clamp(56px, 7vw, 74px);
  height: clamp(56px, 7vw, 74px);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: transform var(--t-med) var(--ease), background-color var(--t-med) var(--ease);
}
.video-player:hover .video-player-play,
.video-player:focus-visible .video-player-play {
  transform: translate(-50%, -50%) scale(1.1);
  background: rgba(255, 255, 255, 0.3);
}
.video-player-play svg { width: 38%; height: 38%; fill: #fff; margin-left: 6%; }
.video-player-text {
  position: absolute;
  left: 0; bottom: 0;
  padding: clamp(1.25rem, 3vw, 2rem) var(--pad-x);
}
.video-player-title {
  display: block;
  font-size: clamp(1.25rem, 2.4vw, 1.75rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: #fff;
}
.video-player-desc {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.8);
}

/* ----- Video modal (injected by bj.js on click) ----- */
.video-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(0, 0, 0, 0.85);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  animation: videoModalIn var(--t-med) var(--ease);
}
@keyframes videoModalIn { from { opacity: 0; } to { opacity: 1; } }
.video-modal-frame {
  position: relative;
  width: 100%;
  max-width: 1100px;
  aspect-ratio: 16 / 9;
}
.video-modal-frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: 4px;
}
.video-modal-close {
  position: absolute;
  top: clamp(0.75rem, 2vw, 1.5rem);
  right: clamp(0.75rem, 2vw, 1.5rem);
  width: 44px; height: 44px;
  border: 0; border-radius: 50%;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  transition: background-color var(--t-fast) var(--ease);
}
.video-modal-close:hover { background: rgba(255, 255, 255, 0.24); }
.video-modal-close svg { width: 22px; height: 22px; }
@media (prefers-reduced-motion: reduce) {
  .video-modal { animation: none; }
  .video-player-thumb { transition: none; }
}

/* ----- Two-column content section: heading left, body right ----- */
.project-block {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: clamp(1.5rem, 5vw, 5rem);
  align-items: start;
  padding: clamp(3rem, 7vw, 6rem) var(--pad-x);
  border-top: 1px solid var(--rule);
}
.project-block-title {
  font-weight: 500;
  font-size: clamp(1.75rem, 3.4vw, 3rem);
  line-height: 1.05; letter-spacing: -0.03em;
  color: var(--ink);
}
/* No measure cap: paragraphs fill the right column out to the page margin. */
.project-block-body p {
  font-size: var(--type-body);
  line-height: var(--lh-body);
  color: var(--ink-soft);
}
.project-block-body p + p { margin-top: 1.5rem; }
.project-block-body p + .project-subhead { margin-top: clamp(2rem, 4vw, 2.75rem); }

/* Subhead used inside Approach / Impact */
.project-subhead {
  font-weight: 500;
  font-size: clamp(1.05rem, 1.4vw, 1.25rem);
  line-height: 1.3; letter-spacing: -0.01em;
  color: var(--ink);
  margin-bottom: 0.75rem;
}

/* Our Approach: 2-up grid of subsections in the body column */
.project-subgrid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(2rem, 3.5vw, 3.25rem) clamp(2rem, 4vw, 4rem);
}
.project-subgrid p {
  font-size: var(--type-body);
  line-height: var(--lh-body);
  color: var(--ink-soft);
}
.project-subgrid p + p { margin-top: 1rem; }
/* Inline definition list (e.g. the three Hawaiian motifs in Our Approach):
   spaced, unbulleted, matching the subgrid body type. */
.project-subgrid-list {
  margin-top: 1rem;
  display: grid;
  gap: 0.6rem;
  font-size: var(--type-body);
  line-height: var(--lh-body);
  color: var(--ink-soft);
}
.project-subgrid-list em {
  font-style: italic;
  color: var(--ink);
}

/* The Work: full-width capability index — heading above, then ruled rows of
   uppercase label (left, ▸ marker) + a descriptive sentence (right column). */
.project-work { display: block; }   /* override the 2-col grid: rows run full width */
.work-index {
  margin-top: clamp(2rem, 4vw, 3rem);
  border-top: 1px solid var(--rule);
}
.work-index-row {
  display: grid;
  grid-template-columns: minmax(14rem, 1fr) minmax(0, 1.9fr);
  gap: clamp(1.25rem, 4vw, 4rem);
  align-items: start;
  padding-block: clamp(1.4rem, 2.4vw, 2rem);
  border-bottom: 1px solid var(--rule-soft);
}
.work-index-label {
  display: flex;            /* marker in its own slot so wrapped lines hang-indent under the text */
  align-items: baseline;
  font-size: var(--type-body);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.3;
  color: var(--ink-mute);
  transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.work-index-label::before {
  content: "\25B8";                 /* ▸ */
  flex: 0 0 auto;
  margin-right: clamp(0.85rem, 1.5vw, 1.25rem);
  color: var(--ink-faint);
  font-size: 0.8em;
  transition: color var(--t-fast) var(--ease);
}
.work-index-detail {
  font-size: var(--type-body);
  line-height: var(--lh-body);
  color: var(--ink-mute);
  transition: color var(--t-fast) var(--ease);
}
/* Hover lifts the whole row: title slides, marker darkens, detail deepens. */
.work-index-row:hover .work-index-label { color: var(--ink-soft); transform: translateX(4px); }
.work-index-row:hover .work-index-label::before { color: var(--ink); }
.work-index-row:hover .work-index-detail { color: var(--ink-soft); }

@media (max-width: 620px) {
  /* Stacked: align the description under the header text (past the ▸ marker)
     instead of flush-left under the marker. 1.3125rem = marker glyph + margin. */
  .work-index-row { grid-template-columns: 1fr; gap: 0.5rem; }
  .work-index-detail { padding-left: 1.3125rem; }
}

/* ----- Impact: card carousel -----
   Cards are bordered with the title pinned to the top and the copy anchored to
   the bottom; prev/next controls appear only when the track overflows. */
.impact {
  --impact-gap: clamp(1rem, 2vw, 1.5rem);
  --impact-line: var(--rule);
  padding: clamp(3rem, 7vw, 6rem) var(--pad-x);
  border-top: 1px solid var(--rule);
}
.impact-title {
  font-weight: 500;
  font-size: clamp(1.75rem, 3.4vw, 3rem);
  line-height: 1.05; letter-spacing: -0.03em;
  color: var(--ink);
  margin-bottom: clamp(2rem, 4vw, 3.25rem);
}
.impact-viewport { width: 100%; }
.impact-track {
  display: flex;
  gap: var(--impact-gap);
  overflow-x: auto;
  /* Horizontal carousel only. overflow-x:auto would otherwise promote
     overflow-y to auto, so a not-yet-revealed off-screen card sitting at its
     reveal start transform (translateY) produced a stray vertical scrollbar. */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;            /* Firefox */
  -webkit-overflow-scrolling: touch;
}
.impact-track::-webkit-scrollbar { display: none; }   /* WebKit */
.impact-card {
  flex: 0 0 calc((100% - 2 * var(--impact-gap)) / 3);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  justify-content: space-between;   /* title pinned top, copy anchored bottom */
  gap: clamp(1.5rem, 3vw, 2.5rem);
  min-height: clamp(360px, 38vw, 460px);
  padding: clamp(1.5rem, 2.2vw, 2.25rem);
  border: 1px solid var(--impact-line);
  border-radius: 16px;
}
.impact-card-title {
  font-weight: 500;
  font-size: clamp(1.2rem, 1.7vw, 1.5rem);
  line-height: 1.2; letter-spacing: -0.01em;
  color: var(--ink);
  margin-bottom: 0.9rem;
}
.impact-card-text p {
  font-size: var(--type-body);
  line-height: var(--lh-body);
  color: var(--ink-mute);
}
.impact-nav {
  display: flex;
  gap: 0.75rem;
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
}
.impact-nav[hidden] { display: none; }
.impact-ctrl {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
}
.impact-ctrl:hover:not(:disabled) { border-color: var(--ink); background: rgba(26, 26, 26, 0.05); }
.impact-ctrl:disabled { opacity: 0.3; cursor: default; }

@media (max-width: 900px) {
  .impact-card { flex-basis: calc((100% - var(--impact-gap)) / 2); }
}
@media (max-width: 620px) {
  .impact-card { flex-basis: 85%; min-height: clamp(300px, 60vw, 380px); }
}

@media (max-width: 860px) {
  .project-block { grid-template-columns: 1fr; gap: clamp(1.5rem, 5vw, 2.25rem); }
  .project-subgrid { grid-template-columns: 1fr; }
}

/* ----- Awards (closing section) -----
   Heading alone in the left column like every other section; each award
   is a single bordered card (badge + title + source) in the right column.
   This bordered-card format is used ONLY for awards. */
.project-awards { align-items: start; }
.award-card {
  display: flex;
  align-items: center;
  gap: clamp(2rem, 6vw, 4.5rem);
  width: 100%;
  padding: clamp(1.5rem, 2.4vw, 2rem);
  border: 1px solid var(--rule);
  border-radius: 14px;
}
.award-card-badge { flex: 0 0 auto; }
.award-card-badge img {
  display: block;
  width: clamp(72px, 9vw, 92px);
  height: auto;
}
.award-card-title {
  font-weight: 500;
  font-size: clamp(1.05rem, 1.5vw, 1.25rem);
  line-height: 1.3; letter-spacing: -0.01em;
  color: var(--ink);
  margin-bottom: 0.4rem;
}
.award-card-source {
  font-size: var(--type-small);
  color: var(--ink-mute);
}
@media (max-width: 860px) {
  .project-awards { align-items: start; }
}
@media (max-width: 560px) {
  .award-card {
    flex-direction: column;
    align-items: flex-start;
    gap: 1.5rem;
  }
}

/* ----- Recognitions: combined awards + press as a grouped index -----
   Header = count + title (left) and a short note (right). Each group is a
   ruled set of rows: name (left, ↗ for outbound links) + source (right). */
.recognitions {
  padding: clamp(3rem, 7vw, 6rem) var(--pad-x);
  border-top: 1px solid var(--rule);
}
.rec-head {
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}
.rec-title {
  font-weight: 500;
  font-size: clamp(1.75rem, 3.4vw, 3rem);
  line-height: 1; letter-spacing: -0.03em;
  color: var(--ink);
}
.rec-group + .rec-group { margin-top: clamp(2.25rem, 4vw, 3.25rem); }
.rec-group-title {
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-mute);
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 0.25rem;
}
.rec-row { border-bottom: 1px dotted rgba(26, 26, 26, 0.22); }
.rec-link,
.rec-static {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: clamp(1.5rem, 4vw, 4rem);
  padding-block: clamp(0.9rem, 1.6vw, 1.2rem);
  color: var(--ink);
  text-decoration: none;
}
.rec-name {
  display: inline-flex;
  align-items: baseline;
  gap: 0.7rem;
  font-size: var(--type-body);
  color: var(--ink);
}
.rec-arrow {
  flex: 0 0 auto;
  align-self: center;
  color: var(--ink-faint);
}
.rec-arrow svg { display: block; transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease); }
.rec-source {
  flex: 0 0 auto;
  font-size: var(--type-body);
  text-align: right;
  color: var(--ink-mute);
  transition: color var(--t-fast) var(--ease);
}
.rec-link:hover .rec-arrow { color: var(--ink); }
.rec-link:hover .rec-arrow svg { transform: translate(2px, -2px); }
.rec-link:hover .rec-name { color: var(--ink); }
.rec-link:hover .rec-source { color: var(--ink-soft); }

@media (max-width: 560px) {
  .rec-link,
  .rec-static { flex-direction: column; align-items: flex-start; gap: 0.3rem; }
  /* Indent the wrapped source to align with the title text, not the arrow
     (15px svg + the .rec-name 0.7rem gap). Static award rows have no arrow,
     so they keep the flush-left source. */
  .rec-source { text-align: left; }
  .rec-link .rec-source { padding-left: calc(15px + 0.7rem); }
}

/* ----- Responsive meta collapse ----- */
@media (max-width: 720px) {
  .project-meta { grid-template-columns: repeat(2, 1fr); row-gap: 2rem; }
}
@media (max-width: 420px) {
  .project-meta { grid-template-columns: 1fr; }
}

/* ============================================================
   Selected Works — auto-scrolling draggable marquee (project page).
   Reuses the home-page logo-marquee mechanics (initMarquee in bj.js):
   content-height, infinite loop, drag to scroll. No pin, no runway.
   ============================================================ */
.selected-works {
  position: relative;
  background: var(--paper);
  border-top: 1px solid var(--rule);
  /* Same top/bottom padding as Recognitions & Impact (--pad-y) so the spacing
     above the heading and below the cards matches those sections exactly. */
  padding-block: var(--pad-y);
  /* Horizontal gutter that the full-bleed .sw-marquee bleeds back out of via
     its negative margin-inline. Without it the marquee overshoots the viewport
     by --pad-x on the right, causing a horizontal-scroll sliver at wide widths. */
  padding-inline: var(--pad-x);
}
.sw-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  /* Horizontal gutter now comes from .selected-works padding-inline (so the
     heading aligns with the page and the marquee bleeds full-width). */
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.sw-title {
  font-weight: 500;
  font-size: clamp(1.75rem, 3.4vw, 3rem);
  line-height: 1.05; letter-spacing: -0.03em;
  color: var(--ink);
}
.sw-viewall {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-size: var(--type-small);
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
  padding-bottom: 2px;
  transition: gap var(--t-fast) var(--ease);
}
.sw-viewall:hover { gap: 0.75rem; }
/* Selected Works marquee: reuse the logo-marquee mechanics (.marquee /
   .marquee-track / .marquee-list) but with project cards instead of logos. */
.sw-marquee {
  cursor: grab;
  padding-block: 0;   /* section's own padding governs spacing — matches Recognitions/Impact (96px) */
  /* Moderate edge fade — softer than the base .marquee's wide 7% (which read
     as heavy white blurring) but a proper gradient, not the hard-ish 28px edge.
     A width-scaled clamp keeps it gentle on mobile and never aggressive on
     ultra-wide screens. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 clamp(48px, 5vw, 96px), #000 calc(100% - clamp(48px, 5vw, 96px)), transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 clamp(48px, 5vw, 96px), #000 calc(100% - clamp(48px, 5vw, 96px)), transparent 100%);
}
.sw-marquee.is-dragging { cursor: grabbing; }
.sw-marquee-list {
  align-items: stretch;
  gap: clamp(1rem, 1.5vw, 1.5rem);
  padding-right: clamp(1rem, 1.5vw, 1.5rem);
}
.sw-card { flex: 0 0 auto; width: clamp(240px, 24vw, 340px); }
.sw-card-link { pointer-events: auto; }
.sw-card-image {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--paper-alt);
}
.sw-card-image img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--t-med) var(--ease);
}
.sw-card-link:hover .sw-card-image img { transform: scale(1.03); }
.sw-card-meta {
  margin-top: 1rem;
  font-size: var(--type-caption);
  text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ink-mute);
}
.sw-card-title {
  margin-top: 0.5rem;
  font-weight: 500;
  font-size: clamp(1.05rem, 1.5vw, 1.3rem);
  line-height: 1.25; letter-spacing: -0.01em;
  color: var(--ink);
}
