/* One typeface, two sizes, one 12-column grid shared by every section. */
:root {
  --bg: #fff;
  --panel: #f2f2f0;
  --ink: #141414;
  --ink-2: #6b6b6b;
  --line: #d9d9d6;
  --f: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --display: var(--f); --display-w: 500; --display-ls: -.015em;
  --big: clamp(24px, 2.7vw, 36px);
  --gap: clamp(16px, 2vw, 24px);
  --sign: "Atkinson Hyperlegible Next", "Helvetica Neue", Arial, sans-serif;
  --tide: #2a63a8; --calder: #c2492a; --night: #b97800; --read: #55732a;
  --studio: #4a4a46; --arrivals: #1f3a5f; --brook: #0b6e4f; --tutor: #a8893a; --college: #8a6d5a;
  --c: var(--ink);
  --radius: 10px;
  --ease: cubic-bezier(.2, .7, .2, 1);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --bg: #121212; --panel: #1b1b1b; --ink: #e6e6e3; --ink-2: #8e8e8a; --line: #333331; --tide: #6fa3e0; --calder: #ef7a58; --night: #f0a92a; --read: #9fbe68; }
}
:root[data-theme="dark"] { --bg: #121212; --panel: #1b1b1b; --ink: #e6e6e3; --ink-2: #8e8e8a; --line: #333331; --tide: #6fa3e0; --calder: #ef7a58; --night: #f0a92a; --read: #9fbe68; color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }

html[data-font="archivo"] { --f: "Archivo", "Helvetica Neue", Arial, sans-serif; }
html[data-font="franklin"] { --f: "Libre Franklin", "Helvetica Neue", Arial, sans-serif; }
html[data-font="hanken"] { --f: "Hanken Grotesk", "Helvetica Neue", Arial, sans-serif; }
html[data-font="schibsted"] { --f: "Schibsted Grotesk", "Helvetica Neue", Arial, sans-serif; }
html[data-font="geist"] { --f: "Geist", "Helvetica Neue", Arial, sans-serif; }
html[data-font="source-serif"] { --f: "Source Serif 4", Georgia, serif; }
/* Pairings: a display face for headlines and statements, Archivo for everything else. */
html[data-font="baskerville"] { --display: "Libre Baskerville", Baskerville, Georgia, serif; --display-w: 400; --display-ls: -.02em; }
html[data-font="young"] { --display: "Young Serif", Georgia, serif; --display-w: 400; --display-ls: -.02em; }
html[data-font="bricolage"] { --display: "Bricolage Grotesque", "Archivo", sans-serif; --display-w: 500; --display-ls: -.03em; }

/* The light switch: the whole site goes ultramarine with warm white type. Overrides light/dark. */
:root[data-palette="blue"] {
  --bg: #0b1fc9; --panel: #1729cf; --ink: #f6f5f1; --ink-2: #b4b8ec; --line: #4352d8;
  --tide: #9cc4ff; --calder: #ffb39c; --night: #ffd27a; --read: #c8e39a; color-scheme: dark;
}

/* The page takes a faint wash of whichever project you're pointing at, or reading. */
body[data-tint="tide"]   { --c: var(--tide); }
body[data-tint="calder"] { --c: var(--calder); }
body[data-tint="night"]  { --c: var(--night); }
body[data-tint="read"]   { --c: var(--read); }
body[data-tint="studio"] { --c: var(--studio); }
body[data-tint="arrivals"] { --c: var(--arrivals); }
body[data-tint="brook"]  { --c: var(--brook); }
body[data-tint="tutor"]  { --c: var(--tutor); }
body[data-tint="college"] { --c: var(--college); }
/* The reel's real work, each a tone picked from the piece itself. */
body[data-tint="cursor"]     { --c: #8d8c86; }  /* the grey dot field */
body[data-tint="pricing"]    { --c: #2ecf72; }  /* the green plan banners */
body[data-tint="button"]     { --c: #a39e92; }  /* the warm grey ground */
body[data-tint="domain"]     { --c: #2f5fd0; }  /* the blue links and card */
body[data-tint="enterprise"] { --c: #a8d85a; }  /* the lime headline and button */
body[data-tint="plus"]       { --c: #3fc6ea; }  /* the cyan trial badge */
body[data-tint="trial"]      { --c: #e0b83c; }  /* the yellow in the hero's photos */
body { --page: var(--bg); }
body[data-tint] { --page: color-mix(in oklab, var(--bg) 97.5%, var(--c)); }

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: 24px; }
body {
  margin: 0; background: var(--page); color: var(--ink); transition: background-color .6s var(--ease);
  font: 400 16px/1.45 var(--f); font-variant-numeric: tabular-nums; -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
p a, .contact a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: var(--line); }
p a:hover, .contact a:hover { text-decoration-color: currentColor; }
button { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
main:focus { outline: none; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: absolute; left: 16px; top: -48px; background: var(--ink); color: var(--bg); padding: 8px 12px; z-index: 20; }
.skip:focus { top: 12px; }

.top, main { max-width: 1280px; margin: 0 auto; padding-inline: var(--gap); }
.grid, .top, .row, .info, .colophon, .case-head, .prose, .pager, .section-head {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap);
}

/* ---------- top ---------- */
.top { padding-block: 20px; align-items: center; grid-template-columns: 1fr auto 1fr; }
.brand { grid-column: 1; justify-self: start; display: inline-flex; align-items: center; gap: 9px; align-self: center; }
.mark { width: 10px; height: 10px; border-radius: 2px; background: var(--c); transition: background .6s var(--ease), transform .6s var(--ease); }
.brand:hover .mark { transform: rotate(45deg); }
.top-nav { grid-column: 2; display: flex; gap: 20px; }
.top-nav a { color: var(--ink-2); }
.top-nav a:hover { color: var(--ink); }
.top-end { grid-column: 3; justify-self: end; display: flex; align-items: center; gap: 8px; }
/* Segmented pills for theme and layout. */
.theme, .layout { display: inline-flex; padding: 3px; border: 1px solid var(--line); border-radius: 999px; }
.theme button, .layout button { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; line-height: 1; background: none; border: 0; padding: 7px 11px; border-radius: 999px; color: var(--ink-2); cursor: pointer; transition: color .2s, background .2s; }
.theme button:hover, .layout button:hover { color: var(--ink); }
.theme button[aria-checked="true"], .layout button[aria-checked="true"] { color: var(--bg); background: var(--ink); }
.layout svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; }

/* ---------- index ---------- */
.intro { padding: 16vh 0 14vh; row-gap: 28px; }
.intro h1 { grid-column: 1 / 10; margin: 0; font-family: var(--display); max-width: 17em; font-size: clamp(32px, 4.4vw, 56px); font-weight: 400; line-height: 1.08; letter-spacing: -.02em; text-wrap: balance; }
.intro p { grid-column: 1 / 7; margin: 0; max-width: 34em; color: var(--ink-2); text-wrap: pretty; }
.intro .statement { display: none; }
.intro .statement p { margin: 0; max-width: none; color: inherit; }
.intro .statement p + p { margin-top: .9em; }
/* The contact line is secondary: body size in the second ink, under the statement. */
.intro .statement .statement-sub { margin-top: 16px; font: 400 16px/1.45 var(--f); letter-spacing: 0; color: var(--ink-2); }
.statement a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; text-decoration-color: color-mix(in oklab, currentColor 40%, transparent); transition: text-decoration-color .2s; }
.statement a:hover { text-decoration-color: currentColor; }
.intro .contact { grid-column: 1 / 10; display: flex; align-items: center; gap: 20px; flex-wrap: wrap; margin-top: 4px; }
.copy { font-size: 14px; line-height: 1; color: var(--bg); background: var(--ink); border: 0; border-radius: 999px; padding: 12px 18px; cursor: pointer; overflow: hidden; transition: transform .15s var(--ease); }
.copy:active { transform: scale(.96); }
/* "Get in touch" rolls up to "Copy email" on hover, and the address appears beside it. */
.copy-roll { display: grid; }
.copy-a, .copy-b { grid-area: 1 / 1; text-align: center; transition: transform .3s var(--ease), opacity .2s linear; }
.copy-b { transform: translateY(110%); opacity: 0; }
.copy:hover .copy-a, .copy:focus-visible .copy-a, .copy.done .copy-a { transform: translateY(-110%); opacity: 0; }
.copy:hover .copy-b, .copy:focus-visible .copy-b, .copy.done .copy-b { transform: none; opacity: 1; }
.email { color: var(--ink-2); opacity: 0; transition: opacity .2s linear; }
.contact:has(.copy:hover, .copy:focus-visible, .copy.done) .email { opacity: 1; }

.section-head { align-items: center; padding-bottom: 12px; border-bottom: 1px solid var(--ink); }
.section-head h2, .label { grid-column: 1 / 3; margin: 0; font: inherit; color: var(--ink-2); }
.layout { grid-column: 10 / 13; justify-self: end; }

.work { list-style: none; margin: 0; padding: 0; }
.work li { border-bottom: 1px solid var(--line); }
.row { align-items: baseline; padding: 14px 0 16px; position: relative; }
.yr { grid-column: 1 / 3; color: var(--ink-2); justify-self: start; }
.title { font-family: var(--display); grid-column: 3 / 7; font-size: var(--big); line-height: 1.12; letter-spacing: -.01em; justify-self: start; }
.client { grid-column: 7 / 10; justify-self: start; }
.kind { grid-column: 10 / 13; color: var(--ink-2); justify-self: start; }
.yr, .title, .client, .kind { transition: color .3s; }
.row:hover .title, .row:focus-visible .title, .row:hover .yr { color: var(--c); }

/* Previews: inline on touch screens, following the cursor with a mouse. */
.thumb { display: none; }
@media (hover: none), (pointer: coarse) {
  .work[data-layout="list"] .thumb { display: block; align-self: center; justify-self: end; }
  .work[data-layout="list"] .thumb .mini { width: 96px; height: 72px; }
}
@media (hover: hover) and (pointer: fine) {
  .work[data-layout="list"] .thumb {
    display: block; position: fixed; left: 0; top: 0; z-index: 5; pointer-events: none;
    transform: translate(calc(var(--mx, 0px) + 28px), calc(var(--my, 0px) - 50%));
    opacity: 0; transition: opacity .15s linear;
  }
  .work[data-layout="list"] .row:hover .thumb { opacity: 1; }
  .work[data-layout="list"] .thumb .mini { transform: scale(.96); transition: transform .35s var(--ease); }
  .work[data-layout="list"] .row:hover .thumb .mini { transform: none; }
  .work[data-layout="list"] .thumb .mini { width: 280px; height: 210px; }
}

.mini { display: grid; place-items: center; overflow: hidden; position: relative; border-radius: 8px; }
.mini-tide { background: #e8e7e1; color: #151515; grid-template-columns: auto auto; place-content: center; gap: 0 10px; align-items: end; padding-bottom: 14%; }
.mini-tide b { font: 600 64px/1 var(--sign); letter-spacing: -.02em; }
.mini-tide span { font: 500 15px/1.2 var(--sign); padding-bottom: 6px; }
.mini-tide svg { position: absolute; left: 10%; bottom: 12%; width: 80%; height: 16%; }
.mini-tide path { fill: none; stroke: #151515; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.mini-type { background: #141414; color: #f2f2f0; font: 500 64px/1 var(--sign); text-align: center; letter-spacing: .02em; }
.mini-night { background: #0b0a08; color: #f5a623; grid-template-columns: auto auto; grid-template-areas: "n d" "n m"; gap: 2px 14px; place-content: center; justify-items: start; font-family: var(--sign); }
.mini-night b { grid-area: n; font: 700 30px/1 var(--sign); border: 2px solid; padding: 6px 8px; align-self: center; }
.mini-night span { grid-area: d; font: 700 26px/1 var(--sign); }
.mini-night small { grid-area: m; font: 500 14px/1 var(--sign); opacity: .75; }
.mini-read { background: #fbfaf7; align-content: center; justify-items: start; gap: 9px; padding: 0 18%; box-shadow: inset 0 0 0 1px #e2e1dc; }
.mini-read s { display: block; height: 5px; width: 100%; background: #cfcdc6; }
.mini-read s.hl { background: #e9d97a; }
.mini-read s.short { width: 50%; }
@media (hover: none), (pointer: coarse) {
  .work[data-layout="list"] .mini-tide { padding: 0; } .work[data-layout="list"] .mini-tide b { font-size: 28px; }
  .work[data-layout="list"] .mini-tide span, .work[data-layout="list"] .mini-tide svg { display: none; }
  .work[data-layout="list"] .mini-type { font-size: 24px; }
  .work[data-layout="list"] .mini-night b { font-size: 18px; padding: 3px 5px; }
  .work[data-layout="list"] .mini-night span, .work[data-layout="list"] .mini-night small { display: none; }
  .work[data-layout="list"] .mini-read { gap: 5px; padding: 0 16%; } .work[data-layout="list"] .mini-read s { height: 3px; }
}

/* Grid: the same rows rearranged into two columns, previews always shown. */
.work[data-layout="grid"] { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 56px var(--gap); padding-top: 24px; }
.work[data-layout="grid"] li { border-bottom: 0; }
.work[data-layout="grid"] .row { grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "thumb thumb thumb" "title title title" "yr client kind"; column-gap: 16px; padding: 0; }
.work[data-layout="grid"] .thumb { grid-area: thumb; display: block; margin-bottom: 14px; }
.work[data-layout="grid"] .title { grid-area: title; margin-bottom: 4px; }
.work[data-layout="grid"] .yr { grid-area: yr; }
.work[data-layout="grid"] .client { grid-area: client; }
.work[data-layout="grid"] .kind { grid-area: kind; justify-self: end; }
.work[data-layout="grid"] .mini { width: 100%; aspect-ratio: 4 / 3; border-radius: var(--radius); }
.work[data-layout="grid"] .mini-tide b { font-size: clamp(64px, 9vw, 120px); }
.work[data-layout="grid"] .mini-tide span { font-size: clamp(15px, 1.6vw, 22px); }
.work[data-layout="grid"] .mini-type { font-size: clamp(64px, 9vw, 120px); }
.work[data-layout="grid"] .mini-night b { font-size: clamp(30px, 4vw, 52px); }
.work[data-layout="grid"] .mini-night span { font-size: clamp(26px, 3.4vw, 44px); }
.work[data-layout="grid"] .mini-night small { font-size: clamp(14px, 1.5vw, 20px); }
.work[data-layout="grid"] .mini-read { gap: clamp(9px, 1.4vw, 16px); }
.work[data-layout="grid"] .mini-read s { height: clamp(5px, .8vw, 9px); }

@media (max-width: 760px) { .work[data-layout="grid"] { grid-template-columns: 1fr; gap: 40px; } }

.work.switching .thumb { transition: none !important; }

/* ---------- list ⇄ grid motion ----------
   Text keeps its size and slides; rows set off 45ms apart; previews fade in once the text is moving. */
:root { --glide: cubic-bezier(.32, .72, 0, 1); }
::view-transition-group(*) { animation-duration: .5s; animation-timing-function: var(--glide); }
::view-transition-group(.text), ::view-transition-group(.thumb), ::view-transition-group(.rest) { animation-duration: .72s; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .3s; animation-timing-function: ease; }
::view-transition-old(.text) { animation: none; opacity: 0; }
::view-transition-new(.text) { animation: none; }
::view-transition-group(t1), ::view-transition-group(c1), ::view-transition-group(k1), ::view-transition-group(y1), ::view-transition-group(p1) { animation-delay: 45ms; }
::view-transition-group(t2), ::view-transition-group(c2), ::view-transition-group(k2), ::view-transition-group(y2), ::view-transition-group(p2) { animation-delay: 90ms; }
::view-transition-group(t3), ::view-transition-group(c3), ::view-transition-group(k3), ::view-transition-group(y3), ::view-transition-group(p3) { animation-delay: 135ms; }
::view-transition-group(info) { animation-delay: 120ms; }
::view-transition-group(colophon) { animation-delay: 150ms; }
::view-transition-new(.thumb):only-child { animation: thumb-in .5s ease-out both; animation-delay: 180ms; }
::view-transition-new(p1):only-child { animation-delay: 225ms; }
::view-transition-new(p2):only-child { animation-delay: 270ms; }
::view-transition-new(p3):only-child { animation-delay: 315ms; }
::view-transition-old(.thumb):only-child { animation: thumb-out .2s ease-out both; }
@keyframes thumb-in { from { opacity: 0; } }
@keyframes thumb-out { to { opacity: 0; } }

/* ---------- experience + how I work ---------- */
.info { margin-top: 16vh; row-gap: 56px; }
.info section { grid-column: 1 / 6; }
.info section + section { grid-column: 7 / 12; }
.label { display: block; margin: 0 0 14px; }
.ledger { list-style: none; margin: 0; padding: 0; }
.ledger li { display: flex; justify-content: space-between; gap: 16px; padding: 11px 0; border-top: 1px solid var(--line); }
.ledger li:last-child { border-bottom: 1px solid var(--line); }
.ledger li span:last-child { color: var(--ink-2); white-space: nowrap; }
.ledger.plain li { display: block; color: var(--ink); }
.colophon { margin-top: 16vh; padding: 16px 0 72px; color: var(--ink-2); border-top: 1px solid var(--line); }
.colophon p { grid-column: 1 / 10; margin: 0; }
kbd { font: inherit; font-size: 12px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; padding: 1px 5px; color: var(--ink); }

/* ---------- case study ---------- */
.case { padding-top: 8vh; }
.back { display: inline-flex; align-items: center; gap: 8px; color: var(--ink-2); }
/* A drawn arrow, so its weight matches the text in every typeface. */
.back::before {
  content: ""; width: 14px; height: 10px; background: currentColor; transition: transform .25s var(--ease);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 10' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13 5H1.5M5.5 1 1.5 5l4 4'/%3E%3C/svg%3E") no-repeat center / contain;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 10' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13 5H1.5M5.5 1 1.5 5l4 4'/%3E%3C/svg%3E") no-repeat center / contain;
}
.back:hover { color: var(--c); }
.back:hover::before { transform: translateX(-3px); }
.case-head { margin-top: 6vh; row-gap: 20px; }
.case-head h1 { grid-column: 1 / 11; margin: 0; font-family: var(--display); font-size: clamp(40px, 6vw, 80px); font-weight: 400; line-height: 1; letter-spacing: -.025em; }
.lede { grid-column: 1 / 8; margin: 0 0 20px; max-width: 30em; font-size: clamp(19px, 1.8vw, 22px); line-height: 1.35; color: var(--ink-2); text-wrap: pretty; }
.facts { grid-column: 1 / 13; display: grid; grid-template-columns: subgrid; margin: 0; padding: 12px 0; border-top: 1px solid var(--ink); }
.facts div:nth-child(1) { grid-column: 1 / 4; }
.facts div:nth-child(2) { grid-column: 4 / 6; }
.facts div:nth-child(3) { grid-column: 6 / 10; }
.facts div:nth-child(4) { grid-column: 10 / 13; }
.facts dt { color: var(--ink-2); }
.facts dd { margin: 0; }

.prose { margin: 72px 0 0; align-items: baseline; }
.prose h2 { grid-column: 1 / 3; margin: 0; font: inherit; color: var(--ink-2); }
.prose p { grid-column: 3 / 9; margin: 0 0 40px; max-width: 36em; text-wrap: pretty; }

/* ---------- demos ---------- */
.demo { margin: 40px 0 0; padding: clamp(20px, 4vw, 48px); background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius); }
.demo figcaption { color: var(--ink-2); margin-top: 24px; max-width: 40em; }
input[type="range"] { accent-color: var(--c); width: 100%; }

.tide-readout { display: grid; gap: 2px; margin-bottom: 28px; }
.tide-time { color: var(--c); }
.tide-verdict { font: 600 clamp(36px, 6vw, 72px)/1 var(--sign); letter-spacing: -.01em; }
.tide-detail { color: var(--ink-2); }
.tide-chart { width: 100%; height: 180px; display: block; overflow: visible; }
.tide-chart .curve { fill: none; stroke: var(--c); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.tide-chart .window { fill: color-mix(in oklab, var(--c) 12%, transparent); }
.tide-chart .cursor { stroke: var(--ink-2); vector-effect: non-scaling-stroke; }
.tide-wrap { position: relative; }
.tide-wrap .knob { position: absolute; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%; background: var(--c); left: var(--kx); top: var(--ky); pointer-events: none; }
.scrub { display: block; margin-top: 14px; }

.type-controls { display: grid; gap: 16px var(--gap); margin-bottom: 28px; }
@media (min-width: 760px) { .type-controls { grid-template-columns: 1fr 1fr auto; align-items: end; } }
.type-controls label { display: grid; gap: 6px; color: var(--ink-2); }
.type-controls output { color: var(--ink); }
.presets, .switch { display: inline-flex; padding: 3px; border: 1px solid var(--line); border-radius: 999px; justify-self: start; }
.presets button, .switch button { font-size: 13px; line-height: 1; padding: 8px 13px; border: 0; border-radius: 999px; background: none; color: var(--ink-2); cursor: pointer; }
.presets button[aria-pressed="true"], .switch button[aria-pressed="true"] { background: var(--ink); color: var(--bg); }
.type-sample {
  font-family: var(--sign); font-weight: var(--w, 480); font-size: calc(var(--s, 72) * 1px); line-height: 1.05; letter-spacing: -.01em;
  margin: 0; padding: 4px 0; min-height: 1.2em; overflow-wrap: anywhere; outline: none; caret-color: var(--ink);
}
@media (max-width: 600px) { .type-sample { font-size: min(calc(var(--s, 72) * 1px), 15vw); } }

.sign { border-radius: 8px; padding: clamp(18px, 3vw, 28px); font-family: var(--sign); transition: background .4s, color .4s; }
.sign[data-mode="night"] { background: #0b0a08; color: #f5a623; }
.sign[data-mode="day"] { background: #fff; color: #10263f; box-shadow: inset 0 0 0 1px var(--line); }
.sign-head { display: flex; align-items: baseline; gap: 12px; border-bottom: 2px solid currentColor; padding-bottom: 12px; margin-bottom: 6px; }
.sign-head strong { font-size: clamp(24px, 4vw, 36px); font-weight: 700; }
.departures { list-style: none; margin: 0; padding: 0; }
.departures li { display: grid; grid-template-columns: auto 1fr auto; gap: 16px; align-items: center; padding: 10px 0; border-bottom: 1px solid color-mix(in oklab, currentColor 22%, transparent); }
.departures li:last-child { border-bottom: 0; }
.departures .line { font-weight: 700; font-size: 16px; border: 2px solid; padding: 4px 8px; min-width: 52px; text-align: center; }
.departures .dir { font-weight: 500; font-size: 18px; }
.departures .min { font-weight: 500; font-size: 16px; text-align: right; }
.sign[data-mode="night"] .line { font-size: 22px; }
.sign[data-mode="night"] .dir { font-size: clamp(24px, 3.8vw, 36px); font-weight: 700; }
.sign[data-mode="night"] .min { font-size: 20px; }
.switch { margin-top: 18px; }

.demo-read { display: grid; gap: var(--gap); }
@media (min-width: 820px) { .demo-read { grid-template-columns: 3fr 2fr; } .demo-read figcaption { grid-column: 1 / -1; margin-top: 0; } }
.page { border-radius: 8px; background: #fbfaf7; color: #1d1c19; padding: clamp(20px, 3vw, 36px); box-shadow: inset 0 0 0 1px #e2e1dc; }
.page-meta { color: #85837b; margin: 0 0 14px; }
.passage { margin: 0; font: 400 20px/1.6 "Source Serif 4", Georgia, serif; }
.sent { all: unset; cursor: pointer; transition: background .2s; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
.sent:hover { background: #f1ecd2; }
.sent:focus-visible { outline: 2px solid #1d1c19; outline-offset: 2px; }
.sent.kept { background: #ece08f; }
.book { border-top: 1px solid var(--c); padding-top: 10px; }
.book-head { margin: 0 0 12px; color: var(--c); }
.kept { list-style: none; margin: 0; padding: 0; }
.kept li { font: 400 17px/1.45 "Source Serif 4", Georgia, serif; padding: 10px 0; border-bottom: 1px solid var(--line); }
.kept li.empty { font: inherit; color: var(--ink-2); border: 0; padding: 0; }

/* ---------- pager ---------- */
.pager { margin-top: 64px; padding: 14px 0 72px; border-top: 1px solid var(--line); }
.pager[hidden] { display: none; }
.pager .prev { grid-column: 1 / 7; color: var(--ink-2); justify-self: start; }
.pager .next { grid-column: 7 / 13; justify-self: end; }
.pager a:hover { color: var(--c); text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px; }
/* A small preview sits still behind the link text, at reduced opacity. */
@media (hover: hover) and (pointer: fine) {
  .pager a { position: relative; }
  .pager a > span:first-child { position: relative; z-index: 1; }
  .pager .thumb {
    display: block; position: absolute; left: 50%; top: 50%; z-index: 0; pointer-events: none;
    width: 140px; height: 105px; transform: translate(-50%, -50%);
    opacity: 0; transition: opacity .2s linear;
  }
  .pager a:hover .thumb { opacity: .3; }
  .pager .thumb .mini { width: 280px; height: 210px; transform-origin: 0 0; transform: scale(.5); }
}

/* ---------- two-column variant ----------
   About, work and experience run down the left; the right column holds one sticky preview
   that changes to whatever project or role you point at. Below 900px it falls back to Classic. */
.stage { display: none; }
@media (min-width: 900px) {
  html[data-page="split"] .view[data-view="index"]:not([hidden]) {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: clamp(40px, 5vw, 88px); align-items: start;
  }
  html[data-page="split"] .view[data-view="index"] > :not(.stage) { grid-column: 1; }
  html[data-page="split"] .stage {
    display: block; grid-column: 2; grid-row: 1 / span 6; position: sticky; top: 24px; margin-top: 10vh;
  }
  html[data-page="split"] .intro { padding: 10vh 0 12vh; }
  html[data-page="split"] .intro h1 { font-size: clamp(30px, 3vw, 42px); }
  html[data-page="split"] .intro h1, html[data-page="split"] .intro p, html[data-page="split"] .intro .contact { grid-column: 1 / -1; }
  html[data-page="split"] .section-head h2 { grid-column: 1 / -1; }
  html[data-page="split"] .section-head .layout, html[data-page="split"] .hint-layout { display: none; }
  html[data-page="split"] .work .thumb { display: none; }
  html[data-page="split"] .work .row { row-gap: 4px; }
  html[data-page="split"] .work .title { grid-column: 1 / -1; grid-row: 1; }
  html[data-page="split"] .work .client { grid-column: 1 / 7; grid-row: 2; }
  html[data-page="split"] .work .kind { grid-column: 7 / 11; grid-row: 2; }
  html[data-page="split"] .work .yr { grid-column: 11 / 13; grid-row: 2; justify-self: end; }
  html[data-page="split"] .info { margin-top: 12vh; }
  html[data-page="split"] .info section, html[data-page="split"] .info section + section, html[data-page="split"] .colophon p { grid-column: 1 / -1; }
  html[data-page="split"] .ledger li[data-preview] { transition: color .3s; }
  html[data-page="split"] .ledger:has(li[data-preview]:hover) li[data-preview]:not(:hover) { color: var(--ink-2); }
  html[data-page="split"] .ledger:has(li[data-preview]:hover) li[data-preview]:not(:hover) span { color: inherit; }
}
.stage-frame { position: relative; aspect-ratio: 4 / 3; width: 100%; }
.stage .mini { position: absolute; inset: 0; border-radius: var(--radius); opacity: 0; transition: opacity .3s linear; }
.stage .mini.on { opacity: 1; }
/* A hairline edge so the dark previews don't melt into the dark page. */
.stage-frame::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius); box-shadow: inset 0 0 0 1px var(--line); pointer-events: none; }
.stage-cap { margin: 12px 0 0; color: var(--ink-2); }
.stage-cap b { font-weight: inherit; color: var(--ink); }
/* Project previews at stage size. */
.stage .mini-tide b, .stage .mini-type { font-size: clamp(72px, 9vw, 132px); }
.stage .mini-tide span { font-size: clamp(16px, 1.6vw, 24px); }
.stage .mini-night b { font-size: clamp(32px, 4vw, 56px); }
.stage .mini-night span { font-size: clamp(28px, 3.4vw, 48px); }
.stage .mini-night small { font-size: clamp(14px, 1.5vw, 22px); }
.stage .mini-read { gap: clamp(10px, 1.4vw, 18px); }
.stage .mini-read s { height: clamp(5px, .8vw, 10px); }
/* Experience previews. */
.mini-plate { background: #d9d6cf; }
.plate { display: grid; gap: .5em; padding: 7% 9%; border-radius: 4px; background: #1d1d1b; color: #f2f2ee; font-family: var(--sign); }
.plate b { font: 700 clamp(26px, 3vw, 42px)/1 var(--sign); }
.plate span { font: 500 clamp(15px, 1.5vw, 21px)/1 var(--sign); opacity: .7; }
.mini-book { background: #e9e6df; }
.cover { width: 34%; aspect-ratio: 2 / 3; display: flex; flex-direction: column; gap: 5%; padding: 9% 10%; background: #1f3a5f; color: #f3efe6; border-left: 6px solid #152a45; }
.cover b { font: 700 clamp(20px, 2.3vw, 32px)/1 var(--sign); margin-bottom: 8%; }
.cover s { display: block; height: 3px; background: rgba(243, 239, 230, .4); }
.cover s:nth-of-type(even) { width: 68%; }
.cover small { margin-top: auto; font: 500 clamp(11px, 1vw, 14px)/1 var(--sign); opacity: .8; }
.mini-wall { background: #cfc7b8; grid-template-columns: repeat(3, 1fr); place-items: stretch; align-content: center; gap: 4%; padding: 0 20%; }
.mini-wall i { aspect-ratio: 3 / 4; background: #f7f5ef; }
.mini-wall i:nth-child(2) { background: #1d1d1b; }
.mini-wall i:nth-child(6) { background: #e9d97a; }
.mini-ward { background: #e8e7e1; }
.ward { width: 68%; display: grid; border-radius: 4px; overflow: hidden; background: #fff; color: #151515; }
.ward b { padding: 6% 8%; background: #0b6e4f; color: #fff; font: 700 clamp(22px, 2.6vw, 36px)/1 var(--sign); }
.ward span { padding: 5% 8%; border-top: 1px solid #ddd; font: 500 clamp(15px, 1.7vw, 24px)/1 var(--sign); }
.mini-spec { background: #fbfaf7; box-shadow: inset 0 0 0 1px #e2e1dc; color: #151515; align-content: center; gap: 12px; }
.mini-spec b { font: 400 clamp(120px, 14vw, 210px)/1.25 "Source Serif 4", Georgia, serif; }
.mini-spec small { font: 400 13px/1 var(--f); color: #6b6b6b; }

/* ---------- gallery variant ----------
   About and experience are pinned on the left, sized to fit the viewport. The right column is
   an endless run of project images; a name appears only on the image you point at. Below 900px
   it falls back to Classic. */
.lead, .reel { display: none; }
@media (min-width: 900px) {
  html[data-page="gallery"] body:has(.view[data-view="index"]:not([hidden])) .top { display: none; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .view[data-view="index"]:not([hidden]) {
    display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: clamp(40px, 5vw, 88px); align-items: start;
  }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .view[data-view="index"] > :not(.lead, .reel) { display: none; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead {
    display: flex; flex-direction: column; justify-content: space-between; gap: 40px;
    position: sticky; top: 0; height: 100vh; overflow: auto;
    padding: clamp(16px, 5vh, 56px) 0 24px; scrollbar-width: none;
  }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .ledger li { padding: clamp(7px, 1.2vh, 11px) 0; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro { display: grid; padding: 0; row-gap: 20px; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro > * { grid-column: 1 / -1; }
  /* One statement, name included, in place of the headline and bio. */
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro h1, html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro > p:not(.statement) { display: none; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro .statement {
    display: block; margin: 0; max-width: 26em; color: var(--ink); font-family: var(--display);
    font-size: clamp(20px, 1.75vw, 26px); font-weight: var(--display-w); line-height: 1.3; letter-spacing: -.01em; text-wrap: pretty;
  }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .info { display: block; margin: 0; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .info section + section { display: none; }
  /* The page holds still; the work moves inside its own full-height column. */
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) body:has(.view[data-view="index"]:not([hidden])) { overflow: hidden; height: 100vh; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .reel { display: block; position: sticky; top: 0; height: 100vh; overflow: hidden; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .reel-track { display: grid; gap: var(--gap); will-change: transform; }
}
.reel-item { position: relative; display: block; }
.reel-extra { display: none; }
.reel .mini { width: 100%; aspect-ratio: 4 / 3; border-radius: var(--radius); }
.reel .mini-tide b, .reel .mini-type { font-size: clamp(72px, 9vw, 140px); }
.reel .mini-tide span { font-size: clamp(16px, 1.6vw, 24px); }
.reel .mini-night b { font-size: clamp(32px, 4vw, 60px); }
.reel .mini-night span { font-size: clamp(28px, 3.4vw, 50px); }
.reel .mini-night small { font-size: clamp(14px, 1.5vw, 22px); }
.reel .mini-read { gap: clamp(10px, 1.4vw, 18px); }
.reel .mini-read s { height: clamp(5px, .8vw, 10px); }
.reel-name {
  position: absolute; left: 16px; bottom: 16px; padding: 8px 14px; border-radius: 999px;
  background: var(--bg); color: var(--ink); opacity: 0; transition: opacity .2s linear;
}
.reel-name span { color: var(--ink-2); }
.reel-name span::before { content: ", "; }
.reel-item:hover .reel-name, .reel-item:focus-visible .reel-name { opacity: 1; }

@media (max-width: 899px) {
  html[data-page="gallery"] .intro h1, html[data-page="gallery"] .intro > p:not(.statement) { display: none; }
  html[data-page="gallery"] .intro .statement {
    display: block; grid-column: 1 / -1; max-width: 26em; color: var(--ink); font-family: var(--display);
    font-size: clamp(20px, 5.4vw, 26px); font-weight: var(--display-w); line-height: 1.3; letter-spacing: -.01em; text-wrap: pretty;
  }
}

/* ---------- minimal variant ----------
   A short note pinned on the left; on the right a wall of work you can only look at.
   No links, no headings, small type. Below 900px it falls back to Classic. */
.side, .wall, .wall-label { display: none; }
@media (min-width: 900px) {
  html[data-page="minimal"] body:has(.view[data-view="index"]:not([hidden])) .top { display: none; }
  html[data-page="minimal"] .view[data-view="index"]:not([hidden]) {
    display: grid; grid-template-columns: minmax(240px, 300px) minmax(0, 1fr); column-gap: clamp(40px, 6vw, 96px); align-items: start;
  }
  html[data-page="minimal"] .view[data-view="index"] > :not(.side, .wall, .wall-label) { display: none; }
  html[data-page="minimal"] .side {
    display: flex; flex-direction: column; gap: 14px; position: sticky; top: 0; padding: 40px 0; font-size: 14px; line-height: 1.5;
  }
  html[data-page="minimal"] .wall { display: flex; gap: 12px; align-items: flex-start; padding: 40px 0; }
  html[data-page="minimal"] .wall-label { display: block; }
}
.side p { margin: 0; }
.side-name { color: var(--ink); }
.side-tldr { color: var(--ink-2); max-width: 26em; }
.side-now { color: var(--ink); }
.side-now span { color: var(--ink-2); margin-right: 6px; }
.side .contact { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 10px; }
.side .copy { font-size: 13px; padding: 10px 15px; }
.side .email { font-size: 13px; }
.wall-col { flex: 1 1 0; min-width: 0; display: grid; gap: 12px; }
.wall-item { cursor: default; }
.wall-item { position: relative; overflow: hidden; border-radius: 8px; }
.wall-item::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--line); pointer-events: none; }
.wall .mini { width: 100%; height: auto; border-radius: 8px; }
.wall-item:hover .mini { filter: brightness(.97); }

/* Gallery and Minimal: pointing at a piece eases the work a little closer inside its frame. The frame clips it, so
   the card keeps its size and its edge; only the picture moves. */
html[data-page="gallery"] .reel-item { overflow: hidden; border-radius: var(--radius); }
html:is([data-page="gallery"], [data-page="minimal"]) :is(.reel-item, .wall-item) .mini { transition: transform .6s var(--glide), filter .2s linear; }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  html:is([data-page="gallery"], [data-page="minimal"]) :is(.reel-item, .wall-item):hover .mini,
  html[data-page="gallery"] .reel-item:focus-visible .mini { transform: scale(1.04); }
}
/* The drawn experience pieces were sized for a big stage; bring them down to wall size. */
.wall .plate b { font-size: 22px; } .wall .plate span { font-size: 13px; }
.wall .cover { width: 42%; } .wall .cover b { font-size: 16px; } .wall .cover small { font-size: 10px; }
.wall .ward b { font-size: 18px; } .wall .ward span { font-size: 13px; }
.wall .mini-spec b { font-size: 96px; } .wall .mini-spec small { font-size: 11px; }
.wall-label {
  position: fixed; left: 0; top: 0; z-index: 12; pointer-events: none; white-space: nowrap;
  transform: translate(calc(var(--mx, 0px) + 14px), calc(var(--my, 0px) + 14px));
  padding: 6px 10px; border-radius: 6px; background: var(--ink); color: var(--bg); font-size: 12px; line-height: 1.3;
  opacity: 0; transition: opacity .12s linear;
}
.wall-label.on { opacity: 1; }
.wall-label span { opacity: .6; margin-left: 6px; }

/* ---------- statement variant ----------
   One paragraph does the talking, set large; each client is written as a small sign in its own
   colours. The right column is the gallery's endless run of work, to look at only: pointing at a
   piece lays a veil over it with the name, which drifts after the cursor but never leaves the
   frame. Below 900px it falls back to Classic. */
.say, .film { display: none; }
@media (min-width: 900px) {
  html[data-page="statement"] body:has(.view[data-view="index"]:not([hidden])) .top { display: none; }
  html[data-page="statement"] .view[data-view="index"]:not([hidden]) {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: clamp(40px, 5vw, 88px); align-items: start;
  }
  html[data-page="statement"] .view[data-view="index"] > :not(.say, .film) { display: none; }
  html[data-page="statement"] .say {
    display: flex; flex-direction: column; justify-content: space-between; gap: 32px;
    position: sticky; top: 0; height: 100vh; overflow: auto; scrollbar-width: none;
    padding: clamp(24px, 7vh, 72px) 0 24px;
  }
  /* The column opens mid-scroll: the first piece is already half gone off the top. */
  html[data-page="statement"] .film { display: grid; gap: var(--gap); padding: 0 0 32px; margin-top: calc(-.36 * .75 * (50vw - var(--gap))); }
}
.say-body { display: grid; gap: clamp(28px, 4.5vh, 44px); justify-items: start; }
.say-text {
  margin: 0; max-width: 20em; color: var(--ink); font-family: var(--display);
  font-size: clamp(24px, 2.3vw, 36px); font-weight: var(--display-w); line-height: 1.3; letter-spacing: var(--display-ls); text-wrap: pretty;
}
.say-text .dim { color: var(--ink-2); }
/* Clients read as the names they are; pointing at one picks out its work on the right. */
.co {
  color: var(--ink); white-space: nowrap; cursor: default;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .18em; text-decoration-color: var(--line);
  transition: text-decoration-color .2s linear;
}
.co:hover { text-decoration-color: currentColor; }
/* Every control is the same 40px pill family as Get in touch. */
.say .contact { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.say .copy { height: 40px; padding: 0 20px; }
.say-foot { display: flex; align-items: center; gap: 8px; }
.say-in, .lamp {
  display: inline-grid; place-items: center; height: 40px; border-radius: 999px;
  border: 1px solid var(--line); background: none; color: var(--ink); transition: border-color .2s linear, background-color .25s linear;
}
.say-in { width: 40px; }
.say-in:hover, .say-in:focus-visible, .lamp:hover, .lamp:focus-visible { border-color: var(--ink); }
.say-in svg { width: 15px; height: 15px; fill: currentColor; }
/* The light switch: an upright pill, knob down for off and up for on. */
.lamp { --travel: 8px; position: relative; width: 24px; padding: 0; cursor: pointer; background: color-mix(in oklab, var(--ink) 9%, transparent); border-color: transparent; }
.lamp-knob {
  position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
  background: var(--ink); transform: translateY(var(--travel)); transition: transform .3s var(--ease), background-color .25s linear;
}
.lamp[aria-checked="true"] { background: var(--ink); border-color: var(--ink); }
.lamp[aria-checked="true"] .lamp-knob { background: var(--bg); transform: translateY(calc(-1 * var(--travel))); }
.top .lamp { --travel: 7px; height: 36px; width: 22px; }
.say .lamp { position: fixed; top: 24px; right: 24px; z-index: 11; }
.say-in svg.ig { fill: none; stroke: currentColor; stroke-width: 1.8; width: 16px; height: 16px; }
.say-in svg.ig .dot { fill: currentColor; stroke: none; }
/* Second action beside Get in touch: same pill, outlined. */
.ask {
  display: inline-flex; align-items: center; height: 40px; padding: 0 20px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--ink); font-size: 14px; line-height: 1; text-decoration: none; transition: border-color .2s linear;
}
.ask:hover, .ask:focus-visible { border-color: var(--ink); }
.side .ask { height: auto; padding: 10px 15px; font-size: 13px; }
/* With two buttons side by side, the revealed address sits underneath instead of between them. */
.say .contact, .side .contact { position: relative; gap: 8px; }
.say .email, .side .email { position: absolute; left: 0; top: calc(100% + 10px); font-size: 14px; }

.film-item { position: relative; overflow: hidden; border-radius: var(--radius); cursor: default; transition: opacity .3s linear; }
.film[data-by] .film-item:not(.match) { opacity: .2; }
.film .mini { width: 100%; aspect-ratio: 4 / 3; border-radius: var(--radius); outline: 1px solid var(--line); outline-offset: -1px; }
.film .mini-tide b, .film .mini-type { font-size: clamp(72px, 9vw, 140px); }
.film .mini-tide span { font-size: clamp(16px, 1.6vw, 24px); }
.film .mini-night b { font-size: clamp(32px, 4vw, 60px); }
.film .mini-night span { font-size: clamp(28px, 3.4vw, 50px); }
.film .mini-night small { font-size: clamp(14px, 1.5vw, 22px); }
.film .mini-read { gap: clamp(10px, 1.4vw, 18px); }
.film .mini-read s { height: clamp(5px, .8vw, 10px); }
.film-veil {
  position: absolute; inset: 0; pointer-events: none;
  background: color-mix(in oklab, var(--page) 86%, transparent);
  opacity: 0; transition: opacity .25s linear;
}
.film-item.on .film-veil { opacity: 1; }
.film-tag {
  position: absolute; left: 0; top: 0; max-width: calc(100% - 48px); will-change: transform;
  display: grid; gap: 4px; color: var(--ink);
}
.film-tag b { font-family: var(--display); font-size: clamp(22px, 2vw, 30px); font-weight: var(--display-w); line-height: 1.15; letter-spacing: -.01em; }
.film-tag span { font-size: 15px; color: var(--ink-2); }


/* ---------- variants menu: one button that opens a panel of dropdowns ---------- */
.typeset[hidden] { display: none; }
.typeset { position: fixed; right: var(--gap); bottom: 16px; z-index: 11; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; font-size: 13px; }
.ts-toggle {
  display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px 0 12px; font: inherit; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 999px; cursor: pointer;
}
.ts-toggle:hover, .ts-toggle[aria-expanded="true"] { border-color: var(--ink); }
.ts-toggle:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.ts-toggle svg { width: 15px; height: 15px; fill: var(--bg); stroke: currentColor; stroke-width: 1.3; stroke-linecap: round; }
.ts-panel {
  order: -1; display: grid; gap: 4px; padding: 6px; min-width: 300px; background: var(--bg); border: 1px solid var(--line); border-radius: 18px;
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, .25); transform-origin: bottom right;
  transition: opacity .18s ease-out, transform .18s ease-out;
}
.ts-panel[hidden] { display: none; }
.ts-panel.closing { opacity: 0; transform: translateY(4px) scale(.98); transition-duration: .12s; }
@starting-style { .ts-panel { opacity: 0; transform: translateY(6px) scale(.97); } }
.ts-panel .pick { justify-content: space-between; height: 38px; border-color: transparent; border-radius: 12px; }
.ts-panel .pick:hover, .ts-panel .pick:focus-within { border-color: var(--line); }
.ts-panel .pick select { text-align: right; }
@media (prefers-reduced-motion: reduce) { .ts-panel, .ts-panel.closing { transition: none; } }
.pick { position: relative; display: inline-flex; align-items: center; gap: 6px; padding: 0 12px; background: var(--bg); border: 1px solid var(--line); border-radius: 999px; color: var(--ink-2); cursor: pointer; }
.pick:hover, .pick:focus-within { color: var(--ink); border-color: var(--ink); }
.pick select {
  appearance: none; -webkit-appearance: none; font: inherit; color: var(--ink); background: none; border: 0;
  padding: 9px 18px 9px 0; cursor: pointer; outline: none; field-sizing: content;
}
.pick::after {
  content: ""; position: absolute; right: 12px; top: 50%; width: 8px; height: 5px; margin-top: -2px; background: currentColor; pointer-events: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 5' fill='none' stroke='%23000' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l3 3 3-3'/%3E%3C/svg%3E") no-repeat center / contain;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 5' fill='none' stroke='%23000' stroke-width='1.3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l3 3 3-3'/%3E%3C/svg%3E") no-repeat center / contain;
}
.pick:has(select:focus-visible) { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---------- small screens ---------- */
@media (max-width: 760px) {
  .top { grid-template-columns: 1fr auto; row-gap: 4px; }
  .brand { grid-column: 1; } .top-end { grid-column: 2; justify-self: end; }
  .top-nav { display: none; }
  .intro { padding: 10vh 0 8vh; }
  .intro h1, .intro p, .intro .contact { grid-column: 1 / -1; }
  .section-head h2 { grid-column: 1 / 7; } .layout { grid-column: 7 / 13; justify-self: end; }
  .work[data-layout="list"] .row { grid-template-columns: minmax(0, 1fr) auto; row-gap: 2px; }
  .work[data-layout="list"] .title { grid-column: 1; grid-row: 1; }
  .work[data-layout="list"] .client { grid-column: 1; grid-row: 2; }
  .work[data-layout="list"] .kind { display: none; }
  .work[data-layout="list"] .yr { grid-column: 1; grid-row: 3; }
  .work[data-layout="list"] .thumb { grid-column: 2; grid-row: 1 / span 3; }
  .info section, .info section + section, .colophon p { grid-column: 1 / -1; }
  .case-head h1, .lede { grid-column: 1 / -1; }
  .facts { grid-template-columns: 1fr 1fr; row-gap: 12px; }
  .facts div:nth-child(n) { grid-column: auto; }
  .prose h2, .prose p { grid-column: 1 / -1; }
  .prose h2 { margin-bottom: 4px; }
  .typeset { bottom: 12px; }
}

/* ---------- motion ---------- */
.view { animation: enter .3s linear; }
@keyframes enter { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

/* ---------- custom cursors ---------- */
/* The layer sits in the top layer (as a popover) so it stays above the painting viewer, which is a modal dialog. */
.cur-layer {
  position: fixed; inset: 0; width: 100vw; height: 100vh; max-width: none; max-height: none; margin: 0; padding: 0; border: 0;
  background: none; overflow: hidden; pointer-events: none; z-index: 2147483647; color: var(--ink);
  --cur-c: #3157d5; --cur-on: #fff;
}
:root[data-theme="dark"] .cur-layer { --cur-c: #4d6ff0; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .cur-layer { --cur-c: #4d6ff0; } }
:root[data-palette="blue"] .cur-layer { --cur-c: #f6f5f1; --cur-on: #0b1fc9; }
.cur-trail { position: absolute; inset: 0; width: 100%; height: 100%; }
.cur { position: absolute; left: 0; top: 0; will-change: transform; opacity: 0; }
.cur.on { opacity: 1; }
html[data-cursor], html[data-cursor] *, html[data-cursor] *::before, html[data-cursor] *::after { cursor: none !important; }
/* Text fields keep the system's text cursor, and the custom one steps aside. */
html[data-cursor] :is(input:not([type="range"], [type="checkbox"], [type="radio"], [type="button"], [type="submit"], [type="reset"], [type="color"], [type="file"]), textarea, [contenteditable="true"], [contenteditable=""]) { cursor: text !important; }

/* Pixel: a small square, which becomes a pixel hand over anything you can click or drag. */
.cur-px { position: absolute; left: -5px; top: -5px; width: 10px; height: 10px; background: currentColor; opacity: .8; }
.cur-hand { position: absolute; display: none; width: 24px; height: 24px; shape-rendering: crispEdges; }
.cur-hand.point { left: -8px; top: -1px; }
.cur-hand.open { left: -12px; top: -10.5px; }
.cur[data-k="pixel"][data-s="link"] .cur-px, .cur[data-k="pixel"][data-s="grab"] .cur-px { display: none; }
.cur[data-k="pixel"][data-s="link"] .cur-hand.point, .cur[data-k="pixel"][data-s="grab"] .cur-hand.open { display: block; }
.cur[data-k="pixel"].down .cur-hand { transform: scale(.88); transform-origin: 50% 20%; }
.cur[data-k="pixel"].down .cur-px { transform: scale(.7); }

/* Label: a dot that opens into a ring over controls, or a pill naming the work under it, and tightens when pressed. */
.cur-dot {
  position: absolute; left: 0; top: 0; display: grid; place-items: center; box-sizing: border-box; width: 14px; height: 14px;
  border: 1.5px solid var(--cur-c); border-radius: 999px; background: var(--cur-c); color: var(--cur-on);
  transform: translate(-50%, -50%); white-space: nowrap; overflow: hidden;
  font-size: 12px; font-weight: 500; letter-spacing: .02em; line-height: 1;
  transition: width .22s var(--glide), height .22s var(--glide), background-color .18s ease-out, transform .16s ease-out;
}
.cur-dot span { opacity: 0; padding: 0 12px; transition: opacity .12s ease-out; }
.cur[data-s="link"] .cur-dot, .cur[data-s="grab"] .cur-dot { width: 38px; height: 38px; background: color-mix(in srgb, var(--cur-c) 12%, transparent); }
.cur[data-s="pill"] .cur-dot { width: var(--pill-w, 120px); height: 30px; }
.cur[data-s="pill"] .cur-dot span { opacity: 1; transition-delay: .06s; }
.cur.down .cur-dot { transform: translate(-50%, -50%) scale(.72); }
.cur[data-s="text"], .cur[data-s="off"] { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .cur-dot, .cur-dot span { transition: none; } }
.cur[data-k="label"] .cur-px, .cur[data-k="label"] .cur-hand, .cur[data-k="pixel"] .cur-dot { display: none; }

/* Mesh: a small solid dot that drifts between two of the field's colours. Over a control it opens into a soft patch
   of the field, multiplied into what is under it (screened in dark), so the link reads as lit rather than covered.
   Outside the Gradient layouts it uses Ruth's own four. */
:root { --mesh-0: #e4ebfa; --mesh-1: #ff9f80; --mesh-2: #ffd04f; --mesh-3: #86b8ff; --mesh-blend: multiply; }
:root[data-theme="dark"] { --mesh-blend: screen; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --mesh-blend: screen; } }
.cur[data-k="mesh"] .cur-px, .cur[data-k="mesh"] .cur-hand, .cur[data-k="mesh"] .cur-dot span { display: none; }
.cur[data-k="mesh"] .cur-dot {
  width: 10px; height: 10px; border: 0; overflow: visible; background: var(--mesh-1);
  animation: mesh-drift 9s ease-in-out infinite alternate;
  transition: width .26s var(--glide), height .26s var(--glide), filter .26s var(--glide), transform .16s ease-out;
}
.cur[data-k="mesh"]:is([data-s="link"], [data-s="grab"]) .cur-dot {
  width: 52px; height: 52px; animation: none; filter: blur(6px);
  background: radial-gradient(circle at 35% 40%, var(--mesh-1), transparent 70%), radial-gradient(circle at 70% 65%, var(--mesh-3), transparent 70%);
}
.cur-layer:has(.cur[data-k="mesh"]:is([data-s="link"], [data-s="grab"])) { mix-blend-mode: var(--mesh-blend); }
.cur[data-k="mesh"].down .cur-dot { transform: translate(-50%, -50%) scale(.6); }
@keyframes mesh-drift { from { background-color: var(--mesh-1); } to { background-color: var(--mesh-3); } }
@media (prefers-reduced-motion: reduce) { .cur[data-k="mesh"] .cur-dot { animation: none; } }

/* ---------- ruled variant ----------
   Classic, drawn as a ruled sheet: two frame lines run the height of the window, every block is a cell whose rules
   run edge to edge, and a small pixel cross marks each place a rule meets the frame. Labels and years are set in a
   pixel face at a whole multiple of its grid so they stay sharp. Everything is square. */
html[data-ruled] {
  --frame: min(1280px, 100vw - 2 * var(--gap)); --pad: clamp(18px, 2.6vw, 32px); --rule: var(--line);
  --pix: "Silkscreen", ui-monospace, monospace; --radius: 0px; overflow-x: clip;
}
html[data-ruled] body::before {
  content: ""; position: fixed; z-index: 0; top: 0; bottom: 0; left: 50%; width: var(--frame); transform: translateX(-50%);
  border-inline: 1px solid var(--rule); pointer-events: none;
}
html[data-ruled] .top, html[data-ruled] main { max-width: none; width: var(--frame); padding-inline: 0; position: relative; }
html[data-ruled] .view:not([data-view="index"]) { padding-inline: var(--pad); }
/* A rule that runs past the frame to both edges of the window. */
html[data-ruled] :is(.top, .intro, .section-head, .work li, .info, .colophon) {
  border-bottom: 1px solid; border-image: linear-gradient(var(--rule) 0 0) 0 0 1 0 / 0 0 1px 0 / 0 100vw;
}
html[data-ruled] :is(.top, .intro, .section-head, .info, .colophon) { position: relative; }
html[data-ruled] :is(.top, .intro, .section-head, .info, .colophon)::before,
html[data-ruled] :is(.top, .intro, .section-head, .info, .colophon)::after {
  content: ""; position: absolute; z-index: 1; bottom: -5px; width: 11px; height: 11px; background: var(--ink); pointer-events: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 11' shape-rendering='crispEdges'%3E%3Cpath d='M5 0h1v11H5zM0 5h11v1H0z'/%3E%3C/svg%3E");
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 11' shape-rendering='crispEdges'%3E%3Cpath d='M5 0h1v11H5zM0 5h11v1H0z'/%3E%3C/svg%3E");
}
html[data-ruled] :is(.top, .intro, .section-head, .info, .colophon)::before { left: -6px; }
html[data-ruled] :is(.top, .intro, .section-head, .info, .colophon)::after { right: -6px; }

html[data-ruled] :is(.section-head h2, .label, .yr, .ledger li span:last-child, .colophon, kbd, .top-nav a) {
  font-family: var(--pix); font-size: 16px; line-height: 1.25; letter-spacing: 0; text-transform: uppercase;
  -webkit-font-smoothing: none; font-variant-numeric: normal;
}
html[data-ruled] .colophon { font-size: 8px; line-height: 2; text-transform: none; }
html[data-ruled] .colophon kbd { font-size: 8px; }

/* Top bar: brand cell, nav, controls, each split by a rule. */
html[data-ruled] .top { padding: 0; column-gap: 0; align-items: stretch; }
html[data-ruled] .top > * { padding: 14px var(--pad); align-self: stretch; display: flex; align-items: center; }
html[data-ruled] .top-nav { border-inline: 1px solid var(--rule); gap: 28px; }
html[data-ruled] .mark { border-radius: 0; }
html[data-ruled] .brand:hover .mark { transform: none; box-shadow: 2px 2px 0 var(--ink); }
html[data-ruled] :is(.theme, .layout, .theme button, .layout button, .copy, .lamp, .lamp-knob, kbd, .mini) { border-radius: 0; }

/* Intro: headline on the left, the note and the contact in a cell of their own on the right. */
html[data-ruled] .intro { padding: 0; column-gap: 0; row-gap: 0; align-items: stretch; }
html[data-ruled] .intro h1 { grid-column: 1 / 9; grid-row: 1 / 3; padding: 14vh var(--pad) var(--pad); max-width: none; font-size: clamp(32px, 4vw, 54px); align-self: end; }
html[data-ruled] .intro > p:not(.statement) { grid-column: 9 / 13; grid-row: 1; max-width: none; padding: 14vh var(--pad) var(--pad); border-left: 1px solid var(--rule); align-self: stretch; display: flex; align-items: end; }
html[data-ruled] .intro .contact { grid-column: 9 / 13; grid-row: 2; margin: 0; padding: var(--pad); border-left: 1px solid var(--rule); border-top: 1px solid var(--rule); }
html[data-ruled] .copy { padding: 12px 16px; }
html[data-ruled] .copy:active { transform: translate(1px, 1px); }

/* Work: a ruled table; the strip over its head takes the colour of the project you point at. */
html[data-ruled] .section-head { margin-top: clamp(56px, 10vh, 120px); padding: 14px var(--pad); column-gap: 0; background: linear-gradient(var(--c) 0 0) top / 100% 3px no-repeat; transition: background-color .3s; }
html[data-ruled] .work .row {
  column-gap: 0; padding: 0; align-items: baseline;
  background: linear-gradient(var(--rule) 0 0) calc(100% * 2 / 12) 0 / 1px 100% no-repeat,
              linear-gradient(var(--rule) 0 0) calc(100% * 6 / 12) 0 / 1px 100% no-repeat,
              linear-gradient(var(--rule) 0 0) calc(100% * 9 / 12) 0 / 1px 100% no-repeat;
}
html[data-ruled] .work .row > :not(.thumb) { padding: 16px var(--pad) 18px; }
html[data-ruled] .work .row > .kind { padding-right: calc(var(--pad) + 24px); }
/* Pointing at a row fills it with a two-pixel checker of its colour and steps a pixel arrow in. */
html[data-ruled] .work .row::before {
  content: ""; position: absolute; inset: 0; z-index: -1; opacity: 0; transition: opacity .15s steps(3);
  background: repeating-conic-gradient(color-mix(in oklab, var(--hc, var(--c)) var(--hc-a, 30%), transparent) 0 25%, transparent 0 50%) 0 0 / 4px 4px;
}
html[data-ruled] .work li { position: relative; isolation: isolate; }
html[data-ruled] .work .row::after {
  content: ""; position: absolute; right: var(--pad); top: 50%; width: 10px; height: 14px; margin-top: -7px; background: var(--c);
  opacity: 0; transform: translateX(-6px); transition: opacity .15s steps(2), transform .2s steps(3);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 7' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h1v1h1v1h1v1h1v1H3v1H2v1H1v1H0z'/%3E%3C/svg%3E") no-repeat center / contain;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 7' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h1v1h1v1h1v1h1v1H3v1H2v1H1v1H0z'/%3E%3C/svg%3E") no-repeat center / contain;
}
html[data-ruled] .work .row:is(:hover, :focus-visible)::before { opacity: 1; }
html[data-ruled] .work .row:is(:hover, :focus-visible)::after { opacity: 1; transform: none; }
html[data-ruled] .work[data-layout="list"] .thumb .mini { box-shadow: 0 0 0 1px var(--ink), 4px 4px 0 var(--ink); }

/* Experience and How I work: two cells split by a rule. */
html[data-ruled] .info { margin-top: clamp(56px, 10vh, 120px); column-gap: 0; row-gap: 0; border-top: 1px solid var(--rule); }
html[data-ruled] main .info { border-image: linear-gradient(var(--rule) 0 0) 1 0 / 1px 0 / 0 100vw; border-bottom: 1px solid; }
html[data-ruled] .info section { grid-column: 1 / 7; padding: var(--pad) 0 0; }
html[data-ruled] .info section + section { grid-column: 7 / 13; border-left: 1px solid var(--rule); }
html[data-ruled] .info .label { padding: 0 var(--pad); margin-bottom: 18px; }
html[data-ruled] .ledger li { padding: 12px var(--pad); align-items: baseline; }
html[data-ruled] .ledger li:last-child { border-bottom: 0; }
html[data-ruled] .colophon { margin-top: 0; padding: 18px var(--pad) 72px; column-gap: 0; border-top: 0; }
html[data-ruled] .colophon p { grid-column: 1 / -1; }
html[data-ruled] .info::before, html[data-ruled] .info::after { bottom: auto; top: -6px; }

@media (max-width: 760px) {
  html[data-ruled] .top-nav { display: none !important; }
  html[data-ruled] .intro h1, html[data-ruled] .intro > p:not(.statement), html[data-ruled] .intro .contact { grid-column: 1 / -1; grid-row: auto; border-left: 0; }
  html[data-ruled] .intro h1 { padding-top: 10vh; }
  html[data-ruled] .intro > p:not(.statement) { padding-top: 0; }
  html[data-ruled] .work .row { background: none; }
  html[data-ruled] .work .row > :not(.thumb) { padding-block: 4px; }
  html[data-ruled] .work .row { padding-block: 12px; }
  html[data-ruled] .info section, html[data-ruled] .info section + section { grid-column: 1 / -1; border-left: 0; }
  html[data-ruled] .info section + section { border-top: 1px solid var(--rule); margin-top: var(--pad); }
}
html[data-ruled] .brand { white-space: nowrap; }

/* Ruled keeps to white until its switch is thrown, then goes black; the theme pill is gone. */
:root[data-ruled]:not([data-palette="black"]) { --bg: #fff; --panel: #f2f2f0; --ink: #141414; --ink-2: #6b6b6b; --line: #d9d9d6; --tide: #2a63a8; --calder: #c2492a; --night: #b97800; --read: #55732a; color-scheme: light; }
:root[data-ruled][data-palette="black"] { --bg: #000; --panel: #0e0e0e; --ink: #ececea; --ink-2: #8c8c88; --line: #2c2c2b; --tide: #6fa3e0; --calder: #ef7a58; --night: #f0a92a; --read: #9fbe68; color-scheme: dark; }
html[data-ruled] .top .theme { display: none; }
/* The switch lies flat: a square knob in a track, left for off, stepping right for on. */
html[data-ruled] .top .lamp {
  width: 40px; height: 22px; padding: 0; border: 1px solid var(--ink); background: var(--bg); border-radius: 0;
}
html[data-ruled] .top .lamp .lamp-knob {
  width: 14px; height: 14px; margin: 0; left: 3px; top: 3px; border-radius: 0; background: var(--ink);
  transform: none; transition: transform .2s steps(4), background-color .2s steps(2);
}
html[data-ruled] .top .lamp[aria-checked="true"] { background: var(--ink); }
html[data-ruled] .top .lamp[aria-checked="true"] .lamp-knob { background: var(--bg); transform: translateX(18px); }
html[data-ruled] .top .lamp:hover .lamp-knob { box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--bg) 40%, transparent); }
html[data-ruled] .top-end::before { content: "Turn the lights off"; font: 16px/1 var(--pix); text-transform: uppercase; color: var(--ink-2); -webkit-font-smoothing: none; margin-right: 4px; }
html[data-ruled][data-palette="black"] .top-end::before { content: "Turn the lights on"; }
html[data-ruled] body, html[data-ruled] .cur-trail { transition: background-color .2s steps(3); }

/* Grid: the four projects as cells, two to a row, split by a centre rule. */
html[data-ruled] .section-head .layout { grid-column: 10 / 13; }
html[data-ruled] .work[data-layout="grid"] {
  gap: 0; padding: 0; background: linear-gradient(var(--rule) 0 0) 50% 0 / 1px 100% no-repeat;
}
/* The preview fills its cell to the rules; only the text under it is inset. */
html[data-ruled] .work[data-layout="grid"] .row { background: none; padding: 0; column-gap: 16px; }
html[data-ruled] .work[data-layout="grid"] .row > :not(.thumb) { padding: 0; }
html[data-ruled] .work[data-layout="grid"] .row > .title { padding: var(--pad) var(--pad) 0; }
html[data-ruled] .work[data-layout="grid"] .row > .yr { padding: 0 0 var(--pad) var(--pad); }
html[data-ruled] .work[data-layout="grid"] .row > .client { padding-bottom: var(--pad); }
html[data-ruled] .work[data-layout="grid"] .row > .kind { padding: 0 calc(var(--pad) + 24px) var(--pad) 0; }
html[data-ruled] .work[data-layout="grid"] .thumb { margin: 0; }
html[data-ruled] .work[data-layout="grid"] .mini { box-shadow: none; }
html[data-ruled] .work[data-layout="grid"] .row::after { top: auto; bottom: calc(var(--pad) + 4px); margin-top: 0; }
@media (max-width: 760px) { html[data-ruled] .work[data-layout="grid"] { background: none; } }

/* The hover checker takes its colour from the project's own picture: the tide board's grey, Calder's black,
   the shelter display's amber, the reading page's highlighter. On black, the pictures' light colours. */
html[data-ruled] :is(.work li, .reel-item):has(.mini-tide) { --hc: #8f8d84; }
html[data-ruled] :is(.work li, .reel-item):has(.mini-type) { --hc: #141414; --hc-a: 22%; }
html[data-ruled] :is(.work li, .reel-item):has(.mini-night) { --hc: #f5a623; --hc-a: 38%; }
html[data-ruled] :is(.work li, .reel-item):has(.mini-read) { --hc: #e2cf5c; --hc-a: 50%; }
html[data-ruled][data-palette="black"] :is(.work li, .reel-item):has(.mini-tide) { --hc: #e8e7e1; --hc-a: 22%; }
html[data-ruled][data-palette="black"] :is(.work li, .reel-item):has(.mini-type) { --hc: #f2f2f0; --hc-a: 18%; }

/* List and grid: the words fade out as they leave and back in as they land, so the trip is mostly unseen. */
html[data-ruled]::view-transition-old(.text), html[data-ruled]::view-transition-old(.rest) { animation: ruled-out .2s ease-out both; }
html[data-ruled]::view-transition-new(.text), html[data-ruled]::view-transition-new(.rest) { animation: ruled-in .72s ease-out both; }
@keyframes ruled-out { to { opacity: 0; } }
@keyframes ruled-in { 0%, 45% { opacity: 0; } to { opacity: 1; } }

/* ---------- footer (Classic, Mesh and Ruled) ----------
   One row on Classic's twelve columns, lined up with the work table: a label, then email, LinkedIn and case studies. */
.site-foot { position: relative; max-width: 1280px; margin: 0 auto; padding-inline: var(--gap); }
html[data-page]:not([data-ruled], [data-mesh]) .site-foot { display: none; }
.sf { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: 10px; align-items: baseline; padding: 24px 0 64px; border-top: 1px solid var(--line); }
.sf-label { grid-column: 1 / 3; margin: 0; color: var(--ink-2); }
.sf-link { justify-self: start; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 4px; text-decoration-color: var(--line); transition: text-decoration-color .2s, color .2s; }
.sf-link:hover, .sf-link:focus-visible { text-decoration-color: currentColor; color: var(--c); }
.sf-link:nth-of-type(1) { grid-column: 3 / 7; }
.sf-link:nth-of-type(2) { grid-column: 7 / 10; }
.sf-link:nth-of-type(3) { grid-column: 10 / 13; }
.sf-px { display: none; }
@media (max-width: 760px) { .sf-label, .sf-link:nth-of-type(n) { grid-column: 1 / -1; } }

/* Ruled: the footer is always black, ruled into the same four cells as the table, with room underneath for the pixels. */
html[data-ruled] .colophon { padding-bottom: var(--pad); }
html[data-ruled] .site-foot {
  --bg: #000; --ink: #ececea; --ink-2: #8c8c88; --line: #2c2c2b; --c: #ececea;
  max-width: none; padding: 0; background: var(--bg); color: var(--ink); z-index: 1; overflow: hidden; color-scheme: dark;
}
html[data-ruled] .sf-px { display: block; position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
html[data-ruled] .sf {
  position: relative; width: var(--frame); margin: 0 auto; padding: 0; min-height: 300px; column-gap: 0; align-items: stretch;
  border-top: 0; border-inline: 1px solid var(--line);
}
html[data-ruled] .sf > * { padding: var(--pad); align-self: stretch; }
html[data-ruled] .sf-link { border-left: 1px solid var(--line); text-decoration: none; }
html[data-ruled] .sf-link:hover, html[data-ruled] .sf-link:focus-visible { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; }
html[data-ruled] .sf-label { font-family: var(--pix); font-size: 16px; line-height: 1.25; text-transform: uppercase; -webkit-font-smoothing: none; }
html[data-ruled] .sf-link:nth-of-type(1) { grid-column: 3 / 7; }
@media (max-width: 760px) {
  html[data-ruled] .sf { min-height: 0; padding-bottom: 160px; }
  html[data-ruled] .sf > * { padding-block: 10px; border-left: 0; }
  html[data-ruled] .sf-label { padding-top: var(--pad); }
}
.cur.inv { color: #ececea; }

/* Ruled's page pixels sit behind everything, and only show with the lights off. */
.page-px { display: none; }
html[data-ruled][data-palette="black"] .page-px { display: block; position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: -1; pointer-events: none; }
/* Ruled's top bar stays put, so the lights are always in reach. Its ground runs out to both edges. */
html[data-ruled] { scroll-padding-top: 88px; }
html[data-ruled] .top {
  position: sticky; top: 0; z-index: 10; background: var(--page); border-inline: 1px solid var(--rule);
  box-shadow: 0 0 0 100vw var(--page); clip-path: inset(0 -100vw -6px); transition: background-color .6s var(--ease), box-shadow .6s var(--ease);
}

/* ---------- ruled gallery ----------
   The gallery drawn on Ruled's sheet. The top bar stays, so the lights are in reach. Below it, the pinned column and the
   run of work are two cells split by a rule. Each picture fills its cell, with a strip under it for the name. There
   are no column labels and no nav. The four projects show once, then the black footer.
   Below 900px it falls back to Ruled. */
@media (min-width: 900px) {
  html[data-page="ruled-gallery"] .view[data-view="index"]:not([hidden]) { column-gap: 0; grid-template-columns: minmax(0, 11fr) minmax(0, 13fr); }
  /* The bar's ground is painted by its own rule's border image rather than a shadow, so the centre rule shows right up to it. */
  html[data-page="ruled-gallery"] .top { box-shadow: none; border-image: linear-gradient(var(--page) calc(100% - 1px), var(--rule) 0) 0 0 1 0 fill / 0 0 1px 0 / 0 100vw; }
  /* No scroll, so no top bar and no footer: the lights switch sits in the corner instead. */
  html[data-page="ruled-gallery"] body:has(.view[data-view="index"]:not([hidden])) :is(.top, .site-foot) { display: none; }
  html[data-page="ruled-gallery"] .lead {
    top: 0; height: 100vh; padding: 0; gap: 0; overflow: visible; justify-content: flex-start;
  }
  /* No labels or nav: the statement, the experience and the work speak for themselves. */
  html[data-page="ruled-gallery"] .top-nav { display: none; }
  html[data-page="ruled-gallery"] .lead .intro::before { display: none; }
  html[data-page="ruled-gallery"] .lead .intro { padding: 0; row-gap: 0; border: 0; border-image: none; }
  html[data-page="ruled-gallery"] .lead .intro::after { display: none; }
  html[data-page="ruled-gallery"] .lead .intro .statement { padding: var(--pad); font-size: clamp(20px, 1.6vw, 24px); }
  /* Get in touch sits under the statement, flush with its text; pointing at it shows the email beside it. */
  html[data-page="ruled-gallery"] .lead .intro .contact {
    grid-column: 1 / -1; grid-row: auto; justify-self: stretch; justify-content: flex-start; flex-wrap: nowrap; gap: 16px;
    margin: 0; padding: 0 var(--pad) var(--pad); border: 0;
  }
  html[data-page="ruled-gallery"] .lead .intro .contact .email { display: inline; position: static; white-space: nowrap; }
  /* Experience sits at the foot of the column, under a rule that meets the frame and the centre rule with a cross. */
  html[data-page="ruled-gallery"] .lead .info { margin: auto 0 0; padding-top: 18px; border: 0; border-top: 1px solid var(--rule); border-image: none; }
  html[data-page="ruled-gallery"] .lead .info section { padding: 0; }
  html[data-page="ruled-gallery"] .lead .ledger li { padding-inline: var(--pad); }
  html[data-page="ruled-gallery"] .reel { padding: 0; border-left: 1px solid var(--rule); }
  html[data-page="ruled-gallery"] .reel-track { gap: 0; }
  /* Each piece is a cell: the picture to the rules, the name and year in a strip below. */
  html[data-page="ruled-gallery"] .reel-item {
    border-bottom: 1px solid; border-image: linear-gradient(var(--rule) 0 0) 0 0 1 0 / 0 0 1px 0 / 0 100vw 0 0;
  }
  html[data-page="ruled-gallery"] .reel-item::after {
    content: ""; position: absolute; z-index: 1; right: -6px; bottom: -6px; width: 11px; height: 11px; background: var(--ink); pointer-events: none;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 11' shape-rendering='crispEdges'%3E%3Cpath d='M5 0h1v11H5zM0 5h11v1H0z'/%3E%3C/svg%3E");
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 11' shape-rendering='crispEdges'%3E%3Cpath d='M5 0h1v11H5zM0 5h11v1H0z'/%3E%3C/svg%3E");
  }
  html[data-page="ruled-gallery"] .reel-item .mini { border-radius: 0; }
  html[data-page="ruled-gallery"] .reel-name {
    position: relative; inset: auto; isolation: isolate; display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
    padding: 16px calc(var(--pad) + 24px) 18px var(--pad); border-radius: 0; background: none; opacity: 1;
  }
  html[data-page="ruled-gallery"] .reel-name span { font: 16px/1.25 var(--pix); text-transform: uppercase; -webkit-font-smoothing: none; }
  html[data-page="ruled-gallery"] .reel-name span::before { content: none; }
  /* Pointing at a piece fills its strip with the two-pixel checker in the picture's colour and steps the arrow in. */
  html[data-page="ruled-gallery"] .reel-name::before {
    content: ""; position: absolute; inset: 0; z-index: -1; opacity: 0; transition: opacity .15s steps(3);
    background: repeating-conic-gradient(color-mix(in oklab, var(--hc, var(--c)) var(--hc-a, 30%), transparent) 0 25%, transparent 0 50%) 0 0 / 4px 4px;
  }
  html[data-page="ruled-gallery"] .reel-name::after {
    content: ""; position: absolute; right: var(--pad); top: 50%; width: 10px; height: 14px; margin-top: -7px; background: var(--c);
    opacity: 0; transform: translateX(-6px); transition: opacity .15s steps(2), transform .2s steps(3);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 7' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h1v1h1v1h1v1h1v1H3v1H2v1H1v1H0z'/%3E%3C/svg%3E") no-repeat center / contain;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 7' shape-rendering='crispEdges'%3E%3Cpath d='M0 0h1v1h1v1h1v1h1v1H3v1H2v1H1v1H0z'/%3E%3C/svg%3E") no-repeat center / contain;
  }
  html[data-page="ruled-gallery"] .reel-item:is(:hover, :focus-visible) .reel-name::before { opacity: 1; }
  html[data-page="ruled-gallery"] .reel-item:is(:hover, :focus-visible) .reel-name::after { opacity: 1; transform: none; }
}

/* Ruled: the back link takes the home page's pixel arrow, turned to point back, and steps rather than slides. */
html[data-ruled] .back::before {
  width: 10px; height: 14px; background: var(--c); transition: transform .2s steps(3);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 7' shape-rendering='crispEdges'%3E%3Cpath d='M4 0h1v7H4v-1H3v-1H2v-1H1V3h1V2h1V1h1z'/%3E%3C/svg%3E") no-repeat center / contain;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 5 7' shape-rendering='crispEdges'%3E%3Cpath d='M4 0h1v7H4v-1H3v-1H2v-1H1V3h1V2h1V1h1z'/%3E%3C/svg%3E") no-repeat center / contain;
}

/* ---------- Gradient ----------
   Classic with a moving colour field, whose colours come from the work (see app.js), laid behind the page
   from the foot of the hero down, faint at first and strongest at the footer. */
.mesh { display: none; }
html[data-mesh] { overflow-x: clip; }
html[data-mesh] .top { position: relative; z-index: 2; }
html[data-mesh] .mesh { display: block; position: absolute; z-index: -1; left: 0; width: 100%; pointer-events: none; }
.mesh canvas { display: block; width: 100%; height: 100%; }
/* Gradient: the box runs from the hero to the bottom of the page and carries the fade, so the colour builds with the
   page, not with the screen. The canvas inside is one screen tall and rides along, so only what can be seen is drawn. */
html[data-page="mesh"] .mesh {
  -webkit-mask: linear-gradient(transparent, rgb(0 0 0 / .12) 30%, rgb(0 0 0 / .45) 65%, rgb(0 0 0 / .85) 90%, #000);
  mask: linear-gradient(transparent, rgb(0 0 0 / .12) 30%, rgb(0 0 0 / .45) 65%, rgb(0 0 0 / .85) 90%, #000);
}
html[data-page="mesh"] .mesh canvas { position: sticky; top: 0; height: min(100vh, 100%); }
.mesh.flat canvas { display: none; }
.mesh.flat { background: linear-gradient(115deg, var(--m0), var(--m1)); }
/* The intro fills the first screen, with the headline set large at its foot. */
html[data-mesh] .intro { min-height: calc(100svh - 76px - 8vh); align-content: end; padding: 12vh 0 18vh; }
html[data-mesh] .intro h1 { grid-column: 1 / 11; max-width: 15em; font-size: clamp(40px, 6vw, 88px); line-height: 1.02; letter-spacing: -.03em; }
html[data-mesh] .intro > p:not(.statement) { color: color-mix(in oklab, var(--ink) 78%, transparent); }
html[data-mesh] .case-head { padding-bottom: 4vh; }
/* The field is bright enough under the bar that grey links lose it, so they take the full ink colour. */
html[data-mesh] .top-nav a { color: var(--ink); }
html[data-mesh] .top-nav a:hover { opacity: .7; }

/* ---------- Project page: image sequence ----------
   Picked under Options, beside the layout. Client on the left and the title on the right, then plates that run the
   full width or sit in pairs, with the tags and each section of text between them, and the facts as credits. The
   plates are drawn, sized in container units so each one scales as a picture would. */

.pc { display: none; }
html[data-case="images"] .case > :not(.back, .pc) { display: none; }
html[data-case="images"] .case .pc { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--gap); }
.pc > * { grid-column: 1 / -1; }
.pc-head { display: grid; grid-template-columns: subgrid; align-items: start; padding: 10vh 0 6vh; }
.pc-client { grid-column: 1 / 7; margin: .35em 0 0; }
.pc-head h1 { grid-column: 7 / 13; margin: 0; font-family: var(--display); font-weight: 400; font-size: clamp(40px, 5.6vw, 76px); line-height: 1; letter-spacing: -.025em; text-wrap: balance; }
.pc-intro, .pc-sec { display: grid; grid-template-columns: subgrid; align-items: start; padding: clamp(56px, 10vh, 120px) 0; }
.pc-tags { grid-column: 1 / 7; display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.pc-tags li { padding: 4px 13px 5px; border: 1.5px solid var(--ink); border-radius: 999px; line-height: 1.25; }
.pc-lede, .pc-sec p { grid-column: 7 / 13; margin: 0; max-width: 32em; font-size: clamp(19px, 1.7vw, 23px); line-height: 1.4; text-wrap: pretty; }
.pc-sec h2 { grid-column: 1 / 7; margin: 0; font-family: var(--display); font-weight: 400; font-size: var(--big); line-height: 1.1; letter-spacing: -.015em; }
.pc-credits { display: grid; grid-template-columns: subgrid; padding: clamp(56px, 10vh, 120px) 0 0; }
.pc-credits h2 { grid-column: 1 / 7; margin: 0; font: inherit; color: var(--ink-2); }
.pc-credits dl { grid-column: 7 / 13; margin: 0; }
.pc-credits dl div { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: var(--gap); padding: 10px 0; border-top: 1px solid var(--line); }
.pc-credits dt { color: var(--ink-2); }
.pc-credits dd { margin: 0; }
@media (max-width: 720px) {
  .pc :is(.pc-head, .pc-intro, .pc-sec, .pc-credits) > *, .pc .shot.half { grid-column: 1 / -1; }
  .pc-head, .pc-intro, .pc-sec { row-gap: 20px; }
  .pc-head h1 { font-size: clamp(36px, 10vw, 52px); }
}

.shot { container-type: inline-size; position: relative; display: grid; place-items: center; margin: 0; overflow: hidden; border-radius: var(--radius); font-family: var(--sign); }
/* In dark, a hairline keeps the black plates from running into the page. */
.shot::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; }
:root[data-theme="dark"] .shot::after { box-shadow: inset 0 0 0 1px var(--line); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .shot::after { box-shadow: inset 0 0 0 1px var(--line); } }
.shot.full { aspect-ratio: 16 / 9; }
.shot.half { grid-column: span 6; aspect-ratio: 4 / 5; }
.shot p { margin: 0; }
.pl-note { position: absolute; left: 4cqw; bottom: 3.4cqw; font: 500 max(11px, 1.6cqw)/1.2 var(--sign); opacity: .7; }
.half .pl-note { font-size: max(11px, 3.2cqw); left: 7cqw; bottom: 6cqw; }
.pl-concrete { background: #b9b6ad; } .pl-epaper { background: #e8e7e1; color: #151515; } .pl-harbour { background: #2a63a8; }
.pl-stone { background: #d6d3cb; color: #151515; } .pl-dark { background: #2b2b29; } .pl-black { background: #141414; color: #f2f2f0; }
.pl-white { background: #f2f2f0; color: #141414; } .pl-calder { background: #c2492a; color: #fff; } .pl-street { background: #3a3d40; }
.pl-night { background: #0b0a08; color: #f5a623; } .pl-amber { background: #f5a623; color: #0b0a08; }
.pl-dusk { background: linear-gradient(#141b26, #0b0a08 70%); } .pl-linen { background: #d9d6cf; color: #1d1d1b; }
.pl-paper { background: #fbfaf7; color: #1d1d1b; box-shadow: inset 0 0 0 1px #e2e1dc; } .pl-green { background: #55732a; color: #fbfaf7; }
.pl-yellow { background: #e9d97a; color: #1d1d1b; }
.pl-split { grid-template-columns: 1fr 1fr; place-items: stretch; }

/* Tide boards */
.t-board { position: relative; display: grid; width: 60cqw; aspect-ratio: 16 / 9; box-sizing: border-box; padding: 3.4cqw 4cqw; background: #e8e7e1; color: #151515; border: 1.2cqw solid #2b2b29; border-radius: .6cqw; box-shadow: 0 1.4cqw 3cqw -1cqw rgb(0 0 0 / .35); align-content: start; }
.t-board .t-where { font: 500 1.5cqw/1 var(--sign); opacity: .7; }
.t-board b { font: 700 11cqw/1 var(--sign); letter-spacing: -.02em; margin-top: 2cqw; }
.t-board .t-until { font: 500 3.4cqw/1.1 var(--sign); }
.t-board .t-now { position: absolute; right: 4cqw; top: 3.4cqw; font: 500 1.5cqw/1 var(--sign); }
.t-board svg { position: absolute; left: 4cqw; right: 4cqw; bottom: 2.6cqw; width: calc(100% - 8cqw); height: 6cqw; }
.t-board path, .t-chart path { fill: none; stroke: #151515; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.t-crop { position: absolute; left: -3cqw; bottom: -18cqw; font: 700 76cqw/1 var(--sign); letter-spacing: -.04em; }
.phone { width: 54cqw; aspect-ratio: 9 / 18; box-sizing: border-box; padding: 9cqw 5cqw; background: #fbfaf7; color: #151515; border: 1.6cqw solid #151515; border-radius: 7cqw; }
.ph-head { display: flex; justify-content: space-between; align-items: baseline; font: 700 4.6cqw/1 var(--sign); margin-bottom: 6cqw !important; }
.ph-head span { font: 500 2.8cqw/1 var(--sign); opacity: .6; }
.phone ol { margin: 0; padding: 0; list-style: none; }
.phone li { display: grid; grid-template-columns: 1fr 1fr auto; padding: 3.2cqw 0; border-top: 1px solid #d4d2cb; font: 500 3.3cqw/1 var(--sign); }
.t-row { display: flex; gap: 3cqw; }
.t-mini { display: grid; width: 24cqw; aspect-ratio: 4 / 3; box-sizing: border-box; padding: 2cqw 2.2cqw; align-content: start; background: #e8e7e1; border: .7cqw solid #2b2b29; border-radius: .4cqw; }
.t-mini b { font: 700 5.6cqw/1 var(--sign); letter-spacing: -.02em; margin-top: 1.4cqw; }
.t-mini span { font: 500 1.7cqw/1.2 var(--sign); }
.t-mini small { margin-top: auto; font: 500 1.2cqw/1 var(--sign); opacity: .6; }
.t-mini.off b { color: #8f8d84; }
.t-chart { position: absolute; inset: 14cqw 8cqw 22cqw; width: calc(100% - 16cqw); height: calc(100% - 36cqw); }
.t-chart rect { fill: #2a63a8; opacity: .18; }
.t-axis { position: absolute; left: 8cqw; right: 8cqw; bottom: 14cqw; display: flex; justify-content: space-between; font: 500 3.2cqw/1 var(--sign); opacity: .6; }
.layers { display: grid; width: 74cqw; gap: 1.4cqw; }
.layers span { padding: 5cqw 5cqw; font: 500 3.6cqw/1 var(--sign); border-radius: .6cqw; }
.l-glass { background: rgb(190 214 230 / .28); color: #e8eef2; box-shadow: inset 0 0 0 1px rgb(220 235 245 / .4); }
.l-paper { background: #e8e7e1; color: #151515; } .l-plate { background: #6b6a64; color: #f2f2ee; } .l-case { background: #44433f; color: #d8d6cf; }
.t-measure { display: flex; align-items: center; gap: 3cqw; }
.t-measure i { width: 1px; height: 20cqw; background: #151515; position: relative; }
.t-measure i::before, .t-measure i::after { content: ""; position: absolute; left: -1.2cqw; width: 2.4cqw; height: 1px; background: #151515; }
.t-measure i::before { top: 0; } .t-measure i::after { bottom: 0; }
.t-measure span { font: 500 1.8cqw/1 var(--sign); writing-mode: vertical-rl; transform: rotate(180deg); }
.t-measure b { font: 700 27cqw/.74 var(--sign); letter-spacing: -.03em; padding-top: 1.6cqw; }

/* Calder */
.c-line { font: 520 6.2cqw/1 var(--sign); letter-spacing: .005em; }
.c-pairs { display: grid; gap: 1.6cqw; width: 76cqw; }
.c-pairs b { font: 500 19cqw/1 var(--sign); letter-spacing: .04em; }
.c-pairs small { font: 500 3cqw/1 var(--sign); opacity: .6; margin-bottom: 4cqw; }
.c-weights { display: grid; gap: 1cqw; width: 76cqw; }
.c-weights span { display: flex; justify-content: space-between; align-items: baseline; font: 22cqw/1 var(--sign); border-bottom: 1px solid rgb(255 255 255 / .35); }
.c-weights small { font: 500 3cqw/1 var(--sign); opacity: .8; }
.c-flag { display: grid; grid-template-columns: auto 1fr; gap: 1cqw 3cqw; align-items: center; width: 62cqw; padding: 3cqw 3.6cqw; background: #f2f2f0; color: #141414; border-radius: .6cqw; box-shadow: 0 0 6cqw rgb(255 250 230 / .18); }
.c-flag b { grid-row: span 2; display: grid; place-items: center; width: 10cqw; aspect-ratio: 1; background: #c2492a; color: #fff; font: 700 7cqw/1 var(--sign); border-radius: .4cqw; }
.c-flag span { font: 600 6cqw/1 var(--sign); }
.c-flag small { font: 500 2cqw/1 var(--sign); opacity: .6; }
.c-far { font: 520 9cqw/1 var(--sign); letter-spacing: .02em; filter: blur(.35cqw); }
.c-set { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; width: 78cqw; background: #d4d2cb; border: 1px solid #d4d2cb; }
.c-set span { display: grid; place-items: center; aspect-ratio: 5 / 4; background: #f2f2f0; font: 500 9cqw/1 var(--sign); }
.c-lit, .c-unlit { display: grid; place-content: center; gap: 2cqw; padding: 0 5cqw; }
.c-lit { background: #fbfaf2; color: #141414; box-shadow: inset 0 0 12cqw rgb(255 240 190 / .6); }
.c-unlit { background: #b9b7b0; color: #141414; }
.c-lit b, .c-unlit b { font: 5.4cqw/1 var(--sign); }
.c-lit small, .c-unlit small { font: 500 1.5cqw/1 var(--sign); opacity: .6; }

/* Night shelter displays */
.n-screen { width: 70cqw; box-sizing: border-box; padding: 2.4cqw 3.4cqw; background: #000; border: 1cqw solid #1d1c19; border-radius: .6cqw; box-shadow: 0 0 8cqw rgb(245 166 35 / .14); }
.n-head { display: flex; justify-content: space-between; font: 500 1.8cqw/1 var(--sign); opacity: .7; padding-bottom: 2cqw !important; border-bottom: 1px solid rgb(245 166 35 / .3); }
.n-dep { display: grid; grid-template-columns: 9cqw 1fr auto; align-items: baseline; padding: 2.2cqw 0 !important; border-bottom: 1px solid rgb(245 166 35 / .18); }
.n-dep b { font: 700 3cqw/1 var(--sign); }
.n-dep span { font: 700 5.4cqw/1 var(--sign); }
.n-dep small { font: 500 2.4cqw/1 var(--sign); }
.n-day { width: 76cqw; padding: 4cqw; background: #fbfaf7; border-radius: 1cqw; box-sizing: border-box; }
.n-day .n-head { font-size: 3cqw; padding-bottom: 3cqw !important; border-color: #d4d2cb; opacity: 1; }
.n-day p:not(.n-head) { display: grid; grid-template-columns: 11cqw 1fr auto; padding: 2cqw 0; border-bottom: 1px solid #e6e4dd; font: 500 3.2cqw/1 var(--sign); }
.n-big { display: grid; gap: 4cqw; width: 74cqw; }
.n-big b { justify-self: start; padding: 2cqw 3cqw; border: .6cqw solid; font: 700 9cqw/1 var(--sign); }
.n-big span { font: 700 17cqw/.95 var(--sign); letter-spacing: -.02em; }
.n-big small { font: 500 5cqw/1 var(--sign); }
.n-shelter { position: relative; width: 46cqw; height: 34cqw; }
.n-roof { position: absolute; left: -4cqw; right: -4cqw; top: 0; height: 1.4cqw; background: #2b2a27; }
.n-glow { position: absolute; left: 13cqw; top: 8cqw; width: 20cqw; height: 13cqw; background: #f5a623; border-radius: .4cqw; box-shadow: 0 0 10cqw 2cqw rgb(245 166 35 / .4); }
.n-post { position: absolute; top: 0; bottom: 0; width: 1cqw; background: #2b2a27; left: 0; }
.n-post + .n-post { left: auto; right: 0; }
.n-shelter::after { content: ""; position: absolute; left: -30cqw; right: -30cqw; bottom: 0; height: 1px; background: rgb(245 166 35 / .25); }
.stat { display: grid; gap: 4cqw; width: 76cqw; }
.stat b { font: 700 40cqw/.85 var(--sign); letter-spacing: -.04em; }
.stat span { font: 500 4.6cqw/1.25 var(--sign); max-width: 20em; }
.notes { display: grid; gap: 3cqw; width: 76cqw; }
.notes p { display: grid; gap: 2.4cqw; padding: 5cqw; background: #fbfaf7; font: 500 5cqw/1.2 var(--sign); border-radius: .6cqw; }
.notes small { font: 500 2.8cqw/1 var(--sign); opacity: .6; }
.n-crop { position: absolute; left: 4cqw; top: 50%; transform: translateY(-50%); display: flex; align-items: center; gap: 4cqw; white-space: nowrap; }
.n-crop b { padding: 1.6cqw 2.4cqw; border: .6cqw solid; font: 700 9cqw/1 var(--sign); }
.n-crop span { font: 700 22cqw/1 var(--sign); letter-spacing: -.02em; }

/* Reading edition */
.tablet { width: 64cqw; aspect-ratio: 4 / 3; box-sizing: border-box; padding: 6cqw 7cqw; background: #fbfaf7; border: 1.6cqw solid #1d1d1b; border-radius: 2.4cqw; }
.r-meta { font: 500 1.6cqw/1 var(--sign); opacity: .55; margin-bottom: 3cqw !important; }
.r-text { font: 400 2.9cqw/1.55 "Source Serif 4", Georgia, serif; }
.shot mark { background: #e9d97a; color: inherit; padding: 0 .1em; }
.kept-list { width: 76cqw; }
.kept-list > p { font: 500 3.4cqw/1 var(--sign); opacity: .8; padding-bottom: 3cqw !important; border-bottom: 1px solid rgb(251 250 247 / .35); }
.kept-list ol { margin: 0; padding: 0; list-style: none; }
.kept-list li { padding: 4cqw 0; border-bottom: 1px solid rgb(251 250 247 / .25); font: 400 5cqw/1.3 "Source Serif 4", Georgia, serif; }
.r-handles { width: 76cqw; font: 400 8.4cqw/1.5 "Source Serif 4", Georgia, serif; }
.r-handles i { position: relative; display: inline-block; width: 0; height: 1.1em; vertical-align: -.2em; border-left: .5cqw solid #1f3a5f; }
.r-handles i::before { content: ""; position: absolute; left: -2cqw; width: 3.5cqw; aspect-ratio: 1; border-radius: 50%; background: #1f3a5f; }
.r-handles i:first-child::before { top: -3cqw; } .r-handles i:last-child::before { bottom: -3cqw; }
.r-spread { display: grid; grid-template-columns: 1fr 1fr; gap: 8cqw; width: 70cqw; }
.r-spread div { display: grid; gap: 2.2cqw; }
.r-spread s { display: block; height: 1cqw; background: #cfcdc6; }
.r-spread s.hl { background: #e9d97a; } .r-spread s.short { width: 55%; }
.bars { display: grid; gap: 7cqw; width: 76cqw; }
.bars p { display: grid; gap: 2.4cqw; font: 500 3.6cqw/1 var(--sign); }
.bars b { display: block; width: var(--v); padding: 3cqw 0 3cqw 3cqw; box-sizing: border-box; min-width: 18cqw; background: #1d1d1b; color: #e9d97a; font: 700 7cqw/1 var(--sign); }
.r-cover { width: 46cqw; }
.r-cover b { font-size: 4.6cqw; }
.r-cover small { font-size: 2.8cqw; }
.r-return { display: grid; gap: 1.6cqw; width: 56cqw; }
.r-card { padding: 2.6cqw 3cqw; background: #fff; border: 1px solid #e2e1dc; border-left: .5cqw solid #e9d97a; font: 400 2.4cqw/1.4 "Source Serif 4", Georgia, serif; }


.ledger li.more { color: var(--ink-2); }

/* ---------- Gallery and Ruled gallery: previews only, and the lights ----------
   The work is shown, not opened. With a Label or Pixel cursor, the cursor names the piece, so Gallery's own name pill
   steps aside. The lights switch sits in the top-right corner of both pages. */
html:is([data-page="gallery"], [data-page="ruled-gallery"]) :is(.work .row, .reel-item) { cursor: default; }
html[data-page="gallery"][data-cursor] .reel-name { display: none; }
html:is([data-page="gallery"], [data-page="ruled-gallery"]) .top-end { display: none; }

.lights { display: none; }
html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lights {
  position: fixed; top: 16px; right: 16px; z-index: 12; display: inline-flex; align-items: center; gap: 10px;
  padding: 6px 6px 6px 14px; font: inherit; font-size: 13px; color: var(--ink-2);
  background: var(--bg); border: 1px solid var(--line); border-radius: 999px; cursor: pointer;
  transition: color .15s var(--ease), border-color .15s var(--ease), transform .12s var(--ease);
}
html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lights:hover { color: var(--ink); border-color: color-mix(in oklab, var(--ink) 30%, var(--line)); }
html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lights:active { transform: scale(.97); }
.lights-track { position: relative; width: 34px; height: 20px; border-radius: 999px; background: color-mix(in oklab, var(--ink) 12%, transparent); transition: background-color .2s var(--ease); }
.lights-knob { position: absolute; left: 3px; top: 3px; width: 14px; height: 14px; border-radius: 999px; background: var(--ink); transition: transform .2s var(--ease), background-color .2s var(--ease); }
.lights[aria-checked="true"] .lights-track { background: var(--ink); }
.lights[aria-checked="true"] .lights-knob { background: var(--bg); transform: translateX(14px); }
/* On the ruled sheet it is the flat switch: square knob in a square track, stepping across, with its label in pixels. */
html[data-ruled] .lights { gap: 12px; padding: 8px 8px 8px 12px; border-radius: 0; border-color: var(--rule); color: var(--ink-2); }
html[data-ruled] .lights-label { font: 16px/1 var(--pix); text-transform: uppercase; -webkit-font-smoothing: none; }
html[data-ruled] .lights-track { width: 40px; height: 22px; box-sizing: border-box; border: 1px solid var(--ink); border-radius: 0; background: var(--bg); transition: background-color .2s steps(2); }
html[data-ruled] .lights-knob { left: 3px; top: 3px; border-radius: 0; transition: transform .2s steps(4), background-color .2s steps(2); }
html[data-ruled] .lights[aria-checked="true"] .lights-track { background: var(--ink); }
html[data-ruled] .lights[aria-checked="true"] .lights-knob { transform: translateX(18px); }
@media (prefers-reduced-motion: reduce) { .lights, .lights-track, .lights-knob { transition: none; } }

/* Pixel scatter names the piece too, in its own pixel pill: square, in the pixel face, stepping open. */
.cur[data-kind="scatter"][data-s="pill"] .cur-dot { display: grid; }
.cur[data-kind="scatter"][data-s="pill"] .cur-px { display: none; }
.cur[data-kind="scatter"] .cur-dot {
  border-radius: 0; border: 0; height: 26px; background: #ececea; color: #000; box-shadow: 3px 3px 0 #3157d5;
  font: 16px/1 var(--pix, "Silkscreen", monospace); text-transform: uppercase; letter-spacing: 0; -webkit-font-smoothing: none;
  transition: width .18s steps(4), height .18s steps(3);
}
html:not([data-palette="black"]) .cur[data-kind="scatter"] .cur-dot { background: #141414; color: #fff; }
.cur[data-kind="scatter"] .cur-dot span { padding: 0 10px; transition: opacity .1s steps(2); }

/* Ruled gallery in the marquee: no name strips (the cursor names the piece), just the same gap as Gallery between
   square pictures, and no rules or crosses between them. */
@media (min-width: 900px) {
  html[data-page="ruled-gallery"] .reel-track { gap: var(--gap); }
  html[data-page="ruled-gallery"] .reel-name { display: none; }
  html[data-page="ruled-gallery"] .reel-item { border-bottom: 0; border-image: none; }
  html[data-page="ruled-gallery"] .reel-item::after { display: none; }
}

/* Recorded work in the reel takes the same 4:3 as every other piece. A close-up is cropped to fill it; a
   whole-page recording sits framed on a pale ground, rounded, with a soft container shadow. */
.reel .mini-video { background: var(--panel); }
.reel .mini-video :is(video, img) { display: block; width: 100%; height: 100%; object-fit: cover; }
.reel .mini-framed { background: #e2e8f1; }
.reel .mini-framed :is(video, img) {
  width: 84%; height: auto; object-fit: initial; border-radius: 6px;
  box-shadow: 0 1px 2px rgb(22 32 52 / .08), 0 10px 28px -6px rgb(22 32 52 / .22);
}
/* The Ruled system squares every corner, inside the artwork too. */
html[data-ruled] .reel .mini-framed :is(video, img) { border-radius: 0; }
/* A still framed the way the pricing piece is drawn: a near-white ground and softer corners. */
.reel .mini-pale { background: #f6f8fb; }
.reel .mini-pale img { border-radius: 10px; }

/* Type: Helvetica Neue with the lights on, IBM Plex Mono with them off. The pixel face stays on the Skills label
   and the switch, which read --pix, not --f. */
html[data-page="ruled-gallery"]:not([data-font]) {
  --f: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace; --display: var(--f); --display-w: 400; --display-ls: -.02em;
}

/* The lights-off switch, brought down to the lights-on one's footprint: same height, a smaller track, less padding,
   and the pixel label at 14px (off Silkscreen's 8px grid, chosen to keep the switch smaller). */
html[data-ruled] .lights { gap: 10px; padding: 6px 6px 6px 12px; }
html[data-ruled] .lights-label { font-size: 14px; }
html[data-ruled] .lights-track { width: 34px; height: 20px; }
html[data-ruled] .lights-knob { left: 2px; top: 2px; }
html[data-ruled] .lights[aria-checked="true"] .lights-knob { transform: translateX(14px); }

/* The intro sits where it does with the lights on: the same inset from the frame, the same distance from the top and
   the same size, so switching moves the type as little as possible. */
@media (min-width: 900px) {
  html[data-page="ruled-gallery"] { --pad: var(--gap); }
  html[data-page="ruled-gallery"] .lead .intro .statement { padding-top: clamp(16px, 5vh, 56px); font-size: clamp(20px, 1.75vw, 26px); }
}

/* ---------- gallery on a phone ----------
   Below 900px the gallery keeps its own content instead of falling back to the template: the intro, Get in touch
   and Skills stacked, then the work in one column, each piece named underneath since there's no cursor to name it.
   The pieces don't run as a marquee; recordings play as they scroll into view. The lights switch sits at the top
   of the page and scrolls away with it. */
@media (max-width: 899px) {
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) body:has(.view[data-view="index"]:not([hidden])) .top { display: none; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .view[data-view="index"] > :not(.lead, .reel) { display: none; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lights { position: absolute; top: 16px; right: 16px; }
  /* Intro, then the work, then Skills: the pinned column opens up so the reel can sit between its two parts. */
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .view[data-view="index"]:not([hidden]) { display: flex; flex-direction: column; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead { display: contents; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro { order: 1; display: grid; padding: 76px 0 0; row-gap: 20px; border: 0; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro > * { grid-column: 1 / -1; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro h1,
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro > p:not(.statement) { display: none; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro .statement {
    display: block; margin: 0; padding: 0; color: var(--ink); font-family: var(--display);
    font-size: 20px; font-weight: var(--display-w); line-height: 1.3; letter-spacing: -.01em; text-wrap: pretty;
  }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro .statement p { margin: 0 0 .7em; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro .statement .statement-sub { margin: 0; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .intro .contact { margin: 0; padding: 0; border: 0; justify-content: flex-start; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .info { order: 3; display: block; margin: 48px 0 0; padding: 0; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .lead .info section + section { display: none; }
  /* The work runs sideways as a strip, out to the edges of the screen, moving on its own. */
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .reel {
    order: 2; display: block; margin: 48px calc(-1 * var(--gap)) 0; padding: 0; border: 0; overflow: hidden; touch-action: pan-y;
  }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .reel-track { display: flex; gap: 12px; width: max-content; padding-left: var(--gap); will-change: transform; }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .reel-item { flex: 0 0 auto; width: min(78vw, 420px); }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .reel-name {
    display: block; position: static; opacity: 1; padding: 10px 0 0; border-radius: 0; background: none; font-size: 15px; line-height: 1.35;
  }
  html:is([data-page="gallery"], [data-page="ruled-gallery"]) .reel-item:hover .mini { transform: none; }
  /* Lights off: the same stack inside the frame. Text is inset from the rules, the Skills rules and the pictures run
     to the frame, and the names sit in a strip under each picture: the title in the mono, the year in the pixel face. */
  html[data-page="ruled-gallery"] .lead .intro { padding-inline: var(--pad); }
  html[data-page="ruled-gallery"] .reel { margin-inline: 0; }
  html[data-page="ruled-gallery"] .reel-track { padding-left: 0; gap: 0; }
  html[data-page="ruled-gallery"] .reel-item { border-right: 1px solid var(--rule); }
  html[data-page="ruled-gallery"] .reel-name { padding: 10px var(--pad) 0; }
  html[data-page="ruled-gallery"] .lead .intro::before, html[data-page="ruled-gallery"] .lead .intro::after { display: none; }
  html[data-page="ruled-gallery"] .reel-name span { font: 16px/1 var(--pix); text-transform: uppercase; -webkit-font-smoothing: none; }
  html[data-page="ruled-gallery"] .reel-name span::before { content: " "; }
  html[data-page="ruled-gallery"] .reel .mini, html[data-page="ruled-gallery"] .reel .mini-framed :is(video, img) { border-radius: 0; }
}
