/* ===========================================================================
   Design tokens — edit these to retheme the whole site.
   Everything below references these variables; no one-off hex codes.
   =========================================================================== */
:root {
  --color-bg: #ffffff;
  --color-text: #111111;
  --color-muted: #6b6b6b;
  --color-accent: #2545ff;          /* single accent color, easy to swap */
  --color-line: #e6e6e6;            /* hairline dividers */
  --color-surface: #f7f7f7;         /* subtle fill (meta block, hover tint) */
  --pattern-color: rgba(17, 17, 17, 0.045); /* background grid line color */
  --pattern-size: 24px;             /* background grid cell size */

  --font-display: "Stack Sans Notch", "Helvetica Neue", Arial, sans-serif; /* headings */
  --font-body: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI",
    "Helvetica Neue", Arial, sans-serif;                                   /* body copy */

  --space-unit: 8px;                /* base spacing scale multiplier */
  --radius: 4px;                    /* corner rounding, if any */
  --card-inset: 40px;               /* wide-layout side inset (About section) */
  --page-pad: 80px;                 /* full-bleed side padding; steps down on
                                       narrow viewports (see Responsive) */

  /* Derived spacing scale — used everywhere instead of raw px */
  --space-1: calc(var(--space-unit) * 1);   /*  8px */
  --space-2: calc(var(--space-unit) * 2);   /* 16px */
  --space-3: calc(var(--space-unit) * 3);   /* 24px */
  --space-4: calc(var(--space-unit) * 4);   /* 32px */
  --space-6: calc(var(--space-unit) * 6);   /* 48px */
  --space-8: calc(var(--space-unit) * 8);   /* 64px */
  --space-12: calc(var(--space-unit) * 12); /* 96px */
  --space-16: calc(var(--space-unit) * 16); /* 128px */

  --container: 68rem;               /* max content width */
  --duration: 200ms;                /* micro-interaction timing */
}

/* ===========================================================================
   Stack Sans Notch — commercial/custom face, not on Google Fonts.
   Drop the web font files into src/fonts/ and rebuild; until then, headings
   gracefully fall back to Helvetica Neue / Arial via --font-display.
   =========================================================================== */
@font-face {
  font-family: "Stack Sans Notch";
  src: url("fonts/StackSansNotch.woff2") format("woff2"),
       url("fonts/StackSansNotch.woff") format("woff");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

/* ===========================================================================
   Base
   =========================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  /* The full-bleed skills arena is 100vw wide; clip the sliver a classic
     (non-overlay) scrollbar would otherwise add as horizontal overflow. */
  overflow-x: clip;
  /* Static graph-paper grid: two 1px hairlines tiled per cell over the base */
  background-color: var(--color-bg);
  background-image:
    linear-gradient(var(--pattern-color) 1px, transparent 1px),
    linear-gradient(90deg, var(--pattern-color) 1px, transparent 1px);
  background-size: var(--pattern-size) var(--pattern-size);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 1.0625rem; /* 17px */
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0 0 var(--space-2);
}

p {
  margin: 0 0 var(--space-2);
  max-width: 65ch;
}

ul,
ol {
  margin: 0 0 var(--space-2);
  padding-left: 1.25em;
}

li {
  margin-bottom: calc(var(--space-1) / 2);
  max-width: 62ch;
}

a {
  color: inherit;
  text-decoration-color: var(--color-line);
  text-underline-offset: 0.2em;
  transition: color var(--duration) ease,
    text-decoration-color var(--duration) ease;
}

a:hover {
  text-decoration-color: currentColor;
}

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: var(--radius);
}

::selection {
  background: var(--color-accent);
  color: var(--color-bg);
}

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--space-3);
}

/* Small-caps section label */
.section-label {
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin: 0 0 var(--space-4);
}

section {
  padding: var(--space-12) 0 0;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--color-text);
  color: var(--color-bg);
  padding: var(--space-1) var(--space-2);
  z-index: 100;
}

.skip-link:focus {
  left: var(--space-2);
  top: var(--space-2);
}

/* ===========================================================================
   Fixed header — barely-there gradient fading to transparent at its bottom.
   JS toggles .is-hidden: hides on scroll down, reappears on scroll up.
   =========================================================================== */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
  padding: var(--space-3) 0 var(--space-6);
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.85),
    rgba(255, 255, 255, 0)
  );
  transition: transform 300ms ease, opacity 300ms ease;
  pointer-events: none; /* let clicks pass through the transparent tail */
}

.site-header.is-hidden {
  transform: translateY(-100%);
  opacity: 0;
}

.site-nav {
  display: flex;
  justify-content: center;
  gap: 120px;
  pointer-events: auto;
}

/* Nav tabs share the small-caps "section label" treatment used for
   "Selected Work", centered with a wide gap between them. */
.site-nav a {
  position: relative;
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 450;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text);
  text-decoration: none;
  transition: color 0.2s ease;
}

/* Animated 1px underline that grows left-to-right across the tab on hover. */
.site-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 1px;
  background: var(--color-text);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease;
}

.site-nav a:hover,
.site-nav a:focus-visible {
  color: var(--color-text);
}

.site-nav a:hover::after,
.site-nav a:focus-visible::after {
  transform: scaleX(1);
}

/* About keeps the wider layout it had inside the old content card. */
@media (min-width: 700px) {
  .statement .container {
    max-width: none;
    margin: 0 calc(var(--card-inset) + 40px);
    padding-left: 0;
    padding-right: 0;
  }
}

/* ===========================================================================
   Hero — full-viewport frame with the intro pinned to the bottom left
   =========================================================================== */
.hero {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  padding: var(--space-16) 0 0;
}

/* Intro sits at the page's bottom-left corner, not the centered column */
.hero .container {
  width: 100%; /* flex item would otherwise shrink-wrap and center */
  max-width: none;
  padding: 0 var(--page-pad);
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(220px, 340px) 1fr;
  gap: var(--space-6);
  align-items: center;
  width: 100%;
}

/* Portrait placeholder — swap for a real <img> when the photo is ready */
.hero-photo {
  aspect-ratio: 4 / 3;
  background: var(--color-bg); /* #fff — white photo backdrop */
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.hero-photo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: bottom;
  display: block;
  transform: scaleX(-1); /* mirror horizontally */
}

.hero-photo .photo-label {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-muted);
}

/* Thin by default; **highlights** step up to regular weight */
.hero-heading {
  font-size: clamp(2rem, 5vw, 4rem); /* up to 64px */
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0;
  padding-bottom: 80px;
}

.hero-line {
  display: block;
}

.hero-line--muted {
  color: #9a9a9a; /* lighter than --color-muted */
}

.hero-heading strong {
  font-weight: 600;
}

/* Bold mid-page statement line */
.statement {
  padding: 200px 0 var(--space-12);
}

.statement .statement-line {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3.5vw, 2.5rem);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.015em;
  max-width: 26ch;
  margin: 0 0 var(--space-6);
}

/* ===========================================================================
   Work carousel — full-bleed swipeable cover cards. The strip fades out at
   both viewport edges; arrows on each side page one card at a time. The
   viewport itself scrolls with snap points, so trackpads/touch just swipe.
   =========================================================================== */
#work {
  padding-top: 200px;
}

.work-carousel {
  --carousel-inset: var(--page-pad);  /* first card starts one page-pad off the screen edge */
  --carousel-fade: 96px;
  --card-w: min(620px, 78vw); /* card width; media height is 2/3 of this */
  position: relative;
  width: 100%;
}

/* At rest only the right side fades; the left fade appears once the strip
   has been scrolled (JS toggles .is-scrolled on the carousel). */
.carousel-viewport {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-left: var(--carousel-inset);
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(
    90deg,
    #000 calc(100% - var(--carousel-fade)),
    transparent 100%
  );
  mask-image: linear-gradient(
    90deg,
    #000 calc(100% - var(--carousel-fade)),
    transparent 100%
  );
}

.work-carousel.is-scrolled .carousel-viewport {
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 var(--carousel-fade),
    #000 calc(100% - var(--carousel-fade)),
    transparent 100%
  );
  mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 var(--carousel-fade),
    #000 calc(100% - var(--carousel-fade)),
    transparent 100%
  );
}

.carousel-viewport::-webkit-scrollbar {
  display: none;
}

.carousel-track {
  display: flex;
  gap: var(--space-3);
  list-style: none;
  margin: 0;
  padding: 0 var(--carousel-inset);
}

.work-card {
  flex: 0 0 var(--card-w);
  margin: 0;
  max-width: none; /* overrides the base li measure limit */
  scroll-snap-align: start;
}

.work-card a {
  display: block;
  text-decoration: none;
}

/* Cover image — 8px radius, placeholder label until real covers are added
   via the `cover` field in content/case-studies.js */
.work-card .card-media {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: 8px;
  margin-bottom: var(--space-2);
}

.work-card .card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 8px;
  transition: transform 400ms ease;
}

.work-card a:hover .card-media img,
.work-card a:focus-visible .card-media img {
  transform: scale(1.03);
}

.work-card .media-label {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-muted);
  text-align: center;
  padding: 0 var(--space-2);
}

/* Smaller title beneath the card, no kicker. On hover a 1px underline draws
   left-to-right beneath the title. */
.work-card .card-title {
  position: relative;
  display: inline-block;
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.work-card .card-title::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 1px;
  background: var(--color-text);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease;
}

.work-card a:hover .card-title::after,
.work-card a:focus-visible .card-title::after {
  transform: scaleX(1);
}

.work-card .card-sub {
  display: block;
  color: var(--color-muted);
  font-size: 0.9375rem;
  margin-top: 2px;
}

.work-card .card-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-top: var(--space-1);
}

.work-card .tag {
  font-family: var(--font-display);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted);
  border: 1px solid var(--color-line);
  border-radius: 999px;
  padding: 2px var(--space-1);
  white-space: nowrap;
}

/* Manual paging arrows, vertically centered on the cover images */
.carousel-btn {
  position: absolute;
  top: calc(var(--card-w) / 3); /* half the 3:2 media height */
  transform: translateY(-50%);
  z-index: 2;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--color-text);
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: color var(--duration) ease, opacity var(--duration) ease,
    visibility var(--duration) ease;
}

.carousel-arrow {
  width: 24px;
  height: 24px;
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
  transition: stroke-width var(--duration) ease;
}

.carousel-arrow path {
  vector-effect: non-scaling-stroke;
}

/* Left arrow only exists once the strip has been scrolled */
.carousel-btn.prev {
  left: var(--space-3);
  opacity: 0;
  visibility: hidden;
}

.work-carousel.is-scrolled .carousel-btn.prev {
  opacity: 1;
  visibility: visible;
}

.carousel-btn.next {
  right: var(--space-3);
}

.carousel-btn:hover .carousel-arrow {
  stroke-width: 3px;
}

.carousel-btn[disabled] {
  opacity: 0;
  visibility: hidden;
  cursor: default;
  pointer-events: none;
}

/* ===========================================================================
   About accordion (plain <details>/<summary>)
   =========================================================================== */
/* About Me: portrait beside the statement + lead copy */
.about-grid {
  display: grid;
  grid-template-columns: 1fr minmax(380px, 580px);
  gap: var(--space-6);
  align-items: center;
  margin-top: var(--space-4);
}

.about-grid .hero-photo {
  margin: 0;
  aspect-ratio: 4 / 5;
}

.about-lead {
  font-size: 1.125rem;
  font-weight: 400;
  line-height: 1.7;
  color: var(--color-text);
  max-width: 750px;
  margin-bottom: var(--space-4);
}

/* ===========================================================================
   Skills polyhedron — a wireframe dodecahedron (1px grey edges, transparent
   faces) floating in the middle of the section, one skill pill riding each of
   its 20 vertices. JS projects the rotating shape and positions everything;
   drag spins it in any direction. Without JS the same markup renders as the
   plain centered pill list below.
   =========================================================================== */
.skills {
  padding-top: 40px;
  padding-bottom: var(--space-16);
}

/* Fallback layout (no JS): a simple centered pill cloud. */
.skills-poly {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-2) var(--space-2);
  max-width: 62rem;
  margin: var(--space-6) auto 0;
}

.skills-poly .poly-lines {
  display: none;
}

.poly-pill {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-size: clamp(0.9rem, 2.88vw, 1.125rem);
  font-weight: 600;
  line-height: 1.2;
  color: var(--color-text);
  background: var(--color-bg);
  border: 1px solid var(--color-line);
  border-radius: 8px;
  padding: 6px 14px;
  white-space: nowrap;
  user-select: none;
  -webkit-user-select: none;
}

/* 3D mode: JS switches the cloud into a square stage and takes over layout.
   Breaks out of the centered .container so the figure can grow past the
   content max-width; the negative margin re-centers it on the viewport. */
.skills-poly.is-3d {
  display: block;
  position: relative;
  width: min(92vw, 1008px);
  height: min(92vw, 1008px);
  max-width: none; /* override the fallback list's 62rem cap */
  left: 50%;
  transform: translateX(-50%);
  cursor: grab;
  touch-action: none; /* drag rotates freely in any direction */
}

.skills-poly.is-3d.is-dragging {
  cursor: grabbing;
}

.skills-poly.is-3d .poly-lines {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.skills-poly.is-3d .poly-lines line {
  stroke: #e0e0e0;
  stroke-width: 1;
}

.skills-poly.is-3d .poly-pill {
  position: absolute;
  top: 0;
  left: 0;
  margin: 0;
  /* JS drives transform/opacity/z-index; origin 0 0 keeps the depth-scale
     centered on the vertex the pill is pinned to. */
  transform-origin: 0 0;
  will-change: transform, opacity;
  pointer-events: none; /* drags land on the stage, never on a pill */
}

/* ===========================================================================
   Footer / contact
   =========================================================================== */
.site-footer {
  /* No top margin: the skills arena sits directly above, so the pills rest
     right on the footer's edge. */
  background: #000000;
  color: #ffffff;
  padding: 200px 0 8px; /* colophon sits 8px off the bottom */
}

.site-footer .container {
  display: flex;
  flex-direction: column;
  min-height: 480px;
  max-width: none;
  margin: 0;
  padding: 0 var(--page-pad);
}

.site-footer .section-label {
  font-size: 1.125rem;
  color: rgba(255, 255, 255, 0.7);
  margin-bottom: var(--space-6);
}

.site-footer .cta {
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 5.5vw, 3.85rem);
  font-weight: 600;
  line-height: 1.15;
  margin-bottom: var(--space-4);
}

.footer-email {
  display: inline-block;
  align-self: flex-start; /* shrink-wrap inside the flex column so the underline matches the text */
  position: relative;
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2vw, 1.625rem);
  color: #ffffff;
  text-decoration: none;
  padding-bottom: 4px;
  margin-bottom: var(--space-6);
}

.footer-email:hover {
  color: #ffffff; /* override the global blue link hover */
}

/* underline draws left-to-right across the full email on hover */
.footer-email::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--duration) ease;
}

.footer-email:hover::after {
  transform: scaleX(1);
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  list-style: none;
  margin: 0 0 var(--space-8);
  padding: 0;
}

/* LinkedIn / Download CV buttons — outlined, invert to white fill on hover */
.footer-btn {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 600;
  color: #ffffff;
  background: transparent;
  border: 1px solid #ffffff;
  border-radius: 8px;
  text-decoration: none;
  padding: var(--space-2) var(--space-4);
  transition: background var(--duration) ease, color var(--duration) ease;
}

.footer-btn:hover {
  background: #ffffff;
  color: #000000;
}

.colophon {
  font-size: 10px;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.7);
  margin-top: auto; /* pushed to the bottom of the footer */
  margin-bottom: 0;
}

/* ===========================================================================
   Case study pages
   =========================================================================== */
.case-hero {
  padding: var(--space-12) 0 var(--space-6);
}

.case-hero .breadcrumb {
  font-family: var(--font-display);
  font-size: 0.875rem;
  color: var(--color-muted);
  text-decoration: none;
  display: inline-block;
  margin-bottom: var(--space-4);
}

.case-hero .breadcrumb {
  position: relative;
}

.case-hero .breadcrumb::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 1px;
  background: var(--color-text);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease;
}

.case-hero .breadcrumb:hover {
  color: var(--color-text);
}

.case-hero .breadcrumb:hover::after,
.case-hero .breadcrumb:focus-visible::after {
  transform: scaleX(1);
}

.case-hero h1 {
  font-size: clamp(2rem, 5vw, 3.5rem);
  font-weight: 700;
  max-width: 20ch;
}

.case-hero .case-subtitle {
  margin: calc(var(--space-1) * -1) 0 0;
  font-family: var(--font-display);
  font-size: clamp(1.125rem, 2.4vw, 1.5rem);
  font-weight: 400;
  color: var(--color-muted);
  max-width: 34ch;
}

.meta-block {
  margin-top: var(--space-4);
  padding: var(--space-3);
  background: var(--color-surface);
  border-radius: var(--radius);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--space-2) var(--space-3);
}

.meta-block div dt {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: 2px;
}

.meta-block div dd {
  margin: 0;
  font-size: 0.9375rem;
}

.case-section {
  padding: var(--space-8) 0 0;
}

.case-section h2 {
  font-size: 1.375rem;
}

.case-section > .container > *:not(h2):not(.section-label):not(.case-figures):not(.case-video) {
  max-width: 62ch;
}

.tldr li {
  font-size: 1.125rem;
  font-weight: 500;
  margin-bottom: var(--space-1);
}

.moves {
  list-style: none;
  padding: 0;
}

.moves li {
  margin-bottom: var(--space-3);
  max-width: 62ch;
}

.moves .move {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
}

.moves .move-body {
  color: var(--color-muted);
}

.decisions {
  list-style: none;
  padding: 0;
  counter-reset: decision;
}

.decisions > li {
  counter-increment: decision;
  position: relative;
  padding: var(--space-3) 0 var(--space-3) calc(var(--space-unit) * 6);
  border-top: 1px solid var(--color-line);
}

.decisions > li::before {
  content: counter(decision, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: var(--space-3);
  font-family: var(--font-display);
  font-size: 0.875rem;
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

.decisions dt {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-top: var(--space-1);
}

.decisions dt:first-child {
  margin-top: 0;
}

.decisions dd {
  margin: 2px 0 0;
  max-width: 58ch;
}

/* Problem and Decision bodies get extra padding */
.decisions dd:nth-child(2),
.decisions dd:nth-child(4) {
  padding-bottom: 8px;
}

/* Decision title above the Problem/Decision/Where list */
.decisions .decision-title {
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: 600;
  margin: 0 0 var(--space-2);
  max-width: 58ch;
}

/* Image placeholder pairs shown after each section */
.case-figures {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3);
  margin-top: var(--space-4);
  max-width: none;
}

.case-figure {
  margin: 0;
}

.case-figure .figure-media {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 16 / 10;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
}

.case-figure .figure-label {
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.case-figure figcaption {
  margin-top: var(--space-1);
  font-size: 0.8125rem;
  color: var(--color-muted);
}

/* Responsive Vimeo walkthrough */
.case-video {
  margin-top: var(--space-4);
  aspect-ratio: 16 / 9;
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
  overflow: hidden;
  max-width: none;
}

.case-video iframe,
.case-video video {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.case-video video {
  object-fit: contain;
  background: #000;
}

@media (max-width: 640px) {
  .case-figures {
    grid-template-columns: 1fr;
  }
}

.case-summary {
  padding: var(--space-8) 0 0;
}

.case-summary .line {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.25rem;
  max-width: 40ch;
}

.case-summary .footnote {
  font-size: 0.8125rem;
  color: var(--color-muted);
  margin-top: var(--space-2);
}

/* Prev/next pagination */
.case-nav {
  margin-top: var(--space-12);
  border-top: 1px solid var(--color-line);
  padding: var(--space-4) 0;
}

.case-nav .container {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.case-nav a {
  position: relative;
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 600;
  text-decoration: none;
}

.case-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 1px;
  background: var(--color-text);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease;
}

.case-nav a:hover::after,
.case-nav a:focus-visible::after {
  transform: scaleX(1);
}

.case-nav .hint {
  display: block;
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-muted);
  margin-bottom: 4px;
}

/* ===========================================================================
   Scroll reveal (progressive enhancement; JS adds .reveal)
   =========================================================================== */
.reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 500ms ease, transform 500ms ease;
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }

  .reveal {
    opacity: 1;
    transform: none;
  }
}

/* ===========================================================================
   Responsive
   =========================================================================== */
/* Full-bleed side padding steps down as the viewport narrows: 80px on the
   desktop layout → 48px on tablets → 24px on phones. Everything that reads
   --page-pad (hero, footer, work carousel inset) scales together. */
@media (max-width: 900px) {
  :root {
    --page-pad: 48px;
  }

  /* Tablet: shorten the body text block */
  .about-lead {
    max-width: 560px;
  }
}

@media (max-width: 640px) {
  :root {
    --page-pad: 24px;
  }

  /* Mobile: fill the available width */
  .about-lead {
    max-width: 100%;
  }
}

@media (max-width: 1200px) {
  .about-grid {
    grid-template-columns: 1fr;
  }

  .about-grid .hero-photo {
    max-width: 400px;
  }
}

@media (max-width: 720px) {
  .about-grid .hero-photo {
    max-width: 260px;
  }
}

@media (max-width: 640px) {
  .hero {
    padding-top: var(--space-12);
  }

  .hero-grid {
    grid-template-columns: 1fr;
  }

  .hero-photo {
    max-width: 260px;
  }

  .work-carousel {
    --card-w: 82vw;
  }

  .carousel-btn {
    width: 40px;
    height: 40px;
  }

  .carousel-btn.prev {
    left: var(--space-2);
  }

  .carousel-btn.next {
    right: var(--space-2);
  }

  .meta-block {
    grid-template-columns: 1fr 1fr;
  }

  .site-nav {
    gap: var(--space-2);
  }
}
