/* ---------- Custom fonts: drop files in ./fonts and declare them here ---------- */
@font-face {
  font-family: 'Redaction 100';
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url('fonts/Redaction_100-Regular.woff2') format('woff2'),
       local('Redaction 100 Regular'), local('Redaction100-Regular');
}
@font-face {
  font-family: 'Redaction 100';
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  src: url('fonts/Redaction_100-Bold.woff2') format('woff2'),
       url('fonts/Redaction100-Bold.otf') format('opentype'),
       local('Redaction 100 Bold'), local('Redaction100-Bold');
}

/* ---------- Theme tokens (from Figma) ---------- */
:root {
  --bg: #ececec;
  --bg-desktop: #ececec;
  --dot: #d7d7d7;
  --name: #242424;
  --subtitle: #7b7b7b;
  --body: #4f4f4f;
  --heading: #393939;
  --muted: #a7a7a7;
  --year: #919191;
  --footer: #656565;
  --chip: #bdbdbd;   /* chip fill, "back" link, WIP border */
  --wip-bg: #f2f2f2;
  --code-bg: #e2e2e2;  /* guide: command blocks, table rules (not in Figma) */
}
[data-theme="dark"] {
  --bg: #242424;
  --bg-desktop: #242424;
  --dot: #4f4f4f;
  --name: #f2f2f2;
  --subtitle: #cccccc;
  --body: #e5e5e5;
  --heading: #f2f2f2;
  --muted: #a7a7a7;
  --year: #b2b2b2;
  --footer: #d8d8d8;
  --chip: #969696;
  --wip-bg: #2f2f2f;  /* extrapolated: no dark home frame in Figma */
  --code-bg: #2f2f2f;
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }
body {
  font-family: 'Roboto Mono', ui-monospace, monospace;
  font-weight: 400;
  background: var(--bg);
  color: var(--body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
a {
  color: inherit;
  text-decoration: underline;
  text-underline-position: from-font;
  text-decoration-skip-ink: none;
}
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
img { max-width: 100%; }
[hidden] { display: none !important; }

/* Mobile-only / desktop-only content switches (matches per-frame copy in Figma) */
.m { display: none; }
@media (max-width: 767px) {
  .m { display: inline; }
  .d { display: none; }
}

/* ---------- Layout ---------- */
.page { display: flex; justify-content: center; }
.column {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 0 32px 12px;
}

/* ---------- Dot grid (mobile 14x11, desktop 32x16) ---------- */
.dots {
  display: grid;
  grid-template-columns: repeat(14, 14px);
  justify-content: space-between;
  row-gap: 8px;
}
/* 1s eases the grid between themes. A painted dot lands its colour instantly
   and fades linearly back to grey over 4s while .is-fading (set in app.js). */
.dot { width: 14px; height: 14px; background: var(--dot); transition: background-color 1000ms ease; }
.dot.is-fading { transition: background-color 4000ms linear; }
@media (prefers-reduced-motion: reduce) { .dot, .dot.is-fading { transition: none; } }
/* Toggle: round on touch (Figma 279:31814). With a pointer it rests square and
   rounds on hover (Figma 276:30353 -> 277:30904). */
.toggle {
  position: relative;
  display: block;
  width: 14px;
  height: 14px;
  overflow: hidden;
  border-radius: 7px;
}
@media (hover: hover) {
  .toggle { border-radius: 0; transition: border-radius 200ms ease-out; }
  .toggle:hover, .toggle:focus-visible { border-radius: 7px; }
}
@media (prefers-reduced-motion: reduce) { .toggle { transition: none; } }
.toggle img { position: absolute; inset: 0; display: block; width: 14px; height: 14px; }
.toggle .icon-dark { display: none; }
[data-theme="dark"] .toggle .icon-light { display: none; }
[data-theme="dark"] .toggle .icon-dark { display: block; }
/* Theme ripple (app.js): drop the default cross-fade so only the circle shows.
   Scoped to .theme-ripple so page-to-page View Transitions keep theirs. */
.theme-ripple::view-transition-old(root),
.theme-ripple::view-transition-new(root) { animation: none; mix-blend-mode: normal; }

/* Page-to-page morphs (only on pages that opt in with @view-transition, i.e.
   the inner pages and index_experiments_*.html; index.html doesn't). A project
   title and its preview land on the case title and hero. Left off during a
   theme ripple, which would otherwise lift them out of the circle. */
html:not(.theme-ripple) .case-title { view-transition-name: vt-title; }
html:not(.theme-ripple) :is(.v2-hero img, .photo-stack > .photo-item:first-child img) { view-transition-name: vt-hero; }
/* Playbook timing: page changes settle in about 300ms */
::view-transition-group(*) { animation-duration: 300ms; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); }

/* ---------- Hero ---------- */
.hero { margin-top: 20px; }
.hero-top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  column-gap: 16px;
  margin-bottom: 4px;
}
.links { display: flex; gap: 12px; font-size: 12px; line-height: 16px; color: var(--body); }
.name {
  font-family: 'Redaction 100', 'Courier New', monospace;
  font-weight: 700;
  font-size: calc(20px * var(--fs, 1));
  line-height: calc(24px * var(--fs, 1));
  letter-spacing: calc(2.6px * var(--fs, 1));
  color: var(--name);
}
/* Typing caret — present only while the name is being typed */
.name-text { cursor: default; }
.name.is-typing .name-text::after {
  content: "_";
  animation: name-caret 800ms steps(1, end) infinite;
}
@keyframes name-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .name.is-typing .name-text::after { content: none; }
}

.role {
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(16px * var(--fs, 1));
  color: var(--subtitle);
}

/* ---------- Bio ---------- */
.bio {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 20px;
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(16px * var(--fs, 1));
  color: var(--body);
  overflow-wrap: break-word;
}

/* ---------- Sections (work / featured) ---------- */
.section { margin-top: 40px; }
.section-head {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 16px;
  font-family: 'Handjet', 'Roboto Mono', monospace;
  font-weight: 600;
  font-variation-settings: "ELGR" 1, "ELSH" 2;
  font-size: 16px;
  line-height: 18px;
  letter-spacing: 0.05em;
  color: var(--heading);
  white-space: nowrap;
}
.section-head .inactive { color: var(--muted); }

/* Tabs: work / lab / experiments / featured / writings */
.tab { padding: 0; color: var(--muted); }
/* five tabs overrun a 320px column at the 20px gap */
@media (max-width: 399px) { .section-head { gap: 12px; } }
.tab[aria-selected="true"] { color: var(--heading); }

.list { display: flex; flex-direction: column; gap: 14px; }
.row { position: relative; display: flex; flex-direction: column; }
.row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 16px;
  white-space: nowrap;
}
.row-title {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(16px * var(--fs, 1));
  color: var(--body);
}
.row-title a { text-decoration: none; }
.row-title a:hover { text-decoration: underline; }
.sep, .year { display: none; }
.company {
  margin-left: auto;
  font-size: 12px;
  line-height: 16px;
  color: var(--muted);
  text-align: right;
}
.tags { display: none; }

/* One-line summary under a work row (Figma 323:15750). Shown on hover or
   focus with a pointer, on tap on touch. */
.row-desc {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(16px * var(--fs, 1));
  color: var(--year);
  white-space: normal;
  /* Rows ease open and shut rather than snapping, so moving between them
     doesn't jolt the list */
  transition: grid-template-rows 250ms ease, opacity 200ms ease;
}
.row-desc p { min-height: 0; overflow: hidden; }
.row-desc p::before { content: ""; display: block; height: 4px; }
.row-desc em { font-style: italic; color: var(--body); }
.row.is-open .row-desc { grid-template-rows: 1fr; opacity: 1; }
.title, .company, .tags { transition: color 250ms ease, font-weight 250ms ease; }
@media (prefers-reduced-motion: reduce) {
  .row-desc, .title, .company, .tags { transition: none; }
}

/* Post-it accent on the active tab and contact links, colour picked per visit
   in the <head> of index.html */
[data-accent] .links a,
[data-accent] .tab[aria-selected="true"] {
  padding: 0 3px;
  margin: 0 -3px;
  background: var(--accent);
  color: #242424;
}

/* Every row is one link end to end, as CDC is in Figma (323:15726) */
.list .row-title a::after { content: ""; position: absolute; inset: 0; }
.list .row-title a:hover { text-decoration: none; }

/* WIP badge — revealed on hover (pointer) or tap (touch) for work rows
   with no case study. display:none keeps it out of flow so nothing shifts. */
.wip {
  display: none;
  align-items: center;
  justify-content: center;
  align-self: center;
  margin-left: 4px;
  /* letter-spacing adds 0.7px of dead space after the final letter, which
     pushes the glyphs left of centre; trim it back off the right padding */
  padding: 1.5px 3.3px 1.5px 4px;
  border: 1px solid var(--chip);
  border-radius: 4px;
  background: var(--wip-bg);
  font-family: 'Handjet', 'Roboto Mono', monospace;
  font-weight: 400;
  font-variation-settings: "ELGR" 1, "ELSH" 2;
  font-size: 14px;
  line-height: 16px;
  letter-spacing: 0.05em;
  color: var(--year);
}
.row[data-wip] .row-title { cursor: default; }

@media (hover: hover) {
  .row[data-wip]:hover .wip,
  .row[data-wip]:focus-within .wip { display: inline-flex; }
}
@media (hover: none) {
  #panel-work .row, #panel-writings .row { cursor: pointer; }
}
.row.is-open .wip { display: inline-flex; }

/* Work-row hover preview: 320x180, 20px right of the column, level with the top
   of the hovered row. It only appears when the viewport can fit it:
   (vw+700)/2 + 340 <= vw, i.e. vw >= 1380, rounded to 1390 for scrollbar
   differences. Below that it stays hidden. */
.row-preview {
  position: absolute;
  left: calc(100% + 20px);
  width: 320px;
  aspect-ratio: 320 / 180;
  object-fit: cover;
  pointer-events: none;
  display: none;
  opacity: 0;
  /* duration is set per change in app.js: 300ms in/out, 450ms between rows */
  transition: opacity 300ms ease;
}
@media (min-width: 1390px) and (hover: hover) {
  .row-preview { display: block; }
}
.row-preview:not([src]) { visibility: hidden; }
.row-preview.is-visible { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .row-preview { transition: none; } }

/* Touch only: tapping a work row expands its image below at column width.
   For CDC the wrapper is a link, so the image is the way into the case study. */
.row-inline { display: block; width: 100%; text-decoration: none; }
.row-inline img, .row-inline video {
  display: block;
  width: 100%;
  aspect-ratio: 600 / 338;
  object-fit: cover;
}

/* ---------- Footer ---------- */
.footer {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: auto;
  padding-top: 40px;
  font-size: 8px;
  line-height: 11px;
  letter-spacing: 1.04px;
  color: var(--footer);
  white-space: nowrap;
}
.footer .line { display: flex; align-items: baseline; gap: 2px; line-height: 1.2; }
.footer .copy-mark { font-size: 10px; }
.footer .sig {
  font-family: 'Redaction 100', 'Courier New', monospace;
  font-weight: 400;
  font-style: normal;
}
/* Home: the footer stays pinned to the bottom of the screen while the page
   scrolls under it (Figma 323:16986 gives it the page fill for this). The
   column's bottom padding keeps the last row clear of it. */
.home { padding-bottom: 90px; }
.home .footer {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  z-index: 10;
  margin-top: 0;
  padding: 8px 32px 12px;
  background: var(--bg);
}

/* ================= Case study ================= */
/* Top bar on every inner page (Figma 367:19583): back on the left, text size
   and theme on the right. Fixed rather than sticky: as a flex item, sticky is
   constrained to its own flex line in Safari and never engages. The bar always
   sits at top:0 anyway, so fixed is visually identical and works everywhere. */
.case .topbar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 24px 32px 8px;
  background: var(--bg);
}
.case .back {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: 'Handjet', 'Roboto Mono', monospace;
  font-weight: 400;
  font-variation-settings: "ELGR" 1, "ELSH" 2;
  font-size: 16px;
  line-height: 20px;
  letter-spacing: 0.05em;
  color: var(--chip);
  text-decoration: none;
}
.case .back:hover { text-decoration: underline; }
.case .back svg { flex: none; display: block; width: 5px; height: 9px; }
.topbar-tools { display: flex; align-items: center; gap: 8px; }
/* +a / -a: 14px chips in the dot-grid grey, Handjet like the back link */
.text-step {
  position: relative;
  width: 14px;
  height: 14px;
  overflow: hidden;
  background: var(--dot);
  font-family: 'Handjet', 'Roboto Mono', monospace;
  font-weight: 400;
  font-variation-settings: "ELGR" 1, "ELSH" 2;
  font-size: 14px;
  line-height: 14px;
  letter-spacing: 0;
  color: var(--footer);
  text-align: center;
}
@media (hover: hover) {
  .text-step { transition: border-radius 200ms ease-out; }
  .text-step:hover:not(:disabled), .text-step:focus-visible { border-radius: 7px; }
}
@media (prefers-reduced-motion: reduce) { .text-step { transition: none; } }
.text-step:disabled { opacity: 0.4; cursor: default; }

.column.case { padding-top: 52px; }
.case-head { margin-top: 48px; display: flex; flex-direction: column; gap: 8px; }
.case-title-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  white-space: nowrap;
}
.case-title {
  font-family: 'Handjet', 'Roboto Mono', monospace;
  font-weight: 700;
  font-variation-settings: "ELGR" 1, "ELSH" 2;
  font-size: 32px;
  line-height: 36px;
  letter-spacing: 0.05em;
  color: var(--body);
}
.case-credit {
  display: flex;
  align-items: baseline;
  gap: 2px;
  font-size: 12px;
  line-height: 18px;
}
.case-credit .year { display: inline; color: var(--year); }
.case-credit .sep, .case-credit .client { display: inline; color: var(--muted); }
.case-sub { font-size: calc(12px * var(--fs, 1)); line-height: calc(16px * var(--fs, 1)); color: var(--subtitle); }

.case-meta {
  margin-top: 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(16px * var(--fs, 1));
}
.case-meta .meta-row { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.case-meta dt { color: var(--year); white-space: nowrap; }
.case-meta dd { font-weight: 500; color: var(--body); text-align: right; }

.case-body { margin-top: 32px; display: flex; flex-direction: column; gap: 32px; min-width: 0; }
.case-section { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.case-section h2 {
  font-size: calc(12px * var(--fs, 1));
  font-weight: 500;
  line-height: calc(16px * var(--fs, 1));
  color: var(--body);
}
.case-section h3 {
  font-size: calc(12px * var(--fs, 1));
  font-weight: 400;
  line-height: calc(16px * var(--fs, 1));
  color: var(--body);
}
.case-section p,
.case-section li {
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(16px * var(--fs, 1));
  color: var(--subtitle);
  overflow-wrap: break-word;
}
.case-section ul { padding-left: 21px; list-style: disc; }
.case-section li { margin-bottom: 0; }
.case-section .prose { display: flex; flex-direction: column; gap: 16px; }
.case-section em.stat { font-style: italic; font-weight: 700; }

/* Screenshot blocks — aspect-ratio reserves space so nothing reflows on load.
   Each block carries --ar-light (and --ar-dark when the dark export differs in
   shape, e.g. CDC Old), so neither theme letterboxes. */
.shot { display: block; width: 100%; height: auto; aspect-ratio: var(--ar-light); }
[data-theme="dark"] .shot { aspect-ratio: var(--ar-dark, var(--ar-light)); }
.shot img { display: block; width: 100%; height: 100%; object-fit: contain; }
[data-theme="dark"] .shot .light-only { display: none; }
.shot .dark-only { display: none; }
[data-theme="dark"] .shot .dark-only { display: block; }

/* ---------- Flow / process diagrams (native chips at every breakpoint) ---------- */
.flow-scroll { min-width: 0; overflow-x: auto; overflow-y: hidden; }
.flow { display: flex; align-items: center; gap: 20px; min-width: 660px; }
.flow-main { flex: 1 1 auto; min-width: 0; }
.flow-row { display: flex; align-items: stretch; justify-content: space-between; gap: 12px; }
.chip {
  padding: 10px;
  border-radius: 2px;
  background: var(--chip);
  font-family: 'Handjet', 'Roboto Mono', monospace;
  font-weight: 400;
  font-variation-settings: "ELGR" 1, "ELSH" 2;
  font-size: 20px;
  line-height: 22px;
  letter-spacing: 0.05em;
  color: var(--heading);
  white-space: nowrap;
}
/* U-turn connector: top line, right elbow, return line, left arrowhead.
   Mirrors Figma "Vector 687" (top y=1, right x=700, bottom y=20, arrow tip x=57). */
.flow-turn {
  position: relative;
  height: 20px;
  margin: 9px 0;
  border-top: 1px solid var(--heading);
  border-right: 1px solid var(--heading);
}
.flow-turn::before {
  content: "";
  position: absolute;
  left: 66px;
  right: 0;
  bottom: 0;
  border-bottom: 1px solid var(--heading);
}
.flow-turn::after {
  content: "";
  position: absolute;
  left: 57px;
  bottom: -5.3px;
  width: 0;
  height: 0;
  border-top: 5.8px solid transparent;
  border-bottom: 5.8px solid transparent;
  border-right: 10px solid var(--heading);
}

/* ---------- Desktop (>= 768px) ---------- */
@media (min-width: 768px) {
  body { background: var(--bg-desktop); }
  .column { width: 700px; padding: 0 0 12px; }

  .dots { grid-template-columns: repeat(32, 14px); }

  /* Home, Figma 323:16443: 700px column, 32 x 12 dot grid */
  /* 300px of open space below the last work row, so the hover previews have
     room to be seen, plus the 34px the pinned footer covers */
  .home { --dot-cols: 32; --dot-rows: 12; padding-bottom: 334px; }
  .home .dots { grid-template-columns: repeat(var(--dot-cols), 14px); }

  .hero { margin-top: 24px; }
  .name { font-size: calc(24px * var(--fs, 1)); line-height: calc(29px * var(--fs, 1)); letter-spacing: calc(3.12px * var(--fs, 1)); }
  .links { font-size: 14px; line-height: 18px; }
  .role { font-size: calc(16px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); }

  .bio { margin-top: 32px; font-size: calc(16px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); }

  .section { margin-top: 80px; }
  .section-head {
    font-weight: 400;
    font-size: 20px;
    line-height: 22px;
    letter-spacing: 0;
  }
  .tab[aria-selected="true"] { font-weight: 600; }
  /* Spacing as padding, not gap, so the pointer never falls between rows
     (which would drop the hover and snap every row back for a moment) */
  .list { gap: 0; }
  .list .row { padding-bottom: 12px; }
  .list .row:last-child { padding-bottom: 0; }
  .row-head { align-items: baseline; }
  .row-title { flex: none; gap: 12px; font-size: 32px; line-height: 42px; letter-spacing: 1.6px; }
  .row-title .company {
    margin-left: 0;
    font-size: 12px;
    line-height: 16px;
    letter-spacing: 0;
    color: var(--year);
    transition: color 250ms ease, font-size 250ms ease;
  }
  .tags { display: inline; font-size: calc(16px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); color: var(--year); }
  .row-desc { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
  .row-desc p { max-width: 450px; }
  /* Figma 323:16436: 12px after the company, sat on the baseline */
  .wip {
    margin-left: 0;
    align-self: baseline;
    /* trailing letter-spacing trimmed off the right so WIP stays centred */
    padding: 1.5px 2.2px 1.5px 4px;
    font-weight: 400;
    letter-spacing: 1.82px;
  }

  /* Hover (Figma 323:16443): the row goes bold italic, its company steps up to
     14px and its summary opens; the other rows fall back to grey */
  .list .row:hover .title,
  .list .row:focus-within .title { font-weight: 700; font-style: italic; }
  .list .row:hover .company,
  .list .row:focus-within .company { font-size: 14px; line-height: 18px; }
  .list .row:hover .tags,
  .list .row:focus-within .tags { color: var(--subtitle); }
  .list:has(.row:hover) .row:not(:hover) .title { color: var(--year); }
  /* the featured title already fills the column; a 14px label would overrun it */
  .featured .row:hover .company,
  .featured .row:focus-within .company { font-size: 12px; line-height: 16px; }
  .list .row:hover .row-desc,
  .list .row:focus-within .row-desc { grid-template-rows: 1fr; opacity: 1; }
  .sep { display: inline; font-size: 16px; line-height: 21px; letter-spacing: 2.08px; color: var(--muted); }
  .year { display: inline; font-size: 14px; line-height: 18px; color: var(--year); }

  .footer { flex-direction: row; justify-content: space-between; align-items: baseline; gap: 0; }
  .footer .copy, .footer .updated { font-size: 12px; letter-spacing: 1.56px; }
  .footer .copy-mark { font-size: inherit; }
  .footer .sig { font-size: 14px; letter-spacing: 1.82px; }
  /* 9px rather than Figma's 12: Figma trims the text box to the glyphs, the
     browser keeps the line box, so this lands the baseline 12px from the edge */
  .home .footer { left: 50%; width: 700px; padding: 8px 0 9px; transform: translateX(-50%); }

  /* Case study */
  .case .topbar {
    left: 50%;
    width: 700px;
    transform: translateX(-50%);
    padding-left: 0;
    padding-right: 0;
  }
  .case-head { margin-top: 48px; }
  .case-credit { font-size: 14px; }
  .case-sub { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
  .case-meta { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
  .case-section h2 { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
  .case-section h3 { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
  .case-section p, .case-section li { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
  .flow { min-width: 0; }
}

/* ================= Photography ================= */
.photo-stack { margin-top: 24px; display: flex; flex-direction: column; min-width: 0; }
.photo-item { display: block; width: 100%; aspect-ratio: var(--ar); }
.photo-item img { display: block; width: 100%; height: 100%; object-fit: cover; }

@media (min-width: 768px) {
  .photo-stack { margin-top: 32px; }
}

/* ================= Case study v2 (Figma 330:17690) ================= */
.v2 .back { color: var(--muted); letter-spacing: 0.13em; }
.v2 .case-head { margin-top: 20px; }
.v2 .v2-hero { margin-top: 24px; }
.v2 .case-body { margin-top: 24px; gap: 32px; }
.v2 .case-section h2 { font-weight: 500; font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); letter-spacing: 0.13em; }
.v2 .case-section .prose { gap: 16px; }
.v2-fig { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.v2-fig figcaption {
  font-style: italic;
  font-weight: 500;
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(16px * var(--fs, 1));
  color: var(--subtitle);
  text-align: center;
}
.v2-flow { gap: 16px; }
.v2-flow .v2-label { font-style: normal; font-weight: 400; text-align: left; }

@media (min-width: 768px) {
  .v2 .case-title { font-size: 32px; line-height: 36px; letter-spacing: 0.13em; }
  .v2 .case-credit { letter-spacing: 0.13em; }
  .v2 .case-sub { font-size: calc(16px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); }
  .v2 .case-meta { letter-spacing: 0.13em; }
  .v2 .v2-hero { margin-top: 32px; }
  .v2 .case-body { margin-top: 32px; gap: 24px; }
  .v2 .case-section h2 { font-size: calc(18px * var(--fs, 1)); line-height: calc(24px * var(--fs, 1)); }
  /* paragraphs are a blank line apart, as in Figma */
  .v2 .case-section .prose { gap: 21px; }
  .v2 .case-section p, .v2 .case-section li { font-size: calc(16px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); }
  .v2-fig figcaption { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
}
/* 300px of room after the last section, so the story can finish scrolling
   before the footer */
@media (min-width: 768px) {
  .v2 .footer { padding-top: 300px; }
}

/* ================= Case study v3 type scale (Figma 429:19419) =================
   Learn is the trial page: section headings 24px and body 16px on desktop.
   Sits on top of .v2; CDC and the other pages move over once it's signed off. */
.shot video { display: block; width: 100%; height: 100%; object-fit: contain; }
.v3 .case-section h2 { font-size: calc(18px * var(--fs, 1)); line-height: calc(24px * var(--fs, 1)); }
.v3 .case-section p { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
.v3 .stat-big { display: block; font-size: calc(32px * var(--fs, 1)); line-height: calc(42px * var(--fs, 1)); }

@media (min-width: 768px) {
  .v3 .case-section h2 { font-size: calc(24px * var(--fs, 1)); line-height: calc(32px * var(--fs, 1)); }
  .v3 .case-section p { font-size: calc(16px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); }
  .v3 .stat-big { font-size: calc(40px * var(--fs, 1)); line-height: calc(53px * var(--fs, 1)); }
}

/* ================= Guide (Figma 352:19420) ================= */
/* Command blocks with a copy button, the way Claude shows code. The Figma
   frame sets commands as plain text; the box and button are added here. */
.guide .case-sub { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
.guide .prose strong { font-weight: 700; }
.guide .prose a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
/* Numbers drawn by hand so they start on the column edge; the browser's
   outside marker overhangs a 24px indent in a monospace face. */
.guide .prose ol { list-style: none; counter-reset: step; }
.guide .prose ol li { position: relative; padding-left: 3ch; counter-increment: step; }
.guide .prose ol li::before { content: counter(step) "."; position: absolute; left: 0; }
.guide h3 { font-weight: 700; color: var(--subtitle); }

.cmd {
  position: relative;
  min-width: 0;
  background: var(--code-bg);
  border-radius: 6px;
}
.cmd pre {
  margin: 0;
  padding: 14px 16px;
  padding-right: 72px;
  overflow-x: auto;
  font-family: 'Roboto Mono', ui-monospace, monospace;
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(18px * var(--fs, 1));
  color: var(--body);
  white-space: pre;
}
.cmd .c { color: var(--year); }  /* shell comments */
.cmd-copy {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 6px;
  border-radius: 4px;
  font-size: 11px;
  line-height: 14px;
  letter-spacing: 0.05em;
  color: var(--year);
  background: var(--code-bg);
}
.cmd-copy:hover, .cmd-copy:focus-visible { color: var(--body); }
.cmd-copy svg { width: 12px; height: 12px; flex: none; }
.cmd-copy .when-done { display: none; }
.cmd-copy.is-done .when-idle { display: none; }
.cmd-copy.is-done .when-done { display: inline; }

.table-wrap { min-width: 0; overflow-x: auto; }
.guide table {
  width: 100%;
  border-collapse: collapse;
  font-size: calc(12px * var(--fs, 1));
  line-height: calc(16px * var(--fs, 1));
  color: var(--subtitle);
  text-align: left;
}
.guide th { font-weight: 500; color: var(--body); white-space: nowrap; }
.guide th, .guide td { padding: 8px 12px 8px 0; border-bottom: 1px solid var(--code-bg); vertical-align: top; }
.guide thead th { border-bottom-color: var(--chip); }
.guide td.mono { white-space: nowrap; }

/* Collapsible section: the summary reads as a section heading with a +/- */
.more > summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  cursor: pointer;
  list-style: none;
}
.more > summary::-webkit-details-marker { display: none; }
.more > summary::after { content: "+"; font-size: 18px; color: var(--year); }
.more[open] > summary::after { content: "\2212"; }
.more > summary:hover h2, .more > summary:focus-visible h2 { text-decoration: underline; text-underline-offset: 3px; }
.more-title { display: flex; flex-direction: column; gap: 4px; }
.more-hint { font-size: calc(12px * var(--fs, 1)); line-height: calc(16px * var(--fs, 1)); color: var(--year); }
.more[open] .more-hint { display: none; }
.more-body { display: flex; flex-direction: column; gap: 16px; margin-top: 16px; min-width: 0; }

@media (min-width: 768px) {
  .more-hint { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
  .guide .case-sub { font-size: calc(16px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); }
  .cmd pre { font-size: calc(14px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); }
  .guide table { font-size: calc(14px * var(--fs, 1)); line-height: calc(18px * var(--fs, 1)); }
  .guide .case-section h3 { font-size: calc(16px * var(--fs, 1)); line-height: calc(21px * var(--fs, 1)); }
}

/* ================= Key guide (fx/fx.js, fx/case-fx.js) ================= */
/* Bottom-right corner of the screen, built on the first arrow press and gone
   a few seconds later. Pointer devices on wide screens only. */
.key-guide {
  position: fixed;
  right: 32px;
  bottom: 24px;
  z-index: 20;
  display: none;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--code-bg);
  border-radius: 6px;
  font-size: 11px;
  line-height: 18px;
  letter-spacing: 0.05em;
  color: var(--year);
  pointer-events: none;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 250ms ease, transform 250ms ease;
}
@media (min-width: 768px) and (hover: hover) {
  .key-guide { display: flex; }
}
.key-guide.is-on { opacity: 1; transform: none; }
.key-guide div { display: flex; align-items: center; gap: 4px; }
.key-guide kbd {
  min-width: 20px;
  padding: 0 5px;
  font: inherit;
  text-align: center;
  color: var(--body);
  background: var(--code-bg);
  border-radius: 3px;
}
.key-guide span { margin-left: 6px; }
/* the home footer is pinned to the bottom, so sit just above it */
body:has(.home) .key-guide { bottom: 52px; }
@media (prefers-reduced-motion: reduce) { .key-guide { transition: none; } }
