/* =========================================================================
   ARC INDEX — Global Design System
   A cultural intelligence practice. Confident silence.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Inter+Tight:wght@300;400;500&display=swap');

/* -------------------------------------------------------------------------
   0. Reset
   ------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body, h1, h2, h3, h4, p, ul, ol, li, figure, figcaption, blockquote, dl, dd {
  margin: 0; padding: 0;
}
html { -webkit-text-size-adjust: 100%; }
body { min-height: 100vh; }
ul, ol { list-style: none; }
a { color: inherit; text-decoration: none; }
button, input, textarea { font: inherit; color: inherit; background: none; border: none; }
img, video { max-width: 100%; display: block; }
button { cursor: pointer; }

/* -------------------------------------------------------------------------
   1. Design Tokens
   ------------------------------------------------------------------------- */
:root {
  /* color */
  --bg: #080808;
  --fg: #F0ECE4;
  --fg-dim: rgba(255, 255, 255, 0.56);
  --fg-faint: rgba(255, 255, 255, 0.28);
  --fg-faint-2: rgba(255, 255, 255, 0.14);
  --surface: #101010;
  --surface-hover: #161616;
  --line: rgba(255, 255, 255, 0.12);
  --line-strong: rgba(255, 255, 255, 0.2);
  /* Blueprint sheets — fixed paper/ink, intentionally not theme-linked */
  --bp-paper: #F6F5F0;
  --bp-ink: #12110E;
  --bp-ink-dim: rgba(18, 17, 14, 0.62);
  --bp-ink-faint: rgba(18, 17, 14, 0.28);

  /* type */
  --font-sans: 'Inter', 'General Sans', -apple-system, sans-serif;
  --font-display: 'Inter Tight', 'Inter', sans-serif;
  --font-mono: 'SF Mono', 'JetBrains Mono', ui-monospace, monospace;

  --text-display: clamp(2.5rem, 6vw, 5.5rem);
  --text-h1: clamp(2rem, 4vw, 3.25rem);
  --text-section: clamp(1.25rem, 2vw, 1.75rem);
  --text-body-lg: clamp(1rem, 1.4vw, 1.25rem);
  --text-body: 1rem;
  --text-small: 0.875rem;
  --text-meta: 0.8125rem;
  --text-micro: 0.6875rem;

  /* motion */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 250ms;
  --dur-base: 400ms;
  --dur-slow: 600ms;

  /* layout */
  --sidebar-w: 28vw;
  --sidebar-min: 400px;
  --pad: 2rem;
  --pad-lg: 3rem;
  --radius: 14px;
  --radius-sm: 8px;
  /* was the height reserved for the bottom dated-index dock strip, now
     removed — kept at 0 rather than deleting the variable outright,
     since .sidebar/.main/.stage below still reference it in calc() */
  --dock-h: 0px;

  --z-overlay: 100;
  --z-sidebar: 10;
}

@media (max-width: 1023px) {
  :root { --sidebar-min: 320px; --pad: 1.5rem; --pad-lg: 2rem; }
}

/* Light mode — off-white, not pure white; near-black text, not pure black.
   Same restraint principle as dark mode (§2), mirrored. */
html[data-theme="light"] {
  --bg: #FAF9F6;
  --fg: #0A0A0A;
  --fg-dim: rgba(10, 10, 10, 0.62);
  --fg-faint: rgba(10, 10, 10, 0.30);
  --fg-faint-2: rgba(10, 10, 10, 0.16);
  --surface: #EFEEEA;
  --surface-hover: #E2E0D9;
  --line: rgba(10, 10, 10, 0.12);
  --line-strong: rgba(10, 10, 10, 0.22);
}

/* -------------------------------------------------------------------------
   2. Base
   ------------------------------------------------------------------------- */
html {
  background: var(--bg);
  color-scheme: dark;
  transition: background-color var(--dur-slow) var(--ease);
  scrollbar-width: none;
}
html[data-theme="light"] { color-scheme: light; }

/* No page scrollbar anywhere on the site — scroll still works (wheel,
   trackpad, keyboard, PageUp/Down), it just never reserves or paints a
   gutter/thumb. Applies to the root scroller; .sidebar__projects and
   .strip__track already hide their own scrollbars entirely too. */
html::-webkit-scrollbar { display: none; width: 0; height: 0; }
body {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--text-body);
  line-height: 1.5;
  background: var(--bg);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  position: relative;
  transition: background-color var(--dur-slow) var(--ease), color var(--dur-slow) var(--ease);
}

/* subtle print-matter grain — texture, not decoration */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 300; letter-spacing: -0.02em; }
p { max-width: 60ch; }

.tnum { font-variant-numeric: tabular-nums; }

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

a:focus-visible, button:focus-visible, input:focus-visible, [tabindex]:focus-visible {
  outline: 1px solid var(--fg);
  outline-offset: 3px;
}

body.overlay-open { overflow: hidden; }

/* text link primitive — underline/arrow, never a pill */
.link {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  color: var(--fg-dim);
  border-bottom: 1px solid var(--line-strong);
  padding-bottom: 2px;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.link:hover, .link:focus-visible { color: var(--fg); border-color: var(--fg); }
.link__arrow { display: inline-block; transition: transform var(--dur-fast) var(--ease); }
.link:hover .link__arrow, .link:focus-visible .link__arrow { transform: translateX(4px); }

.eyebrow {
  font-size: var(--text-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--fg-dim);
}

.meta {
  font-size: var(--text-meta);
  color: var(--fg-dim);
  letter-spacing: 0.02em;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* -------------------------------------------------------------------------
   3. App Shell
   ------------------------------------------------------------------------- */
.shell {
  display: flex;
  min-height: 100vh;
  min-height: 100dvh;
}

/* -------------------------------------------------------------------------
   4. Sidebar
   ------------------------------------------------------------------------- */
.sidebar {
  position: fixed;
  top: 0; left: 0; bottom: var(--dock-h);
  width: var(--sidebar-w);
  min-width: var(--sidebar-min);
  max-width: 560px;
  height: calc(100vh - var(--dock-h));
  height: calc(100dvh - var(--dock-h));
  display: flex;
  flex-direction: column;
  padding: var(--pad);
  z-index: var(--z-sidebar);
  border-right: 1px solid var(--line);
  background: var(--bg);
}

.sidebar__utility {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

.sidebar__show-all {
  font-size: var(--text-meta);
  letter-spacing: 0.02em;
  color: var(--fg-dim);
  transition: color var(--dur-fast) var(--ease);
}
.sidebar__show-all:hover, .sidebar__show-all:focus-visible { color: var(--fg); }

.toggle {
  position: relative;
  width: 40px;
  height: 22px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: transparent;
  flex-shrink: 0;
}
.toggle__knob {
  position: absolute;
  top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--fg-dim);
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.toggle[aria-pressed="true"] .toggle__knob {
  transform: translateX(18px);
  background: var(--fg);
}
.toggle[aria-pressed="true"] { border-color: var(--fg-dim); }

.sidebar__wordmark {
  flex-shrink: 0;
  margin-top: clamp(2rem, 4vh, 3rem);
  margin-bottom: clamp(1.5rem, 3vh, 2.25rem);
}
.sidebar__wordmark img {
  width: min(100%, 200px);
  height: auto;
  margin: 0 auto;
  transition: filter var(--dur-slow) var(--ease);
}
html[data-theme="light"] .sidebar__wordmark img { filter: brightness(0); }
.sidebar__wordmark-text {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.5rem;
  letter-spacing: 0.08em;
}

.sidebar__meta {
  flex-shrink: 0;
  font-size: var(--text-meta);
  color: var(--fg-dim);
  letter-spacing: 0.02em;
  line-height: 1.6;
  margin-bottom: clamp(1.5rem, 3vh, 2.25rem);
  text-align: center;
}
.sidebar__meta strong { color: var(--fg-dim); font-weight: 400; }
.sidebar__clock { color: var(--fg-dim); transition: opacity 300ms var(--ease); }

.about-card {
  flex-shrink: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem 1.375rem;
  margin-bottom: 1.75rem;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
  text-align: left;
  width: 100%;
  display: block;
}
.about-card:hover, .about-card:focus-visible { background: var(--surface-hover); border-color: var(--line-strong); }
.about-card__label {
  font-size: var(--text-meta);
  color: var(--fg);
  margin-bottom: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.4em;
}
.about-card__label .link__arrow { transition: transform var(--dur-fast) var(--ease); }
.about-card:hover .about-card__label .link__arrow { transform: translateX(4px); }
.about-card__text {
  font-size: var(--text-small);
  color: var(--fg-dim);
  line-height: 1.5;
}

/* Fills the rest of the sidebar's height instead of a fixed 210px box —
   all featured projects show at once, no internal scroll/fade-mask
   hinting at hidden entries below. overflow-y:auto stays only as a
   fallback for a genuinely short viewport, not the normal case. */
.sidebar__projects {
  flex: 1 1 auto;
  overflow-y: auto;
  margin: 0 -0.75rem;
  padding: 0 0.75rem;
  scrollbar-width: none;
}
.sidebar__projects::-webkit-scrollbar { display: none; width: 0; height: 0; }

.project-card {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  padding: 0.875rem;
  border-radius: var(--radius-sm);
  transform: scale(1);
  transition: background var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
  cursor: pointer;
}
.project-card:hover, .project-card:focus-visible, .project-card.is-active {
  background: var(--surface-hover);
  transform: scale(1.015);
}
.project-card__thumb {
  flex-shrink: 0;
  width: 44px; height: 44px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  overflow: hidden;
  color: var(--bg);
  line-height: 1.1;
  text-align: center;
}
.project-card__thumb--img img { width: 100%; height: 100%; object-fit: cover; object-position: 58% 46%; display: block; }
/* MELT + Agora's hero is a centered mark lockup, not an off-center photo — the
   shared 58%/46% crop above was tuned for the other case studies' imagery. */
.project-card[data-slug="melt-agora-records"] .project-card__thumb--img img { object-position: center; }
.project-card__body { min-width: 0; }
.project-card__name {
  font-size: var(--text-small);
  font-weight: 500;
  color: var(--fg);
  margin-bottom: 0.15rem;
  display: flex;
  align-items: center;
  gap: 0.5em;
}
/* shared small tag/label — hairline border, modest radius, never a pill
   (pill/stadium shape is reserved for commerce actions, see .pill-btn) */
.tag, .project-card__concept {
  font-family: 'SF Mono', 'JetBrains Mono', ui-monospace, monospace;
  font-size: var(--text-micro);
  color: var(--fg-dim);
  border: 1px solid var(--line-strong);
  border-radius: 3px;
  padding: 1px 5px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  flex-shrink: 0;
}
.project-card__desc {
  font-size: var(--text-micro);
  color: var(--fg-dim);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* -------------------------------------------------------------------------
   5. Main / Visual Stage / Dated Strip
   ------------------------------------------------------------------------- */
.main {
  margin-left: var(--sidebar-w);
  width: calc(100% - var(--sidebar-w));
  min-width: calc(100% - 560px);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  padding-bottom: var(--dock-h);
  position: relative;
}
@media (min-width: 1024px) {
  .main { margin-left: max(var(--sidebar-w), var(--sidebar-min)); width: auto; flex: 1 1 auto; }
}

.stage {
  position: relative;
  flex: 1 1 auto;
  /* floor, not a target — flex-grow still fills exactly (100vh - strip)
     when nothing follows the strip, same as the original one-viewport
     layout; the floor only kicks in once journal-feed content pushes the
     page taller, so stage never collapses toward 0 */
  min-height: calc(100vh - var(--dock-h));
  min-height: calc(100dvh - var(--dock-h));
  overflow: hidden;
  background: var(--surface);
}

.stage__layer {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  cursor: pointer;
  /* Stacked layers have no z-index, so without this, later siblings in
     DOM order paint (and hit-test) above earlier ones regardless of
     which is actually visible — opacity:0 hides a layer but doesn't
     stop it from intercepting clicks meant for the one underneath it.
     Only the active layer should ever be clickable. */
  pointer-events: none;
}
.stage__layer.is-active { opacity: 1; pointer-events: auto; }
.stage__field {
  position: absolute;
  inset: -6%;
  animation: kenburns 32s ease-in-out infinite alternate;
}
.stage__field.is-static-safe { animation: none; }

.stage__heroimg { position: absolute; inset: 0; }
.stage__heroimg img,
.stage__heroimg video { width: 100%; height: 100%; object-fit: cover; display: block; }
.stage__layer--hero-img .stage__index { display: none; }
.stage__layer--hero-img .stage__caption { display: none; }
/* The kitchen island shot's subject sits in the lower two-thirds of the
   frame — a center crop on a tall stage panel cuts too far into the
   island itself, so bias the crop down toward it. */
.stage__layer[data-slug="temma-court"] .stage__heroimg img { object-position: center 68%; }

.stage__caption {
  position: absolute;
  right: clamp(1.5rem, 4vw, 4rem);
  bottom: clamp(1.5rem, 4vw, 4rem);
  left: clamp(1.5rem, 4vw, 4rem);
  z-index: 2;
}

.stage__wordmark {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(1.75rem, 4vw, 3.5rem);
  letter-spacing: -0.02em;
  line-height: 1.02;
  color: var(--bg);
  mix-blend-mode: normal;
}

.stage__index {
  position: absolute;
  top: clamp(-2rem, -3vw, -1rem);
  right: clamp(-1rem, -2vw, 0.5rem);
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(8rem, 22vw, 18rem);
  line-height: 1;
  color: var(--bg);
  opacity: 0.18;
  letter-spacing: -0.03em;
  z-index: 1;
  pointer-events: none;
  font-variant-numeric: tabular-nums;
}

.stage__diagram { position: absolute; inset: 0; z-index: 1; opacity: 0.5; pointer-events: none; }

.stage__empty {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--fg-dim);
  font-size: var(--text-meta);
}

.stage__hint {
  margin-top: 0.6rem;
  font-size: var(--text-meta);
  color: var(--bg);
  opacity: 0.6;
}

/* scroll cue — bare double-chevron, no scrim/shadow/card chrome at all.
   Centered at the bottom of the hero (the standard placement for this
   pattern — bottom-right is conventionally reserved for back-to-top/chat
   affordances, not "keep scrolling" cues). The two chevrons glow via an
   opacity pulse, staggered so it reads as a downward flow — no position
   movement/bounce, which was rejected in an earlier pass. */
.stage__scroll-cue {
  position: absolute;
  left: 50%; bottom: 0;
  transform: translateX(-50%);
  z-index: 3;
  display: flex; align-items: center; justify-content: center;
  width: 56px; height: 56px;
  background: none;
  border: none; padding: 0; margin: 0;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.94);
  transition: opacity var(--dur-slow) var(--ease), color var(--dur-slow) var(--ease);
}
.stage__scroll-cue.is-hidden { opacity: 0; pointer-events: none; }
/* flipped automatically when the active hero's bottom-center patch
   (sampled live via canvas in app.js) is bright enough that white
   chevrons would wash out against it */
.stage__scroll-cue.is-light { color: rgba(10, 10, 10, 0.82); }
.stage__scroll-chevron { opacity: 0.32; animation: stage-scroll-glow 1.8s ease-in-out infinite; }
.stage__scroll-chevron--2 { animation-delay: 0.3s; }
@keyframes stage-scroll-glow {
  0%, 100% { opacity: 0.32; }
  45% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .stage__scroll-chevron { animation: none; opacity: 0.85; }
}

@keyframes kenburns {
  from { transform: scale(1); }
  to { transform: scale(1.06); }
}

/* homepage journal feed — "The Feed": saturated color-block cards, the
   closest of the three proposals to the Porto Rocha reference. Colors
   rotate by position rather than tracking the kind taxonomy — this is a
   deliberate, stated exception to the site's monochrome restraint,
   scoped to this one section. */
/* border-top gives the strip→feed handoff a deliberate seam instead of
   dead air — matters most mid-scroll, when the strip is pinned and this
   is the first thing visible sliding in underneath it */
.journal-feed { padding: 1.5rem var(--pad-lg) clamp(5rem, 10vw, 7rem); border-top: 1px solid var(--line); }
.journal-feed__head { margin-bottom: 1.5rem; }

/* Homepage mirror of the Temma Court case study — same .tc-excerpt /
   .tc-gallery-section rules as temma-court.html apply unchanged; this
   just gives the mirror the same top seam the journal feed has, since
   the two are never visible at the same time. */
.stage-temma-mirror { border-top: 1px solid var(--line); }
.stage-temma-mirror .tc-excerpt { padding-top: clamp(3rem, 7vw, 5rem); }

.jf-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.85rem; }
.jf-card {
  border-radius: var(--radius-sm); overflow: hidden; position: relative;
  display: flex; flex-direction: column; justify-content: space-between;
  min-height: 220px; padding: 1.1rem;
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease);
}
.jf-card:hover, .jf-card:focus-visible { transform: translateY(-3px); }
.jf-card--wide { grid-column: span 2; }
.jf-card--tall { grid-row: span 2; min-height: 460px; }

.jf-kind { font-family: var(--font-mono); font-size: var(--text-micro); letter-spacing: 0.05em; opacity: 0.75; }
.jf-title { font-family: var(--font-display); font-weight: 500; font-size: clamp(1.05rem, 1.7vw, 1.4rem); line-height: 1.15; margin-top: auto; text-wrap: balance; }
.jf-date { font-family: var(--font-mono); font-size: var(--text-micro); margin-top: 0.6rem; opacity: 0.72; }

.jf-card--c1 { background: #C13E63; color: #FFF3EC; }
.jf-card--c2 { background: #16110F; color: #F0ECE4; border: 1px solid var(--line); }
.jf-card--c3 { background: #1C5E56; color: #EAFBF6; }
.jf-card--c4 { background: #D97A2E; color: #201200; }
.jf-card--c5 { background: #F0ECE4; color: #0A0A0A; }
.jf-card--c6 { background: #2C3E9E; color: #E9ECFF; }

@media (max-width: 1023px) {
  .jf-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .journal-feed { padding: 1.25rem 1.5rem 4rem; }
  .jf-grid { grid-template-columns: 1fr; }
  .jf-card--wide, .jf-card--tall { grid-column: span 1; grid-row: span 1; min-height: 220px; }
}

/* -------------------------------------------------------------------------
   6. Overlays (Index / About) — full-screen channel swap
   ------------------------------------------------------------------------- */
.overlay {
  position: fixed;
  inset: 0;
  left: 0;
  z-index: var(--z-overlay);
  background: var(--bg);
  opacity: 0;
  transform: scale(0.985);
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
  display: flex;
  flex-direction: column;
}
.overlay.is-open {
  opacity: 1;
  transform: scale(1);
  pointer-events: auto;
}
/* About overlay keeps the sidebar instrument panel visible beside it —
   the Index overlay is truly full-bleed and replaces the sidebar's column. */
@media (min-width: 768px) {
  .overlay--pane { left: max(var(--sidebar-w), var(--sidebar-min)); }
}

/* About panel content — each top-level section fades up into place in a
   quiet top-to-bottom cascade on open, instead of appearing all at once.
   Delay lives on the section itself (not gated behind .is-open) so the
   cascade replays correctly every time the panel reopens. */
.about__section {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 480ms var(--ease), transform 480ms var(--ease);
}
.overlay--pane.is-open .about__section { opacity: 1; transform: translateY(0); }
.about__section:nth-of-type(1) { transition-delay: 90ms; }
.about__section:nth-of-type(2) { transition-delay: 180ms; }
.about__section:nth-of-type(3) { transition-delay: 270ms; }
.about__section:nth-of-type(4) { transition-delay: 360ms; }

@media (prefers-reduced-motion: reduce) {
  .about__section {
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    transform: none !important;
  }
}

/* Leaflet gives its own panes/controls z-index values well above 100
   (up to 1000+), so a homepage mirror's map — a sibling of .overlay, not
   a descendant — bleeds straight through any open overlay regardless of
   --z-overlay. Hiding it outright while an overlay is open is simpler
   and more robust than chasing Leaflet's internal stacking. */
body.overlay-open .tc-map-section { visibility: hidden; }

.overlay__search {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--line);
  padding: 0 var(--pad-lg);
  height: 56px;
}
.overlay__search-cursor { color: var(--fg-faint); margin-right: 0.6rem; font-weight: 300; }
.overlay__search-input {
  flex: 1;
  height: 100%;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  color: var(--fg);
  letter-spacing: -0.01em;
  outline: none;
}
.overlay__search-input:focus, .overlay__search-input:focus-visible { outline: none; }
.overlay__search-input::placeholder { color: var(--fg-faint); }
.overlay__search-submit {
  display: flex; align-items: center; justify-content: center;
  height: 100%;
  color: var(--fg-dim);
  font-size: 1.2rem;
  padding: 0.5rem;
  transition: transform var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.overlay__search-submit:hover { color: var(--fg); transform: translateX(3px); }
.overlay__close {
  display: flex; align-items: center; justify-content: center;
  height: 100%;
  color: var(--fg-dim);
  font-size: 1.4rem;
  font-weight: 300;
  padding: 0.5rem 0 0.5rem 1.5rem;
  margin-left: 1rem;
  border-left: 1px solid var(--line);
  transition: color var(--dur-fast) var(--ease);
}
.overlay__close:hover, .overlay__close:focus-visible { color: var(--fg); }

.overlay__body {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

.overlay__filters {
  flex-shrink: 0;
  width: 220px;
  padding: 1.9rem var(--pad) var(--pad-lg) calc(var(--pad) + 1rem);
  overflow-y: auto;
  border-right: 1px solid var(--line);
}
.overlay__filter-item {
  position: relative;
  display: flex;
  align-items: baseline;
  width: 100%;
  text-align: left;
  font-size: var(--text-small);
  color: var(--fg-dim);
  padding: 0.6rem 0.25rem;
  margin-left: -0.75rem;
  padding-left: 0.75rem;
  border-radius: var(--radius-sm);
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.overlay__filter-item::before {
  content: '';
  position: absolute;
  left: -1rem; top: 50%;
  width: 2px; height: 0;
  background: var(--fg);
  transform: translateY(-50%);
  transition: height var(--dur-fast) var(--ease);
}
.overlay__filter-item:hover, .overlay__filter-item:focus-visible { color: var(--fg); background: var(--surface); }
.overlay__filter-item.is-active { color: var(--fg); font-weight: 500; }
.overlay__filter-item.is-active::before { height: 16px; }
.overlay__filter-label { flex: 1 1 auto; min-width: 0; }

.overlay__grid-wrap { flex: 1 1 auto; overflow-y: auto; }

.grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 23vw;
  grid-auto-flow: dense;
  gap: 2rem;
  padding: var(--pad-lg);
  padding-top: 2.5rem;
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  opacity: 1;
  transform: scale(1);
  transition: opacity var(--dur-base) var(--ease), transform var(--dur-base) var(--ease);
}
.tile.is-hidden { opacity: 0; transform: scale(0.96); pointer-events: none; position: absolute; visibility: hidden; }

/* Full Index entrance — same top-to-bottom fade-up cascade as the About
   panel, but strictly one-shot: gated behind :not(.is-entered), which
   app.js adds to #overlay-index once the cascade finishes and removes
   again on close. Without this gate, every later search/category
   filter click would replay the same translateY delay on newly-shown
   tiles — a distracting "bump" instead of the plain, instant fade
   .tile.is-hidden already handles below. */
#overlay-index:not(.is-entered) .tile:not(.is-hidden) { opacity: 0; transform: translateY(14px); }
#overlay-index.is-open:not(.is-entered) .tile:not(.is-hidden) { opacity: 1; transform: translateY(0); }
#overlay-index:not(.is-entered) .tile:nth-child(1) { transition-delay: 60ms; }
#overlay-index:not(.is-entered) .tile:nth-child(2) { transition-delay: 115ms; }
#overlay-index:not(.is-entered) .tile:nth-child(3) { transition-delay: 170ms; }
#overlay-index:not(.is-entered) .tile:nth-child(4) { transition-delay: 225ms; }
#overlay-index:not(.is-entered) .tile:nth-child(5) { transition-delay: 280ms; }
#overlay-index:not(.is-entered) .tile:nth-child(6) { transition-delay: 335ms; }

@media (prefers-reduced-motion: reduce) {
  #overlay-index:not(.is-entered) .tile {
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    transform: none !important;
  }
}
.tile--sq { grid-column: span 2; grid-row: span 1; }
.tile--tall { grid-column: span 2; grid-row: span 2; }
.tile--wide { grid-column: span 4; grid-row: span 1; }

.tile__media {
  position: relative;
  flex: 1 1 auto;
  border-radius: var(--radius-sm);
  overflow: hidden;
  transition: filter var(--dur-fast) var(--ease);
}
.tile:hover .tile__media, .tile:focus-visible .tile__media { filter: brightness(1.08); }
.tile__media--blueprint { background: var(--bp-paper); }
.tile__media--blueprint svg { width: 100%; height: 100%; display: block; }
.tile__media--blueprint img { width: 100%; height: 100%; display: block; object-fit: cover; }
.tile__media--photo img { width: 100%; height: 100%; display: block; object-fit: cover; }
/* Temma Court's wide tile uses the same kitchen island shot as the
   homepage hero, but the tile's box is much shorter and wider than the
   hero frame — the hero's own 68% bias crops too far down here, cutting
   off the sculptural bowl sitting on the island. A lighter bias keeps
   the whole bowl in frame. */
.tile[data-slug="temma-court"] .tile__media--photo img { object-position: center 48%; }

.tile__index {
  position: absolute;
  bottom: -0.4rem; right: -0.2rem;
  font-family: var(--font-display);
  font-size: clamp(3rem, 8vw, 6rem);
  color: var(--bg);
  opacity: 0.2;
  font-weight: 300;
  z-index: 1;
}
.tile__wordmark {
  position: absolute; left: 1rem; bottom: 1rem; right: 1rem;
  z-index: 2;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(0.95rem, 1.6vw, 1.4rem);
  color: var(--bg);
  line-height: 1.05;
}
.tile__foot {
  padding-top: 1rem;
  flex-shrink: 0;
}
.tile__title { font-size: var(--text-small); color: var(--fg); font-weight: 500; display: flex; align-items: center; gap: 0.5em; }
.tile__desc { font-size: var(--text-micro); color: var(--fg-dim); margin-top: 0.35rem; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

.grid__empty {
  padding: 4rem var(--pad-lg);
  color: var(--fg-dim);
  font-size: var(--text-small);
  grid-column: 1 / -1;
}

/* -------------------------------------------------------------------------
   7. About
   ------------------------------------------------------------------------- */
.about {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
  overflow: hidden;
}
.about__center {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0 0 6rem;
}

.about__hero {
  height: 46vh;
  min-height: 320px;
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.about__hero-field { position: absolute; inset: 0; }
.about__hero-caption {
  position: absolute; left: var(--pad-lg); bottom: 1.5rem;
  font-size: var(--text-meta); color: var(--bg); opacity: 0.7;
}

.about__section {
  padding: 3.5rem var(--pad-lg) 0;
  max-width: 1100px;
}
.about__label { font-size: var(--text-meta); color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 1.25rem; }

.about__statement { max-width: 68ch; }
.about__statement p { font-size: var(--text-body-lg); line-height: 1.55; color: var(--fg); margin-bottom: 1.1rem; }
.about__statement p:last-child { margin-bottom: 0; }

/* Horizontal row, spanning the same width as the founder card below it —
   two columns (General Inquiries / Social) separated by a hairline,
   framed top+bottom as one unit. Columns size to their own content
   rather than stretching to fill the row, so the pair reads as a
   compact, deliberate pairing instead of two overstretched halves. */
.contact-pairs--row {
  display: flex; flex-wrap: nowrap;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  margin-top: 2.5rem; padding: 1.75rem 0;
}
.contact-pairs--row .contact-pairs__item { flex: 0 1 auto; min-width: 0; padding: 0 2rem; }
.contact-pairs--row .contact-pairs__item:first-child { padding-left: 0; }
.contact-pairs--row .contact-pairs__item:last-child { padding-right: 0; }
.contact-pairs--row .contact-pairs__item + .contact-pairs__item { border-left: 1px solid var(--line); }
.contact-pairs__label { display: block; font-size: var(--text-meta); color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 0.4rem; }
.contact-pairs__value { font-size: var(--text-small); color: var(--fg); overflow-wrap: anywhere; }
.contact-pairs__value-row { display: flex; align-items: center; gap: 0.5rem; }
.contact-pairs__icon { width: 20px; height: 20px; flex-shrink: 0; color: var(--fg-dim); }

.team-grid { display: grid; grid-template-columns: 1fr; }
.team-card { display: flex; gap: 2rem; flex-wrap: wrap; align-items: flex-start; }
.team-card__portrait {
  width: 140px; height: 140px; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--line);
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 2.5rem; color: var(--fg-faint); font-weight: 300;
  overflow: hidden;
}
.team-card__portrait img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; display: block; }
.team-card__body { flex: 1 1 300px; }
.team-card__name { font-family: var(--font-display); font-size: var(--text-section); font-weight: 400; margin-bottom: 4px; }
.team-card__role { font-size: var(--text-meta); color: var(--fg); margin-bottom: 10px; letter-spacing: 0.02em; }
.team-card__bio { font-size: var(--text-small); color: var(--fg-dim); line-height: 1.6; max-width: none; margin-bottom: 1rem; }
.team-card__bio:last-child { margin-bottom: 0; }

.team-card__bio-toggle {
  display: inline-flex; align-items: center; gap: 0.4em;
  font: inherit; font-size: var(--text-small); color: var(--fg-dim);
  background: none; border: none; border-bottom: 1px solid var(--line-strong);
  padding: 0 0 2px; cursor: pointer; margin-bottom: 10px;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.team-card__bio-toggle:hover, .team-card__bio-toggle:focus-visible { color: var(--fg); border-color: var(--fg); }
.team-card__bio-toggle .link__arrow { display: inline-block; transition: transform var(--dur-fast) var(--ease); }
.team-card__bio-toggle:hover .link__arrow, .team-card__bio-toggle:focus-visible .link__arrow { transform: translateX(4px); }

.team-card__bio-full { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--dur-base) var(--ease); }
.team-card__bio-full.is-expanded { grid-template-rows: 1fr; }
.team-card__bio-full-inner { overflow: hidden; min-height: 0; opacity: 0; transition: opacity var(--dur-fast) var(--ease); }
.team-card__bio-full.is-expanded .team-card__bio-full-inner { opacity: 1; transition-delay: 100ms; }
.team-card__bio-full-inner > .team-card__bio:first-child { margin-top: 0; }
.team-card__tagline {
  font-style: italic; font-size: var(--text-small); color: var(--fg-dim);
  letter-spacing: 0.04em; margin-bottom: 1rem;
}
.team-card__portfolio-link { margin-top: 0; }
#team-bio-full.is-expanded ~ .team-card__portfolio-link { margin-top: 1rem; }

.offerings__tabs { display: flex; flex-wrap: wrap; gap: 0 1.75rem; margin-bottom: 1.5rem; }
.offerings__tab {
  font-family: inherit; font-size: var(--text-small); color: var(--fg-dim); background: none; border: none;
  padding: 0.4rem 0; position: relative; cursor: pointer; transition: color var(--dur-fast) var(--ease);
}
.offerings__tab:hover, .offerings__tab:focus-visible { color: var(--fg); }
.offerings__tab.is-primary { color: var(--fg); }
.offerings__tab.is-primary::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--fg);
}
.about__section p.body-copy { font-size: var(--text-body); color: var(--fg-dim); line-height: 1.6; max-width: 68ch; }
.offerings__detail {
  border: 1px solid var(--line); border-radius: var(--radius); padding: 1.75rem 2rem;
}
.offerings__detail #offerings-detail-label { display: block; margin-bottom: 0.75rem; }
.offerings__detail p.body-copy { max-width: none; margin: 0; }

.world-clock { margin-top: 2rem; }
.world-clock__row {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 0.85rem 0; border-top: 1px solid var(--line);
}
.world-clock__row:last-child { border-bottom: 1px solid var(--line); }
.world-clock__city, .world-clock__time { font-size: var(--text-meta); color: var(--fg-dim); font-weight: 400; letter-spacing: 0.02em; }

.client-filter { display: flex; flex-wrap: wrap; gap: 0 1.5rem; margin-bottom: 1.5rem; border-bottom: 1px solid var(--line); padding-bottom: 1.25rem; }
.client-filter button { font-size: var(--text-small); color: var(--fg-dim); padding: 0.3rem 0; }
.client-filter button.is-active { color: var(--fg); }
.client-index { columns: 2; column-gap: 3rem; }
@media (max-width: 767px) { .client-index { columns: 1; } }
.client-index li { break-inside: avoid; padding: 0.55rem 0; font-size: var(--text-small); color: var(--fg); border-top: 1px solid var(--line); }

.event-item { padding: 1rem 0; border-top: 1px solid var(--line); }
.event-item:last-child { border-bottom: 1px solid var(--line); }
.event-item__title { font-size: var(--text-small); color: var(--fg); margin-bottom: 0.3rem; }
.event-item__meta { font-size: var(--text-micro); color: var(--fg-dim); }

.merch-card { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.merch-card__img { height: 160px; position: relative; }
.merch-card__body { padding: 1.1rem 1.25rem; }
.merch-card__name { font-size: var(--text-small); font-weight: 500; margin-bottom: 0.2rem; }
.merch-card__price { font-size: var(--text-meta); color: var(--fg-dim); margin-bottom: 1rem; }
.pill-btn {
  display: inline-block;
  background: var(--fg);
  color: var(--bg);
  font-size: var(--text-meta);
  font-weight: 500;
  padding: 0.6rem 1.25rem;
  border-radius: 999px;
  transition: opacity var(--dur-fast) var(--ease);
}
.pill-btn:hover, .pill-btn:focus-visible { opacity: 0.82; }

/* -------------------------------------------------------------------------
   8. Standalone pages (project / dispatch / journal / contact) shell
   ------------------------------------------------------------------------- */
.page {
  min-height: 100vh;
  min-height: 100dvh;
}
.page__nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.5rem var(--pad-lg);
  opacity: 0.6;
}
.page__nav-back { font-size: var(--text-meta); color: #FFFFFF; display: flex; align-items: center; gap: 0.5em; transition: color var(--dur-slow) var(--ease); }
.page__nav-back .link__arrow { display: inline-block; transform: rotate(180deg); transition: transform var(--dur-fast) var(--ease); }
.page__nav-back:hover .link__arrow { transform: rotate(180deg) translateX(4px); }
.page__nav-word { width: 120px; height: auto; display: block; transition: filter var(--dur-slow) var(--ease); }
html[data-theme="light"] .page__nav-back { color: #0A0A0A; }
html[data-theme="light"] .page__nav-word { filter: brightness(0); }

/* On light-background inserts within an otherwise-dark page (e.g. the
   Temma Court map, a warm-paper document treatment) the fixed nav needs
   to flip dark too, or white-on-white becomes illegible. Toggled by
   scroll position — see initNavAdaptiveColor in util.js. */
.page__nav.is-on-light .page__nav-back { color: #0A0A0A; }
.page__nav.is-on-light .page__nav-word { filter: brightness(0); }

/* Mirror case for light-mode theme: the page background is light so the
   nav defaults dark (above), but the photo/video hero at the top of every
   case study is still visually dark media — same adaptive check, opposite
   direction, overriding the light-theme default back to white while the
   nav overlaps that hero. */
html[data-theme="light"] .page__nav.is-on-dark .page__nav-back { color: #FFFFFF; }
html[data-theme="light"] .page__nav.is-on-dark .page__nav-word { filter: none; }

/* Photography & Videography archive — same tc-excerpt → view-toggle →
   masonry grid structure as every case study page, not a page-specific
   layout. #page-root just adds clearance for the fixed nav, since this
   page (unlike the case studies) has no hero image above the excerpt. */
.ph-empty { font-size: var(--text-small); color: var(--fg-dim); padding: 3rem var(--pad-lg) 4rem; border-top: 1px solid var(--line); max-width: 52ch; margin: 0 auto; }

/* Hero rapid-cycle — same .tc-video__frame box (16:9, max-height 88vh)
   every case study opens on, but instead of one fixed image/video, two
   stacked layers crossfade through every photo in the archive on a
   timer (see initHeroCycle in photography.js). */
.ph-hero-section { display: flex; justify-content: center; padding: clamp(3.5rem, 8vw, 5.5rem) var(--pad-lg) 0; }
.ph-hero-section + .tc-excerpt { padding-top: clamp(3rem, 6vw, 4.5rem); padding-bottom: clamp(2.25rem, 5vw, 3.75rem); }
.ph-hero {
  position: relative;
  width: 100%; max-width: 520px;
  aspect-ratio: 3 / 4; max-height: 76vh;
  background: var(--bg);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
/* object-fit: contain, not cover — the archive mixes portrait and
   landscape shots, and cropping every one to fill a fixed 3:4 box was
   cutting into the actual subject. Letterboxing onto the frame's own
   --bg instead keeps every photo shown whole. */
.ph-hero__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: contain;
  opacity: 0;
  transition: opacity 35ms linear;
}
.ph-hero__img.is-active { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .ph-hero__img { transition: none; }
}

.story-frame--video { cursor: pointer; }
.story-frame__video { width: 100%; height: auto; display: block; border-radius: var(--radius-sm); background: #000; }
.story-frame__play {
  position: absolute; inset: 0; z-index: 1; margin: auto; width: 52px; height: 52px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(240,236,228,0.5); border-radius: 50%;
  background: rgba(10,10,10,0.35); color: #f0ece4;
  cursor: pointer; transition: background 0.15s ease, border-color 0.15s ease;
}
.story-frame__play svg { transform: translateX(1px); }
.story-frame--video:hover .story-frame__play { background: rgba(10,10,10,0.55); border-color: rgba(240,236,228,0.85); }
html[data-theme="light"] .story-frame__play { border-color: rgba(10,10,10,0.35); background: rgba(240,236,228,0.55); color: #0a0a0a; }
html[data-theme="light"] .story-frame--video:hover .story-frame__play { background: rgba(240,236,228,0.8); border-color: rgba(10,10,10,0.6); }

/* project hero */
.p-hero {
  position: relative;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
}
.p-hero__field { position: absolute; inset: 0; }
.p-hero__index { display: none; }
.p-hero__content { position: relative; z-index: 2; padding: 0 var(--pad-lg) 4rem; width: 100%; }
.p-hero__category { font-size: var(--text-meta); color: var(--bg); opacity: 0.7; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 1rem; display: flex; gap: 0.75rem; align-items: center; }
.p-hero__title { font-family: var(--font-display); font-weight: 300; font-size: clamp(2.5rem, 7vw, 6.5rem); line-height: 0.98; letter-spacing: -0.02em; color: var(--bg); max-width: 16ch; }
.p-hero__scroll { display: none; }

.p-body {
  max-width: 1400px;
  margin: 0 auto;
  padding: clamp(4rem, 8vw, 8rem) var(--pad-lg);
}
.p-brief {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3rem;
  padding-bottom: clamp(4rem, 8vw, 7rem);
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(4rem, 8vw, 7rem);
}
@media (max-width: 900px) { .p-brief { grid-template-columns: 1fr; gap: 2.5rem; } }
.p-brief__block .eyebrow { margin-bottom: 1rem; display: block; }
.p-brief__block p { font-size: var(--text-body); color: var(--fg-dim); line-height: 1.6; }

.p-media { margin-top: clamp(3rem, 6vw, 5rem); margin-bottom: clamp(3rem, 6vw, 5rem); }
.p-media:first-child { margin-top: 0; }
.p-media__frame { position: relative; border-radius: var(--radius-sm); overflow: hidden; }
.cs-video { width: 100%; height: 100%; object-fit: cover; display: block; background: #000; }
.p-media--full .p-media__frame { aspect-ratio: 16/9; }
.p-media--pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.p-media--pair .p-media__frame { aspect-ratio: 4/5; }
@media (max-width: 767px) { .p-media--pair { grid-template-columns: 1fr; } }
.p-media__caption { margin-top: 0.75rem; font-size: var(--text-meta); color: var(--fg-dim); }

.p-diagram { position: absolute; inset: 0; opacity: 0.6; pointer-events: none; }

.p-credits {
  border-top: 1px solid var(--line);
  padding-top: clamp(2.5rem, 5vw, 4rem);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 2rem;
}
.p-credits__item .eyebrow { display: block; margin-bottom: 0.5rem; }
.p-credits__item div { font-size: var(--text-small); color: var(--fg); }

.p-nextprev {
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.p-nextprev a {
  padding: 2.5rem var(--pad-lg);
  display: block;
  transition: background var(--dur-fast) var(--ease);
}
.p-nextprev a:hover { background: var(--surface); }
.p-nextprev a:first-child { border-right: 1px solid var(--line); }
.p-nextprev .eyebrow { margin-bottom: 0.6rem; display: block; }
.p-nextprev__title { font-family: var(--font-display); font-size: clamp(1.25rem, 2.5vw, 1.75rem); font-weight: 300; }

/* reveal */
.reveal { opacity: 0; transform: translateY(20px); transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease); }
.reveal.is-visible { opacity: 1; transform: translateY(0); }
/* Gallery cells fade in without the slide-up — in a masonry grid, cells
   in different columns cross the reveal threshold at slightly different
   scroll moments, so the translateY here made neighboring images look
   momentarily out of alignment with each other mid-scroll. The grid's
   own positions are unaffected; only the transition motion changes. */
.tc-gallery-cell.reveal { transform: none; }

/* -------------------------------------------------------------------------
   Rich case study template (.cs-) — reusable layout for flagship projects.
   Sits on the same dark canvas + token system as the rest of the site;
   diagrams/technical drawings are shown in light "exhibit" frames since
   they're authored on white, rather than forcing a dark-mode filter.
   ------------------------------------------------------------------------- */
.cs-hero {
  display: flex; flex-direction: column; align-items: center;
  position: relative;
  padding: clamp(4rem, 9vh, 6rem) var(--pad-lg) clamp(1.5rem, 3vh, 2.5rem);
  text-align: center;
}
.cs-hero__text {
  width: 100%;
  display: flex; flex-direction: column; align-items: center;
  margin-top: clamp(3rem, 5.25vw, 5.5rem);
}
.cs-hero__index { display: none; }
.cs-hero__art {
  position: relative; z-index: 1;
  width: 100%; max-width: min(820px, 86vw);
  border-radius: var(--radius-sm);
  overflow: hidden;
  box-shadow: 0 50px 100px -30px rgba(0, 0, 0, 0.65);
}
.cs-hero__art img { width: 100%; display: block; }
.cs-hero__title {
  position: relative; z-index: 1;
  font-family: var(--font-display); font-weight: 300;
  font-size: clamp(1.65rem, 3.2vw, 2.75rem); line-height: 1.08; letter-spacing: -0.005em;
  color: var(--fg);
  max-width: 20ch;
}
.cs-hero__meta { position: relative; z-index: 1; margin-top: 1.5rem; color: var(--fg-dim); font-size: var(--text-small); white-space: nowrap; }
.cs-hero__scroll { display: none; }

.cs-body { max-width: 1320px; margin: 0 auto; padding: 0 var(--pad-lg); }
.cs-hero + .cs-body { margin-top: 0; }

.cs-recap {
  margin-top: clamp(3.5rem, 7vw, 6rem);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
  padding: clamp(1.5rem, 3vw, 2.5rem) clamp(1.5rem, 4vw, 3rem);
}
.cs-recap__row {
  display: grid; grid-template-columns: 160px 1fr; gap: 1.5rem 2rem;
  padding: 1.25rem 0; border-top: 1px solid var(--line);
  align-items: baseline;
}
.cs-recap__row:first-child { border-top: none; padding-top: 0; }
.cs-recap__row--block { align-items: start; }
.cs-recap__value { font-size: var(--text-body); color: var(--fg); }
.cs-recap__tags { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.cs-recap__specs { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem 2rem; }
.cs-recap__specs > div { display: flex; flex-direction: column; gap: 0.35rem; }
.cs-recap__specs-k { font-size: var(--text-micro); letter-spacing: 0.03em; text-transform: uppercase; color: var(--fg-faint); }
.cs-recap__specs-v { font-size: var(--text-small); color: var(--fg); line-height: 1.4; }
@media (max-width: 480px) { .cs-recap__specs { grid-template-columns: 1fr; } }
.cs-recap__tag {
  font-size: var(--text-micro); letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--fg-dim); border: 1px solid var(--line-strong); border-radius: 999px;
  padding: 0.3rem 0.85rem;
}
.cs-recap__block h4 { font-family: var(--font-display); font-weight: 400; font-size: var(--text-section); color: var(--fg); margin-bottom: 0.6rem; }
.cs-recap__block p { font-size: var(--text-small); color: var(--fg-dim); line-height: 1.7; max-width: 62ch; }
@media (max-width: 640px) { .cs-recap__row { grid-template-columns: 1fr; gap: 0.5rem; } }

.cs-thesis { padding: clamp(5rem, 11vw, 9rem) 0; text-align: center; border-bottom: 1px solid var(--line); }
.cs-thesis__q {
  font-family: var(--font-display); font-weight: 300;
  font-size: clamp(1.75rem, 4.5vw, 3.25rem);
  line-height: 1.15; letter-spacing: -0.01em;
  max-width: 20ch; margin: 0 auto;
  color: var(--fg);
}

.cs-section { padding: clamp(3.5rem, 7vw, 6rem) 0; border-bottom: 1px solid var(--line); }
.cs-section__head { margin-bottom: clamp(2rem, 4vw, 3rem); }
.cs-section__title { font-family: var(--font-display); font-weight: 300; font-size: var(--text-h1); color: var(--fg); }
.cs-section__lede { font-size: var(--text-body-lg); color: var(--fg-dim); max-width: 62ch; line-height: 1.6; margin-top: 1rem; }

.cs-cols-2 { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4rem); margin-top: clamp(2rem, 4vw, 3rem); }
.cs-cols-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(2rem, 4vw, 3rem); margin-top: clamp(2rem, 4vw, 3rem); }
@media (max-width: 900px) { .cs-cols-2, .cs-cols-3 { grid-template-columns: 1fr; gap: 2.5rem; } }

/* standalone .cs-col (from a blocks[] array item, not a .cs-cols grid child)
   needs its own top spacing — grid children get it from .cs-cols-2/3 instead */
.cs-section > .cs-col { margin-top: clamp(2rem, 4vw, 3rem); }
.cs-col h3 { font-family: var(--font-display); font-weight: 400; font-size: var(--text-section); color: var(--fg); margin-bottom: 1rem; }
.cs-col p { font-size: var(--text-body); color: var(--fg-dim); line-height: 1.7; }
.cs-col__role { color: var(--fg-dim); font-size: var(--text-small); margin-bottom: 1rem; }
.cs-col ul { margin-top: 0.5rem; }
.cs-col li { font-size: var(--text-small); color: var(--fg-dim); padding: 0.65rem 0; border-top: 1px solid var(--line); }
.cs-col li:first-child { border-top: none; }
.cs-note { margin-top: clamp(2rem, 4vw, 3rem); font-size: var(--text-body); color: var(--fg-dim); line-height: 1.7; max-width: 72ch; }

.cs-gallery { display: grid; gap: 1.25rem; margin-top: clamp(2rem, 4vw, 3rem); }
.cs-gallery--2 { grid-template-columns: 1fr 1fr; }
.cs-gallery--3 { grid-template-columns: 1fr 1fr 1fr; }
.cs-gallery--4 { grid-template-columns: 1fr 1fr 1fr 1fr; }
/* --6: for source images too low-res to stretch across 4 columns without
   softening — smaller tiles keep them close to native resolution. */
.cs-gallery--6 { grid-template-columns: repeat(6, 1fr); }
@media (max-width: 900px) { .cs-gallery--3, .cs-gallery--4, .cs-gallery--6 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .cs-gallery--2, .cs-gallery--3, .cs-gallery--4, .cs-gallery--6 { grid-template-columns: 1fr; } }
.cs-gallery figure { margin: 0; }
.cs-gallery img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--radius-sm); display: block; aspect-ratio: 4 / 5; }
.cs-gallery figcaption { margin-top: 0.75rem; font-size: var(--text-meta); color: var(--fg-dim); line-height: 1.4; }

/* Option A — full-width uncropped plates, stacked */
.cs-plates { display: grid; gap: clamp(2rem, 4vw, 3rem); margin-top: clamp(2rem, 4vw, 3rem); }
/* --cols3: constrains plates to a 3-up grid instead of full-width stacking,
   for source images too low-res to stretch edge-to-edge without softening. */
.cs-plates--cols3 { grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 900px) { .cs-plates--cols3 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .cs-plates--cols3 { grid-template-columns: 1fr; } }
.cs-plates figure { margin: 0; }
.cs-plates img { width: 100%; height: auto; display: block; border-radius: var(--radius-sm); }
.cs-plates figcaption { margin-top: 0.85rem; font-size: var(--text-meta); color: var(--fg-dim); line-height: 1.4; }

/* Option B — smaller, paired side by side, uncropped (natural ratio) */
.cs-pair { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.25rem, 3vw, 2rem); margin-top: clamp(2rem, 4vw, 3rem); }
.cs-pair figure { margin: 0; }
.cs-pair img { width: 100%; height: auto; display: block; border-radius: var(--radius-sm); }
.cs-pair figcaption { margin-top: 0.75rem; font-size: var(--text-meta); color: var(--fg-dim); line-height: 1.4; }
@media (max-width: 720px) {
  .cs-pair { grid-template-columns: 1fr; }
}

.cs-reversal { margin-top: clamp(2rem, 4vw, 3rem); border-top: 1px solid var(--line); }
.cs-reversal__row {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 1.5rem;
  padding: 1.1rem 0; border-bottom: 1px solid var(--line);
}
.cs-reversal__tag {
  flex: 0 0 9.5rem;
  font-size: var(--text-meta); letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-faint);
}
.cs-reversal__row--active .cs-reversal__tag { color: var(--fg-dim); }
.cs-reversal__chain { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; font-size: var(--text-small); color: var(--fg-faint); }
.cs-reversal__row--active .cs-reversal__chain { color: var(--fg-dim); }
.cs-reversal__arrow, .cs-reversal__dot { color: var(--fg-faint); }
.cs-reversal__hub { color: var(--fg); font-family: var(--font-display); font-weight: 400; font-size: var(--text-body); }
@media (max-width: 620px) { .cs-reversal__tag { flex-basis: 100%; } }

.cs-layers {
  display: flex; flex-direction: column;
  margin-top: clamp(2rem, 4vw, 3rem);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  overflow: hidden;
}
.cs-layers__band {
  padding: 0.95rem 1.25rem;
  font-family: var(--font-display); font-weight: 300; font-size: var(--text-section);
  color: var(--fg);
  background: rgba(255, 255, 255, calc(0.025 + var(--i) * 0.018));
  border-top: 1px solid var(--line);
}
.cs-layers__band:first-child { border-top: none; }

.cs-framework__row, .cs-zone {
  display: grid; grid-template-columns: 200px 1fr; gap: 2rem;
  padding: clamp(1.5rem, 3vw, 2rem) 0;
  border-top: 1px solid var(--line);
}
.cs-framework__row:last-child, .cs-zone:last-child { border-bottom: none; }
.cs-framework, .cs-zones { border-bottom: 1px solid transparent; margin-top: clamp(2rem, 4vw, 3rem); }
.cs-framework__label, .cs-zone__label {
  font-family: var(--font-display); font-weight: 300; font-size: var(--text-section); color: var(--fg);
}
.cs-zone__label small { display: block; font-family: var(--font-sans); font-weight: 400; font-size: var(--text-meta); color: var(--fg-faint); letter-spacing: 0.04em; text-transform: uppercase; margin-bottom: 0.35rem; }
.cs-framework__body h4, .cs-zone__body h4 { font-size: var(--text-body); font-weight: 500; color: var(--fg); margin-bottom: 0.5rem; }
.cs-framework__body p, .cs-zone__body p { font-size: var(--text-small); color: var(--fg-dim); line-height: 1.65; max-width: 60ch; }
@media (max-width: 700px) { .cs-framework__row, .cs-zone { grid-template-columns: 1fr; gap: 0.75rem; } }

.cs-diagrams { margin-top: clamp(2rem, 4vw, 3rem); display: grid; gap: clamp(2rem, 4vw, 3rem); }
.cs-diagram { display: block; margin-top: clamp(2rem, 4vw, 3rem); }
.cs-diagram__frame { background: #efedea; border-radius: var(--radius-sm); padding: clamp(1rem, 3vw, 2rem); overflow: hidden; }
.cs-diagram__frame img { width: 100%; height: auto; display: block; }
.cs-diagram__caption { margin-top: 0.9rem; font-size: var(--text-meta); color: var(--fg-dim); }

/* Blueprint sheets are fixed white-paper / black-ink — deliberately NOT
   theme-adaptive. A technical drawing doesn't switch to dark mode. */
.cs-diagram__frame--blueprint {
  background: var(--bp-paper);
  border: 1px solid var(--bp-ink-faint);
  padding: clamp(1.25rem, 3vw, 2.25rem);
}
.cs-diagram__frame--blueprint svg { width: 100%; height: auto; display: block; }
.cs-bp-line { stroke: var(--bp-ink-dim); }
.cs-bp-line-strong { stroke: var(--bp-ink); }
.cs-bp-line-faint { stroke: var(--bp-ink-faint); }
.cs-bp-fill { fill: var(--bp-ink); }
.cs-bp-label {
  font-family: var(--font-display);
  fill: var(--bp-ink-dim);
  font-size: 13px;
  letter-spacing: 0.04em;
}
.cs-bp-label--strong { fill: var(--bp-ink); font-weight: 500; }
.cs-bp-label--amber { fill: var(--bp-ink); font-weight: 500; }
.cs-bp-eyebrow {
  font-family: var(--font-display);
  fill: var(--bp-ink-faint);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.cs-quote { padding: clamp(4rem, 9vw, 7.5rem) 0; text-align: center; }
.cs-quote p {
  font-family: var(--font-display); font-weight: 300;
  font-size: clamp(1.5rem, 3.5vw, 2.5rem); line-height: 1.3;
  color: var(--fg); max-width: 30ch; margin: 0 auto;
}

.cs-disclaimer { padding: 2rem 0 clamp(4rem, 8vw, 6rem); }
.cs-disclaimer p { font-size: var(--text-micro); color: var(--fg-faint); line-height: 1.7; max-width: 72ch; }

/* small labeled color-swatch list — campaign-internal palette documentation,
   not a site theme control; kept flat/hairline per the no-shadow rule */
.cs-swatches { display: flex; flex-wrap: wrap; gap: 1.5rem 2rem; margin-top: clamp(2rem, 4vw, 3rem); }
.cs-swatch { display: flex; align-items: center; gap: 0.6rem; }
.cs-swatch__dot { width: 14px; height: 14px; border-radius: 50%; border: 1px solid var(--line-strong); flex-shrink: 0; }
.cs-swatch__name { font-size: var(--text-small); color: var(--fg-dim); }

/* dispatch */
.d-header {
  padding: clamp(7rem, 14vw, 10rem) var(--pad-lg) clamp(3rem, 6vw, 5rem);
  max-width: 900px;
}
.d-header__dateline { font-size: var(--text-meta); color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 1.5rem; display: flex; gap: 1rem; }
.d-header__title { font-family: var(--font-display); font-weight: 300; font-size: clamp(2rem, 5vw, 3.5rem); line-height: 1.05; letter-spacing: -0.02em; }
.d-body { max-width: 700px; padding: 0 var(--pad-lg) clamp(5rem, 10vw, 8rem); }
.d-body p { font-size: var(--text-body-lg); line-height: 1.65; color: var(--fg); margin-bottom: 1.5rem; }
.d-body .source-link { font-size: var(--text-small); color: var(--fg-dim); border-bottom: 1px solid var(--line-strong); }
.d-body .source-link:hover { color: var(--fg); border-color: var(--fg); }
.d-attribution { font-size: var(--text-small); color: var(--fg-faint); margin-top: -0.75rem; }
.d-byline { font-size: var(--text-small); color: var(--fg-dim); margin-top: 2.5rem; padding-top: 2rem; border-top: 1px solid var(--line); }

/* newsletter signup — reusable partial, dropped in at the close of Journal
   entries. Reuses the site's existing mono-label (.i-field label) and
   hairline-underline input treatment (.i-field input) rather than
   inventing a new pattern. */
.newsletter { max-width: 700px; margin-top: 3rem; padding-top: 2.25rem; border-top: 1px solid var(--line); }
.newsletter__eyebrow {
  font-family: var(--font-mono); font-size: var(--text-micro); letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--fg-dim); margin-bottom: 0.85rem;
}
.newsletter__line { font-size: var(--text-body-lg); line-height: 1.5; color: var(--fg); margin-bottom: 1.5rem; }
.newsletter__form { display: flex; align-items: flex-end; gap: 1.5rem; }
.newsletter__form[hidden] { display: none; }
.newsletter__input {
  flex: 1 1 auto; min-width: 0; background: transparent; border: none; border-bottom: 1px solid var(--line-strong);
  color: var(--fg); font-family: var(--font-sans); font-size: var(--text-body); padding: 0.55rem 0;
  transition: border-color var(--dur-fast) var(--ease);
}
.newsletter__input:focus { outline: none; border-color: var(--fg); }
.newsletter__input::placeholder { color: var(--fg-faint); }
.newsletter__submit {
  display: inline-flex; align-items: center; gap: 0.4em; flex-shrink: 0;
  font: inherit; font-size: var(--text-small); color: var(--fg-dim);
  background: none; border: none; border-bottom: 1px solid var(--line-strong);
  padding: 0 0 calc(0.55rem + 1px); cursor: pointer;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.newsletter__submit:hover, .newsletter__submit:focus-visible { color: var(--fg); border-color: var(--fg); }
.newsletter__submit:disabled { cursor: default; opacity: 0.6; }
.newsletter__submit .link__arrow { display: inline-block; transition: transform var(--dur-fast) var(--ease); }
.newsletter__submit:hover .link__arrow, .newsletter__submit:focus-visible .link__arrow { transform: translateX(4px); }
.newsletter__status { font-size: var(--text-body); color: var(--fg-dim); }
.newsletter__status.is-error { color: var(--fg); }
@media (max-width: 560px) {
  .newsletter__form { flex-direction: column; align-items: stretch; gap: 1.25rem; }
  .newsletter__submit { align-self: flex-start; }
}

.d-hero { max-width: 900px; margin: 0 auto; padding: 0 var(--pad-lg) clamp(3rem, 6vw, 5rem); }
.d-hero img { width: 100%; border-radius: var(--radius); display: block; }
.d-hero--pending {
  aspect-ratio: 4/3; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  display: flex; align-items: center; justify-content: center;
}
.d-hero--pending span { font-size: var(--text-meta); color: var(--fg-faint); text-transform: uppercase; letter-spacing: 0.04em; }

/* journal archive */
.j-list { max-width: 1100px; margin: 0 auto; padding: clamp(7rem, 12vw, 9rem) var(--pad-lg) 6rem; }
.j-year { font-size: var(--text-meta); color: var(--fg-dim); text-transform: uppercase; letter-spacing: 0.06em; margin: 3rem 0 0.5rem; }
.j-year:first-child { margin-top: 0; }
.j-item {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 2rem;
  padding: 1.5rem 0;
  border-top: 1px solid var(--line);
  align-items: baseline;
  transition: opacity var(--dur-fast) var(--ease);
}
@media (max-width: 640px) { .j-item { grid-template-columns: 1fr; gap: 0.5rem; } }
.j-item__date { font-size: var(--text-meta); color: var(--fg-dim); }
.j-item__title { font-size: var(--text-body-lg); font-weight: 400; }
.j-item__title:hover { color: var(--fg-dim); }

/* contact */
.c-page { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; justify-content: center; padding: 6rem var(--pad-lg); }
.c-mail { font-family: var(--font-display); font-weight: 300; font-size: clamp(2.25rem, 8vw, 6rem); letter-spacing: -0.02em; line-height: 1.05; margin-bottom: 2.5rem; word-break: break-word; }
.c-mail:hover { color: var(--fg-dim); }
.c-rows { display: flex; flex-wrap: wrap; gap: 2.5rem; }
.c-row { }
.c-row .contact-pairs__label { margin-bottom: 0.5rem; }
.c-row .contact-pairs__value { font-size: 1.1rem; }
.c-start-project { margin-top: 3rem; }

/* project inquiry overlay + form — full-bleed (no sidebar on contact.html,
   unlike .overlay--pane on the homepage), same .overlay base as the About
   panel. No backend on this static site: submit composes a formatted
   mailto: and opens it in the visitor's own mail client — see
   assets/js/data.js ABOUT.inquiry for the upgrade-path note. */
.inquiry-overlay__body { flex: 1 1 auto; overflow-y: auto; padding: clamp(2rem, 5vw, 4rem) var(--pad-lg) 4rem; }
.inquiry-form { max-width: 640px; margin: 0 auto; }
.inquiry-form__title { font-family: var(--font-display); font-weight: 300; font-size: clamp(1.5rem, 3.5vw, 2rem); margin-bottom: 0.75rem; }
.inquiry-form__lede { color: var(--fg-dim); font-size: var(--text-body); line-height: 1.6; max-width: 60ch; margin-bottom: 2.5rem; }

.i-field { margin-bottom: 1.75rem; }
.i-field:last-of-type { margin-bottom: 0; }
.i-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.i-field label {
  display: block; font-family: var(--font-mono); font-size: var(--text-micro);
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--fg-dim); margin-bottom: 0.6rem;
}
.i-field label .i-req { color: var(--fg-faint); text-transform: none; letter-spacing: 0; margin-left: 0.3rem; }
.i-field input, .i-field textarea, .i-field select {
  width: 100%; background: transparent; border: none; border-bottom: 1px solid var(--line-strong);
  color: var(--fg); font-family: var(--font-sans); font-size: var(--text-body); padding: 0.55rem 0;
  transition: border-color var(--dur-fast) var(--ease);
}
.i-field input:focus, .i-field textarea:focus, .i-field select:focus { outline: none; border-color: var(--fg-dim); }
.i-field input::placeholder, .i-field textarea::placeholder { color: var(--fg-faint); }
.i-field textarea { resize: vertical; min-height: 80px; font-family: inherit; }
.i-field select { appearance: none; -webkit-appearance: none; cursor: pointer; }
.i-chips { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.i-chip {
  font-family: var(--font-mono); font-size: var(--text-micro); letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--fg-dim); background: none; border: 1px solid var(--line-strong); border-radius: 999px;
  padding: 0.4rem 0.9rem; cursor: pointer; transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.i-chip.is-on { color: var(--fg); border-color: var(--fg-dim); }
.i-hint { font-size: var(--text-small); color: var(--fg-faint); margin-top: 0.5rem; line-height: 1.5; }
.i-submit-row { margin-top: 2.5rem; display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap; }
.i-submit {
  font-family: var(--font-mono); font-size: var(--text-small); letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--bg); background: var(--fg); border: 1px solid var(--fg); border-radius: 999px;
  padding: 0.75rem 1.75rem; cursor: pointer; transition: opacity var(--dur-fast) var(--ease);
}
.i-submit:hover { opacity: 0.85; }
.i-submit-note { font-size: var(--text-small); color: var(--fg-faint); }

@media (max-width: 560px) { .i-row { grid-template-columns: 1fr; } }

/* -------------------------------------------------------------------------
   10. Responsive — tablet / mobile
   ------------------------------------------------------------------------- */
@media (max-width: 1023px) {
  .sidebar { width: 35vw; }
  .grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 34vw; }
  .tile--sq, .tile--tall, .tile--wide { grid-column: span 2; }
  .tile--tall { grid-row: span 2; }
  .about { flex-direction: column; overflow-y: auto; }
  .about__center { overflow-y: visible; padding-bottom: 0; }
}

@media (max-width: 767px) {
  .shell { display: block; }
  .sidebar {
    position: sticky;
    top: 0;
    width: calc(100% - (var(--pad) * 2)); min-width: 0; max-width: none;
    margin: 0 auto;
    height: auto;
    border-right: none;
    border-bottom: 1px solid var(--line);
    z-index: 40;
  }
  .sidebar__projects { max-height: 40vh; }
  .main { margin-left: 0; width: 100%; }
  .stage { min-height: 60vh; }

  .overlay { left: 0; }
  .overlay__body { flex-direction: column; overflow-y: auto; }
  .overlay__filters {
    width: 100%;
    border-right: none;
    border-bottom: 1px solid var(--line);
    display: flex;
    gap: 1.5rem;
    overflow-x: auto;
    padding: 1rem var(--pad);
    white-space: nowrap;
  }
  .overlay__filter-item { width: auto; margin-left: 0; padding: 0.35rem 0; }
  .overlay__filter-item::before { left: 0; top: auto; bottom: -2px; width: 0; height: 2px; transform: none; }
  .overlay__filter-item.is-active::before { width: 100%; height: 2px; }
  .grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 42vw; padding: 1.25rem; }
  .tile--sq { grid-column: span 1; grid-row: span 1; }
  .tile--tall { grid-column: span 1; grid-row: span 2; }
  .tile--wide { grid-column: span 2; grid-row: span 1; }

  .about__hero { height: 32vh; }
  .about__section { padding: 2.5rem 1.5rem 0; }
  .contact-pairs--row { flex-direction: column; padding: 0.5rem 0; }
  .contact-pairs--row .contact-pairs__item { padding: 1.25rem 0; border-left: none !important; }
  .contact-pairs--row .contact-pairs__item:first-child { padding-top: 1.25rem; }
  .contact-pairs--row .contact-pairs__item:last-child { padding-bottom: 1.25rem; }
  .contact-pairs--row .contact-pairs__item + .contact-pairs__item { border-top: 1px solid var(--line); }
  .team-card { gap: 1.25rem; }
  .p-hero__content { padding: 0 1.5rem 3rem; }
  .p-body { padding: 3rem 1.5rem; }
  .p-nextprev { grid-template-columns: 1fr; }
  .p-nextprev a:first-child { border-right: none; border-bottom: 1px solid var(--line); }
  .j-item { grid-template-columns: 1fr; }
  .c-page { padding: 5rem 1.5rem; }
}

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

/* -------------------------------------------------------------------------
   12. Temma Court — editorial visual essay, modeled on Aman's own
   property-page pattern: hero video -> excerpt -> grid.
   Restraint over spectacle: near-black/warm-white, no card chrome, no
   forced crops. Full arc: hero video -> excerpt -> full grid (all 32
   images, one unified set, lightbox on click) -> location -> closing
   beat. The video is the page's opening frame — no separate cover.
   ------------------------------------------------------------------------- */
.tc-body { background: var(--bg); color: var(--fg); }

.tc-progress { position: fixed; top: 0; left: 0; width: 2px; height: 100vh; background: var(--line); z-index: 50; }
.tc-progress__fill { width: 100%; height: 0%; background: var(--fg-dim); }

/* Video reserve — full-bleed 16:9 slot, isolated by generous top/bottom
   padding so it reads as a deliberate pause. */
.tc-video { }
/* max-height caps the frame on wide-but-short viewports (ultrawide
   monitors, maximized wide windows) — at true 16:9 a very wide frame
   can grow taller than the viewport itself, pushing the controls bar
   below the fold. Capped, the footage still fills edge-to-edge via
   object-fit:cover on the <video>, just cropped a little top/bottom
   instead of letterboxed. */
/* Pure black, not var(--surface) — no poster/placeholder image on either
   the case study or homepage video, so this is genuinely the only thing
   visible until the first frame decodes and paints over it. On the
   homepage this also covers the project's own brand-tinted
   .stage__field sitting behind it. */
.tc-video__frame { position: relative; width: 100%; aspect-ratio: 16 / 9; max-height: 88vh; overflow: hidden; background: #000; }
/* In fullscreen the frame should fill the whole screen, not stay capped
   by the 88vh scroll-layout constraint above. Only the case study's
   frame has a fullscreen trigger — the homepage's stripped-down pill
   doesn't — so this is unreachable there regardless. */
.tc-video__frame:fullscreen, .tc-video__frame:-webkit-full-screen {
  width: 100vw; height: 100vh; max-height: none; aspect-ratio: auto;
}
/* Temma Court's case-study hero: the kitchen island shot's subject sits
   in the lower two-thirds of the frame, so bias the 16:9 crop down
   toward it instead of centering into the upper cabinetry. */
#tc-hero-frame img { object-position: center 68%; }
.tc-video__frame img, .tc-video__frame video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Case-study page heroes fill the entire first screen, same footprint
   as the homepage stage — this only targets the opening .tc-video
   section's own frame, not every .tc-video__frame on the site (the
   Motion archive's stacked clip list keeps its normal 16:9 box). */
.tc-video .tc-video__frame { aspect-ratio: auto; max-height: none; height: 100vh; height: 100dvh; }

/* Controls — two variants share this same fade/positioning base and the
   .tc-video__volume/mute styling below: the homepage's stripped-down
   corner pill (mute + volume only, no modifier class) and the case
   study's original full-width bar (.tc-video__controls--full — adds
   play/pause, a scrubbable track, and fullscreen). Hidden by default,
   faded in while the cursor is over/near the frame (or via keyboard
   focus) and shown briefly on load so first-time visitors notice it
   exists — see initVideoControlsVisibility in temma-court.js. */
.tc-video__controls {
  position: absolute; right: 0; bottom: 0;
  /* bottom inset kept small and separate from the right inset so the
     pill sits close to the same vertical band as the flush-bottom
     scroll-cue chevron beside it, rather than floating noticeably
     higher than it. */
  padding: 0 clamp(1.25rem, 3.5vw, 2rem) 0.85rem 0;
  opacity: 0; pointer-events: none;
  transition: opacity var(--dur-base) var(--ease);
}
.tc-video__frame.is-controls-active .tc-video__controls,
.tc-video__frame:focus-within .tc-video__controls {
  opacity: 1; pointer-events: auto;
}
.tc-video__controls--full {
  left: 0; right: 0; bottom: 0;
  display: flex; align-items: center; gap: 0.85rem;
  padding: clamp(1.5rem, 4vw, 2.25rem) clamp(1rem, 3vw, 1.75rem) clamp(0.9rem, 2.5vw, 1.4rem);
  background: linear-gradient(180deg, rgba(8, 8, 8, 0) 0%, rgba(8, 8, 8, 0.5) 100%);
}

.tc-video__play, .tc-video__mute, .tc-video__fullscreen {
  flex: none; width: 22px; height: 22px; border-radius: 50%; border: none;
  background: none; display: flex; align-items: center; justify-content: center;
  color: #F0ECE4; cursor: pointer; opacity: 0.85; transition: opacity var(--dur-fast) var(--ease);
}
.tc-video__play:hover, .tc-video__mute:hover, .tc-video__fullscreen:hover,
.tc-video__play:focus-visible, .tc-video__mute:focus-visible, .tc-video__fullscreen:focus-visible { opacity: 1; }

.tc-video__track {
  flex: 1 1 auto; position: relative; height: 16px; display: flex; align-items: center; cursor: pointer;
}
.tc-video__track::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%);
  height: 2px; background: rgba(240, 236, 228, 0.3);
}
.tc-video__track-fill {
  position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  height: 2px; width: 0%; background: #F0ECE4;
}
.tc-video__track-fill::after {
  content: ''; position: absolute; right: -4px; top: 50%; transform: translate(50%, -50%);
  width: 8px; height: 8px; border-radius: 50%; background: #F0ECE4;
  opacity: 0; transition: opacity var(--dur-fast) var(--ease);
}
.tc-video__track:hover .tc-video__track-fill::after,
.tc-video__track:focus-visible .tc-video__track-fill::after,
.tc-video__track.is-scrubbing .tc-video__track-fill::after { opacity: 1; }

/* Volume — always visible (not hover-revealed on its own) so it's
   reachable on touch devices too, not just mouse. Native
   <input type="range">, restyled to match the site's thin-line-plus-dot
   language rather than OS chrome. In the corner-pill variant it also
   carries its own backdrop since it's the only thing in the group; in
   the full-bar variant the bar's own gradient scrim already does that
   job, so the extra backdrop is redundant there but harmless. */
.tc-video__volume {
  display: flex; align-items: center; gap: 0.6rem; flex: none;
  background: rgba(8, 8, 8, 0.4);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  border-radius: 999px;
  padding: 0.4rem 0.85rem;
}
.tc-video__controls--full .tc-video__volume { background: none; backdrop-filter: none; -webkit-backdrop-filter: none; padding: 0; }
.tc-video__volume-slider {
  width: 60px; -webkit-appearance: none; appearance: none; background: transparent; height: 16px;
}
.tc-video__volume-slider::-webkit-slider-runnable-track {
  height: 2px; background: rgba(240, 236, 228, 0.3);
}
.tc-video__volume-slider::-webkit-slider-thumb {
  -webkit-appearance: none; width: 8px; height: 8px; border-radius: 50%;
  background: #F0ECE4; margin-top: -3px; cursor: pointer;
}
.tc-video__volume-slider::-moz-range-track { height: 2px; background: rgba(240, 236, 228, 0.3); border: none; }
.tc-video__volume-slider::-moz-range-thumb { width: 8px; height: 8px; border-radius: 50%; background: #F0ECE4; border: none; cursor: pointer; }

@media (max-width: 640px) {
  .tc-video__volume-slider { width: 40px; }
}

/* Excerpt — centered intro block between the hero video and the grid,
   Aman's own pattern: small-caps location, title, short paragraph. Copy
   is a placeholder until real case-study text is written. */
.tc-excerpt { max-width: 1040px; margin: 0 auto; padding: clamp(4.5rem, 10vw, 7.5rem) var(--pad-lg) clamp(3.5rem, 8vw, 6rem); text-align: center; }
.tc-excerpt__location {
  font-size: var(--text-meta); text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-dim);
}
.tc-excerpt__title {
  margin-top: 0.75rem; font-family: var(--font-display); font-weight: 300;
  font-size: var(--text-h1); letter-spacing: -0.01em; color: var(--fg);
}
.tc-excerpt__body {
  margin-top: 1.5rem; max-width: 80ch; margin-left: auto; margin-right: auto;
  font-size: var(--text-body); line-height: 1.55; color: var(--fg-dim);
}

/* Gallery — one unified, unbroken 32-image sequence. No section labels;
   the cut between images carries the rhythm on its own. Masonry via CSS
   columns, true to each image's natural aspect ratio (no forced crops),
   generous gutters, zero card chrome. Each cell fades in individually on
   scroll (rather than the whole grid at once) — the grid is many
   viewport-heights tall, so a single reveal trigger on the whole thing
   can never reach its intersection threshold; per-cell reveal has no
   such ceiling. */
.tc-gallery-section { padding: 0 var(--pad-lg) clamp(3rem, 7vw, 5rem); }
.tc-grid-view { max-width: 1500px; margin: 0 auto; }

/* Grid / Single view toggle — Aman's own pattern: two quiet icon+label
   pairs, the active one carrying a thin underline. Purely a display
   switch on the same 32-image sequence below (see .tc-gallery-section
   [data-view="single"]), no separate markup or data per mode. */
.tc-view-toggle { max-width: 1500px; margin: 0 auto; padding: 0 var(--pad-lg) clamp(2rem, 4vw, 3rem); display: flex; justify-content: center; gap: 2.25rem; }
.tc-view-toggle__btn { display: flex; align-items: center; gap: 0.6rem; color: var(--fg-faint); transition: color var(--dur-fast) var(--ease); }
.tc-view-toggle__btn svg { flex-shrink: 0; display: block; }
.tc-view-toggle__btn span { font-size: var(--text-small); position: relative; padding-bottom: 4px; }
.tc-view-toggle__btn:hover, .tc-view-toggle__btn:focus-visible { color: var(--fg-dim); }
.tc-view-toggle__btn.is-active { color: var(--fg); }
.tc-view-toggle__btn.is-active span::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--fg); }

.tc-gallery-grid { column-count: 3; column-gap: clamp(1.5rem, 3vw, 2.5rem); transition: opacity 220ms var(--ease); }
.tc-gallery-section.is-switching .tc-gallery-grid,
.tc-gallery-section.is-switching .tc-slideshow { opacity: 0; }
.tc-gallery-cell {
  position: relative; overflow: hidden;
  break-inside: avoid; margin-bottom: clamp(1.5rem, 3vw, 2.5rem); cursor: pointer;
}
.tc-gallery-cell img { width: 100%; height: auto; display: block; }
@media (max-width: 900px) { .tc-gallery-grid { column-count: 2; } }
@media (max-width: 560px) { .tc-gallery-grid { column-count: 1; } }

/* Video panel — Full Index's own pattern: one full-width tile per row,
   stacked, title/caption below the frame. Each clip plays in the exact
   same .tc-video__frame the Temma Court hero video uses (see the
   VIDEO_CONTROLS_HTML wiring in photography.js) — same 16:9 frame, same
   control bar — not a page-specific player. */
.ph-video-list { max-width: 860px; margin: 0 auto; display: flex; flex-direction: column; gap: clamp(2.5rem, 6vw, 4.5rem); }
/* Sharp corners here, not the rounded ones .story-frame__video carries
   by default elsewhere — a full, uncropped rectangular frame. */
.ph-video-list .tc-video__frame,
.ph-video-list .story-frame__video { border-radius: 0; }
.ph-video-caption { margin-top: 0.85rem; font-size: var(--text-small); color: var(--fg-dim); }
.ph-video-caption--full { display: flex; flex-direction: column; gap: 1rem; }
.ph-video-caption--full p { margin: 0; max-width: none; }
.ph-video-caption__heading { color: var(--fg); font-weight: 500; }

/* Single view: a proper slideshow — one image at a time, letterboxed
   full within a fixed dark frame (never cropped, unlike the cover-fit
   hero frame, since these images span both portrait macro shots and
   wide landscape rooms), with the same prev/next arrows as the
   lightbox for visual consistency. Grid stays in the DOM underneath —
   .tc-gallery-section[data-view] just toggles which one is visible. */
.tc-gallery-section:not([data-view="single"]) .tc-slideshow { display: none; }
.tc-gallery-section[data-view="single"] .tc-grid-view { display: none; }
.tc-slideshow { max-width: 1400px; margin: 0 auto; transition: opacity 220ms var(--ease); }
/* .tc-slideshow__row is the positioning context for the arrows — sized
   to the frame alone (arrows are absolute, out of flow), with side
   padding reserved so the buttons sit in the page's own black, clear of
   the frame's own overflow:hidden edge, never overlapping the photo the
   way the fullscreen lightbox's arrows deliberately do. */
.tc-slideshow__row { position: relative; padding: 0 56px; }
.tc-slideshow__frame {
  position: relative;
  height: min(76vh, 820px);
  background: var(--bg);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.tc-slideshow__img { width: 100%; height: 100%; object-fit: contain; display: block; }
.tc-slideshow__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--fg-dim); cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}
.tc-slideshow__nav:hover, .tc-slideshow__nav:focus-visible { color: var(--fg); }
.tc-slideshow__nav--prev { left: 0; }
.tc-slideshow__nav--next { right: 0; }
@media (max-width: 640px) {
  .tc-slideshow__row { padding: 0 32px; }
  .tc-slideshow__nav { width: 28px; height: 28px; }
}
.tc-slideshow__counter {
  text-align: center;
  margin-top: 1rem;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.04em;
  color: var(--fg-faint);
}
@media (prefers-reduced-motion: reduce) {
  .tc-gallery-grid { transition: none; }
}

/* Location — Leaflet on a warm paper/ink basemap, the same fixed
   light treatment as the blueprint diagram sheets elsewhere on the site
   (deliberately NOT theme-adaptive — a map reads as a document, not a
   photo, so it sits as a warm-white/grey inset against the page's dark
   ground rather than matching it). Free/keyless CARTO tiles, nudged
   warmer with a CSS filter since Positron's default is cool grey-blue.
   Pin and distance callouts are custom divIcons styled to the site's
   own type system, not any library default. */
.tc-map-section {
  --tc-map-accent: #1A00FF;
  --tc-map-paper: #DFDACD;
  --tc-map-paper-hover: #D3CDBE;
  padding: 0 var(--pad-lg) clamp(3rem, 7vw, 5rem);
}
.tc-map-label {
  max-width: 1500px; margin: 0 auto clamp(1.25rem, 3vw, 2rem);
  font-size: var(--text-meta); text-transform: uppercase; letter-spacing: 0.06em; color: var(--fg-dim);
}
.tc-map {
  max-width: 1500px; margin: 0 auto; aspect-ratio: 2.1 / 1; min-height: 320px;
  background: var(--tc-map-paper); border: 1px solid var(--bp-ink-faint);
}
.tc-map .leaflet-container { background: var(--tc-map-paper); font-family: var(--font-sans); }
.tc-map .leaflet-tile-pane { filter: sepia(0.25) saturate(0.5) brightness(0.86) contrast(1.02); }
.tc-map .leaflet-div-icon { background: transparent; border: none; }
.tc-map .leaflet-control-zoom { border: none; box-shadow: none; margin: 12px; }
.tc-map .leaflet-control-zoom a {
  width: 26px; height: 26px; line-height: 24px; background: var(--tc-map-paper); color: var(--bp-ink-dim);
  border: 1px solid var(--bp-ink-faint); border-radius: 0; font-weight: 400;
}
.tc-map .leaflet-control-zoom a:first-child { border-bottom: none; }
.tc-map .leaflet-control-zoom a:hover { background: var(--tc-map-paper-hover); color: var(--bp-ink); }
.tc-map .leaflet-control-attribution {
  background: rgba(223, 218, 205, 0.85); color: var(--bp-ink-faint); font-size: 10px; padding: 2px 6px;
}
.tc-map .leaflet-control-attribution a { color: var(--bp-ink-dim); }

.tc-map-pin { display: flex; align-items: center; gap: 0.5rem; white-space: nowrap; transform: translate(-4px, -10px); }
.tc-map-pin__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--bp-ink); flex: none; box-shadow: 0 0 0 4px rgba(18, 17, 14, 0.12); }
.tc-map-pin__label {
  font-size: var(--text-small); font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--bp-ink);
}

.tc-map-note { display: flex; align-items: center; gap: 0.4rem; white-space: nowrap; transform: translate(-3px, -8px); color: var(--tc-map-accent); }
.tc-map-note__icon { flex: none; display: flex; }
.tc-map-note__dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; display: block; }
.tc-map-note__text { font-size: var(--text-micro); font-weight: 500; letter-spacing: 0.05em; text-transform: uppercase; }

/* Staging/styling credit — a quiet footer-style detail, same italic/dim
   treatment as .team-card__tagline elsewhere on the site. Deliberately
   plain-text unless a verified link is on hand; never guess a link. */
.tc-credit {
  text-align: center;
  font-style: italic;
  font-size: var(--text-small);
  color: var(--fg-dim);
  letter-spacing: 0.02em;
  padding: 0 var(--pad-lg) clamp(2.5rem, 6vw, 4rem);
}

/* Return to top — the page's real last word after the map, so scroll
   ends on a deliberate gesture rather than just stopping. */
.tc-return {
  display: flex; justify-content: center; padding: 0 var(--pad-lg) clamp(4rem, 9vw, 6rem);
}
.tc-return__btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0.5rem 0.75rem; color: #FFFFFF; opacity: 0.6;
  background: none; border: none; cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease);
}
.tc-return__btn:hover, .tc-return__btn:focus-visible { opacity: 1; }
.tc-return__btn svg { display: block; transition: transform var(--dur-fast) var(--ease); }
.tc-return__btn:hover svg, .tc-return__btn:focus-visible svg { transform: translateY(-2px); }

/* Lightbox — single-image detail view, minimal chrome, opened from any
   grid image with prev/next paging across the full 32-image set. */
.tc-lightbox {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  background: rgba(8, 8, 8, 0.96);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; visibility: hidden; transition: opacity var(--dur-base) var(--ease);
}
.tc-lightbox.is-open { opacity: 1; visibility: visible; }
.tc-lightbox__img { max-width: min(90vw, 1600px); max-height: 88vh; width: auto; height: auto; object-fit: contain; display: block; }
.tc-lightbox__close {
  position: absolute; top: clamp(1rem, 3vw, 2rem); right: clamp(1rem, 3vw, 2rem);
  width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--fg-dim); font-size: 1.5rem; line-height: 1; cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}
.tc-lightbox__close:hover, .tc-lightbox__close:focus-visible { color: var(--fg); }
.tc-lightbox__nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  background: none; border: none; color: var(--fg-dim); cursor: pointer;
  transition: color var(--dur-fast) var(--ease);
}
.tc-lightbox__nav:hover, .tc-lightbox__nav:focus-visible { color: var(--fg); }
.tc-lightbox__nav--prev { left: clamp(0.5rem, 2vw, 1.5rem); }
.tc-lightbox__nav--next { right: clamp(0.5rem, 2vw, 1.5rem); }

@media (max-width: 700px) {
  .tc-progress { display: none; }
}
