/* v3: a contact sheet on a light table. The page is the table, the work is printed film strips on photo paper,
   and the picks are circled in red grease pencil. One deliberate light look, so colours are set for every theme. */
:root {
  --table: #e6e0d4;
  --paper: #f7f4ee;
  --ink: #1a1915;
  --ink-2: #5a564e;
  --ink-3: #8b867b;
  --rule: #cfc7b7;
  --film: #151412;
  --film-2: #24221e;
  --edge: #d8c9a4;
  --red: #d2372a;
  --tape: #111;

  --cond: "Archivo", "Arial Narrow", Arial, sans-serif;
  --sans: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;
  --hand: "Permanent Marker", "Marker Felt", cursive;

  --fs-micro: 0.6875rem;
  --fs-small: 0.8125rem;
  --fs-ui: 0.9375rem;
  --fs-body: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  --fs-h1: clamp(3rem, 0.6rem + 6.4vw, 7.5rem);
  --fs-h2: clamp(2.75rem, 1rem + 6vw, 7rem);

  --gut: max(16px, 4.5vw);
  --barh: 60px;
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-io: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  color-scheme: light;
}
*, *::before, *::after { box-sizing: border-box; }
html { background: var(--grain), var(--table); scroll-behavior: smooth; scroll-padding-top: calc(var(--barh) + 12px); scrollbar-gutter: stable; }
/* film grain on the table, under everything that sits on it */
:root { --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.15' numOctaves='1' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.16 0 0 0 0 0.14 0 0 0 0 0.11 0.6 0 0 0 -0.26'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E"); }
body {
  margin: 0; background: var(--grain), var(--table); color: var(--ink); font-family: var(--sans); font-size: var(--fs-body); line-height: 1.55;
  -webkit-font-smoothing: antialiased; overflow-x: hidden;
}
/* paper grain over everything, very faint */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 90; pointer-events: none; opacity: 0.32; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.45 0 0 0 0 0.4 0 0 0 0 0.32 0 0 0 0.18 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* inertial smooth scrolling (Lenis) */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }
img, video { display: block; max-width: 100%; }
a { color: inherit; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }
[hidden] { display: none !important; }
.wrap { padding-inline: var(--gut); max-width: 1680px; margin-inline: auto; }
.mono { font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.04em; text-transform: uppercase; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.note { font-family: var(--hand); font-weight: 400; color: var(--red); letter-spacing: 0.01em; }

/* carets on links and controls, drawn as SVG chevrons so they stay crisp in every font, centred on the capitals */
.crt { display: inline-block; width: 0.5em; height: 0.8em; vertical-align: -0.06em; overflow: visible;
  fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- top bar ---------- */
.top { position: sticky; top: 0; z-index: 50; height: var(--barh); background: var(--grain), color-mix(in srgb, var(--table) 66%, transparent); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.top .wrap { height: 100%; display: flex; align-items: center; gap: 24px; }
.stamp {
  position: relative; margin-right: auto; padding: 4px 11px 3px; color: var(--red); text-decoration: none;
  font-family: var(--cond); font-weight: 800; font-stretch: 75%; font-size: 1.125rem; letter-spacing: 0.04em; transform: rotate(-2deg);
}
/* the box is drawn in grease pencil: four straight strokes, slightly off true, that overshoot at the corners */
.stamp::before { content: ""; position: absolute; inset: -4px -6px; pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 34' preserveAspectRatio='none'%3E%3Cpath fill='none' stroke='%23d2372a' stroke-width='2.2' stroke-linecap='round' d='M1 5.6 L119 4 M114 0.8 L115.4 33.2 M119.4 30 L0.8 31.2 M5.4 33.6 L6.2 1'/%3E%3C/svg%3E") center / 100% 100% no-repeat; }
.nav { display: flex; gap: clamp(14px, 2.4vw, 32px); }
.nav a { position: relative; font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.08em; text-transform: uppercase; text-decoration: none; color: var(--ink-2); padding: 6px 0; transition: color 160ms ease; }
.nav a:hover, .nav a.on { color: var(--ink); }
/* the current section gets a grease-pencil underline */
.nav a::after {
  content: ""; position: absolute; left: -3px; right: -3px; bottom: 0; height: 6px; transform: scaleX(0); transform-origin: left; transition: transform 320ms var(--ease-out);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 6' preserveAspectRatio='none'%3E%3Cpath d='M1 4 C 20 1.5, 45 5, 70 2.5 S 95 3, 99 2' fill='none' stroke='%23d2372a' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}
.nav a.on::after { transform: scaleX(1); }
/* case study controls share the bar: the section links fade out, these fade in */
.top .wrap { position: relative; }
.nav { transition: opacity 160ms ease; }
.top.case .nav { opacity: 0; pointer-events: none; }
.case-nav {
  position: absolute; top: 0; bottom: 0; left: var(--gut); right: var(--gut); display: flex; align-items: center; justify-content: flex-end; pointer-events: none;
  opacity: 0; visibility: hidden; transform: translateY(4px); transition: opacity 200ms ease, transform 260ms var(--ease-out), visibility 0s 200ms;
}
.top.case-on .case-nav { opacity: 1; visibility: visible; transform: none; transition: opacity 200ms ease, transform 260ms var(--ease-out), visibility 0s; }
.case-nav button { pointer-events: auto; border: 0; background: none; cursor: pointer; padding: 8px 0; font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); transition: color 160ms ease; }
.case-nav button:hover { color: var(--red); }
/* prev, frame count and next sit centred on the page; back is at the right */
.v-pn { position: absolute; left: 50%; transform: translateX(-50%); display: flex; align-items: center; white-space: nowrap; }
.v-frame { color: var(--ink-3); }
/* thin dividers either side of the frame count */
.v-frame::before, .v-frame::after { content: "|"; margin-inline: 18px; color: var(--ink-3); }

/* ---------- hero ---------- */
.hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 300px); gap: 24px 48px; align-items: end; padding-top: clamp(32px, 4.5vw, 72px); padding-bottom: clamp(28px, 3.5vw, 48px); }
.hero h1, .sec-head h2, .hello-sec h2, .v-title {
  margin: 0; font-family: var(--cond); font-weight: 800; font-stretch: 68%; text-transform: uppercase; line-height: 0.86; letter-spacing: -0.005em;
}
.hero h1 { font-size: var(--fs-h1); max-width: 15ch; text-wrap: balance; }
.hero h1 .amp { color: var(--red); }
.hero-side { padding-bottom: 0.6em; }
.hero-side p { margin: 0 0 14px; color: var(--ink-2); font-size: var(--fs-ui); }
.hero-side .hero-meta { margin: 0; color: var(--ink-3); }
/* a proofreader's insert on the headline: a red caret before the full stop, with the added words written above */
.nb { white-space: nowrap; }
.hero h1 .ins, .hello-sec h2 .ins { position: relative; display: inline-block; width: 0.06em; height: 0.7em; }
.ins svg { position: absolute; left: -0.15em; bottom: -0.2em; width: 0.32em; height: 0.26em; overflow: visible; }
/* drawn like the sheet's grease-pencil marks: two quick, slightly bowed strokes that cross past the point */
.ins path { fill: none; stroke: var(--red); stroke-width: 2.8; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; opacity: 0.92; }
.ins .note { position: absolute; left: -0.12em; bottom: 0.78em; font-size: max(1.15rem, 0.24em); line-height: 1; white-space: nowrap; text-transform: none; letter-spacing: 0; transform: rotate(-6deg); transform-origin: left bottom; }
/* in the contact line the insert sits after the "?", so the note is written past it and the caret reaches back before it */
.hello-sec h2 .ins .note { left: 0.2em; bottom: 0.3em; }
.hello-sec h2 .ins svg { left: -0.6em; bottom: -0.1em; }

/* ---------- the sheet ---------- */
.sheet-sec { position: relative; }

.sheet {
  position: relative; background: var(--paper); padding: clamp(18px, 2.6vw, 40px) clamp(14px, 2.2vw, 36px) clamp(16px, 2vw, 28px);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04), 0 18px 40px -18px rgba(60, 45, 20, 0.35), 0 2px 6px rgba(60, 45, 20, 0.08);
}
.strips { display: grid; gap: clamp(14px, 1.8vw, 26px); }
.strip { --n: 3; position: relative; background: var(--film); padding: 30px 12px 34px; }
.strip:nth-child(3n + 1) { transform: rotate(-0.25deg); }
.strip:nth-child(3n + 2) { transform: rotate(0.2deg) translateX(4px); }
.strip:nth-child(3n) { transform: rotate(-0.1deg) translateX(-3px); }
/* a short last strip keeps running as blank film to the end of the row, then ends in one straight, angled cut.
   The clip reaches well above and below the film so grease-pencil marks spilling over the edges aren't cut */
.strip.cut { clip-path: polygon(-60px -60px, 100% -60px, 100% 0, calc(100% - 36px) 100%, calc(100% - 36px) calc(100% + 60px), -60px calc(100% + 60px)); }
/* sprocket holes, top and bottom */
.strip::before, .strip::after {
  content: ""; position: absolute; left: 0; right: 0; height: 9px;
  background: radial-gradient(closest-side, var(--film-2) 92%, transparent) 0 0 / 15px 9px repeat-x;
  -webkit-mask: linear-gradient(90deg, #000 0 9px, transparent 9px) 0 0 / 15px 100%; mask: linear-gradient(90deg, #000 0 9px, transparent 9px) 0 0 / 15px 100%;
}
.strip::before { top: 6px; }
.strip::after { bottom: 6px; }
.edge { position: absolute; left: 12px; right: 12px; display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); gap: 12px; font-family: var(--mono); font-size: 10.5px; line-height: 1; letter-spacing: 0.08em; color: var(--edge); white-space: nowrap; pointer-events: none; }
.edge.t { top: 17px; }
.edge.b { bottom: 15px; }
.edge span { overflow: hidden; text-overflow: ellipsis; }
.edge.b span { text-transform: uppercase; }
.edge.b i { font-style: normal; opacity: 0.6; }
.frames { display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); gap: 12px; }
.frame {
  position: relative; display: block; aspect-ratio: 3 / 2; background: #2b2925; outline-offset: 4px; text-decoration: none;
}
.frame img { width: 100%; height: 100%; object-fit: cover; }
.frame .ring, .shot .ring { position: absolute; inset: -16px -14px; width: calc(100% + 28px); height: calc(100% + 32px); overflow: visible; pointer-events: none; z-index: 2; }
.ring path { fill: none; stroke: var(--red); stroke-width: 1.15; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; opacity: 0.92; }
.drawn .ring path { animation: draw 900ms var(--ease-io) forwards; animation-delay: var(--d, 0ms); }
/* crop marks and the box sit a little tighter to the frame than the loop */
.frame .mk-box, .shot .mk-box, .frame .mk-crop, .shot .mk-crop, .frame .mk-brackets, .shot .mk-brackets { inset: -8px; width: calc(100% + 16px); height: calc(100% + 16px); }
.frame .mk-wave, .shot .mk-wave { inset: 0; width: 100%; height: 100%; }
/* small marks keep their shape in a corner, at a slight tilt */
.frame .ring.sm, .shot .ring.sm { inset: auto; width: clamp(42px, 4vw, 64px); height: clamp(42px, 4vw, 64px); transform: rotate(var(--tilt, 0deg)); }
.ring.sm path { stroke-width: 2.6; }
.ring.sm.at-tl { top: -14px; left: -12px; }
.ring.sm.at-tr { top: -14px; right: -12px; }
.ring.sm.at-br { bottom: -10px; right: -10px; }
.ring.sm.at-bl { bottom: -10px; left: -10px; }
@keyframes draw { to { stroke-dashoffset: 0; } }
.pick {
  position: absolute; z-index: 3; right: -6px; top: -40px; font-family: var(--hand); color: var(--red); font-size: clamp(1.3rem, 1.05rem + 0.8vw, 1.75rem); line-height: 1;
  transform: rotate(-5deg); white-space: nowrap; opacity: 0; transition: opacity 400ms ease 700ms; pointer-events: none;
}
.drawn .pick { opacity: 1; }
.pick.n-tl { right: auto; left: 64px; transform: rotate(-4deg); }
.pick.n-bl { top: auto; right: auto; bottom: 10px; left: 12px; transform: rotate(-3deg); }
.pick.n-br { top: auto; bottom: 10px; right: 14px; transform: rotate(-6deg); }
/* a few notes run off the film onto the sheet (desktop only, where there is paper to run onto) */
@media (min-width: 761px) {
  .frame .pick.leak.n-tr { right: -1.1em; top: -56px; transform: rotate(-7deg); }
  .frame .pick.leak.n-tl { left: -0.5em; top: -52px; transform: rotate(-6deg); }
}
@media (hover: hover) and (pointer: fine) {
  .frame { cursor: zoom-in; }
  .frame:hover img { filter: brightness(1.06); }
}
.sheet-foot { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 18px 2px 0; color: var(--ink-3); }

/* the loupe: a ring of glass that magnifies whatever frame is under the pointer */
.loupe {
  position: fixed; left: 0; top: 0; z-index: 40; width: 209px; height: 209px; margin: -104.5px 0 0 -104.5px; border-radius: 50%; pointer-events: none;
  background-color: var(--film); background-repeat: no-repeat; opacity: 0; transform: scale(0.6); transition: opacity 180ms ease, transform 240ms var(--ease-out);
  box-shadow: 0 0 0 7px #1d1c19, 0 0 0 9px #3a3832, 0 16px 34px rgba(0, 0, 0, 0.35), inset 0 0 22px rgba(0, 0, 0, 0.35);
}
.loupe.on { opacity: 1; transform: scale(1); }
/* the loupe is the pointer while it's up */
.looking .frame { cursor: none; }
/* once three.js has loaded, a lens shader draws inside the ring instead of the flat zoom */
.loupe canvas { display: none; position: absolute; inset: 0; width: 100% !important; height: 100% !important; border-radius: 50%; }
.loupe.gl { background-image: none !important; }
.loupe.gl canvas { display: block; }

/* ---------- behind the camera: one roll of my photographs, scrolled sideways ---------- */
.photos-sec { padding-top: clamp(96px, 12vw, 180px); }
/* a quieter head than the other sections, so the work stays the main story */
.reel {
  --h: clamp(220px, 10rem + 10vw, 340px);
  display: flex; gap: 12px; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scroll-padding-inline: 22px;
  padding: 34px 22px 36px; transform: rotate(-0.25deg); scrollbar-width: none;
  /* sprocket holes scroll with the frames (background-attachment: local) */
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='9'%3E%3Crect width='9' height='9' rx='2' fill='%2324221e'/%3E%3C/svg%3E") 0 6px / 15px 9px repeat-x local,
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='9'%3E%3Crect width='9' height='9' rx='2' fill='%2324221e'/%3E%3C/svg%3E") 0 calc(100% - 6px) / 15px 9px repeat-x local,
    var(--film);
  box-shadow: 0 18px 40px -22px rgba(60, 45, 20, 0.45);
}
/* no scrollbar: it scrolls by drag, wheel, swipe or arrow keys */
.reel::-webkit-scrollbar { display: none; }
.reel:focus-visible { outline-offset: 6px; }
.shot { position: relative; flex: none; height: var(--h); aspect-ratio: var(--ar); padding: 0; border: 0; background: #2b2925; scroll-snap-align: start; cursor: zoom-in; }
.shot img { width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.shot .re { position: absolute; left: 0; font-family: var(--mono); font-size: 10.5px; line-height: 1; letter-spacing: 0.08em; color: var(--edge); white-space: nowrap; pointer-events: none; }
.shot .re.t { top: -21px; }
.shot .re.b { bottom: -22px; }
.shot .pick { top: -27px; right: 6px; }
.shot .pick.n-tl { right: auto; left: 52px; }
.reel.dragging { cursor: grabbing; scroll-snap-type: none; }
.reel.dragging .shot { cursor: grabbing; }
@media (hover: hover) and (pointer: fine) {
  .reel, .reel .shot { cursor: grab; }
  .shot:hover img { filter: brightness(1.06); }
}
.reel-foot { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 18px 2px 0; color: var(--ink-3); }
.reel-foot a { color: var(--ink); text-decoration: none; transition: color 160ms ease; }
.reel-foot a:hover { color: var(--red); }

/* ---------- section heads ---------- */
.sec-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 300px); gap: 16px 48px; align-items: end; margin-bottom: clamp(26px, 3vw, 44px); }
.sec-head h2 { font-size: var(--fs-h2); }
.sec-head p { margin: 0; padding-bottom: 0.5em; color: var(--ink-2); font-size: var(--fs-ui); }
.log-sec, .hello-sec { padding-top: clamp(96px, 12vw, 180px); }

/* ---------- so far: a shoot log ---------- */
/* the same margin all round: top to the column labels, bottom to the last rule */
.logsheet { background: var(--paper); padding: clamp(14px, 2.4vw, 36px); box-shadow: 0 18px 40px -22px rgba(60, 45, 20, 0.35), 0 2px 6px rgba(60, 45, 20, 0.07);}
.log-cols, .roll summary { display: grid; grid-template-columns: 11rem minmax(0, 1fr) minmax(0, 1.2fr) 1.5rem; gap: 16px; align-items: center; }
.log-cols { padding: 0 0 10px; color: var(--ink-3); border-bottom: 2px solid var(--ink); }
.roll { border-bottom: 1px solid var(--rule); }
.roll summary { list-style: none; cursor: pointer; padding: 16px 0; }
.roll summary::-webkit-details-marker { display: none; }
.roll .when { font-family: var(--mono); font-size: var(--fs-small); }
.roll .where { position: relative; justify-self: start; font-family: var(--cond); font-stretch: 80%; font-weight: 700; font-size: clamp(1.25rem, 1rem + 0.9vw, 1.75rem); line-height: 1.1; text-transform: uppercase; }
.roll .what { color: var(--ink-2); font-size: var(--fs-ui); }
.roll .plus { font-family: var(--mono); color: var(--ink-3); transition: transform 300ms var(--ease-out); justify-self: end; }
.roll[open]:not(.closing) .plus { transform: rotate(45deg); color: var(--red); }
.roll .now { position: absolute; left: calc(100% + 10px); top: -10px; font-family: var(--hand); font-weight: 400; font-size: 1rem; color: var(--red); text-transform: none; transform: rotate(-6deg); white-space: nowrap; }
.roll .body { overflow: hidden; display: grid; grid-template-columns: 11rem minmax(0, 1fr); gap: 16px; padding: 0; }
.roll .body > :last-child { margin-bottom: 22px; }
.roll .body ul { grid-column: 2; margin: 0; padding-left: 1.1em; color: var(--ink-2); max-width: 70ch; }
.roll .body li + li { margin-top: 6px; }
/* set like every other link: uppercase mono with a caret, red on hover */
.roll .body .go { grid-column: 2; justify-self: start; margin-top: 4px; border: 0; background: none; padding: 0; cursor: pointer; color: var(--ink);
  font-family: var(--mono); font-weight: 500; font-size: var(--fs-small); letter-spacing: 0.08em; text-transform: uppercase; transition: color 160ms ease; }
@media (hover: hover) { .roll .body .go:hover { color: var(--red); } }
@media (hover: hover) and (pointer: fine) { .roll summary:hover .where { color: var(--red); } }

/* ---------- contact ---------- */
.hello-sec { padding-bottom: 28px; }
.hello-sec h2 { font-size: var(--fs-h2); max-width: 15ch; text-wrap: balance; }
/* the address on a strip of label-maker tape */
.tape { display: inline-flex; align-items: center; gap: 4px; margin-top: clamp(28px, 4vw, 48px); padding: 8px 8px 8px 18px; background: var(--tape); color: #f1efe8; transform: rotate(-1.2deg); box-shadow: 0 8px 18px -10px rgba(0, 0, 0, 0.6); }
.tape #mail { font-family: var(--mono); font-weight: 500; font-size: clamp(1rem, 0.85rem + 0.7vw, 1.375rem); letter-spacing: 0.1em; text-transform: uppercase; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.15), 0 -1px 0 rgba(0, 0, 0, 0.6); }
.tape button { position: relative; margin-left: 12px; border: 0; cursor: pointer; padding: 9px 14px; background: var(--red); color: #fff; font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.08em; text-transform: uppercase; transition: transform 160ms var(--ease-out); }
.tape button:active { transform: scale(0.96); }
.tape .l-done { position: absolute; inset: 0; display: grid; place-items: center; opacity: 0; }
.tape button.done .l-copy { opacity: 0; }
.tape button.done .l-done { opacity: 1; }
.links { list-style: none; margin: 40px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 12px 36px; }
.links a { font-family: var(--mono); font-weight: 500; font-size: var(--fs-small); letter-spacing: 0.08em; text-transform: uppercase; text-decoration: none; transition: color 160ms ease; }
.links a:hover { color: var(--red); }
.foot { display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: clamp(80px, 10vw, 140px); padding-top: 18px; border-top: 1px solid var(--rule); color: var(--ink-3); }

/* ---------- project viewer: the frame blown up into a sheet of prints ---------- */
/* while a case study is open the sheet is pinned where it was (top is set from script) and the viewer is the page,
   pulled up under the shared bar so it scrolls beneath the frosted bar like the sheet does */
body.viewing main { position: fixed; left: 0; right: 0; }
.viewer { position: relative; z-index: 45; min-height: 100vh; margin-top: calc(-1 * var(--barh)); background: var(--grain), var(--table); }
.viewer.anim-in { animation: v-in 520ms var(--ease-drawer) both; }
.viewer.anim-out { animation: v-out 320ms var(--ease-io) both; }
@keyframes v-in { from { transform: translateY(40px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes v-out { to { transform: translateY(24px); opacity: 0; } }
.v-in { padding-top: calc(var(--barh) + clamp(32px, 5vw, 72px)); padding-bottom: 96px; }
.v-head { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 340px); gap: 24px 48px; align-items: end; }
.v-title { font-size: var(--fs-h2); }
.v-meta { margin: 0; display: grid; gap: 10px; padding-bottom: 0.5em; }
.v-meta div { display: grid; grid-template-columns: 6.5rem 1fr; gap: 12px; border-top: 1px solid var(--rule); padding-top: 8px; }
.v-meta dt { font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3); padding-top: 3px; }
.v-meta dd { margin: 0; font-size: var(--fs-small); }
.v-cover { position: relative; margin: clamp(28px, 4vw, 56px) 0 0; background: var(--film); padding: clamp(8px, 1vw, 14px); }
.v-cover img { width: 100%; max-height: 78vh; object-fit: cover; }
.v-intro { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); gap: 24px 48px; margin-top: clamp(40px, 5vw, 72px); }
.v-intro h3 { margin: 0; font-family: var(--hand); font-weight: 400; color: var(--red); font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.4rem); line-height: 1.1; transform: rotate(-2deg); transform-origin: left; }
.prose p { margin: 0 0 1em; max-width: 64ch; }
.v-links { display: flex; flex-wrap: wrap; gap: 12px; }
.v-links a { display: inline-block; padding: 10px 16px; background: var(--ink); color: var(--paper); text-decoration: none; font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.08em; text-transform: uppercase; }
.v-block { margin-top: clamp(56px, 7vw, 104px); }
.v-block.join { margin-top: clamp(16px, 2.2vw, 32px); } /* continues the block above, at the prints gap */
.v-block .txt { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); gap: 12px 48px; margin-bottom: 26px; }
.v-block h4 { margin: 0; font-family: var(--cond); font-stretch: 80%; font-weight: 800; text-transform: uppercase; font-size: clamp(1.4rem, 1.1rem + 1vw, 2rem); line-height: 1; }
.prints { display: grid; gap: clamp(16px, 2.2vw, 32px); align-items: start; }
.prints.m-2 { grid-template-columns: var(--cols, repeat(2, minmax(0, 1fr))); } /* --cols: widths in proportion to aspect ratios give one row height */
.prints.m-3 { grid-template-columns: var(--cols, repeat(3, minmax(0, 1fr))); }
/* each picture is a bordered print */
.print { margin: 0; padding: clamp(8px, 1vw, 14px); background: #fff; box-shadow: 0 14px 28px -18px rgba(60, 45, 20, 0.5), 0 1px 3px rgba(60, 45, 20, 0.12); cursor: zoom-in; transition: transform 300ms var(--ease-out); }
.print:nth-child(3n + 1) { transform: rotate(-0.35deg); }
.print:nth-child(3n + 2) { transform: rotate(0.3deg); }
/* every print has a dark ground behind it, so transparent artwork with light lines still shows */
.print img, .print video { width: 100%; height: auto; background: var(--film); }
.print.vid { cursor: default; }
/* films have no transparency, so their ground matches the white border; a dark one bleeds through the tilted, un-antialiased edge */
.print.vid video { aspect-ratio: var(--ar, 16 / 9); object-fit: cover; background: #fff; }
/* sound toggle sits on the film's bottom-left corner, inside the white border */
/* films sit straight: a tilted video shimmers along its edge while it plays */
.print.vid { position: relative; transform: none; }
.snd { position: absolute; left: calc(clamp(8px, 1vw, 14px) + 10px); bottom: calc(clamp(8px, 1vw, 14px) + 10px); display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 50%; background: rgba(21, 20, 18, 0.72); color: #fff; cursor: pointer; transition: background 160ms ease; }
.snd svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.snd .spk { fill: currentColor; }
.snd .on, .snd[aria-pressed="true"] .off { display: none; }
.snd[aria-pressed="true"] .on { display: inline; }
.snd[aria-pressed="true"] { background: var(--red); }
@media (hover: hover) and (pointer: fine) { .snd:hover { background: rgba(21, 20, 18, 0.9); } .snd[aria-pressed="true"]:hover { background: var(--red); filter: brightness(1.1); } }
@media (hover: hover) and (pointer: fine) { .print:not(.vid):hover { transform: rotate(0deg) translateY(-3px); } }
.v-pn-foot { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: clamp(72px, 9vw, 128px); border-top: 2px solid var(--ink); }
.v-pn-foot button { border: 0; background: none; cursor: pointer; text-align: left; padding: 18px 0; display: grid; gap: 6px; }
.v-pn-foot button + button { text-align: right; }
.v-pn-foot small { font-family: var(--mono); font-size: var(--fs-micro); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
.v-pn-foot b { font-family: var(--cond); font-stretch: 75%; font-weight: 800; text-transform: uppercase; font-size: clamp(1.5rem, 1rem + 2vw, 2.75rem); line-height: 1; transition: color 160ms ease; }
.v-pn-foot button:hover b { color: var(--red); }

/* ---------- lightbox ---------- */
.lightbox { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: 24px; background: rgba(21, 20, 18, 0.92); cursor: zoom-out; animation: lb 220ms ease both; }
@keyframes lb { from { opacity: 0; } }
.lightbox figure { margin: 0; display: grid; gap: 12px; justify-items: center; }
.lightbox img { max-width: 94vw; max-height: 86vh; object-fit: contain; background: var(--film); border: 10px solid #fff; }
.lightbox figcaption { color: var(--edge); }
.lb-close { position: absolute; top: max(14px, env(safe-area-inset-top)); right: var(--gut); border: 0; background: none; padding: 8px 0; cursor: pointer; color: var(--edge); transition: color 160ms ease; }
.lb-close:hover { color: #fff; }

/* ---------- narrow ---------- */
@media (max-width: 1100px) {
}
@media (max-width: 760px) {
  :root { --barh: 54px; }
  .nav { display: none; }
  .hero, .sec-head, .v-head, .v-intro, .v-block .txt { grid-template-columns: 1fr; }
  .hero-side { padding-bottom: 0; }
  .strip { --n: 2; padding: 24px 8px 28px; }
  .strip:nth-child(n) { transform: rotate(-0.2deg); }
  .strip:nth-child(even) { transform: rotate(0.2deg); }
  .frames { gap: 8px; }
  .edge { font-size: 8.5px; left: 8px; right: 8px; gap: 8px; }
  .edge.b i { display: none; }
  .pick { top: -30px; font-size: 1.1rem; }
  .pick.n-tl { left: 0; }
  .ring path { stroke-width: 1.7; }
  .ring.sm path { stroke-width: 3; }
  /* the roll runs off both edges of the screen, so it reads as something to swipe */
  .reel { --h: 260px; margin-inline: calc(-1 * var(--gut)); padding-inline: var(--gut); scroll-padding-inline: var(--gut); gap: 8px; transform: none; }
  .shot .re { font-size: 8.5px; }
  .log-cols { display: none; }
  .roll:first-child summary { padding-top: 0; }
  .roll summary { grid-template-columns: minmax(0, 1fr) 1.5rem; row-gap: 2px; }
  .roll .when { grid-column: 1; grid-row: 2; }
  .roll .where { grid-column: 1; grid-row: 1; }
  .roll .what { grid-column: 1; grid-row: 3; }
  .roll .plus { grid-column: 2; grid-row: 1; }
  .roll .body { grid-template-columns: minmax(0, 1fr); }
  .roll .body ul, .roll .body .go { grid-column: 1; }
  .prints.m-2, .prints.m-3 { grid-template-columns: 1fr; }
  .v-frame { display: none; }
  /* nudged right of centre so it clears the stamp on a phone */
  .v-pn { left: calc(50% + 22px); }
  #v-next::before { content: "|"; margin-inline: 14px; color: var(--ink-3); }
  .case-nav .l-long { display: none; }
  .tape { max-width: 100%; }
  .tape #mail { font-size: 0.9375rem; letter-spacing: 0.06em; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .drawn .ring path { animation: none; stroke-dashoffset: 0; }
  .viewer.anim-in, .viewer.anim-out, .lightbox { animation: none; }
}
