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

:root {
  --bg: oklch(97% 0.003 260);
  --bgAlpha: oklch(97% 0.003 260 / 0.85);
  --text: oklch(15% 0.004 260);
  --muted: oklch(45% 0.008 260);
  --muted2: oklch(35% 0.01 260);
  --faint: oklch(50% 0.008 260);
  --strong: oklch(25% 0.005 260);
  --line: rgba(0, 0, 0, 0.12);
  --lineSoft: rgba(0, 0, 0, 0.08);
  --lineStrong: rgba(0, 0, 0, 0.3);
  --stripe1: oklch(90% 0.004 260);
  --stripe2: oklch(85% 0.004 260);
  --activeBg: rgba(0, 0, 0, 0.06);
  --hoverRow: rgba(0, 0, 0, 0.03);
  --pad: clamp(24px, 7vw, 100px);
  --lightboxBg: oklch(97% 0.003 260 / 0.94);
  --lightboxFg: oklch(20% 0.005 260);
  --scrambleL: 50%;
  color-scheme: light;
}

:root[data-theme="dark"] {
  --scrambleL: 58%;
  --bg: oklch(14% 0.004 260);
  --bgAlpha: oklch(14% 0.004 260 / 0.85);
  --text: oklch(96% 0.003 260);
  --muted: oklch(62% 0.008 260);
  --muted2: oklch(75% 0.01 260);
  --faint: oklch(58% 0.008 260);
  --strong: oklch(85% 0.005 260);
  --line: rgba(255, 255, 255, 0.12);
  --lineSoft: rgba(255, 255, 255, 0.08);
  --lineStrong: rgba(255, 255, 255, 0.3);
  --stripe1: oklch(22% 0.004 260);
  --stripe2: oklch(18% 0.004 260);
  --activeBg: rgba(255, 255, 255, 0.1);
  --hoverRow: rgba(255, 255, 255, 0.03);
  --lightboxBg: oklch(14% 0.004 260 / 0.94);
  --lightboxFg: oklch(90% 0.003 260);
  color-scheme: dark;
}

* { box-sizing: border-box; }
/* overflow-x:hidden must live on html only — on body it breaks position:sticky
   for the body's children (the top nav) in some browsers */
/* reserves the scrollbar's width even when there's nothing to scroll yet,
   so switching to a taller view (e.g. Work's grid densities) doesn't
   shrink the whole page by the scrollbar's width right as it appears */
html { overflow-x: hidden; scrollbar-gutter: stable; }
body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  font-family: "Inter", Helvetica, Arial, sans-serif;
  display: flex;
  flex-direction: column;
  transition: background 0.2s ease, color 0.2s ease;
}
/* without an explicit flex-basis, the SPA swapping #app's content between
   routes of very different heights could leave the flex column's size
   (and the sticky footer riding on it) out of sync until the next reflow —
   this pins it down so the footer never has to "catch up" */
#app { flex: 1 0 auto; }
a { color: inherit; text-decoration: none; }
img, video { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; }

@keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

/* easter egg: 5 rapid clicks on the theme toggle */
@keyframes discoFlash {
  0%   { background: #fff; color: #111; }
  8%   { background: #0a0a0a; color: #fff; }
  16%  { background: #ff2ec4; color: #111; }
  24%  { background: #00e5ff; color: #111; }
  32%  { background: #fff700; color: #111; }
  40%  { background: #0a0a0a; color: #fff; }
  48%  { background: #7c3aed; color: #fff; }
  56%  { background: #fff; color: #111; }
  64%  { background: #ff2ec4; color: #111; }
  72%  { background: #00ff85; color: #111; }
  80%  { background: #0a0a0a; color: #fff; }
  88%  { background: #fff; color: #111; }
  94%  { background: #00e5ff; color: #111; }
  100% { background: var(--bg); color: var(--text); }
}
.disco-strobe {
  animation: discoFlash 1s steps(1, end) 1;
  transition: none !important;
}
.disco-strobe * { transition: none !important; }
.page { animation: fadeIn 0.4s ease; }

/* ---------- nav ---------- */
/* no background — the nav's own pixels invert against whatever scrolls beneath
   it via mix-blend-mode, so it always reads regardless of what's underneath */
.nav {
  position: sticky; top: 0; z-index: 95;
  display: flex; justify-content: space-between; align-items: center; gap: 24px;
  padding: 20px var(--pad);
  background: transparent;
  color: #fff;
  mix-blend-mode: difference;
  isolation: isolate;
  flex-wrap: wrap;
}
.nav-logo { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; cursor: pointer; white-space: nowrap; overflow: hidden; flex: none; }
/* the nav bar is blended with mix-blend-mode: difference, which flips every
   colour over a light page — pre-invert the shuffling letters there so they
   come out as the same true hue as in dark mode */
:root:not([data-theme="dark"]) .nav-logo span { filter: invert(1); }
.nav-links { display: flex; gap: 28px; font-size: 14px; font-weight: 600; }
.nav-link { cursor: pointer; padding-bottom: 4px; border-bottom: 1px solid transparent; opacity: 0.6; transition: opacity 0.2s ease; }
.nav-link:hover { opacity: 1; }
.nav-link.active { border-bottom-color: currentColor; opacity: 1; }
.nav-right { display: flex; align-items: center; gap: 14px; }
.nav-clock { font-size: 12px; letter-spacing: 0.02em; white-space: nowrap; opacity: 0.6; }
@media (max-width: 1024px) {
  .nav-clock { display: none; }
}

/* ---------- mobile menu ---------- */
.nav-menu-toggle {
  display: none; flex: none; width: 26px; height: 20px; margin: 0; padding: 0; border: 0;
  position: relative; cursor: pointer; background: none;
}
.nav-menu-toggle span {
  position: absolute; left: 0; width: 100%; height: 1.5px; background: currentColor;
  transition: transform 0.25s ease, opacity 0.2s ease;
}
.nav-menu-toggle span:nth-child(1) { top: 2px; }
.nav-menu-toggle span:nth-child(2) { top: 9px; }
.nav-menu-toggle span:nth-child(3) { top: 16px; }
.nav-menu-toggle.open span:nth-child(1) { top: 9px; transform: rotate(45deg); }
.nav-menu-toggle.open span:nth-child(2) { opacity: 0; }
.nav-menu-toggle.open span:nth-child(3) { top: 9px; transform: rotate(-45deg); }

.mobile-nav-overlay {
  display: none; position: fixed; inset: 0; z-index: 90;
  background: var(--bg); color: var(--text);
  opacity: 0; pointer-events: none; transition: opacity 0.25s ease;
  flex-direction: column; justify-content: space-between;
  overflow-y: auto;
}
.mobile-nav-overlay.open { opacity: 1; pointer-events: auto; }
.mobile-nav-links { display: flex; flex-direction: column; gap: 28px; padding: 110px var(--pad) 40px; }
.mobile-nav-link { font-size: 32px; font-weight: 600; letter-spacing: -0.01em; cursor: pointer; opacity: 0.6; }
.mobile-nav-link.active { opacity: 1; }
body.mobile-nav-locked { overflow: hidden; }

.mobile-nav-footer { display: flex; flex-direction: column; gap: 22px; padding: 0 var(--pad) 50px; }
.mobile-nav-footer .theme-toggle { width: 30px; height: 30px; opacity: 1; }
.mobile-nav-social, .mobile-nav-legal { display: flex; gap: 18px; font-size: 13px; }
.mobile-nav-social { font-weight: 700; }
.mobile-nav-legal { opacity: 0.6; }
.mobile-nav-legal-link { cursor: pointer; }

@media (max-width: 1024px) {
  .nav-links { display: none; }
  .nav-right .theme-toggle { display: none; }
  .nav-menu-toggle, .mobile-nav-overlay { display: flex; }
}

.theme-toggle {
  width: 26px; height: 26px; border: 0;
  background: none; color: inherit; cursor: pointer; flex: none; padding: 0;
  display: flex; align-items: center; justify-content: center;
  opacity: 0.6; transition: opacity 0.2s ease;
}
.theme-toggle:hover { opacity: 1; }
.theme-toggle svg { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

/* ---------- media placeholders ---------- */
.stripe {
  background: repeating-linear-gradient(45deg, var(--stripe1), var(--stripe1) 10px, var(--stripe2) 10px, var(--stripe2) 20px);
}
.media-fill { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.media-natural { display: block; width: 100%; height: auto; }
.media-wrap { position: relative; overflow: hidden; background: var(--stripe1); }
.hero-inner > .media-wrap,
.featured-card > .media-wrap {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
/* the hero video keeps its own real proportions rather than being cropped to
   fill — so whatever letterboxing shows around it should blend into the page
   instead of standing out as its own grey box. transparent rather than
   var(--bg): there's nothing else behind it but body (already the same
   color), and transparent can never go out of sync on a theme transition —
   it has no color of its own to animate, so it just tracks body instantly */
.hero-inner > .media-wrap { background: transparent; }
.hero-inner > .media-wrap > video,
.hero-inner > .media-wrap > mux-video { background: transparent; }

/* ---------- welcome: hero ---------- */
.hero {
  /* full container width, height follows from the ratio — max-height
     used to cap this, but combined with aspect-ratio it was shrinking
     the box narrower than the container on taller viewports instead of
     just capping height, so it's dropped */
  position: relative; width: 100%; aspect-ratio: 16/9;
  padding: 0 var(--pad) 40px; background: transparent; box-sizing: border-box;
}
.hero-inner { position: relative; width: 100%; height: 100%; overflow: hidden; }
.hero-inner > .media-wrap { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero-play {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  cursor: pointer; background: transparent;
  opacity: 1; transition: opacity 0.25s ease;
}
/* while a hero clip is playing, its play/pause UI hides itself; hovering
   reveals the browser's own native controls (volume, scrub, fullscreen)
   instead, so this custom glyph steps aside rather than doubling up */
.hero-inner.is-playing .hero-play,
.hero-inner:hover .hero-play { opacity: 0; pointer-events: none; }
.hero-play-glyph {
  width: 64px; height: 64px; border-radius: 50%; border: 1.5px solid rgba(255,255,255,0.75);
  display: flex; align-items: center; justify-content: center; backdrop-filter: blur(2px);
}
.hero-play-glyph::before {
  content: ""; width: 0; height: 0; border-top: 11px solid transparent; border-bottom: 11px solid transparent;
  border-left: 16px solid #fff; margin-left: 3px;
}
.hero-detail { width: 100vw; margin-left: calc(-50vw + 50%); margin-right: calc(-50vw + 50%); }
.hero-detail-top { padding-top: 28px; }

/* editorial intro */
.intro { display: flex; gap: 60px; flex-wrap: wrap; padding: 100px var(--pad) 90px; max-width: 1440px; margin: 0 auto; }
/* min-height reserves room for the tallest the shuffling role word can
   make this wrap to (3 lines), so Selected Work below never jumps when a
   longer word rotates in — em-based so it scales with the clamp() font-size */
/* overflow: hidden is the real fix for the shuffle's mid-scramble jitter —
   random scrambled characters aren't the same width as the real letters,
   so the browser briefly re-wraps to more lines than the settled text
   needs; clipping that keeps it from ever pushing Selected Work around */
.intro-headline { flex: 1.3; min-width: 280px; font-size: clamp(32px, 5vw, 58px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.05; min-height: 3.15em; overflow: hidden; }
@media (max-width: 1024px) {
  /* narrower column wraps the longest role word ("multidisciplinary
     designer") onto a 4th line instead of 3 */
  .intro-headline { min-height: 4.2em; }
}
.role-roulette-wrap { position: relative; display: inline-block; cursor: pointer; }
/* fixed, not absolute — appended to <body> with JS-computed top/left, since
   .intro-headline's overflow: hidden (see above) would otherwise clip an
   absolutely-positioned dropdown nested inside it */
.role-dropdown {
  position: fixed; z-index: 120;
  display: flex; flex-direction: column;
  background: var(--bg); border: 1px solid var(--lineStrong); border-radius: 4px;
  padding: 6px; min-width: 240px; max-height: 320px; overflow-y: auto;
  box-shadow: 0 12px 30px rgba(0,0,0,0.18);
}
.role-dropdown-item {
  font-size: 15px; font-weight: 500; padding: 9px 12px; border-radius: 3px; cursor: pointer; white-space: nowrap;
}
.role-dropdown-item:hover { background: var(--activeBg); }
.intro-bio { flex: 1; min-width: 240px; display: flex; flex-direction: column; gap: 22px; }
.intro-bio p { font-size: 18.4px; line-height: 1.75; color: var(--muted2); max-width: 420px; margin: 0; }
.heart-icon { vertical-align: -2px; margin: 0 1px; }
.intro-mail-link { color: var(--text); border-bottom: 1px solid var(--text); cursor: pointer; }

/* selected work grid */
.selected-work { padding: 0 var(--pad) 150px; max-width: min(2100px, 94vw); margin: 0 auto; }
.selected-work-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 44px; }
.selected-work-head h2 { font-size: 22px; font-weight: 600; letter-spacing: -0.01em; margin: 0; }
.selected-work-head span { font-size: 13px; color: var(--muted); cursor: pointer; }
/* same rules as the project detail's editorial gallery (.editorial-gallery/
   .editorial-row): flexible rows with generous, viewport-relative gaps
   instead of a rigid grid — that's what gives editorial its spacious feel */
.featured-grid { display: flex; flex-direction: column; gap: clamp(140px, 20vh, 280px); }
/* nowrap: the two cards' flex-basis percentages sum to 100%, leaving no
   room for the gap — under wrap that pushed the second card onto its own
   line (stacked, not side by side); nowrap lets them flex-shrink to fit
   instead. Mobile stacking is handled by flex-direction:column below, not
   by wrapping. */
.featured-row { display: flex; gap: clamp(28px, 6vw, 110px); flex-wrap: nowrap; align-items: flex-start; }
.featured-card { cursor: pointer; position: relative; overflow: hidden; flex: 0 1 auto; }
/* mobile + tablet: a plain, bold single column instead of the desktop
   off-grid drift — !important overrides the per-card flex-basis/margin-top
   inline styles that FEATURED_ROWS sets in JS for desktop */
@media (max-width: 1024px) {
  .featured-grid { gap: 48px; }
  /* flex-basis governs the MAIN axis, which becomes height once the row
     flips to column — align-items:stretch (overriding the desktop row's
     flex-start) plus an explicit width is what actually makes each card
     span full width here; flex-basis:100% alone was sizing height, not
     width, collapsing every card to 0x0 */
  .featured-row { flex-direction: column; gap: 24px; align-items: stretch; }
  .featured-card { width: 100% !important; flex-basis: auto !important; margin-top: 0 !important; }
}
.card-overlay {
  position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; padding: 28px;
  opacity: 0; transition: opacity 0.25s ease;
  color: #fff;
  /* inverts against whatever's beneath it instead of relying on a dark
     scrim, so the title stays legible over light frames too */
  mix-blend-mode: difference;
}
.featured-card:hover .card-overlay { opacity: 1; }
.card-overlay-row { display: flex; align-items: baseline; gap: 16px; }
.card-overlay-row .t { font-size: 26px; font-weight: 600; letter-spacing: -0.01em; }
.tag-row { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.tag-pill { font-size: 11px; padding: 4px 10px; border: 1px solid var(--lineStrong); border-radius: 999px; color: var(--muted2);  transition: color 0.3s ease-in-out, border-color 0.3s ease-in-out, background-color 0.3s ease-in-out; }
html .tag-pill.tag-hl {
  /* same hues as the shuffle effect, softened to pastel: the fill is light
     enough that dark text reads on every one of them, in both themes */
  color: #1a1a1a;
  border-color: transparent;
  background-color: hsl(var(--tag-hue) 92% 80%);
}
.card-overlay .tag-pill { color: #fff; border-color: rgba(255,255,255,0.5); }
/* hover doesn't really exist on touch — show the title overlay plainly on
   mobile/tablet instead of gating it behind :hover, and drop the pills */
@media (max-width: 1024px) {
  .card-overlay { opacity: 1; }
  .card-overlay .tag-row { display: none; }
}

/* ---------- work (grid) ---------- */
.work-page { padding: 70px var(--pad) 110px; max-width: 1440px; margin: 0 auto; width: 100%; }
.work-page.work-page-wide { max-width: 1800px; }
.work-head { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 16px; margin-bottom: 36px; }
.work-head h1 { font-size: 32px; font-weight: 600; letter-spacing: -0.01em; margin: 0; }
.work-count { font: 14px ui-monospace, Menlo, monospace; color: var(--faint); }
.density-switch { display: flex; gap: 6px; }
.density-btn { width: 34px; height: 30px; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.density-icon { width: 14px; height: 14px; }
.density-icon.list-icon { width: 16px; display: flex; flex-direction: column; gap: 2px; height: 10px; }
.density-icon.list-icon span { height: 2px; background: var(--muted); display: block; }
.density-icon.d1 { border: 1px solid var(--muted); }
.density-icon.d1.active { border-color: var(--text); }
.density-icon.d2 { display: grid; grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(2, 1fr); gap: 2px; }
.density-icon.d2 span { background: var(--muted); }
.density-icon.d2.active span { background: var(--text); }
.density-icon.dall { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); gap: 1px; }
.density-icon.dall span { background: var(--muted); }
.density-icon.dall.active span { background: var(--text); }

.project-grid { display: grid; gap: 32px; }
.project-grid.density-1 { grid-template-columns: 1fr; gap: 56px; }
.project-grid.density-2 { grid-template-columns: repeat(3, 1fr); gap: 48px 32px; }
@media (max-width: 1100px) {
  .project-grid.density-2 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .project-grid.density-2 { grid-template-columns: 1fr; }
}

.card-thumb { aspect-ratio: 4/3; }
.card-thumb-full { aspect-ratio: 2.4 / 1; }
.card-index { font: 11px ui-monospace, Menlo, monospace; color: var(--faint); }
.card-default { display: flex; flex-direction: column; gap: 10px; cursor: pointer; }
.card-default .card-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: space-between; }
.card-default .card-meta .title { font-size: 14px; font-weight: 500; }
.card-default .card-meta .loc { font-size: 13px; color: var(--muted); }

.card-full { display: flex; flex-direction: column; gap: 14px; cursor: pointer; }
.card-full .card-meta { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.card-full .card-meta .title { font-size: 16px; font-weight: 500; }
.card-full .card-meta .loc { font-size: 13px; color: var(--muted); }
.card-full .card-meta .tag-row { margin-left: auto; margin-top: 0; }
@media (max-width: 1024px) {
  .density-btn[data-set-density="2"] { display: none; }
  .card-full .card-meta .tag-row { margin-left: 0; }
}

/* "All" density on Work — every project's gallery flattened into one grid,
   same masonry layout as Notes (.screens-grid/.screens-col, JS round-robin
   columns — desktop 4 / tablet 3 / mobile 2). Only difference from Notes:
   each tile fades/lifts into place the first time it scrolls into view
   instead of all appearing at once. */
.all-content-item, .reveal {
  opacity: 0; transform: translateY(28px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.all-content-item.is-visible, .reveal.is-visible { opacity: 1; transform: translateY(0); }

.list-rows { display: flex; flex-direction: column; }
.list-row { cursor: pointer; position: relative; display: flex; align-items: center; gap: 20px; padding: 18px 0; border-bottom: 1px solid var(--lineSoft); }
.list-row .li-idx { font: 11px ui-monospace, Menlo, monospace; color: var(--faint); flex: none; width: 24px; }
.list-row .li-title { font-size: 16px; font-weight: 500; flex: none; position: relative; }
.list-row .li-tags { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }
.list-row .li-loc { font-size: 13px; color: var(--muted); flex: none; white-space: nowrap; }
@media (max-width: 1024px) {
  .list-row { padding: 10px 0; gap: 12px; }
  .list-row .li-title { font-size: 14px; }
  .list-row .li-tags, .list-row .li-loc { display: none; }
}
.list-preview-stamp {
  position: fixed; width: 254px; max-width: 41vw; z-index: 10; pointer-events: none;
  overflow: hidden; background: var(--stripe1);
  opacity: 0; transform: scale(0.94);
  transition: opacity 0.4s ease, transform 0.4s ease;
}
.list-preview-stamp.in { opacity: 1; transform: scale(1); }
.list-preview-stamp.out { opacity: 0; transform: scale(0.96); }
.list-preview-stamp img { display: block; width: 100%; height: auto; }

/* ---------- detail ---------- */
.detail-narrow { max-width: 1440px; margin: 0 auto; padding: 0 var(--pad); }
.detail-wide { max-width: 80vw; margin: 0 auto; padding: 0 clamp(16px, 5vw, 72px); }
.detail-scroll-area { position: relative; padding-bottom: 110px; }
.detail-back { cursor: pointer; font-size: 13px; color: var(--muted); padding: 28px 0 20px; width: fit-content; }
.detail-meta { padding: 36px 0; border-bottom: 1px solid var(--line); }
/* exactly the list view's row pattern: idx + "Client — Title" alone on the
   left, tag-row's own auto margin pulls it (and location right after it)
   to the far right */
.detail-title-group { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; width: 100%; }
.detail-idx { font: 13px ui-monospace, Menlo, monospace; color: var(--faint); }
.detail-title { font-size: 30px; font-weight: 600; letter-spacing: -0.01em; }
.detail-title-group .tag-row { margin-left: auto; margin-top: 0; }
.detail-loc { font-size: 13px; color: var(--muted); white-space: nowrap; }
.detail-blurb p { margin: 0 0 1em; }
.detail-blurb p:last-child { margin-bottom: 0; }
.detail-body { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 0 clamp(32px, 6vw, 110px); }
.detail-body .detail-blurb { flex: 1 1 380px; }
.detail-resources { flex: 0 1 440px; margin-left: auto; padding: 32px 0; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.detail-resources .prompt-card { width: 100%; }
@media (max-width: 900px) { .detail-resources { flex: 1 1 100%; margin-left: 0; padding-top: 0; } }
.detail-blurb { max-width: 640px; padding: 32px 0; font-size: 16px; line-height: 1.8; color: var(--muted2); }
.gallery-toggle { display: flex; justify-content: flex-end; gap: 6px; padding-bottom: 10px; }
.gallery-toggle .opt { font-size: 12px; padding: 7px 14px; border: 1px solid var(--lineStrong); cursor: pointer; color: var(--muted); }
.gallery-toggle .opt.active { background: var(--activeBg); color: var(--text); }

.detail-footer { display: flex; gap: 60px; flex-wrap: wrap; padding: 50px 0 90px; border-top: 1px solid var(--lineSoft); margin-top: 40px; }
.detail-footer h3 { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--faint); margin: 0 0 16px; font-weight: 600; }
.detail-footer ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.detail-credits { flex: 1.4; min-width: 240px; }
.detail-credits li { display: flex; gap: 16px; font-size: 14px; }
.detail-credits .credit-role { color: var(--muted); min-width: 140px; flex: none; }
.detail-credits .credit-name { color: var(--strong); }
.detail-links { flex: 1; min-width: 200px; }
.detail-links li a { font-size: 14px; color: var(--strong); border-bottom: 1px solid var(--lineSoft); word-break: break-all; }
.detail-links li a:hover { color: var(--muted); }

.gallery-spacious { display: flex; flex-direction: column; align-items: center; gap: 160px; padding: 60px 0 80px; }
.gallery-spacious-item { display: flex; flex-direction: column; gap: 24px; width: 100%; max-width: 1000px; }
.gallery-spacious-item .media-wrap { width: 100%; aspect-ratio: 16/10; cursor: pointer; }
.gallery-spacious-item .caption { max-width: 640px; font-size: 15px; line-height: 1.8; color: var(--muted2); }

.gallery-grid { column-count: 3; column-gap: 28px; padding: 20px 0 40px; }
.gallery-grid .media-wrap { margin-bottom: 28px; break-inside: avoid; cursor: pointer; }
.gallery-grid img, .gallery-grid video { width: 100%; height: auto; }
@media (max-width: 800px) { .gallery-grid { column-count: 2; } }

/* editorial gallery: uncropped media, sized well under the container, drifting
   left/right/center per row for a floaty off-grid feel. nothing exceeds viewport height. */
.editorial-gallery { display: flex; flex-direction: column; gap: clamp(140px, 20vh, 280px); padding: 60px 0 80px; }

.editorial-row.single { display: flex; }
.editorial-row.single.align-left { justify-content: flex-start; }
.editorial-row.single.align-center { justify-content: center; }
.editorial-row.single.align-right { justify-content: flex-end; }
.editorial-item { display: flex; flex-direction: column; gap: 16px; max-width: min(100%, 1140px); cursor: pointer; }
.editorial-item.size-m { max-width: min(100%, 820px); }
.editorial-item.size-s { max-width: min(100%, 560px); }

.editorial-row.pair { display: flex; gap: clamp(28px, 6vw, 110px); flex-wrap: wrap; align-items: flex-start; }
.editorial-row.pair.align-left { justify-content: flex-start; }
.editorial-row.pair.align-center { justify-content: center; }
.editorial-row.pair.align-right { justify-content: flex-end; }
/* default (no size specified) and the two real sizes a paired column can be */
.editorial-col { display: flex; flex-direction: column; gap: 16px; max-width: min(100%, 680px); cursor: pointer; }
.editorial-col.size-m { max-width: min(100%, 760px); }
.editorial-col.size-s { max-width: min(100%, 460px); }

.editorial-gallery .media-wrap { width: fit-content; max-width: 100%; background: transparent; }
.media-wrap.vimeo-embed { width: 100%; aspect-ratio: 16/9; }
.media-wrap.media-ratio { width: 100%; }
.media-wrap.media-ratio > .media-natural { width: 100%; height: 100%; max-height: none; object-fit: cover; display: block; }
.prompt-card { width: 440px; max-width: 100%; background: transparent; border: 1px solid var(--lineStrong); border-radius: 4px; cursor: default; }
.prompt-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-bottom: 1px solid var(--line); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); }
.prompt-copy { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; color: var(--muted2); background: none; border: 0; border-radius: 4px; cursor: pointer; }
.prompt-copy:hover { color: var(--text); background: var(--stripe1); }
.link-card { display: block; color: inherit; text-decoration: none; cursor: pointer; transition: border-color 0.2s ease; }
.link-card:hover { border-color: var(--text); }
.link-card-arrow { display: inline-flex; color: var(--muted2); }
.link-card:hover .link-card-arrow { color: var(--text); }
.link-card-body { padding: 14px; font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 12px; line-height: 1.7; color: var(--muted2); }
.link-card-body p { margin: 0; }
.prompt-card.is-collapsed pre { max-height: 118px; overflow: hidden; -webkit-mask-image: linear-gradient(to bottom, #000 40%, transparent); mask-image: linear-gradient(to bottom, #000 40%, transparent); }
.prompt-more { display: block; width: 100%; padding: 9px 14px; font: inherit; font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted2); background: none; border: 0; border-top: 1px solid var(--line); cursor: pointer; text-align: right; }
.prompt-more:hover { color: var(--text); background: var(--stripe1); }
.prompt-card pre { margin: 0; padding: 14px; max-height: 360px; overflow: auto; }
.prompt-card code { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 12px; line-height: 1.7; color: var(--muted2); white-space: pre-wrap; word-break: break-word; }
.vimeo-placeholder { display: flex; align-items: center; justify-content: center; cursor: pointer; background: var(--stripe1); }
.vimeo-placeholder-glyph {
  width: 56px; height: 56px; border-radius: 50%; border: 1.5px solid rgba(255,255,255,0.75);
  display: flex; align-items: center; justify-content: center;
}
.vimeo-placeholder-glyph::before {
  content: ""; width: 0; height: 0; border-top: 10px solid transparent; border-bottom: 10px solid transparent;
  border-left: 14px solid #fff; margin-left: 3px;
}
.editorial-gallery .media-natural { width: auto; height: auto; max-width: 100%; max-height: 85vh; }
.editorial-gallery .caption { font-size: 15px; line-height: 1.8; color: var(--muted2); }

/* below this, two columns side by side get too small to read — stack them
   instead of squeezing both into half the width */
@media (max-width: 760px) {
  .editorial-row.pair { flex-direction: column; align-items: stretch; }
  .editorial-col, .editorial-col.size-m, .editorial-col.size-s { max-width: 100%; margin-top: 0 !important; }
}

@media (max-width: 640px) {
  .editorial-row.pair { gap: 24px; }
  .editorial-col { margin-top: 0 !important; max-width: 100%; }
  .editorial-gallery .media-natural { max-height: 70vh; }
}

/* fixed at vertical center for the whole detail page, always visible */
.project-nav {
  position: fixed; top: 50%; left: 0; right: 0; transform: translateY(-50%);
  display: flex; justify-content: space-between; padding: 0 18px;
  font-size: 13px; z-index: 40; pointer-events: none;
}
.project-nav a {
  cursor: pointer; color: var(--muted2); pointer-events: auto;
  display: flex; align-items: center; gap: 10px;
  /* padding grows the hover/tap target by 25px on every side; the matching
     negative margin keeps the visible arrow/text sitting exactly where it was */
  padding: 25px; margin: -25px;
  opacity: 0.5; transition: opacity 0.2s ease;
}
.project-nav a:hover { opacity: 1; color: var(--text); }
.project-nav .arrow { font-size: 24px; font-weight: 700; line-height: 1; flex: none; }
.project-nav .proj-title {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 26vw;
  opacity: 0; transition: opacity 0.2s ease;
}
.project-nav a:hover .proj-title { opacity: 1; }
@media (max-width: 780px) {
  .project-nav {
    position: static; transform: none; padding: 30px 0; border-top: 1px solid var(--line); opacity: 1 !important;
  }
  .project-nav a { opacity: 1; }
  .project-nav .proj-title { opacity: 1; max-width: none; }
}

/* lightbox */
.lightbox { position: fixed; inset: 0; z-index: 100; background: var(--lightboxBg); display: flex; align-items: center; justify-content: center; padding: 56px; animation: fadeIn 0.15s ease; }
.lightbox-body { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; width: 100%; height: 100%; max-width: 1800px; }
.lightbox-media { position: relative; width: 100%; flex: 1 1 auto; min-height: 0; overflow: hidden; }
/* only present when a lightbox item carries {title, tags} — Work's "All"
   view, where items are mixed across every project (see lightboxCaptionHTML) */
.lightbox-caption { flex: none; text-align: center; color: var(--lightboxFg); margin-bottom: 10px; }
.lightbox-caption .t { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 8px; cursor: pointer; }
.lightbox-caption .t:hover { text-decoration: underline; }
.lightbox-caption .tag-row { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; margin-top: 0; }
.lightbox-caption .tag-pill { color: var(--lightboxFg); border-color: var(--lightboxFg); opacity: 0.7; }
.lightbox-slide {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  transform: translateX(0); transition: transform 0.28s ease;
}
.lightbox-slide img, .lightbox-slide video, .lightbox-slide mux-video { max-width: 75vw; max-height: 75vh; object-fit: contain; }
.lightbox-slide.lb-off-left { transform: translateX(-100%); }
.lightbox-slide.lb-off-right { transform: translateX(100%); }
.lightbox-close { position: fixed; top: 28px; right: 36px; font-size: 14px; color: var(--lightboxFg); cursor: pointer; }
.lightbox-nav {
  position: fixed; top: 50%; transform: translateY(-50%); font-size: 24px; font-weight: 700; line-height: 1;
  color: var(--lightboxFg); cursor: pointer; padding: 12px; user-select: none;
  opacity: 0.6; transition: opacity 0.15s ease;
}
.lightbox-nav:hover { opacity: 1; }
.lightbox-prev { left: 12px; }
.lightbox-next { right: 12px; }
.lightbox-counter { position: fixed; bottom: 28px; left: 50%; transform: translateX(-50%); font-size: 13px; color: var(--lightboxFg); opacity: 0.7; }

/* ---------- screens ---------- */
.screens-page { max-width: 1800px; margin: 0 auto; width: 100%; padding: 70px var(--pad) 110px; }
.screens-title { font-size: 32px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 6px; }
.screens-sub { font-size: 14px; color: var(--muted); margin-bottom: 36px; }
/* a real masonry (JS-computed round-robin column assignment) rather than
   CSS columns — CSS columns fill one column completely before starting the
   next, so scanning left-to-right across the top reads items out of order;
   round-robin (item 0,1,2,3 into col 1,2,3,4, then 4,5,6,7 into 1,2,3,4...)
   keeps the reading order matching file order left-to-right, top-to-bottom */
.screens-grid { display: flex; gap: 8px; align-items: flex-start; }
.screens-col { display: flex; flex-direction: column; gap: 8px; flex: 1; min-width: 0; }
.screens-grid .media-wrap { border-radius: 4px; }
.screens-item { cursor: pointer; }
.screens-grid img, .screens-grid video { width: 100%; height: auto; border-radius: 4px; }

/* ---------- about ---------- */
.about-page { max-width: 1440px; margin: 0 auto; width: 100%; padding: 70px var(--pad) 130px; }
.about-hero { display: flex; gap: 80px; flex-wrap: wrap; padding-bottom: 90px; align-items: flex-start; }
.about-hero-text { flex: 1; min-width: 300px; display: flex; flex-direction: column; gap: 30px; }
.about-eyebrow { font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); }
.about-hero-text h1 { font-size: clamp(30px, 4vw, 44px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.2; max-width: 520px; margin: 0; }
.about-hero-text p { font-size: 16px; line-height: 1.85; color: var(--muted2); max-width: 460px; margin: 0; }
.about-actions { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 10px; }
.btn-primary { font-size: 14px; font-weight: 500; padding: 12px 20px; border: 1px solid var(--text); border-radius: 2px; white-space: nowrap; cursor: pointer; }
.btn-ghost { font-size: 14px; font-weight: 500; padding: 12px 20px; color: var(--muted2); cursor: pointer; }
.about-portrait { display: block; flex: none; width: 280px; aspect-ratio: 4/5; border-radius: 16px; }
.about-portrait-label {
  position: absolute; left: 12px; bottom: 12px; z-index: 1;
  padding: 6px 12px; border-radius: 999px; font-size: 12px; font-weight: 500; letter-spacing: 0.01em;
  color: #fff; background: rgba(0, 0, 0, 0.62); backdrop-filter: blur(6px);
  opacity: 0; transform: translateY(4px); transition: opacity 0.2s ease, transform 0.2s ease; pointer-events: none;
}
.about-portrait:hover .about-portrait-label, .about-portrait:focus-visible .about-portrait-label { opacity: 1; transform: translateY(0); }
@media (hover: none) { .about-portrait-label { opacity: 1; transform: none; } }

/* left-label / right-content row, reused for What I Do, Clients, Exhibitions */
.about-row { display: flex; gap: 80px; flex-wrap: wrap; padding: 50px 0 90px; border-top: 1px solid var(--line); }
.about-row:last-child { padding-bottom: 0; }
.about-row-label { flex: none; width: 180px; font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); }

.about-services { flex: 1; min-width: 280px; display: flex; flex-wrap: wrap; gap: 14px; font-size: 22px; font-weight: 500; letter-spacing: -0.01em; color: var(--strong); }
.about-services .dot { color: var(--faint); }

.about-row-content { flex: 1; min-width: 280px; display: flex; flex-direction: column; gap: 40px; }

/* client-supplied logo files come in whatever colors/formats they came
   in — a CSS mask ignores all of that and uses the PNG purely as a
   shape, filled with the current theme color, so every logo reads as a
   flat monochrome mark that flips with light/dark like everything else.
   The track is duplicated once in the markup and looped with translateX
   (-50% -> 0) so it reads as a continuous left-to-right scroll. */
.client-logos-wrap { overflow: hidden; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 80px 0; }
.client-logos { display: flex; flex-wrap: nowrap; gap: 56px; align-items: center; width: max-content; animation: client-logos-marquee 32s linear infinite; }
.client-logo {
  flex: none; height: 46.5px; background-color: var(--strong);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: left center; mask-position: left center;
  -webkit-mask-size: contain; mask-size: contain;
}
@keyframes client-logos-marquee {
  from { transform: translateX(-50%); }
  to { transform: translateX(0%); }
}

.clients-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: 40px; row-gap: 40px; }
.clients-row.exhib-clients-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.clients-col-label { font-size: 13px; font-weight: 400; letter-spacing: 0.08em; text-transform: uppercase; color: var(--faint); margin-bottom: 16px; }
.client-list { display: flex; flex-direction: column; gap: 2px; }
.client-list div { font-size: 17px; color: var(--strong); padding: 6px 0; }

@media (max-width: 1024px) {
  .clients-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .clients-row.exhib-clients-row { grid-template-columns: 1fr; }
}

.exhib-row { display: flex; justify-content: flex-start; align-items: baseline; gap: 12px; padding: 6px 0; }
.exhib-row span:first-child { font-size: 17px; color: var(--strong); }
.exhib-row .loc { font-size: 14px; color: var(--muted); white-space: nowrap; }


/* ---------- footer ---------- */
.site-footer {
  margin-top: auto; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px;
  padding: 18px var(--pad); font-size: 12px; font-weight: 600;
  position: sticky; bottom: 0; z-index: 40; pointer-events: none;
  background: transparent; color: #fff; mix-blend-mode: difference; isolation: isolate;
}
/* the footer's own box spans the full width even though its text sits at
   the two edges — without this, that empty middle strip still swallowed
   clicks meant for whatever sits at the same height (e.g. the view-toggle
   button), so only the actual links stay clickable */
.site-footer a, .site-footer .footer-link { pointer-events: auto; }
.site-footer .links { display: flex; gap: 18px; }
.site-footer .links:first-child { font-weight: 400; }
.site-footer .social-links { align-items: center; gap: 16px; font-weight: 700; }
.site-footer a:hover { opacity: 0.7; }
.site-footer .footer-link { cursor: pointer; opacity: 0.5; }
.site-footer .footer-link:hover { opacity: 0.8; }
@media (max-width: 1024px) {
  /* unsticky on mobile — just a normal footer at the true end of the page */
  .site-footer { position: static; }
}

/* ---------- legal (impressum / datenschutz) ---------- */
.legal-page { max-width: 760px; margin: 0 auto; width: 100%; padding: 70px var(--pad) 110px; }
.legal-page h1 { font-size: 28px; font-weight: 600; letter-spacing: -0.01em; margin: 0 0 40px; }
.legal-section { padding: 28px 0; border-top: 1px solid var(--line); }
.legal-section:first-of-type { border-top: 0; padding-top: 0; }
.legal-section h2 { font-size: 15px; font-weight: 600; margin: 0 0 10px; }
.legal-section p { font-size: 14px; line-height: 1.8; color: var(--muted2); margin: 0; }
.legal-section a { text-decoration: underline; text-underline-offset: 2px; }

/* ---------- editorial/grid view toggle (preview) ---------- */
/* same no-background, always-legible trick as the top nav: its own pixels
   invert against whatever's behind, so it reads over any image or video.
   sits inline with the footer (bottom: 28px puts it at the same height as
   the footer's text) — .site-footer is pointer-events: none outside its
   actual links now, so the two no longer fight over clicks in that band */
.view-toggle {
  position: fixed; left: 50%; bottom: 9px; transform: translateX(-50%); z-index: 40;
  padding: 10px 20px; margin: 0; border: 1px solid var(--lineStrong); border-radius: 999px; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
  -webkit-appearance: none; appearance: none;
  font-size: 13px; letter-spacing: 0.02em; cursor: pointer;
  background: transparent; color: #fff; mix-blend-mode: difference; isolation: isolate;
}

/* ---------- hover-scrub preview cards ---------- */
.media-wrap.scrub img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; transition: opacity 0.22s ease;
}
.media-wrap.scrub img.active { opacity: 1; }
.media-wrap.scrub video.scrub-video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 0.22s ease; pointer-events: none;
}
.media-wrap.scrub video.scrub-video.active { opacity: 1; }
/* the welcome page's ambient rotation dissolves slower than a hover-scrub
   flick — that's what makes it read as calm background motion, not a glitch */
.media-wrap.scrub.ambient img { transition: opacity 1.2s ease; }

/* easter egg: 5 rapid clicks on the editorial/grid toggle scrambles the
   gallery into one crooked, overlapping screenful — item positions/rotation
   are randomized inline by triggerChaos(), this just sets up the stage */
.chaos-mode { position: relative; height: 100vh; overflow: hidden; }
.chaos-mode .editorial-item,
.chaos-mode .editorial-col { transition: transform 0.4s ease, top 0.4s ease, left 0.4s ease; }
