/* McMorrow Design — v2 prototype
   Modernist / Swiss direction: shared 12-column grid, giant cropped
   display type occluded by imagery, hairline rules, one accent color. */

:root {
  --ink: #1a1a1a;
  --paper: #f4f1ea;
  --accent: #707c49;
  --rule: rgba(26, 26, 26, 0.25);
  --grotesk: 'Space Grotesk', sans-serif;
  --body: 'Inter', sans-serif;
  /* the type ramp: every component composes from these tiers —
     no component defines a private size */
  --fs-display: clamp(2.4rem, 6.5vw, 5.5rem); /* statements, giant moments */
  --fs-h1: clamp(2.1rem, 4.6vw, 4.2rem);      /* page / case titles */
  --fs-h2: clamp(2rem, 4.5vw, 3.8rem);        /* section headlines */
  --fs-h3: 1.5rem;                            /* subsection headlines */
  --fs-h4: 1.15rem;                           /* box / compartment headlines */
  --fs-quote: clamp(1.4rem, 2.6vw, 2.2rem);   /* pull quotes */
  --fs-lede: 1.15rem;                         /* intro / lede paragraphs, wt 500 */
  --fs-p1: 1rem;                              /* default body */
  --fs-p2: 0.95rem;                           /* compartment & column body */
  --fs-small: 0.85rem;                        /* meta, captions, footnotes */
  --fs-label: 0.78rem;                        /* small caps labels */
  /* the one grid every section shares */
  --cols: repeat(12, 1fr);
  --gutter: 1.5rem;
  /* vertical rhythm: one scale everywhere */
  --sp-sm: 1.5rem;  /* within a block */
  --sp-md: 3rem;    /* between related blocks */
  --sp-lg: 6rem;    /* between sections */
  /* page margin grows on very wide screens, capping content at
     1560px and centering it while backgrounds stay full-bleed */
  --margin: max(3vw, calc((100vw - 1560px) / 2));
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* text selection picks up the page's accent (per-project brand color
   on case pages, site green everywhere else) */
::selection {
  background: var(--page-accent, var(--accent));
  color: var(--paper);
}
/* Kodak yellow is too light for paper-colored text */
.theme-kodak ::selection { color: var(--ink); }

body {
  font-family: var(--body);
  background: var(--paper);
  color: var(--ink);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  cursor: url('../assets/images/cursor-standard.png'), auto;
}

a:hover, button:hover {
  cursor: url('../assets/images/cursor-hover.png'), pointer;
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }

/* no orphans: paragraphs avoid a lone word on their last line
   (progressive enhancement; ignored by older browsers) */
p { text-wrap: pretty; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.grid {
  display: grid;
  grid-template-columns: var(--cols);
  column-gap: var(--gutter);
  padding-left: var(--margin);
  padding-right: var(--margin);
}

/* Labels: small, uppercase, tracked */
.label {
  font-family: var(--grotesk);
  font-size: var(--fs-label);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
}

/* ---------- Header ---------- */
.v2-header {
  padding-top: 1.4rem;
  padding-bottom: 1.4rem;
  border-bottom: 1px solid var(--rule);
  align-items: baseline;
}
.v2-header .wordmark {
  grid-column: 1 / 5;
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.02em;
}
.v2-header .header-clock {
  grid-column: 5 / 9;
  text-align: center;
  color: rgba(26, 26, 26, 0.45);
}
.v2-header nav {
  grid-column: 9 / 13;
  display: flex;
  gap: 2rem;
  justify-content: flex-end;
}
.v2-header nav a { font-weight: 700; }
.v2-header nav a:hover { color: var(--accent); }
/* external/social links read quieter than the page links */
.v2-header nav .nav-ext {
  font-weight: 400;
  color: rgba(26, 26, 26, 0.55);
}
.v2-header nav .nav-ext:hover { color: var(--accent); }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: 80vh;
  overflow: hidden; /* crops the display word at the edges */
}
.hero-copy {
  position: relative;
  z-index: 3;
  padding-top: 4.4rem;
  align-items: start;
  /* the block spans the hero's top; let hovers pass through to the
     photos beneath, except over the text itself */
  pointer-events: none;
}
.hero-copy .hero-manifesto { pointer-events: auto; }
.hero-copy .hero-manifesto { margin-bottom: 0; }
.hero-manifesto {
  grid-column: 8 / 13;
  font-size: var(--fs-lede);
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: -0.01em;
  max-width: 46ch;
}

/* Giant display word: type as form. Cropped by the hero's edges,
   sandwiched between the two images. */
.display-word {
  position: absolute;
  z-index: 1;
  bottom: -0.24em;
  left: -0.02em;
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: 23vw;
  line-height: 1;
  letter-spacing: -0.04em;
  white-space: nowrap;
  color: var(--accent);
  /* Space Grotesk tops out at 700; stroke the letters in the same
     color to fatten them further */
  -webkit-text-stroke: 0.012em var(--accent);
  user-select: none;
  pointer-events: none;
}

/* Hero images: arranged on the 12-column rhythm (left edges land on
   column lines, 1 col = 8.333%), sizes stepped in clear ratios
   (large / medium / small), split between the two planes of the
   type sandwich. */
.hero-photo {
  position: absolute;
  filter: grayscale(1);
  transition: filter 0.35s ease;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.hero-photo:hover { filter: grayscale(0); }
.hero-photo.dragging { cursor: grabbing; }

/* large pair */
.hero-photo--back {           /* col 2, lower-left of the top cluster */
  z-index: 2;
  width: clamp(184px, 24.15vw, 460px);
  top: 14%;
  left: 8.333%;
}
.hero-photo--front {          /* col 8, full vertical: left edge lines
                                 up with the manifesto text above */
  z-index: 2;
  bottom: 5%;
  width: clamp(112px, 11.8vw, 225px);
  left: calc(var(--margin) + 7 * (100% - 2 * var(--margin) + var(--gutter)) / 12);
}

/* medium pair */
.hero-photo--specimen {       /* col 4; top edge lines up with the
                                 top of the manifesto type */
  z-index: 2;
  width: clamp(138px, 16.1vw, 306px);
  top: 4.4rem; /* = .hero-copy padding-top */
  left: 25%;
}
.hero-photo--people {         /* mid-page, clearly above the word */
  z-index: 2;
  width: clamp(138px, 16.1vw, 306px);
  top: 60%;
  left: 32%;
}

/* small pair */
.hero-photo--album {          /* overlapping the laptop's upper-right corner */
  z-index: 2;
  width: clamp(83px, 9.3vw, 180px);
  top: 39%;
  left: 68.5%;
}
.hero-photo--house {          /* center-left, sunk into the word */
  z-index: 2;
  width: clamp(99px, 10.9vw, 210px);
  top: 72%;
  left: 24%;
}

/* ---------- Work index ---------- */
.work-index { padding-top: var(--sp-lg); padding-bottom: 2rem; }
.section-head {
  padding-bottom: 1rem;
  align-items: baseline;
}
.section-head .label { grid-column: 1 / 4; }
.section-head .count { grid-column: 12 / 13; text-align: right; color: var(--accent); }

.work-row {
  align-items: center;
  padding-top: 2.2rem;
  padding-bottom: 2.2rem;
  border-bottom: 1px solid var(--rule);
  position: relative;
}
.work-row .num {
  grid-column: 1 / 2;
  font-family: var(--grotesk);
  font-size: 0.9rem;
  color: var(--accent);
}
.work-row .title {
  grid-column: 2 / 8;
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: clamp(1.6rem, 3.4vw, 3rem);
  line-height: 1.05;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  transition: color 0.2s ease, transform 0.2s ease;
}
.work-row .meta {
  grid-column: 8 / 12;
  font-size: var(--fs-small);
  color: rgba(26, 26, 26, 0.65);
}
.work-row .arrow {
  grid-column: 12 / 13;
  text-align: right;
  font-family: var(--grotesk);
  font-size: 1.4rem;
  transition: transform 0.2s ease;
}
.work-row:hover .title { color: var(--accent); transform: translateX(0.4rem); }
.work-row:hover .arrow { transform: translate(0.3rem, -0.3rem); }

/* ---------- Work preview: cover image beside the cursor.
   Reveals via a mask expanding from the center; on row switch the new
   image expands over the old one, which holds underneath. ---------- */
.work-preview {
  position: fixed;
  top: 0;
  left: 0;
  width: clamp(220px, 24vw, 340px);
  aspect-ratio: 4 / 3;
  z-index: 40;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease; /* exit fade only; entry is the mask */
}
.work-preview.active {
  opacity: 1;
  transition: none; /* appear instantly, let the mask do the reveal */
}
.work-preview .layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.work-preview .layer--over {
  clip-path: inset(50% 50% 50% 50%);
}
.work-preview .layer--over.expand {
  clip-path: inset(0 0 0 0);
  transition: clip-path 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
}

@media (prefers-reduced-motion: reduce) {
  .work-preview,
  .work-preview .layer--over.expand { transition: none; }
}

/* ---------- Archive hero: hairline compartments, big type, and a
   dot rolling along its track — panel-footer inspiration, house
   palette ---------- */
.archive-hero { padding: 2.4rem var(--margin) 3rem; }
.ah-frame {
  display: grid;
  grid-template-columns: 5fr 4fr 3fr;
  border: 1px solid var(--ink);
}
.ah-panel { padding: 1.6rem; min-height: 15rem; }
.ah-panel + .ah-panel { border-left: 1px solid var(--ink); }
.ah-panel--title {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 2rem;
}
.ah-title {
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: clamp(2.6rem, 6vw, 5.2rem);
  line-height: 0.95;
  text-transform: uppercase;
  letter-spacing: -0.02em;
}
.ah-caption { color: rgba(26, 26, 26, 0.6); line-height: 1.7; }

/* middle panel: a dot rolls back and forth along a hairline,
   squashing softly as it lands at either end */
.ah-panel--track { position: relative; overflow: hidden; }
.ah-panel--track::after {
  content: '';
  position: absolute;
  left: 1.6rem;
  right: 1.6rem;
  bottom: 2rem;
  height: 1px;
  background: var(--ink);
}
.ah-dot {
  position: absolute;
  bottom: calc(2rem + 1px);
  left: 1.6rem;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--ink);
}
/* The shuttle: one ball drops toward the wall, gathering speed the
   whole way (gravity ease-in). On impact the balls toss out like the
   wall is the ground — fast off the launch, slowing into the peak,
   never resting, then accelerating back down until they're one ball
   again. Then the same thing happens mirrored at the other wall. */
.ah-dot--main { animation: ah-shuttle 8s infinite; }
@keyframes ah-shuttle {
  0%   { left: calc(100% - 1.6rem - 20px); animation-timing-function: cubic-bezier(0.6, 0, 1, 1); }
  22%  { left: 1.6rem; }
  50%  { left: 1.6rem; animation-timing-function: cubic-bezier(0.6, 0, 1, 1); }
  72%  { left: calc(100% - 1.6rem - 20px); }
  100% { left: calc(100% - 1.6rem - 20px); }
}
/* the multiplied balls: hidden while stacked inside the main ball,
   ejected on each impact, then falling back in — never fading in
   the open, every appearance happens under cover of the main ball */
.ah-dot--b1, .ah-dot--b2, .ah-dot--b3, .ah-dot--b4 {
  opacity: 0;
  animation: 8s infinite;
}
.ah-dot--b1 { animation-name: ah-cradle-1; }
.ah-dot--b2 { animation-name: ah-cradle-2; }
.ah-dot--b3 { animation-name: ah-cradle-3; }
.ah-dot--b4 { animation-name: ah-cradle-4; }
@keyframes ah-cradle-1 {
  0%, 21.9% { left: 1.6rem; transform: translateX(0); opacity: 0; }
  22.0% { left: 1.6rem; transform: translateX(0); opacity: 1; animation-timing-function: cubic-bezier(0.25, 1, 0.5, 1); }
  28.5% { left: 1.6rem; transform: translateX(1050%); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0); }
  40.0% { left: 1.6rem; transform: translateX(0); opacity: 1; }
  40.2% { left: 1.6rem; opacity: 0; }
  49%, 71.9% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 0; }
  72.0% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 1; animation-timing-function: cubic-bezier(0.25, 1, 0.5, 1); }
  78.5% { left: calc(100% - 1.6rem - 20px); transform: translateX(-1050%); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0); }
  90.0% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 1; }
  90.2% { left: calc(100% - 1.6rem - 20px); opacity: 0; }
  99%, 100% { left: 1.6rem; transform: translateX(0); opacity: 0; }
}
@keyframes ah-cradle-2 {
  0%, 22.7% { left: 1.6rem; transform: translateX(0); opacity: 0; }
  22.8% { left: 1.6rem; transform: translateX(0); opacity: 1; animation-timing-function: cubic-bezier(0.25, 1, 0.5, 1); }
  28.6% { left: 1.6rem; transform: translateX(760%); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0); }
  39.2% { left: 1.6rem; transform: translateX(0); opacity: 1; }
  39.4% { left: 1.6rem; opacity: 0; }
  49%, 72.7% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 0; }
  72.8% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 1; animation-timing-function: cubic-bezier(0.25, 1, 0.5, 1); }
  78.6% { left: calc(100% - 1.6rem - 20px); transform: translateX(-760%); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0); }
  89.2% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 1; }
  89.4% { left: calc(100% - 1.6rem - 20px); opacity: 0; }
  99%, 100% { left: 1.6rem; transform: translateX(0); opacity: 0; }
}
@keyframes ah-cradle-3 {
  0%, 23.6% { left: 1.6rem; transform: translateX(0); opacity: 0; }
  23.7% { left: 1.6rem; transform: translateX(0); opacity: 1; animation-timing-function: cubic-bezier(0.25, 1, 0.5, 1); }
  28.7% { left: 1.6rem; transform: translateX(490%); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0); }
  38.4% { left: 1.6rem; transform: translateX(0); opacity: 1; }
  38.6% { left: 1.6rem; opacity: 0; }
  49%, 73.6% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 0; }
  73.7% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 1; animation-timing-function: cubic-bezier(0.25, 1, 0.5, 1); }
  78.7% { left: calc(100% - 1.6rem - 20px); transform: translateX(-490%); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0); }
  88.4% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 1; }
  88.6% { left: calc(100% - 1.6rem - 20px); opacity: 0; }
  99%, 100% { left: 1.6rem; transform: translateX(0); opacity: 0; }
}
@keyframes ah-cradle-4 {
  0%, 24.4% { left: 1.6rem; transform: translateX(0); opacity: 0; }
  24.5% { left: 1.6rem; transform: translateX(0); opacity: 1; animation-timing-function: cubic-bezier(0.25, 1, 0.5, 1); }
  28.8% { left: 1.6rem; transform: translateX(240%); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0); }
  37.6% { left: 1.6rem; transform: translateX(0); opacity: 1; }
  37.8% { left: 1.6rem; opacity: 0; }
  49%, 74.4% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 0; }
  74.5% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 1; animation-timing-function: cubic-bezier(0.25, 1, 0.5, 1); }
  78.8% { left: calc(100% - 1.6rem - 20px); transform: translateX(-240%); animation-timing-function: cubic-bezier(0.5, 0, 0.75, 0); }
  87.6% { left: calc(100% - 1.6rem - 20px); transform: translateX(0); opacity: 1; }
  87.8% { left: calc(100% - 1.6rem - 20px); opacity: 0; }
  99%, 100% { left: 1.6rem; transform: translateX(0); opacity: 0; }
}
.ah-square {
  position: absolute;
  top: 1.5rem;
  left: 1.6rem;
  width: 10px;
  height: 10px;
  background: var(--accent);
  animation: ah-blink 2.4s linear infinite;
}
@keyframes ah-blink {
  0%, 55% { opacity: 1; }
  56%, 100% { opacity: 0.15; }
}

.ah-panel--meta {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.7rem 1.4rem;
  align-content: start;
}
.ah-panel--meta .ah-k { color: rgba(26, 26, 26, 0.5); }
.ah-panel--meta .ah-v { font-family: var(--grotesk); font-weight: 700; }

@media (max-width: 767px) {
  .ah-frame { grid-template-columns: 1fr; }
  .ah-panel { min-height: 0; }
  .ah-panel + .ah-panel { border-left: none; border-top: 1px solid var(--ink); }
  .ah-panel--track { min-height: 7rem; }
}
@media (prefers-reduced-motion: reduce) {
  .ah-dot, .ah-square { animation: none; }
  .ah-dot--main { opacity: 1; }
}

/* case pages open with the same panel frame, no animation:
   title + category left, lede center, spec table right */
.case-hero { padding: 2.4rem var(--margin) var(--sp-md); }
.case-hero .ah-panel { min-height: 12rem; }
.case-hero .ah-title { font-size: var(--fs-h1); }
.case-hero .case-lede {
  margin: 0;
  font-size: var(--fs-lede);
  max-width: 44ch;
}
@media (max-width: 767px) {
  .case-hero .ah-panel--lede:empty { display: none; }
}

/* ---------- Archive index: compact rows ---------- */
.archive-index { padding-top: 3rem; }

.index-head {
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--ink);
  color: rgba(26, 26, 26, 0.45);
}
/* on the main page the labels sit under the section head */
.section-head + .index-head { padding-top: 1.1rem; }
.index-head .col-num { grid-column: 1 / 2; }
.index-head .col-project { grid-column: 2 / 8; }
.index-head .col-cat { grid-column: 8 / 12; }

.work-row--sm {
  padding-top: 0.55rem;
  padding-bottom: 0.55rem;
}
.work-row--sm .title {
  font-family: var(--body);
  font-weight: 500;
  font-size: 0.95rem;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.4;
}
.work-row--sm .meta { font-size: 0.85rem; }
.work-row--sm .arrow { font-size: 0.95rem; }
.work-row--sm:hover .title { transform: translateX(0.25rem); }

/* ---------- Archive strip ---------- */
.archive-strip {
  padding-top: 2.2rem;
  padding-bottom: 5rem;
  align-items: center;
}
.archive-strip .label { grid-column: 1 / 4; }
.archive-strip .archive-link {
  grid-column: 8 / 13;
  justify-self: end;
  font-family: var(--grotesk);
  font-weight: 500;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 0.15rem;
}
.archive-strip .archive-link:hover { color: var(--accent); border-color: var(--accent); }

/* ---------- About page ----------
   Two-column composition: the portrait anchors the left, one content
   column carries everything else. Groups are separated by a single,
   consistent measure of air. */
.about-v2 {
  position: relative;
  overflow: hidden; /* crops the display word */
  padding-bottom: 15vw;
}
.about-layout {
  padding-top: 5rem;
  align-items: start;
}
/* everything lives in the content column unless said otherwise */
.about-layout > * { grid-column: 8 / 13; }

.about-portrait {
  grid-column: 1 / 5;
  grid-row: 3 / 8; /* holds the left column below the hero */
  margin-top: 4.5rem;
  margin-bottom: calc(var(--sp-lg) + 3rem);
  width: 100%;
  filter: grayscale(1);
  transition: filter 0.35s ease;
}
.about-portrait:hover { filter: grayscale(0); }

/* hero: statement plays the title on the left, intro copy sits
   beside it on the right — same pattern as the case pages */
.about-v2 .about-layout .statement {
  grid-column: 1 / 8;
  grid-row: 1 / 3;
  margin: 0;
  font-size: clamp(1.6rem, 2.8vw, 2.8rem);
}
.about-layout .about-label:first-of-type {
  grid-column: 8 / 13;
  grid-row: 1;
  margin-top: 0.5rem;
}
.about-layout .about-text {
  grid-column: 8 / 13;
  grid-row: 2;
}

/* groups: label sits tight to its content, big air between groups */
.about-label {
  margin-top: 4.5rem;
  color: var(--accent);
}
.about-text {
  margin-top: 1rem;
  font-size: 1rem;
  max-width: 62ch;
}
.about-text p + p { margin-top: 1rem; }

/* the video tucks into the portrait's bottom-right corner */
.about-video {
  grid-column: 4 / 9;
  grid-row: 5 / 8;
  align-self: end;
  width: 74%;
  max-width: 540px;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  filter: grayscale(1);
  transition: filter 0.35s ease;
}
.about-video:hover { filter: grayscale(0); }

.about-contact-block { margin-top: 4.5rem; }
.about-contact-block .about-label { display: block; margin-top: 0; }
.about-contact { margin-top: 1rem; }
.about-email {
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: 1.3rem;
  border-bottom: 1px solid var(--ink);
}
.about-email:hover { color: var(--accent); border-color: var(--accent); }

.display-word--about { z-index: 0; }

/* ---------- Case study pages ---------- */
.case-v2 {
  position: relative;
  overflow: hidden;     /* crops the display word */
  padding-bottom: 16vw; /* room for the cut-off project name */
}
.display-word--case {
  z-index: 0;
  /* left-aligned like the home hero; short names hug the left edge */
  /* per-project brand color; falls back to the site green */
  color: var(--page-accent, var(--accent));
  -webkit-text-stroke: 0.012em var(--page-accent, var(--accent));
}

.case-head { padding-top: 3rem; align-items: start; }
.case-head .label { grid-column: 1 / 4; grid-row: 1; color: var(--accent); }
.case-title {
  grid-column: 1 / 8;
  grid-row: 2;
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: clamp(3rem, 9vw, 8rem);
  line-height: 0.95;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  margin-top: 1rem;
}
.case-lede {
  /* sits beside the title, top-aligned with it */
  grid-column: 8 / 13;
  grid-row: 2;
  margin-top: 1.2rem;
  margin-bottom: 2rem;
  font-size: 1.15rem;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: -0.01em;
  max-width: 46ch;
}
.case-meta {
  grid-column: 1 / 13;
  margin-top: 2.5rem;
  padding-top: 0.8rem;
  border-top: 1px solid var(--rule);
  color: rgba(26, 26, 26, 0.55);
}

/* meta line tucked directly under the title, quiet grey */
.case-meta--under {
  grid-column: 1 / 13;
  grid-row: 3;
  margin-top: 1.2rem;
  padding-top: 0;
  border-top: none;
  color: rgba(26, 26, 26, 0.55);
}

/* Asymmetric fields on the shared 12-column grid: spans vary
   (dominant plane vs. counterweight) and items stagger vertically,
   composing groups instead of symmetric rows. */
.grid > .f-1-13  { grid-column: 1 / 13; }
.grid > .f-1-4   { grid-column: 1 / 4; }
.grid > .f-5-10  { grid-column: 5 / 10; }
.grid > .f-1-5   { grid-column: 1 / 5; }
.grid > .f-5-9   { grid-column: 5 / 9; }
.grid > .f-6-9   { grid-column: 6 / 9; }
.grid > .f-6-10  { grid-column: 6 / 10; }
.grid > .f-9-12  { grid-column: 9 / 12; }
.grid > .f-1-6   { grid-column: 1 / 6; }

/* hero band: centered and capped instead of full-bleed */
.grid > .bleed {
  grid-column: 1 / 13;
  width: 80%;
  max-width: 1100px;
  margin-inline: auto;
  max-height: 62vh;
  object-fit: cover;
}
/* logo covers: half-width, never cropped, generous air around */
.grid > .bleed--logo {
  width: 40%;
  max-width: 550px;
  max-height: 30vh;
  object-fit: contain;
  margin-block: 2.5rem;
}

/* plates: photographic media crops to consistent proportions;
   artwork and UI screens keep their natural ratio */
.grid > .r-wide { aspect-ratio: 16 / 10; object-fit: cover; }
.grid > .r-std  { aspect-ratio: 4 / 3;   object-fit: cover; }
.grid > .r-sq   { aspect-ratio: 1 / 1;   object-fit: cover; }
.grid > .r-tall { aspect-ratio: 4 / 5;   object-fit: cover; }
.grid > .f-1-7   { grid-column: 1 / 7; }
.grid > .f-1-8   { grid-column: 1 / 8; }
.grid > .f-1-9   { grid-column: 1 / 9; }
.grid > .f-1-10  { grid-column: 1 / 10; }
.grid > .f-2-12  { grid-column: 2 / 12; }
.grid > .f-3-13  { grid-column: 3 / 13; }
.grid > .f-4-13  { grid-column: 4 / 13; }
.grid > .f-6-13  { grid-column: 6 / 13; }
.grid > .f-7-10  { grid-column: 7 / 10; }
.grid > .f-7-13  { grid-column: 7 / 13; }
.grid > .f-4-10  { grid-column: 4 / 10; }
.grid > .f-2-9   { grid-column: 2 / 9; }
.grid > .f-2-10  { grid-column: 2 / 10; }
.grid > .f-7-12  { grid-column: 7 / 12; }
.grid > .f-8-12  { grid-column: 8 / 12; }
.grid > .f-8-13  { grid-column: 8 / 13; }
.grid > .f-9-13  { grid-column: 9 / 13; }
.grid > .f-10-13 { grid-column: 10 / 13; }

/* vertical stagger */
.grid > .drop-1 { margin-top: 3.5rem; }
.grid > .drop-2 { margin-top: 7rem; }
.grid > .drop-3 { margin-top: 11rem; }
/* pull up into the previous row's space, for collage accents */
.grid > .raise-1 { margin-top: -6rem; }

/* video embeds: wrapper enforces 16:9, iframe fills it */
.grid > .embed-wrap { position: relative; width: 100%; padding-top: 56.25%; }
/* feature videos: larger, centered, with air after the copy above */
.grid > .embed-wrap--wide {
  width: 92%;
  max-width: 1200px;
  padding-top: 51.75%; /* 56.25% of the 92% width keeps 16:9 */
  margin-top: 1.5rem;
  margin-inline: auto;
}

/* click-to-play poster: cover still fills the video slot exactly,
   with a bare play glyph; the whole surface starts playback */
.embed-wrap--poster { cursor: pointer; }
.grid .embed-wrap--poster img {
  position: absolute;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  object-fit: cover;
}
.play-btn {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 96px;
  height: 96px;
  border: none;
  background: none;
  color: #fff;
  display: grid;
  place-items: center;
  cursor: pointer;
  filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.45));
  transition: transform 0.25s ease;
}
.play-btn svg { width: 54px; height: 54px; }
.embed-wrap--poster:hover .play-btn,
.embed-wrap--poster:focus-within .play-btn {
  transform: translate(-50%, -50%) scale(1.12);
}
.embed-wrap iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* media scale: case imagery runs 20% smaller than its grid field,
   with a hard cap so nothing balloons on very large screens */
.case-media img, .case-media video,
.case-group img, .case-group video,
.grid > .embed-wrap {
  width: 80%;
  max-width: 960px;
}
/* full-row media centers itself; staggered collage pieces stay
   anchored to their column line */
.grid > img.f-1-13, .grid > video.f-1-13,
.grid > img.f-2-12, .grid > video.f-2-12,
.grid > img.f-4-10, .grid > video.f-4-10,
.grid > .embed-wrap.f-1-13, .grid > .embed-wrap.f-2-12 { margin-inline: auto; }

/* portrait video embeds: phone-shaped frame sized by its own aspect
   ratio instead of the 16:9 padding hack, centered and capped so it
   reads tall without swallowing the page */
.grid > .embed-wrap--portrait {
  width: min(100%, 420px);
  max-width: 420px;
  padding-top: 0;
  aspect-ratio: 240 / 406; /* native ratio of the source video */
  margin-inline: auto;
}

/* standalone media band (no copy) */
.case-media { padding-top: var(--sp-md); row-gap: 2.5rem; }
.case-media--flush { padding-top: var(--sp-sm); }
.case-media--pad { padding-bottom: var(--sp-lg); } /* air before a flush section */
.case-media--airy { row-gap: 4.5rem; padding-bottom: var(--sp-md); } /* loose stack */
/* optical centering nudge for asymmetric artwork */
.grid > img.optical-right { transform: translateX(3.5%); }
.case-media > * { width: 100%; align-self: start; }
.case-media video { display: block; }
.case-caption {
  grid-column: 1 / 7;
  margin-top: 0.8rem;
  font-size: 0.85rem;
  color: rgba(26, 26, 26, 0.55);
}
/* captioned media: the description rides directly under its photo */
.grid > figure { margin: 0; }
.grid > figure img { width: 100% !important; max-width: none !important; }
.section-dark .case-caption { color: rgba(244, 241, 234, 0.65); }

/* case groups: each opens with a rule to mark the division, then one
   of three patterns — collage (default), headline row, or type-left. */
.case-group { padding-top: var(--sp-lg); align-items: start; row-gap: 2.5rem; }
.case-group::before {
  /* full-bleed hairline, edge to edge like the header and footer rules */
  content: '';
  grid-column: 1 / 13;
  width: calc(100% + 2 * var(--margin));
  margin-left: calc(-1 * var(--margin));
  height: 1px;
  background: var(--ink);
  margin-bottom: var(--sp-md);
}

/* pattern: headline row — big type left, supporting copy right,
   media in full rows below */

/* summary strip: boxed one-liners right under the hero frame,
   no divider of its own */
.case-group--summary { padding-top: 0; }
.case-group--summary::before { display: none; }

/* level rows: headline and copy sit on the same center line */
.case-group--center { align-items: center; }
.case-group--center .row-title { margin-bottom: 0; }

/* flush groups continue the thought above: no dividing rule,
   tighter air */
.case-group--flush { padding-top: var(--sp-md); }
.case-group--flush::before { display: none; }
.case-group--row .row-title {
  grid-column: 1 / 7;
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: var(--fs-h2);
  line-height: 1.02;
  letter-spacing: -0.02em;
  margin-bottom: var(--sp-md);
}
.case-group--row .case-body {
  grid-column: 8 / 13;
  font-size: 0.95rem;
  max-width: 46ch;
}
/* headline with its contact line directly beneath, flush left */
.grid > .request-block { grid-column: 1 / 10; }
.request-block .row-title { margin-bottom: 1rem; }
.request-block p { font-size: var(--fs-p2); }
.request-block a { text-decoration: underline; text-underline-offset: 3px; }
.request-block a:hover { color: var(--accent); }


.case-group .label { grid-column: 1 / 4; color: var(--accent); }
.case-group .case-body {
  grid-column: 7 / 13;
  max-width: 52ch;
  margin-bottom: 2.5rem;
}
.case-group img,
.case-group video { width: 100%; align-self: start; display: block; }
.case-body h2 {
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: var(--fs-h3);
  margin-bottom: 1rem;
}
.case-body p + p { margin-top: 1rem; }
.case-body a { text-decoration: underline; text-underline-offset: 3px; }
.case-body a:hover { color: var(--accent); }

/* paired note columns (Overview / Approach style): equal type,
   adjacent columns with a long measure, hugging the left side */
.case-group .note { font-size: var(--fs-p2); max-width: 52ch; line-height: 1.6; }
.case-group .note .label { display: block; margin-bottom: 1rem; }
.case-group .note p + p { margin-top: 1rem; }
.case-group .note--a { grid-column: 1 / 6; }
.case-group .note--b { grid-column: 6 / 11; }

/* giant word moments (Capture / Analyze / Refine) */
.case-word {
  grid-column: 1 / 7;
  align-self: center;
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: clamp(3.5rem, 9vw, 8rem);
  line-height: 0.95;
  text-transform: uppercase;
  letter-spacing: -0.02em;
}
/* giant words all read from the left edge — no alternating sides */
.case-word--right { grid-column: 1 / 7; text-align: left; }

/* contact sheet: compact slide grid, three per row, every slide
   the same size */
.grid > .sheet {
  grid-column: span 4;
  width: 100%;
  max-width: none;
  border: 1px solid var(--rule);
}
/* small variant: six per row, for tall phone-screen shots */
.grid > .sheet--sm { grid-column: span 2; }

/* timeline: a thin rule threaded through dots — year up top, the
   moment in quiet small type below */
.grid > .timeline {
  grid-column: 1 / 13;
  position: relative;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  column-gap: var(--gutter);
  margin-top: 2.5rem;
  margin-bottom: 3rem;
}
.timeline::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: calc(2.2rem + 4px); /* through the dots' centers */
  height: 1px;
  background: var(--rule);
}
.tl-point { display: flex; flex-direction: column; }
.tl-year {
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: var(--fs-h4);
  line-height: 1;
  margin-bottom: 1.1rem;
}
.tl-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
  position: relative;
  z-index: 1;
  margin-bottom: 1.1rem;
}
.tl-event {
  font-size: var(--fs-small);
  line-height: 1.5;
  color: rgba(26, 26, 26, 0.6);
  max-width: 22ch;
}
@media (max-width: 767px) {
  .grid > .timeline { grid-template-columns: repeat(2, 1fr); row-gap: 2rem; }
  .timeline::before { display: none; }
}

/* spec table: boxed rows — label column, vertical divider, value
   column, framed like the hero compartments */
.grid > .spec { grid-column: 1 / 13; border: 1px solid var(--ink); margin-top: 2.5rem; }
.spec-row {
  display: grid;
  grid-template-columns: 1fr 2fr;
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-p2);
}
.spec-row:last-child { border-bottom: none; }
.spec-row .k { font-family: var(--grotesk); font-weight: 500; padding: 0.6rem 1.2rem; }
.spec-row .v { border-left: 1px solid var(--rule); padding: 0.6rem 1.2rem 0.6rem 1.5rem; }

/* rule columns: dense list content sits in ruled compartments,
   a variation of the hero's box frame */
.grid > .rule-cols {
  grid-column: 1 / 13;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--ink);
}
.rule-cols > div {
  border-left: 1px solid var(--ink);
  padding: 1.3rem 1.5rem 1.6rem;
}
.rule-cols > div:first-child { border-left: none; }
.grid > .rule-cols--2 { grid-template-columns: repeat(2, 1fr); }
.grid > .rule-cols--4 { grid-template-columns: repeat(4, 1fr); }

/* four-up drops to a boxed 2x2 before phones */
@media (max-width: 1000px) {
  .grid > .rule-cols--4 { grid-template-columns: repeat(2, 1fr); }
  .grid > .rule-cols--4 > div:nth-child(odd) { border-left: none; }
  .grid > .rule-cols--4 > div:nth-child(n+3) { border-top: 1px solid var(--ink); }
}
.rule-cols p + p { margin-top: 0.8rem; }
/* compartment headlines: one standard everywhere — bold and accent
   colored, whether set as an h3 or a small-caps label */
.rule-cols h3 {
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: var(--fs-h4);
  margin-bottom: 0.6rem;
  color: var(--accent);
}
.rule-cols .label {
  display: block;
  margin-bottom: 0.6rem;
  /* match the h3 treatment exactly: same size, case, and tracking */
  font-weight: 700;
  font-size: var(--fs-h4);
  text-transform: none;
  letter-spacing: normal;
}
/* imagery inside a compartment gets air before the copy below */
.rule-cols img { margin-bottom: 1.6rem; }
/* the headline sits in its own box at the top of the compartment */
.rule-cols > div > h3:first-child,
.rule-cols > div > .label:first-child {
  display: block;
  margin: -1.3rem -1.5rem 1.2rem;
  padding: 0.8rem 1.5rem;
  border-bottom: 1px solid var(--ink);
}
.rule-cols p { font-size: var(--fs-p2); line-height: 1.55; }
.rule-cols p + p { margin-top: 0.9rem; }

/* dynamic statement: staggered display lines with accent words,
   framed with generous air above and below */
.grid > .statement {
  grid-column: 1 / 13;
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: var(--fs-display);
  line-height: 1.04;
  letter-spacing: -0.02em;
  margin: 3.5rem 0 2rem;
}
.statement .ln { display: block; }
/* a statement standing alone in its section leans on the section's
   own padding — no extra margin stacking */
.case-group > .statement:only-child { margin-top: 0; }
/* display lines stay flush left — no staggered indents */
.statement .ind-1,
.statement .ind-2 { margin-left: 0; }
.statement em { font-style: normal; color: var(--accent); }
.statement .brand-red { color: #e00000; }
/* caps variant: manifesto copy as stacked display lines */
.statement--caps {
  text-transform: uppercase;
  line-height: 0.98;
  font-size: clamp(2.2rem, 5.8vw, 5rem);
}

/* ---------- Kodak page theme: single yellow accent + ruled rhythm ---------- */
.theme-kodak {
  --accent: #f5b400; /* Kodak yellow is the only accent on this page */
}
.theme-kodak .statement em,
.theme-kodak .statement .brand-red { color: var(--accent); }



/* pull quote: fills most of the left, flush with the page's left edge */
.case-quote {
  grid-column: 1 / 8;
  font-family: var(--grotesk);
  font-weight: 500;
  font-size: var(--fs-quote);
  line-height: 1.25;
  letter-spacing: -0.01em;
}

/* ---------- IKEA Homestead: needs diagram as a live section ----------
   Flush blue band, headline in the house type, and yellow blobs that
   slowly morph while their labels drift inside. */
.ikea-needs {
  --ik-blue: #1e449c;
  --ik-yellow: #fcd018;
  margin-top: var(--sp-lg);
  background: var(--ik-blue);
  padding-top: var(--sp-lg);
  padding-bottom: var(--sp-lg);
}
/* the whole composition lives in a centered, capped box inside the
   band: headline left, cluster right, both vertically centered */
.needs-layout {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: center;
  column-gap: 4rem;
  width: min(1200px, 100% - 2 * var(--margin));
  margin-inline: auto;
}
.needs-title {
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: clamp(1.6rem, 2.8vw, 2.5rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--paper);
  text-wrap: balance; /* even, natural line breaks */
}
.needs-stage {
  position: relative;
  height: clamp(320px, 40vw, 500px);
}
.blob {
  position: absolute;
  display: grid;
  place-items: center;
  background: var(--ik-yellow);
  color: var(--ik-blue);
  font-family: var(--grotesk);
  font-weight: 700;
  text-align: center;
  line-height: 1.15;
  animation: blob-morph 14s ease-in-out infinite alternate;
}
.blob span {
  max-width: 78%;
  animation: blob-drift 11s ease-in-out infinite alternate;
}
.blob--sm {
  width: clamp(110px, 13vw, 165px);
  height: clamp(110px, 13vw, 165px);
  left: 30%;
  top: 4%;
  font-size: clamp(0.8rem, 1.1vw, 1rem);
}
.blob--md {
  width: clamp(150px, 18vw, 230px);
  height: clamp(150px, 18vw, 230px);
  left: 10%;
  top: 48%;
  font-size: clamp(0.9rem, 1.25vw, 1.15rem);
  animation-duration: 17s;
  animation-delay: -6s;
}
.blob--md span { animation-duration: 13s; animation-delay: -4s; }
.blob--lg {
  width: clamp(210px, 26vw, 330px);
  height: clamp(210px, 26vw, 330px);
  left: 47%;
  top: 16%;
  font-size: clamp(1.2rem, 1.9vw, 1.8rem);
  animation-duration: 20s;
  animation-delay: -11s;
}
.blob--lg span { animation-duration: 15s; animation-delay: -8s; }
@keyframes blob-morph {
  0%   { border-radius: 37% 63% 60% 40% / 59% 39% 61% 41%; }
  33%  { border-radius: 66% 34% 41% 59% / 37% 65% 35% 63%; }
  66%  { border-radius: 40% 60% 69% 31% / 63% 35% 65% 37%; }
  100% { border-radius: 59% 41% 34% 66% / 41% 61% 39% 59%; }
}
@keyframes blob-drift {
  0%   { transform: translate(0, 0); }
  50%  { transform: translate(7px, -6px); }
  100% { transform: translate(-7px, 5px); }
}
@media (prefers-reduced-motion: reduce) {
  .blob, .blob span { animation: none; border-radius: 50% 50% 48% 52% / 52% 48% 52% 48%; }
}
@media (max-width: 767px) {
  .needs-layout { grid-template-columns: 1fr; }
  .needs-title { margin-bottom: 1.5rem; }
  .needs-stage { height: 110vw; }
  .blob--sm { left: 22%; top: 3%; width: 30vw; height: 30vw; }
  .blob--md { left: 46%; top: 22%; width: 40vw; height: 40vw; }
  .blob--lg { left: 16%; top: 48%; width: 56vw; height: 56vw; }
}

/* IKEA moodboard trees: three images in an overlapping circular
   cluster that orbits slowly; each image stays upright (counter-
   rotation) and swells on hover */
.grid > .tree-ring {
  grid-column: 1 / 13;
  justify-self: center;
  position: relative;
  width: clamp(360px, 58vw, 740px);
  height: clamp(360px, 58vw, 740px);
  margin-block: 2rem;
}
/* the cluster holds its shape; each image slowly sways in place,
   on its own clock so they never move in unison */
.tree {
  position: absolute;
  width: 34%;
  animation: tree-sway 10s ease-in-out infinite alternate;
}
/* desynced on purpose: prime-spaced durations and offsets, with
   every other tile swinging the opposite direction, so neighbors
   never fall into step */
.tree:nth-child(even) { animation-duration: 13s; animation-delay: -5s; }
.tree:nth-child(3n)   { animation-duration: 16s; animation-delay: -9s; }
.tree:nth-child(odd)  { animation-direction: alternate-reverse; }
.tree:nth-child(5n)   { animation-duration: 11s; animation-delay: -3s; }
.tree:nth-child(7n)   { animation-duration: 19s; animation-delay: -13s; }
.tree:nth-child(4n)   { animation-name: tree-sway-lg; }
@keyframes tree-sway {
  from { transform: rotate(-4.5deg); }
  to   { transform: rotate(4.5deg); }
}
@keyframes tree-sway-lg {
  from { transform: rotate(-6.5deg); }
  to   { transform: rotate(6.5deg); }
}
/* one dense cluster: trees keep to the upper-left half, slides to
   the lower-right, meeting and overlapping along the diagonal */
.tree--1  { left: 13%; top: 2%; }
.tree--2  { left: 0;   top: 16%; }
.tree--3  { left: 37%; top: 12%; z-index: 2; }
.tree--4  { left: 5%;  top: 32%; }
.tree--5  { left: 30%; top: 30%; z-index: 2; }
.slide--1 { left: 51%; top: 36%; z-index: 3; }
.slide--2 { left: 25%; top: 48%; }
.slide--3 { left: 63%; top: 46%; z-index: 2; }
.slide--4 { left: 38%; top: 58%; }
.slide--5 { left: 57%; top: 62%; z-index: 2; }
.tree img {
  display: block;
  width: 100%;
  border: 1px solid var(--rule);
  cursor: zoom-in;
  transition: transform 0.35s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.tree:hover { z-index: 5; }
.tree img:hover { transform: scale(1.14); }


/* collage variants: same sway + lightbox, sized per set */
/* three-image cluster (Bar Corso process) */
.grid > .tree-ring--3 {
  width: clamp(320px, 52vw, 640px);
  height: clamp(260px, 40vw, 500px);
}
.tree-ring--3 .tree { width: 60%; }
.tree-ring--3 .tree:nth-child(1) { left: 18%; top: 0; }
.tree-ring--3 .tree:nth-child(2) { left: 0; top: 38%; width: 52%; }
.tree-ring--3 .tree:nth-child(3) { left: 40%; top: 34%; z-index: 2; }
/* four-image cluster: varied sizes and staggered offsets so it
   reads as a pile, not a 2x2 grid */
.grid > .tree-ring--4 {
  width: clamp(340px, 58vw, 720px);
  height: clamp(320px, 48vw, 600px);
}
.tree-ring--4 .tree:nth-child(1) { width: 56%; left: 0; top: 4%; }
.tree-ring--4 .tree:nth-child(2) { width: 44%; left: 52%; top: 12%; z-index: 2; }
.tree-ring--4 .tree:nth-child(3) { width: 46%; left: 6%; top: 54%; }
.tree-ring--4 .tree:nth-child(4) { width: 54%; left: 44%; top: 42%; z-index: 2; }

/* full deck cloud (Kodak): a wide organic oval, denser at the
   center, thinning toward the edges (sunflower spread) */
.grid > .tree-ring--deck {
  width: min(100%, 1240px);
  height: clamp(320px, 48vw, 640px);
}
.tree-ring--deck .tree { width: 17%; }
.tree-ring--deck .tree:nth-child(1) { left: 48.0%; top: 37.2%; }
.tree-ring--deck .tree:nth-child(2) { left: 31.2%; top: 46.9%; z-index: 2; }
.tree-ring--deck .tree:nth-child(3) { left: 44.7%; top: 22.3%; }
.tree-ring--deck .tree:nth-child(4) { left: 53.7%; top: 55.7%; }
.tree-ring--deck .tree:nth-child(5) { left: 18.4%; top: 36.9%; }
.tree-ring--deck .tree:nth-child(6) { left: 62.5%; top: 23.8%; z-index: 2; }
.tree-ring--deck .tree:nth-child(7) { left: 33.9%; top: 64.2%; }
.tree-ring--deck .tree:nth-child(8) { left: 28.7%; top: 13.2%; }
.tree-ring--deck .tree:nth-child(9) { left: 72.0%; top: 50.5%; }
.tree-ring--deck .tree:nth-child(10) { left: 9.7%; top: 53.3%; z-index: 2; }
.tree-ring--deck .tree:nth-child(11) { left: 55.6%; top: 6.0%; }
.tree-ring--deck .tree:nth-child(12) { left: 53.1%; top: 72.4%; }
.tree-ring--deck .tree:nth-child(13) { left: 8.1%; top: 20.2%; }
.tree-ring--deck .tree:nth-child(14) { left: 81.7%; top: 31.5%; z-index: 2; }
.tree-ring--deck .tree:nth-child(15) { left: 17.3%; top: 73.9%; }
.tree-ring--deck .tree:nth-child(16) { left: 34.1%; top: 0.0%; }
.tree-ring--deck .tree:nth-child(17) { left: 77.0%; top: 65.9%; }
.tree-ring--deck .tree:nth-child(18) { left: 0.0%; top: 40.8%; z-index: 2; }
.tree-ring--deck .tree:nth-child(19) { left: 75.6%; top: 7.7%; }
.tree-ring--deck .tree:nth-child(20) { left: 40.0%; top: 79.0%; }
.tree-ring--deck .tree:nth-child(21) { left: 6.7%; top: 0.3%; }
.tree-ring--deck .tree:nth-child(22) { left: 87.0%; top: 44.7%; z-index: 2; }
.tree-ring--deck .tree:nth-child(23) { left: 0.0%; top: 67.8%; }
.tree-ring--deck .tree:nth-child(24) { left: 52.9%; top: 0.0%; }

/* album cloud (Daily Album Cover): square tiles in a wide oval */
.grid > .tree-ring--album {
  width: min(100%, 1240px);
  height: clamp(360px, 58vw, 760px);
}
.tree-ring--album .tree { width: 15%; }
.tree-ring--album .tree:nth-child(1) { left: 48.4%; top: 34.7%; }
.tree-ring--album .tree:nth-child(2) { left: 32.9%; top: 43.7%; z-index: 2; }
.tree-ring--album .tree:nth-child(3) { left: 45.6%; top: 21.0%; }
.tree-ring--album .tree:nth-child(4) { left: 53.7%; top: 52.0%; }
.tree-ring--album .tree:nth-child(5) { left: 21.2%; top: 34.7%; }
.tree-ring--album .tree:nth-child(6) { left: 61.8%; top: 22.3%; z-index: 2; }
.tree-ring--album .tree:nth-child(7) { left: 35.5%; top: 59.8%; }
.tree-ring--album .tree:nth-child(8) { left: 30.7%; top: 12.6%; }
.tree-ring--album .tree:nth-child(9) { left: 70.7%; top: 47.2%; }
.tree-ring--album .tree:nth-child(10) { left: 13.1%; top: 49.9%; z-index: 2; }
.tree-ring--album .tree:nth-child(11) { left: 55.4%; top: 5.9%; }
.tree-ring--album .tree:nth-child(12) { left: 53.2%; top: 67.4%; }
.tree-ring--album .tree:nth-child(13) { left: 11.7%; top: 19.1%; }
.tree-ring--album .tree:nth-child(14) { left: 79.7%; top: 29.6%; z-index: 2; }
.tree-ring--album .tree:nth-child(15) { left: 20.1%; top: 68.9%; }
.tree-ring--album .tree:nth-child(16) { left: 35.5%; top: 0.0%; }
.tree-ring--album .tree:nth-child(17) { left: 75.4%; top: 61.3%; }
.tree-ring--album .tree:nth-child(18) { left: 0.0%; top: 38.2%; z-index: 2; }
.tree-ring--album .tree:nth-child(19) { left: 74.0%; top: 7.6%; }
.tree-ring--album .tree:nth-child(20) { left: 41.1%; top: 74.0%; }
.tree-ring--album .tree:nth-child(21) { left: 10.2%; top: 0.5%; }
.tree-ring--album .tree:nth-child(22) { left: 87.0%; top: 41.7%; z-index: 2; }
.tree-ring--album .tree:nth-child(23) { left: 2.9%; top: 63.1%; }
.tree-ring--album .tree:nth-child(24) { left: 53.0%; top: 0.0%; }
.tree-ring--album .tree:nth-child(25) { left: 69.3%; top: 74.0%; }
.tree-ring--album .tree:nth-child(26) { left: 0.0%; top: 19.6%; z-index: 2; }
.tree-ring--album .tree:nth-child(27) { left: 87.0%; top: 14.4%; }
.tree-ring--album .tree:nth-child(28) { left: 22.7%; top: 74.0%; }

/* ---------- UX walkthrough rows: screen on one side, copy on the
   other, alternating down the page ---------- */
.case-group > .ux-row {
  grid-column: 1 / 13;
  justify-self: center;
  width: min(100%, 1220px);
  padding: 0;
  margin-top: var(--sp-md);
  align-items: center;
}
/* standardized card behind every screenshot: soft rounded panel,
   extra side padding so tiles read as a consistent grid; the
   screenshot inside gets rounded corners of its own */
.ux-shot, .ux-popouts-main, .ux-thumb, .ux-page {
  display: block;
  background: rgba(26, 26, 26, 0.06);
  padding: 1.4rem 2.4rem;
  border-radius: 12px;
}
.ux-thumb { border-radius: 8px; }
/* every card shares the column width and defaults to a square;
   taller screens scroll inside their card, and everything still
   expands in the slideshow */
.ux-shot--tour {
  aspect-ratio: 9 / 16 !important; /* phone-height card... */
  max-height: 72vh;                /* ...but never the full viewport */
}
/* fit cards hug their screenshot: no fixed square, no inner scroll */
.ux-shot--fit { aspect-ratio: auto !important; overflow: hidden !important; }
.ux-shot, .ux-popouts-main, .ux-page {
  aspect-ratio: 1 / 1;
  cursor: zoom-in;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(26, 26, 26, 0.25) transparent;
}
.ux-shot img[hidden] { display: none !important; }
.ux-shot img, .ux-popouts-main img, .ux-thumb img, .ux-page img {
  display: block;
  width: 100% !important;
  max-width: none !important;
  border-radius: 10px;
}
.ux-row .ux-shot {
  grid-column: 1 / 7;
  width: 100% !important;
}
.ux-row .ux-copy { grid-column: 8 / 13; max-width: 44ch; font-size: var(--fs-p2); }
.ux-row--flip .ux-shot { grid-column: 7 / 13; grid-row: 1; }
.ux-row--flip .ux-copy { grid-column: 1 / 6; grid-row: 1; }
.ux-copy .label { display: block; margin-bottom: 1rem; color: var(--accent); }
.ux-copy h3 {
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: var(--fs-h3);
  line-height: 1.15;
  margin-bottom: 1rem;
}
.ux-copy p + p { margin-top: 1rem; }

/* before/after pair: tall pages cropped to a band, click to expand */
.case-group > .ux-beforeafter {
  grid-column: 1 / 13;
  justify-self: center;
  width: min(100%, 1080px);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gutter);
  margin-top: 3.5rem;
}
.ux-beforeafter figure { margin: 0; }
.ux-beforeafter figcaption { margin-top: 0.7rem; color: var(--accent); }

/* security pop-outs: the page view large, expanded states beneath */
.ux-row .ux-popouts { grid-column: 1 / 7; width: 100%; }
/* inline variant: thumbs live under the tour card and swap its content */
.ux-popouts--inline { position: relative; }
.ux-popouts--inline .ux-shot--tour { width: 100% !important; }
/* the thumbs surface only while the tour is on the security section
   (or a pop-out is open); space stays reserved so nothing reflows */
.ux-popouts--inline .ux-popout-thumbs {
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity 0.35s ease, transform 0.35s ease, visibility 0s 0.35s;
}
.ux-popouts--inline.thumbs-in .ux-popout-thumbs,
.ux-popouts--inline.popout-open .ux-popout-thumbs {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity 0.35s ease, transform 0.35s ease;
}
/* pop-out mode: the card keeps the tour's height; the expanded state
   fills it, cropped top and bottom */
.ux-shot--tour.popout-active { overflow: hidden; }
.ux-shot--tour .popout-view {
  height: 100%;
  object-fit: cover;
  object-position: center;
}
.ux-popout-thumbs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.7rem;
  margin-top: 0.7rem;
}
.ux-thumb {
  padding: 0.5rem 0.7rem;
  cursor: zoom-in;
  transition: transform 0.25s ease;
}
.ux-thumb img {
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: center 42%;
  border-radius: 6px;
}
.ux-thumb:hover { transform: scale(1.06); }

@media (max-width: 767px) {
  .ux-row .ux-shot,
  .ux-row--flip .ux-shot,
  .case-group > .ux-shot,
  .ux-row .ux-popouts { grid-column: 1 / 13; grid-row: auto; }
  .ux-row .ux-copy,
  .ux-row--flip .ux-copy { grid-column: 1 / 13; grid-row: auto; margin-top: 1.5rem; }
  .case-group > .ux-beforeafter { grid-template-columns: 1fr; }
}

/* anything lightboxable invites the zoom cursor */
[data-lightbox] img { cursor: zoom-in; }

/* fullscreen slideshow (see js/lightbox.js) */
.lb-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: rgba(20, 20, 18, 0.94);
}
.lb-overlay { grid-template-rows: 1fr auto; }
.lb-overlay:focus { outline: none; }

/* the slide strip: the current image centered, neighbors peeking */
.lb-track {
  width: 100vw;
  overflow-x: auto;
  overflow-y: hidden;
  display: flex;
  align-items: center;
  align-self: stretch;
  /* fixed-pixel peek: neighbors show a constant 48px sliver at the
     page edges (72px edge region minus the 24px gap), on any screen */
  padding: 0 72px;
  gap: 24px;
  cursor: grab;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.lb-track::-webkit-scrollbar { display: none; }
.lb-track.lb-grabbing { cursor: grabbing; }
.lb-track.lb-zoom-lock { overflow-x: hidden; }

.lb-slide {
  flex: 0 0 calc(100vw - 144px);
  height: 100%;
  display: grid;
  place-items: center;
  position: relative;
}

@media (max-width: 767px) {
  .lb-track { padding: 0 36px; gap: 14px; }
  .lb-slide { flex-basis: calc(100vw - 72px); }
}
.lb-slide img {
  cursor: zoom-in;
  transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
  touch-action: none;
  max-width: 100%;
  max-height: 76vh;
  display: block;
}
.lb-slide img.lb-zoomed { cursor: grab; }
.lb-slide img.lb-dragging { cursor: grabbing; transition: none; }
.lb-gif-freeze { position: absolute; }

/* hud: dot pill + play control, anchored just under the current image
   (top is set by the script each frame) */
.lb-hud {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: calc(100vh - 70px); /* fallback until first placement */
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.lb-dots {
  display: flex;
  align-items: center;
  height: 34px;
  padding: 0 9px;
  background: rgba(244, 241, 234, 0.14);
}
.lb-dots[hidden] { display: none; }
.lb-dot {
  /* the button is a larger invisible hit area; the visible square is
     drawn by ::after inside it, so the two can't interfere */
  box-sizing: content-box;
  width: 7px;
  height: 7px;
  padding: 13px 4px;
  border: none;
  background: none;
  position: relative;
  opacity: 0.45;
  cursor: pointer;
}
.lb-dot::after {
  content: '';
  position: absolute;
  inset: 13px 4px;
  background: var(--dot-color, var(--paper));
}
.lb-dot:focus:not(:focus-visible) { outline: none; }
.lb-play {
  width: 34px;
  height: 34px;
  border: none;
  display: grid;
  place-items: center;
  background: rgba(244, 241, 234, 0.14);
  color: var(--paper);
  cursor: pointer;
}
.lb-play[hidden] { display: none; }
.lb-play svg { width: 15px; height: 15px; display: block; }
.lb-play:hover, .lb-dot:hover { opacity: 1; }

.lb-close {
  position: absolute;
  top: 1rem;
  right: 1.4rem;
  background: none;
  border: none;
  color: var(--paper);
  font-family: var(--grotesk);
  font-size: 2rem;
  padding: 1rem;
  cursor: pointer;
  opacity: 0.75;
}
.lb-close:hover { opacity: 1; color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .tree { animation: none; }
  .tree img:hover { transform: none; }
}

/* ---------- Process trio: three columns side by side — number and
   title over the carded screen, copy below it ---------- */
.process { align-items: stretch; }
.grid > .process-col { display: flex; flex-direction: column; }
.process-col .label { color: var(--accent); }
.process-title {
  font-family: var(--grotesk);
  font-weight: 700;
  font-size: var(--fs-h3);
  margin: 0.6rem 0 1.2rem;
}
.process-note {
  font-size: var(--fs-p2);
  line-height: 1.55;
  max-width: 34ch;
}
/* the card holds screen, badge, and copy; cards stretch to one
   shared height across the row */
.process-stage {
  position: relative;
  width: 100%;
  flex: 1;
  display: flex;
  flex-direction: column;
  background: rgba(26, 26, 26, 0.06);
  padding: 1.4rem 1.6rem;
}
.process-stage .process-mock {
  width: 72%;
  max-width: none;
  display: block;
  margin-inline: auto;
  border-radius: 10px;
}
.process-stage .process-note { margin-top: 1.5rem; }
.process-anim {
  position: absolute;
  right: -0.9rem;
  bottom: -0.9rem;
  width: clamp(72px, 7vw, 104px);
  aspect-ratio: 1 / 1;
  border: 1px solid var(--rule);
  background: var(--paper);
}
.process-anim i { position: absolute; display: block; }

/* 01 capture: viewfinder — corner brackets, a drifting focus point,
   and a soft shutter blink */
.process-anim--capture .corner { width: 12px; height: 12px; }
.process-anim--capture .c1 { top: 16%; left: 16%; border-top: 1px solid var(--ink); border-left: 1px solid var(--ink); }
.process-anim--capture .c2 { top: 16%; right: 16%; border-top: 1px solid var(--ink); border-right: 1px solid var(--ink); }
.process-anim--capture .c3 { bottom: 16%; left: 16%; border-bottom: 1px solid var(--ink); border-left: 1px solid var(--ink); }
.process-anim--capture .c4 { bottom: 16%; right: 16%; border-bottom: 1px solid var(--ink); border-right: 1px solid var(--ink); }
.process-anim--capture .focus {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  top: 42%; left: 40%;
  animation: k-focus 11s ease-in-out infinite;
}
.process-anim--capture .flash {
  inset: 16%;
  background: var(--ink);
  opacity: 0;
  animation: k-flash 11s linear infinite;
}
@keyframes k-focus {
  0%, 18%   { transform: translate(0, 0); }
  28%, 48%  { transform: translate(26px, -16px); }
  58%, 82%  { transform: translate(-12px, 22px); }
  100%      { transform: translate(0, 0); }
}
@keyframes k-flash {
  0%, 49%, 52%, 100% { opacity: 0; }
  50.5%              { opacity: 0.07; }
}

/* capture burst: random constellation revealed by the shutter flash,
   built by js/kodak-anim.js, quick in and slow fade out */
.process-anim--capture .burst {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.9s ease;
}
.process-anim--capture .burst.on {
  opacity: 1;
  transition: opacity 0.1s ease;
}
.process-anim--capture .burst line { stroke: var(--ink); stroke-width: 0.35; opacity: 0.5; }
.process-anim--capture .burst circle { fill: var(--accent); }

/* 02 analyze: recognition graph — nodes light up in turn while the
   inputs it reads cycle below */
.process-anim--analyze svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.process-anim--analyze line { stroke: var(--rule); stroke-width: 0.5; }
.process-anim--analyze circle {
  fill: var(--paper);
  stroke: var(--ink);
  stroke-width: 0.75;
}
/* four nodes light on the same 3s beat as the four words below;
   the fifth stays passive structure */
.process-anim--analyze .n1,
.process-anim--analyze .n2,
.process-anim--analyze .n3,
.process-anim--analyze .n4 { animation: k-node 12s linear infinite; }
.process-anim--analyze .n2 { animation-delay: 3s; }
.process-anim--analyze .n3 { animation-delay: 6s; }
.process-anim--analyze .n4 { animation-delay: 9s; }
@keyframes k-node {
  0%, 4%    { fill: var(--paper); stroke: var(--ink); }
  7%, 20%   { fill: var(--accent); stroke: var(--accent); }
  25%, 100% { fill: var(--paper); stroke: var(--ink); }
}
/* connections draw out from the lit node, then fade */
.process-anim--analyze .e {
  stroke: var(--accent);
  stroke-width: 0.75;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  opacity: 0;
  animation: k-edge 12s linear infinite;
}
.process-anim--analyze .e2 { animation-delay: 3s; }
.process-anim--analyze .e3 { animation-delay: 6s; }
.process-anim--analyze .e4 { animation-delay: 9s; }
@keyframes k-edge {
  0%, 6%      { stroke-dashoffset: 1; opacity: 1; }
  12%, 19%    { stroke-dashoffset: 0; opacity: 1; }
  24%         { stroke-dashoffset: 0; opacity: 0; }
  24.1%, 100% { stroke-dashoffset: 1; opacity: 0; }
}
.process-anim--analyze .tags {
  position: absolute; left: 10%; bottom: 9%;
  font-family: var(--grotesk);
  /* sized to fit the small docked card */
  font-size: 0.5rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.1em;
}
.process-anim--analyze .tags span {
  position: absolute; left: 0; bottom: 0;
  white-space: nowrap; opacity: 0;
  animation: k-tag 12s linear infinite;
}
.process-anim--analyze .tags span:nth-child(2) { animation-delay: 3s; }
.process-anim--analyze .tags span:nth-child(3) { animation-delay: 6s; }
.process-anim--analyze .tags span:nth-child(4) { animation-delay: 9s; }
@keyframes k-tag {
  0%, 4%    { opacity: 0; }
  7%, 20%   { opacity: 1; }
  25%, 100% { opacity: 0; }
}

/* 03 refine: loose layers settle into a composed stack */
.process-anim--refine .layer {
  width: 46%; height: 34%;
  top: 50%; left: 50%;
  border: 1px solid var(--ink);
}
/* One shared 14s timeline. While the cards sit apart, the yellow hops
   between them a few times and settles on the top card at full
   separation; then all three converge into a single card, hold,
   and drift apart again to repeat. */
.process-anim--refine .l1 { animation: k-refine1 14s ease-in-out infinite; }
.process-anim--refine .l2 { animation: k-refine2 14s ease-in-out infinite; }
.process-anim--refine .l3 { animation: k-refine3 14s ease-in-out infinite; }
/* soft grey flash the moment the cards become one — sized and
   positioned to match the merged card exactly, not the whole panel */
.process-anim--refine .flash {
  top: 50%;
  left: 50%;
  width: 46%;
  height: 34%;
  transform: translate(-50%, -50%);
  background: var(--ink);
  opacity: 0;
  animation: k-ref-flash 14s linear infinite;
}
@keyframes k-ref-flash {
  0%, 69.5%, 72%, 100% { opacity: 0; }
  70.5%                { opacity: 0.07; }
}

@keyframes k-refine1 {
  /* motion: one card slowly comes apart (0-55), converges (55-70),
     holds as one (70-100). The convergence gets its own easing:
     gentle out of the gate, quick through the middle, soft landing. */
  0%        { transform: translate(-50%, -50%) rotate(0deg); }
  55%       { transform: translate(-72%, -84%) rotate(-2deg);
              animation-timing-function: cubic-bezier(0.75, 0, 0.25, 1); }
  70%, 100% { transform: translate(-50%, -50%) rotate(0deg); }
  /* color: first look, mid-drift */
  0%, 12%   { border-color: var(--ink); }
  14%, 22%  { border-color: var(--accent); }
  25%, 100% { border-color: var(--ink); }
}
@keyframes k-refine2 {
  0%        { transform: translate(-50%, -50%) rotate(0deg); }
  55%       { transform: translate(-40%, -42%) rotate(1.5deg);
              animation-timing-function: cubic-bezier(0.75, 0, 0.25, 1); }
  70%, 100% { transform: translate(-50%, -50%) rotate(0deg); }
  /* color: second look */
  0%, 26%   { border-color: var(--ink); }
  28%, 36%  { border-color: var(--accent); }
  39%, 100% { border-color: var(--ink); }
}
@keyframes k-refine3 {
  0%        { transform: translate(-50%, -50%) rotate(0deg); }
  55%       { transform: translate(-26%, -12%) rotate(3deg);
              animation-timing-function: cubic-bezier(0.75, 0, 0.25, 1); }
  70%, 100% { transform: translate(-50%, -50%) rotate(0deg); }
  /* color: the choice — lands while still drifting apart, holds
     through max separation and the merge, then relaxes */
  0%, 41%   { border-color: var(--ink); }
  44%, 76%  { border-color: var(--accent); }
  84%, 100% { border-color: var(--ink); }
}

@media (prefers-reduced-motion: reduce) {
  .process-anim i,
  .process-anim circle,
  .process-anim .tags span { animation: none !important; }
  .process-anim--analyze .tags span:first-child { opacity: 1; }
  .process-anim--refine .l3 { border-color: var(--accent); } /* static choice */
}

/* prev / next */
/* after a dark band, the color change already divides — no rule,
   and the links tuck up close to the band */
.section-dark + .case-pagination { border-top: none; margin-top: 1.5rem; }
.case-pagination {
  margin-top: var(--sp-lg);
  padding-top: 1.4rem;
  padding-bottom: 1.4rem;
  border-top: 1px solid var(--ink);
  font-family: var(--grotesk);
  font-weight: 700;
}
.case-pagination .prev { grid-column: 1 / 7; }
.case-pagination .next { grid-column: 7 / 13; text-align: right; }
.case-pagination a:hover { color: var(--accent); }
/* second row: return to the archive index, beneath prev/next */
.case-pagination .back-archive {
  grid-column: 1 / 13;
  margin-top: 1.4rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
}

@media (max-width: 767px) {
  /* tighter rhythm on small screens */
  :root { --sp-md: 2rem; --sp-lg: 4rem; }
  /* title and lede stack again on small screens */
  .case-title { grid-column: 1 / 13; }
  .case-lede { grid-column: 1 / 13; grid-row: 3; margin-top: 2rem; }
  .case-meta--under { grid-row: 4; }
  .case-media > *,
  .case-group img,
  .case-group video { grid-column: 1 / 13 !important; margin-top: 1.5rem; }
  /* phones get the full column width back */
  .case-media img, .case-media video,
  .case-group img, .case-group video,
  .grid > .embed-wrap, .grid > .bleed, .about-video { width: 100%; }
  /* collage stagger flattens on phones: images stack in one column,
     so the desktop drop/raise offsets would read as uneven gaps —
     every image keeps the same 1.5rem rhythm instead */
  .grid > .drop-1, .grid > .drop-2, .grid > .drop-3,
  .grid > .raise-1 { margin-top: 1.5rem; }
  /* asymmetric-art nudges also reset once everything is centered */
  .grid > img.optical-right { transform: none; }
  .case-group .case-body { grid-column: 1 / 13; margin-top: 1rem; margin-bottom: 0.5rem; }
  .case-group--row .row-title { grid-column: 1 / 13; margin-bottom: 1rem; }
  .case-group .note--a, .case-group .note--b { grid-column: 1 / 13; }
  .grid > .process-col { grid-column: 1 / 13; margin-bottom: 2.5rem; }
  .process-anim { right: -0.6rem; bottom: -0.6rem; }
  .grid > .rule-cols { grid-template-columns: 1fr; }
  .rule-cols > div { border-left: none; padding: 0.9rem 1rem 1.1rem; border-top: 1px solid var(--ink); }
  .rule-cols > div:first-child { border-top: none; }
  .rule-cols > div > h3:first-child,
  .rule-cols > div > .label:first-child { margin: -0.9rem -1rem 1rem; padding: 0.7rem 1rem; }
  /* SWOT stays a boxed 2x2 even on phones */
  .grid > .rule-cols--4 { grid-template-columns: repeat(2, 1fr); }
  .grid > .rule-cols--4 > div { border-top: none; padding: 0.9rem 1rem 1.1rem; }
  .grid > .rule-cols--4 > div:nth-child(even) { border-left: 1px solid var(--ink); }
  .grid > .rule-cols--4 > div:nth-child(n+3) { border-top: 1px solid var(--ink); }
  .statement .ind-1, .statement .ind-2 { margin-left: 0; }
  .case-word, .case-word--right { grid-column: 1 / 13; text-align: left; }
  .grid > .sheet { grid-column: span 6; }
  .grid > .sheet--sm { grid-column: span 4; }
  .case-quote { grid-column: 1 / 13; }
  .case-caption { grid-column: 1 / 13; }
}

/* ---------- Mobile home page: work rows as rolodex bands ----------
   Each row doubles in height and centers the project image beside
   its number; title and meta sit below the image. The band nearest
   the viewport's center holds the open card — its image flips up
   flat while the neighboring band folds shut (see js/row-band.js). */
@media (max-width: 767px) {
  .work-row--band {
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: 1rem;
    row-gap: 0;
    min-height: 2.75rem;
    /* no top/right padding: the image runs flush to the divider above
       and to the screen's right edge */
    padding: 0 0 0.6rem var(--margin);
    text-align: left;
  }
  .work-row--band .arrow { display: none; }
  /* the wrapper dissolves so number and image place on the band grid */
  .work-row--band .band-row { display: contents; }
  .work-row--band .num {
    grid-column: 1;
    grid-row: 1;
    align-self: start;
    font-size: 1.6rem;
    line-height: 1;
    padding-top: 0.6rem;
  }
  .work-row--band .band-media {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
    display: block;
    width: 0; /* collapsed: text gets the full band width */
    perspective: 700px;
    transition: width 0.55s cubic-bezier(0.25, 0.8, 0.25, 1);
  }
  .work-row--band.band-active .band-media { width: min(58vw, 300px); }
  /* name and subhead below the image, flush left with the number */
  .work-row--band .title {
    grid-column: 1 / -1;
    grid-row: 3;
    font-size: 1.5rem;
    margin-top: 0.5rem;
  }
  .work-row--band .meta { grid-column: 1 / -1; grid-row: 4; }
  .work-row--band .band-media img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    max-height: 0;
    opacity: 0;
    transform-origin: 50% 100%;
    transform: rotateX(-84deg);
    transition:
      max-height 0.55s cubic-bezier(0.25, 0.8, 0.25, 1),
      transform 0.55s cubic-bezier(0.25, 0.8, 0.25, 1),
      opacity 0.3s ease;
  }
  .work-row--band.band-active .band-media img {
    max-height: 46vw;
    opacity: 1;
    transform: rotateX(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .work-row--band .band-media img { transition: none; }
}
/* desktop safety net: if a band was built at a small window size,
   the image stays hidden and the row falls back to the plain layout */
@media (min-width: 768px) {
  .work-row--band .band-media { display: none; }
  .work-row--band .band-row { display: contents; }
}

/* ---------- Touch devices: scroll replaces hover ---------- */
@media (hover: none) {
  /* media blooms to color as it scrolls through the viewport */
  .hero-photo.in-color,
  .about-portrait.in-color,
  .about-video.in-color { filter: grayscale(0); }

  /* work rows carry a small inline thumbnail instead of the
     cursor-following preview (band rows manage their own layout) */
  .work-row:not(.work-row--band) { padding-right: 104px; }
  .work-row .arrow { display: none; }
  .row-thumb {
    position: absolute;
    right: var(--margin);
    top: 50%;
    width: 72px;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    opacity: 0;
    transform: translateY(-50%) translateX(14px);
    transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
  }
  .thumb-in .row-thumb {
    opacity: 1;
    transform: translateY(-50%) translateX(0);
  }
}

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

/* ---------- Scroll reveal: quick fade + settle (see js/reveal.js) ---------- */
.rv {
  opacity: 0;
  transform: translateY(16px);
}
.rv-in {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 0.45s cubic-bezier(0.22, 0.9, 0.3, 1),
    transform 0.45s cubic-bezier(0.22, 0.9, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .rv { opacity: 1; transform: none; }
  .rv-in { transition: none; }
}

/* ---------- Dark sections: warm dark grey with a whisper of grain ---------- */
.section-dark {
  position: relative;
  background-color: #292825;
  color: var(--paper);
}
/* film grain baked into the page and band backgrounds only — it sits
   behind all content and images, monochrome, with its opacity baked
   into the tile; still flickers like TV static */
body, .section-dark, .ikea-needs {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.45' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.16'/%3E%3C/svg%3E");
  animation: grain-static 0.9s steps(1) infinite;
}
/* dark bands show grain more, so theirs is a touch finer */
.section-dark {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.16'/%3E%3C/svg%3E");
}
@keyframes grain-static {
  0%   { background-position: 0 0; }
  12%  { background-position: -46px 29px; }
  25%  { background-position: 33px -71px; }
  37%  { background-position: -58px -40px; }
  50%  { background-position: 71px 22px; }
  62%  { background-position: -24px 63px; }
  75%  { background-position: 49px -18px; }
  87%  { background-position: -67px -55px; }
  100% { background-position: 0 0; }
}
@media (prefers-reduced-motion: reduce) {
  body, .section-dark, .ikea-needs { animation: none; }
}

/* dark-section overrides: light type, light hairlines */
.section-dark .index-head {
  color: rgba(244, 241, 234, 0.45);
  border-bottom-color: rgba(244, 241, 234, 0.7);
}
.section-dark .work-row { border-bottom-color: rgba(244, 241, 234, 0.25); }
.section-dark .work-row .meta { color: rgba(244, 241, 234, 0.6); }
.section-dark .archive-link { border-bottom-color: var(--paper); }
.section-dark .archive-link:hover { color: var(--accent); border-bottom-color: var(--accent); }
.section-dark.v2-footer { border-top-color: rgba(244, 241, 234, 0.35); }
/* dark footer text: specific enough to beat the light-footer rules,
   and light enough to pass AA on the dark ground */
.section-dark.v2-footer .foot-col .label { color: rgba(244, 241, 234, 0.72); }
.section-dark.v2-footer .copy { color: rgba(244, 241, 234, 0.8); }

/* spotlight: a dark band with even air around its media */
.spotlight {
  padding-top: 5rem;
  padding-bottom: 5rem;
}

/* dark case sections: light rules and muted light text throughout */
.section-dark.case-group,
.section-dark.case-media { padding-bottom: var(--sp-lg); }
/* when a dark band follows light content, the paper gets a breath of
   margin and the divider line drops — the background change already
   marks the break */
.case-v2 > :not(.section-dark) + .section-dark { margin-top: var(--sp-lg); }
.case-v2 > :not(.section-dark) + .section-dark.case-group::before { display: none; }
/* and the mirror: light content following a dark band drops its rule
   and tightens up — the color change already divides */
.case-v2 > .section-dark + .case-group:not(.section-dark)::before { display: none; }
.case-v2 > .section-dark + .case-group:not(.section-dark) { padding-top: var(--sp-md); }
.section-dark.case-group::before { background: rgba(244, 241, 234, 0.6); }

.section-dark .spec { border-color: rgba(244, 241, 234, 0.6); }
.section-dark .spec-row { border-bottom-color: rgba(244, 241, 234, 0.25); }
.section-dark .spec-row .v { border-left-color: rgba(244, 241, 234, 0.25); }
.section-dark .rule-cols { border-color: rgba(244, 241, 234, 0.6); }
.section-dark .rule-cols > div { border-color: rgba(244, 241, 234, 0.25); }
.section-dark .rule-cols > div > h3:first-child,
.section-dark .rule-cols > div > .label:first-child { border-bottom-color: rgba(244, 241, 234, 0.6); }
.section-dark .process-stage { background: rgba(244, 241, 234, 0.08); }
.section-dark .sheet { border-color: rgba(244, 241, 234, 0.25); }
.section-dark .case-caption { color: rgba(244, 241, 234, 0.55); }
.section-dark .case-body p,
.section-dark .process-note { color: rgba(244, 241, 234, 0.85); }

/* ---------- Footer: labeled metadata columns ---------- */
.v2-footer {
  border-top: 1px solid var(--ink);
  padding-top: 2.2rem;
  padding-bottom: 3rem;
  font-size: 0.85rem;
  align-items: start;
  row-gap: 2rem;
}
.v2-footer .foot-col { display: flex; flex-direction: column; gap: 0.35rem; }
.v2-footer .foot-col .label { color: rgba(26, 26, 26, 0.45); margin-bottom: 0.35rem; }
.v2-footer .foot-col:nth-of-type(1) { grid-column: 1 / 4; }
.v2-footer .foot-col:nth-of-type(2) { grid-column: 4 / 7; }
.v2-footer .foot-col:nth-of-type(3) { grid-column: 7 / 10; }
.v2-footer .copy {
  grid-column: 10 / 13;
  text-align: right;
  color: rgba(26, 26, 26, 0.55);
}
.v2-footer a:hover { color: var(--accent); }

/* Halftone canvas (shared with v1 effect) */
#halftone-canvas {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
}

/* ---------- Mobile ---------- */
@media (max-width: 767px) {
  .v2-header .wordmark { grid-column: 1 / 13; }
  .v2-header nav { grid-column: 1 / 13; justify-content: flex-start; margin-top: 0.8rem; }
  .v2-header .header-clock { display: none; }
  /* nth-of-type selectors so these beat the desktop column rules,
     which otherwise win on specificity and cram three columns
     side by side on a phone */
  .v2-footer .foot-col:nth-of-type(1),
  .v2-footer .foot-col:nth-of-type(2),
  .v2-footer .foot-col:nth-of-type(3),
  .v2-footer .copy { grid-column: 1 / 13; text-align: left; }
  .about-v2 .about-layout .statement { grid-column: 1 / 13; grid-row: auto; }
  .about-layout .about-label:first-of-type,
  .about-layout .about-text { grid-column: 1 / 13; grid-row: auto; }
  .about-layout .about-label:first-of-type { margin-top: 3rem; }

  /* small screens: a collage band above the copy and one below it,
     each with generous air, so images never crowd the text */
  .hero { min-height: 0; padding-top: 52vw; padding-bottom: 116vw; }
  .hero-manifesto { grid-column: 1 / 13; }
  .display-word { font-size: 34vw; bottom: -0.22em; }

  /* above the copy: mural with the specimen overlapping below-right */
  .hero-photo--back     { top: 2vw;  bottom: auto; left: 26vw; width: 41vw; }
  .hero-photo--specimen { top: 12vw; bottom: auto; left: 50vw; width: 44vw; }
  /* below the copy: laptop left, house overlapping its top-right
     corner, the album tucked bottom right */
  .hero-photo--front    { top: auto; bottom: 34vw; left: 10vw; width: 36vw; }
  .hero-photo--house    { top: auto; bottom: 77vw; left: 35vw; width: 28vw; }
  .hero-photo--album    { top: auto; bottom: 38vw; left: 64vw; width: 26vw; }
  /* five images on small screens; the walking illustration sits out */
  .hero-photo--people { display: none; }

  /* about page stacks into one column */
  .about-layout > * { grid-column: 1 / 13; }
  
  /* reorder: statement, background label+text, then overlapping portrait+video */
  .about-v2 .about-layout .statement { order: 1; }
  .about-layout .about-label:first-of-type { order: 2; margin-top: 3rem; }
  .about-layout .about-text { order: 3; }
  .about-portrait { 
    grid-column: 1 / 10; 
    grid-row: auto; 
    order: 4;
    margin-top: 3rem;
    margin-bottom: 0;
    width: 85%;
    max-width: 420px;
  }
  .about-video { 
    grid-column: 6 / 13; 
    grid-row: auto; 
    order: 5;
    width: 80%;
    max-width: 360px;
    margin-top: -28%;
    margin-left: auto;
  }
  .about-contact-block { order: 6; }
  .about-label { margin-top: 3rem; }

  /* case + about pages: the display word grows to 34vw on mobile, so
     the room reserved for its cropped top must grow with it
     (visible portion ≈ 0.78 × 34vw ≈ 27vw) */
  .case-v2 { padding-bottom: 28vw; }
  .about-v2 { padding-bottom: 28vw; }

  .work-row:not(.work-row--band) .title { grid-column: 2 / 13; }
  .work-row:not(.work-row--band) .meta { grid-column: 2 / 12; margin-top: 0.5rem; }
  .work-row .arrow { position: absolute; right: var(--margin); top: 2.2rem; }
  .archive-strip .archive-link { grid-column: 1 / 13; justify-self: start; margin-top: 1rem; }
  .v2-footer .copy { grid-column: 1 / 13; }
  .v2-footer .social { grid-column: 1 / 13; justify-content: flex-start; margin-top: 0.8rem; }
}

/* ---------- Amazon Key Marquee Animation ---------- */
@font-face {
  font-family: 'Ember Modern';
  src: url('../assets/Fonts/WOFF/EmberModernDisplayStd-Bold.woff2') format('woff2'),
       url('../assets/Fonts/EmberModernDisplayStd-Bold.ttf') format('truetype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* rounded corners on the hero image only */
.page-ak .ak-hero-img {
  border-radius: 12px;
}

/* campaign collage: staggered like the other case collages — the
   marquee is the dominant plane, the two campaign photos are the small
   counterweights (portrait tucked top-right, banner raised into the
   marquee's leftover space below-left) */
.ak-collage {
  /* the marquee reads as a second hero, so it gets full section air
     from the hero illustration above */
  padding-top: var(--sp-lg);
  padding-bottom: var(--sp-md);
}

.ak-collage img {
  border-radius: 12px;
}

/* closing illustration strip: generous air on both sides so it reads
   as the page's quiet sign-off */
.ak-endcap {
  padding-top: var(--sp-lg);
  padding-bottom: calc(var(--sp-lg) + 2rem);
}

/* sized to match the page's largest photos, not the full wide field */
.ak-endcap img {
  width: 68%;
}

/* the portrait poster shares the page's rounded panel language and
   spans two rows so the marquee sits beside its lower half */
.page-ak .ak-poster {
  border-radius: 12px;
  grid-row: span 2;
}

/* the hero fills its indented field so the walking-people card can
   tuck over its lower-right corner */
.page-ak .ak-hero-img {
  width: 100%;
  max-width: none;
}

/* transparent illustration cutouts sit on an off-white card so they
   carry the same panel weight as the photography around them */
.ak-collage .ak-illo {
  background: #faf8f3;
  padding: 2rem 2.2rem;
}

.ak-marquee-section {
  background: #0d1017;
  overflow: hidden;
  /* rounded corners to match the page's hero image */
  border-radius: 12px;
  /* dominant element of the group: full field width, breaking the 80%
     media scale the subordinate pieces follow */
  width: 100%;
  aspect-ratio: 1500 / 620;
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  padding: 0.5cqw 0;
  container-type: inline-size;
}

.ak-marquee-line {
  white-space: nowrap;
  overflow: hidden;
  font-family: 'Ember Modern', var(--grotesk);
  /* five rows fill the 1500x620 frame edge to edge like the reference;
     line-height 1 leaves room for descenders inside the clipped line box */
  font-size: 7.9cqw;
  font-weight: 700;
  font-kerning: normal;
  line-height: 1;
  letter-spacing: -0.015em;
}

.ak-marquee-content {
  display: inline-block;
  /* hold until the display font is ready: the loop's geometry depends
     on Ember Modern's metrics, so starting in the fallback font and
     swapping mid-cycle makes the strip jump */
  animation-play-state: paused;
  /* collapse inter-span whitespace so the strip is exactly three copy
     widths — the mid-hold copy shifts depend on it to be invisible */
  font-size: 0;
  /* three pulses per cycle; motion keeps the measured GIF speeds while
     each stop holds about a second longer than the reference */
  animation-duration: 12.4s;
  animation-iteration-count: infinite;
  /* stagger: irregular per-row phase offsets so rows stop and start at
     clearly different moments, loosely cascading downward. Kept under
     ~half the hold so there's still a moment where all rows sit still.
     Delays are offset by -12.4s (one cycle) so rows start mid-motion. */
  animation-delay: calc(var(--row-delay, 0s) - 12.4s);
}

.ak-fonts-in .ak-marquee-content {
  animation-play-state: running;
}

.ak-marquee-line:nth-child(1) .ak-marquee-content { --row-delay: 0s; }
.ak-marquee-line:nth-child(2) .ak-marquee-content { --row-delay: 0.14s; }
.ak-marquee-line:nth-child(3) .ak-marquee-content { --row-delay: 0.25s; }
.ak-marquee-line:nth-child(4) .ak-marquee-content { --row-delay: 0.48s; }
.ak-marquee-line:nth-child(5) .ak-marquee-content { --row-delay: 0.38s; }
.ak-marquee-line:nth-child(6) .ak-marquee-content { --row-delay: 0.55s; }

.ak-marquee-content span {
  display: inline-block;
  font-size: 7.9cqw;
  padding-right: 0.24em;
}

/* Colors alternate phrase by phrase within each line */
.ak-marquee-content .mq-b { color: #1e7fe8; }
.ak-marquee-content .mq-w { color: #fff; }

/* Left to right pulse */
.ak-marquee-line--ltr .ak-marquee-content {
  animation-name: ak-pulse-ltr;
}

/* Right to left pulse */
.ak-marquee-line--rtl .ak-marquee-content {
  animation-name: ak-pulse-rtl;
}

/* Pulsed marquee matching the reference: rest, snap to peak speed,
   decay back to rest — measured frame by frame from the GIF at a 3.12s
   cadence. Three pulses per cycle, each traveling at least one full
   copy width, like the single-pulse version. Layout still varies at
   every stop: each strip is THREE identical copies, and during two of
   the holds the strip is shifted by an exact copy multiple via steps(1)
   — the layout is identical before and after, so the shift is invisible
   but it re-centers the strip and desyncs where each stop lands. The
   cycle ends exactly two copy widths from where it began, so the wrap
   at peak speed is seamless, and travel depth stays well inside the
   strip so rows never run out of text. */
@keyframes ak-pulse-rtl {
  0% {
    /* seam: entering at peak speed, tapering to rest */
    transform: translateX(0%);
    animation-timing-function: cubic-bezier(0.12, 0.63, 0.35, 1);
  }
  7.5%, 24% {
    transform: translateX(-16.2%);
    animation-timing-function: cubic-bezier(0.55, 0, 0.3, 1);
  }
  40.8% {
    /* rest; invisible +1 copy shift mid-hold */
    transform: translateX(-57.2%);
    animation-timing-function: steps(1);
  }
  48%, 57.3% {
    transform: translateX(-23.8667%);
    animation-timing-function: cubic-bezier(0.55, 0, 0.3, 1);
  }
  74.1% {
    /* rest; invisible +1 copy shift mid-hold */
    transform: translateX(-67.8667%);
    animation-timing-function: steps(1);
  }
  82%, 90.6% {
    transform: translateX(-34.5334%);
    animation-timing-function: cubic-bezier(0.5, 0, 0.8, 0.34);
  }
  100% {
    /* back at peak speed as the loop wraps (exactly 2 copies deep) */
    transform: translateX(-66.6667%);
  }
}

/* mirror of the rtl profile so rightward rows also stay within
   -67.87% depth — deeper excursions can outrun the narrower strips */
@keyframes ak-pulse-ltr {
  0% {
    transform: translateX(-66.6667%);
    animation-timing-function: cubic-bezier(0.2, 0.66, 0.5, 1);
  }
  9.4%, 17% {
    /* rest; invisible -1 copy shift mid-hold */
    transform: translateX(-34.5334%);
    animation-timing-function: steps(1);
  }
  22%, 25.9% {
    transform: translateX(-67.8667%);
    animation-timing-function: cubic-bezier(0.55, 0, 0.3, 1);
  }
  42.7%, 50% {
    /* rest; invisible -1 copy shift mid-hold */
    transform: translateX(-23.8667%);
    animation-timing-function: steps(1);
  }
  55%, 59.2% {
    transform: translateX(-57.2%);
    animation-timing-function: cubic-bezier(0.55, 0, 0.3, 1);
  }
  76%, 92.5% {
    transform: translateX(-16.2%);
    animation-timing-function: cubic-bezier(0.65, 0, 0.88, 0.37);
  }
  100% {
    transform: translateX(0%);
  }
}

/* mobile: the marquee takes the full column like every other case
   image, so it reads larger with standard image margins */
@media (max-width: 767px) {
  /* the marquee takes the full column like every other case image */
  .ak-marquee-section { width: 100%; }
  /* stacked layout: no row spans or corner overlaps */
  .page-ak .ak-poster { grid-row: auto; }
}
