/* d-recreation: Raian Pollock site, after the design language of clintbalcom.com (measured 24 Sep 2026),
   with its own ground, portrait treatment, header and headline. Own code; no source code, images or text copied.
   Fonts: Rethink Sans (OFL), self-hosted from static/fonts. */

/* A stand-in sized like Rethink Sans, so text set in the stand-in before the font arrives breaks into the same lines
   and nothing below jumps when it swaps (28 Sep 2026: the 006 title re-wrapped from three lines to two at 1.3 s on a
   slow phone and moved the page by 0.25). Metrics from the font file against Arial with fontTools: average advance
   0.4721 em against 0.4541, ascent 992 and descent 310 per 1000. */
@font-face {
  font-family: "Rethink Sans Fallback";
  src: local("Arial"), local("ArialMT"), local("Liberation Sans");
  size-adjust: 103.96%;
  ascent-override: 95.43%;
  descent-override: 29.82%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Rethink Sans";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("fonts/rethink-sans-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Rethink Sans";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("fonts/rethink-sans-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  color-scheme: light dark;
  /* closed palette, light */
  --ground: #dcede5;      /* jade mist: the page */
  --ink: #16201b;         /* text */
  --ink-2: #43554c;       /* secondary text, >= 4.5:1 on ground and on panel */
  --accent: #17664c;      /* deep jade: active nav, current dot, "Chose", focus, tether dot */
  --panel: #ffffff;       /* reveal panel, split chip (artifacts have no mat: they are prints, see .frame) */
  --hair: rgba(22, 32, 27, .26);
  --band: #dcede5;        /* header band once scrolled: solid ground */
  --curtain: rgba(220, 237, 229, .93);
  --logo-tile: transparent; /* company marks sit bare on the light ground */
  --logo-pad: 0px;
  --chip: rgba(23, 102, 76, .11); /* the bracket's hover: one quiet jade chip (the source's cyan/magenta split was removed, Raian 24 Sep) */
  --portrait-filter: grayscale(1) brightness(1.12) contrast(1.06);
  --portrait-blend: multiply;
  --portrait-mask: radial-gradient(ellipse 47% 48% at 50% 52%, #000 54%, rgba(0,0,0,.5) 77%, transparent 100%);
  --shadow-open: 0 3px 0 rgba(0, 0, 0, .03), 0 3px 66px rgba(0, 0, 0, .2), -40px 9px 84px rgba(0, 0, 0, .18);

  --font: "Rethink Sans", "Rethink Sans Fallback", Helvetica, Arial, sans-serif;

  /* the source's measured scale */
  --size-l: 3rem;      /* 48 */
  --size-m: 1.5rem;    /* 24 */
  --size-s: 1rem;      /* 16 */

  /* the source's measured grid and rhythm */
  --outerPad: min(7.5vw, 124px);
  --inner: 1650px;
  --centerMargin: calc(50% - 4.3rem);
  --vertGapLarge: 11.5rem;
  --vertGap: 7.5rem;
  --innerPad: 5.25rem;
  --headerPadTop: 5.25rem;
  --cvGap: calc(var(--size-m) * 1.4);
  --dot: 12px;

  /* a print resting on the table: a paper corner, and a shadow in the ground's own dark jade
     (a black shadow on jade mist turns grey and muddy). Three layers: contact, near, ambient;
     no sideways offset, lift kept under 10px, so it rests rather than floats. */
  --print-radius: 2px;
  --print-dim: none;
  --print-shadow:
    0 0 0 .5px rgba(22, 52, 40, .07),
    0 1px 1.5px rgba(22, 52, 40, .13),
    0 3px 6px -1px rgba(22, 52, 40, .08),
    0 10px 22px -6px rgba(22, 52, 40, .14);
  --print-shadow-lift:
    0 0 0 .5px rgba(22, 52, 40, .07),
    0 2px 3px rgba(22, 52, 40, .12),
    0 6px 12px -2px rgba(22, 52, 40, .09),
    0 18px 34px -10px rgba(22, 52, 40, .18);
  /* the edge ring for white screenshots only: blended with "darken", so it shows on a white or
     near-white edge and vanishes on the beige and darker ones (a pixel darker than the ring keeps
     its own colour). The ring colour is the threshold. */
  --print-ring: rgb(229, 232, 229);
  /* the same print shadow for a cut-out card (drop-shadow follows the card's own edge, not the image box) */
  --print-drop: drop-shadow(0 1px 1.5px rgba(22, 52, 40, .14)) drop-shadow(0 7px 12px rgba(22, 52, 40, .11));

  /* motion */
  --drift: 1.2em;
  --ease-out: cubic-bezier(.25, 1, .5, 1);
  --ease-enter: cubic-bezier(.42, 0, .21, 1);
  --ease-line: cubic-bezier(.57, 0, .12, 1);
  --ease-lift: cubic-bezier(.12, .93, .42, 1.2);
  --ease-bounce: cubic-bezier(.34, 1.56, .62, 1.2);
  --t-hover: .42s;
  --t-line: .21s;
  --t-enter: .48s;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ground: #101814;
    --ink: #e3eee8;
    --ink-2: #a2b5ab;
    --accent: #7ccfab;
    --panel: #1b2520;
    --chip: rgba(124, 207, 171, .14);
    --logo-tile: #dfe9e4; /* dark marks (SEOmonitor, Botify) vanish on the dark ground: a pale tile carries every mark */
    --logo-pad: 2px;
    --hair: rgba(227, 238, 232, .22);
    --band: #101814;
    --curtain: rgba(16, 24, 20, .93);
    /* dark: the photo's light backdrop read as a lit oval (G2 fix). The home page swaps in a cut-out of the
       subject (assets/person/raian-b-cut.webp, macOS Vision subject lift) and only the shoulders fade. */
    --portrait-filter: grayscale(1) brightness(.9) contrast(1.06);
    --portrait-blend: normal;
    --portrait-mask: linear-gradient(to bottom, #000 60%, rgba(0,0,0,.55) 78%, transparent 94%);
    --shadow-open: 0 3px 0 rgba(0, 0, 0, .2), 0 3px 66px rgba(0, 0, 0, .55), -40px 9px 84px rgba(0, 0, 0, .45);
    /* on a dark table a print barely casts a shadow: black only (never a light edge, which glows),
       mostly a darkening right under the edge; the print's own lightness does the separating */
    --print-shadow:
      0 0 0 1px rgba(0, 0, 0, .28),
      0 1px 2px rgba(0, 0, 0, .5),
      0 8px 20px -6px rgba(0, 0, 0, .55);
    --print-shadow-lift:
      0 0 0 1px rgba(0, 0, 0, .28),
      0 2px 4px rgba(0, 0, 0, .5),
      0 14px 30px -8px rgba(0, 0, 0, .6);
    --print-ring: transparent; /* nothing melts on a dark ground */
    --print-dim: brightness(.9); /* a light print is the brightest thing in a dark room: turned down a little, so the text still leads */
    --print-drop: brightness(.9) drop-shadow(0 1px 2px rgba(0, 0, 0, .5)) drop-shadow(0 8px 14px rgba(0, 0, 0, .45));
  }
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: 7rem; background: var(--ground); }
body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  overflow-x: clip;
}
h1, h2, h3, h4, p, ul, ol, figure, dl, dd { margin: 0; padding: 0; }
ul, ol { list-style: none; }
img, video { display: block; max-width: 100%; height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

.wrap { max-width: var(--inner); margin: 0 auto; padding: 0 var(--outerPad); }
.push { margin-inline-start: var(--centerMargin); }
.pull { width: 75%; }

h1 { font-size: clamp(var(--size-l), 4.76vw, 78px); font-weight: 700; line-height: 1.2; text-wrap: pretty; letter-spacing: -.005em; }
h2 { font-size: var(--size-l); font-weight: 700; line-height: 1.3; text-wrap: balance; }
h3 { font-weight: 700; line-height: 1.2; }
p { font-size: var(--size-m); line-height: 1.4; text-wrap: pretty; }
p + p { margin-block-start: 1em; }
.quiet { color: var(--ink-2); }
.small { font-size: var(--size-s); }
.nowrap { white-space: nowrap; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* links: a 1px underline that wipes away to the right on hover (the source's link) */
a { color: inherit; text-decoration: none; position: relative; }
a.line::before, .line-list a::before {
  content: ""; position: absolute; left: 0; bottom: 0; width: 100%; height: 1px;
  background: currentColor; transform-origin: center left;
  transition: transform var(--t-line) var(--ease-line);
}
@media (hover: hover) {
  a.line:hover::before, .line-list a:hover::before { transform: scaleX(0); transform-origin: center right; }
}
a:focus-visible, button:focus-visible, video:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 2px;
}
a:active, button:active { transform: scale(.97); }
a.title-link:active { transform: none; }

/* ---------- header: name left, nav on the push line ---------- */
.site-head {
  position: fixed; top: 0; left: 0; right: 0; z-index: 200;
  padding-block: var(--headerPadTop) 1.1rem;
  transition: transform .39s var(--ease-lift);
}
.site-head::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--band); box-shadow: 0 1px 0 var(--hair);
  opacity: 0; transition: opacity .3s ease;
}
.scrolled .site-head { transform: translateY(calc(var(--headerPadTop) / -2)); }
.scrolled .site-head::before { opacity: 1; }
.site-head .wrap { display: grid; grid-template-columns: calc(var(--centerMargin)) minmax(0, 1fr); align-items: baseline; }
.me {
  font-size: 1.875rem; font-weight: 700; line-height: 1.15; letter-spacing: -.01em;
  justify-self: start; display: inline-block;
}
.nav { display: flex; flex-wrap: wrap; gap: 0 1.9rem; font-size: 1.125rem; font-weight: 500; }
/* 4 px more tap area each side, taken back by the margin, so "Work" is 46 px wide on a phone and nothing moves
   (27 Sep 2026: page-check.py measured "Work" 38 px and "Notes" 43 px wide) */
.nav a { display: inline-flex; align-items: center; min-height: 44px; padding-inline: 4px; margin-inline: -4px; }
.nav a::before { content: ""; position: absolute; left: 4px; right: 4px; bottom: 8px; height: 1px; background: currentColor; transform: scaleX(0); transform-origin: center right; transition: transform var(--t-line) var(--ease-line); }
@media (hover: hover) { .nav a:hover::before { transform: scaleX(1); transform-origin: center left; } }
.nav a[aria-current], .nav a.here { color: var(--accent); }
.nav a[aria-current]::before, .nav a.here::before { transform: scaleX(1); height: 2px; background: var(--accent); }

/* ---------- mast (first frame) ---------- */
.mast { position: relative; max-width: 1920px; margin: 0 auto; overflow: hidden; overflow: clip; padding-block-start: var(--headerPadTop); background: var(--ground); isolation: isolate; }
.mast::after {
  content: ""; position: absolute; z-index: 2; bottom: 0; right: 0;
  left: calc(var(--outerPad) + max(0px, (100% - var(--inner)) / 2));
  height: 1px; background: var(--hair);
}
.mast.home { min-height: clamp(560px, 46vw, 720px); }
.mast h1 { position: relative; z-index: 3; padding: calc(var(--vertGapLarge) - var(--size-l) + .5rem) 36% 0 0; }
/* the home headline wraps in balanced lines: the longer "... for the agentic era." left "era." alone (25 Sep 2026) */
.page-home .mast h1 { text-wrap: balance; }
.mast-sub { position: relative; z-index: 3; padding: 1.9rem 36% calc(var(--vertGapLarge) * .62) 0; max-width: calc(44rem + 36%); }
.mast-sub p:not(.contact-line) { color: var(--ink-2); }
.mast-sub .status { font-weight: 500; color: var(--ink); margin-block-end: .6em; }
.mast-sub .contact-line { margin-block-start: 1.1em !important; }

/* portrait: a vignette that dissolves into the ground on every side (the source bleeds it off the
   right edge and cuts it hard on the hairline; here it floats and the hairline runs clean beneath) */
.portrait-plane { position: absolute; inset: 0; pointer-events: none; } /* no z-index here: a stacking context would cut the blend off from the ground */
.portrait {
  position: absolute; z-index: 1; right: max(-4vw, -72px); bottom: -3%;
  /* starts below the header row, so the name and the nav never sit on the hair */
  height: min(calc(103% - var(--headerPadTop) - 1rem), 760px); width: auto; max-width: none; aspect-ratio: 1;
  filter: var(--portrait-filter);
  mix-blend-mode: var(--portrait-blend);
  -webkit-mask-image: var(--portrait-mask);
          mask-image: var(--portrait-mask);
  transform: translate3d(0, var(--plax, 0px), 0);
  will-change: transform;
}

/* headline: lines rise into place once, after load (the one move of this page's own) */
.js .rise .w { display: inline-block; overflow: hidden; overflow: clip; vertical-align: top; padding-block-end: .12em; margin-block-end: -.12em; }
.js .rise .w > span { display: inline-block; transform: translate3d(0, 108%, 0); }
.loaded .rise .w > span { transform: none; transition: transform .6s var(--ease-out) calc(var(--l, 0) * 90ms + 120ms); }
.js .mast .portrait-plane { opacity: 0; }
.loaded .mast .portrait-plane { opacity: 1; transition: opacity 1s ease .1s; }

/* ---------- main ---------- */
main { padding: var(--vertGap) 0; overflow-x: hidden; overflow-x: clip; }
main > .wrap { display: flex; flex-direction: column; gap: var(--vertGap); }
.intro { max-width: 44rem; }
.contact-line { font-size: var(--size-s) !important; display: flex; flex-wrap: wrap; gap: .2em 1.6em; margin-block-start: 1.6em !important; }
.contact-line a, .contact-line > span { display: inline-flex; align-items: center; min-height: 44px; font-weight: 500; }
.contact-line a::before { bottom: 11px !important; }

/* entrance: the drift-in (sideways drift + fade, once per block, staggered) */
.js .drift { opacity: 0; transform: translate3d(var(--drift), 0, 0); transition: transform var(--t-enter) var(--ease-enter) var(--d, 0ms), opacity var(--t-enter) ease var(--d, 0ms); }
.js .drift.shown { opacity: 1; transform: none; }

.section-lead { margin-block-end: calc(var(--vertGap) * .6); }

/* ---------- gallery rows (home) ---------- */
.group + .group { margin-block-start: var(--vertGap); }
.group-head {
  display: grid; grid-template-columns: calc(var(--centerMargin) - var(--innerPad)) var(--innerPad) minmax(0, 1fr);
  align-items: baseline; margin-block-end: calc(var(--vertGap) * .72);
}
.group-head h2 { grid-column: 1; }
.group-head p { grid-column: 3; max-width: 44rem; }
.rows { display: flex; flex-direction: column; gap: calc(var(--vertGap) * .8); }
/* GTM / Ops (Raian, 24 Sep): one head per area, in the left column under a hairline, set as a real
   sub-heading (the size of "Evidence" on a case page), never as a small grey label over a title */
.area + .area { margin-block-start: calc(var(--vertGap) * 1.1); }
.area-head {
  display: grid; grid-template-columns: calc(var(--centerMargin) - var(--innerPad)) var(--innerPad) minmax(0, 1fr);
  font-size: var(--size-m); font-weight: 700; color: var(--ink);
  padding-block-start: .9em; border-block-start: 1px solid var(--hair); margin-block-end: calc(var(--vertGap) * .5);
}
.area-head::before { content: none; }
.meta-line { font-size: var(--size-s) !important; color: var(--ink-2); margin-block-start: .9em !important; }
/* architecture diagram (Raian, 24 Sep: one per case study, on brand, enriched with tools, skill and repo).
   Ink for the machine steps, jade only where his rules sit, hairlines for structure. */
.arch { margin-block: calc(var(--vertGap) * .2) var(--vertGap); }
.arch-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
/* 1060px: the diagram's smallest words (12.5 units of 1200) never draw below 11px. A column narrower than that
   scrolls sideways (phones, tablets, windows under ~1250px); G3 critic F2, 25 Sep */
.arch-svg { display: block; width: 100%; min-width: 1060px; height: auto; color: var(--ink); font-family: var(--font); }
/* the sign that it scrolls: the edge the diagram continues past fades out, and the next step is cut part way.
   The fades follow the scroll (right only at the start, both in the middle, left only at the end) and do
   nothing where the diagram fits, because a scroll timeline with nothing to scroll is inactive. */
@property --arch-fade-l { syntax: '<length>'; inherits: false; initial-value: 0px; }
@property --arch-fade-r { syntax: '<length>'; inherits: false; initial-value: 0px; }
@keyframes arch-fades {
  0% { --arch-fade-l: 0px; --arch-fade-r: 64px; }
  6% { --arch-fade-l: 40px; }
  94% { --arch-fade-r: 64px; }
  100% { --arch-fade-l: 40px; --arch-fade-r: 0px; }
}
@supports (animation-timeline: scroll()) {
  .arch-scroll {
    animation: arch-fades linear both;
    animation-timeline: scroll(self inline);
    -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--arch-fade-l), #000 calc(100% - var(--arch-fade-r)), transparent);
            mask-image: linear-gradient(to right, transparent, #000 var(--arch-fade-l), #000 calc(100% - var(--arch-fade-r)), transparent);
  }
}
/* browsers without scroll timelines: a fixed fade on the right wherever the diagram is sure to overflow
   (the column is 85% of the window up to 1653px), with room at the end so the last step scrolls clear of it */
@supports not (animation-timeline: scroll()) {
  @media (max-width: 1246px) {
    .arch-scroll { padding-inline-end: 56px; -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent); }
  }
  /* phones: the scroller runs to the screen edge (see the phone block), so the end room adds the page margin */
  @media (max-width: 767px) { html .arch-scroll { padding-inline-end: calc(var(--outerPad) + 40px); } }
}
/* A caption starts where its picture starts, like every photo caption on the site (Raian, 27 Sep 2026: "the diagram
   and its caption seems to be misaligned"). A rail draws across the full width, never narrower than 1060px (it scrolls
   below that); --cap-left is the fraction of it left of its first mark (tools/arch_svg.py data-left). */
.arch figcaption { margin-inline-start: max(calc(1060px * var(--cap-left, 0)), calc(100% * var(--cap-left, 0))); max-width: 44rem; }
/* the caption under a chart hero: small print on the chart's own left edge, like every figcaption */
.case-hero-cap { font-size: var(--size-s); color: var(--ink-2); max-width: 44rem; margin: 1.2em 0 0; }
/* a screenshot inside the story: full content width, its caption on the picture's own left edge */
.shot-fig { margin-block: calc(var(--vertGap) * .2) var(--vertGap); }
/* two pictures in a row belong together (Raian, 28 Sep 2026: the site's history "just below Solvue"): a shorter gap */
.shot-fig:has(+ .shot-fig) { margin-block-end: calc(var(--vertGap) * .4); }
.shot-fig figcaption { margin-inline-start: 0; max-width: 44rem; }
/* a detail crop (one card of a page) shows at its true size, never stretched: f.max in site.json (27 Sep 2026) */
.shot-fig > .full-link { display: block; max-width: var(--shot-max, none); }
.arch-svg .a-ink { fill: var(--ink); }
.arch-svg .a-muted { fill: var(--ink-2); }
.arch-svg .a-tool { fill: var(--ink); opacity: .78; }
.arch-svg .a-fill { fill: var(--ink); }
.arch-svg .a-dot { fill: var(--ground); stroke: var(--ink); stroke-width: 1.6; }
.arch-svg .a-line { stroke: var(--ink); stroke-width: 1.3; fill: none; }
.arch-svg .a-soft { opacity: .6; }
.arch-svg .a-hair { stroke: var(--hair); stroke-width: 1; }
.arch-svg .a-dotted { stroke: var(--ink); stroke-width: 1.1; stroke-dasharray: 2 4; opacity: .6; fill: none; }
.arch-svg .a-store { fill: none; stroke: var(--ink); stroke-width: 1.1; }
.arch-svg .a-jade { fill: var(--accent); }
.arch-svg .a-jade-text { fill: var(--accent); }
.arch-svg .a-jade-bar { stroke: var(--accent); stroke-width: 2.4; stroke-linecap: round; }
.arch-svg .a-jade-line { stroke: var(--accent); stroke-width: 1.3; fill: none; }
.arch-svg .a-jade-dash { stroke: var(--accent); stroke-width: 1.3; stroke-dasharray: 3 4; }
/* tool icons: grey at rest, their own colour while the reader is on the diagram (like the Experience marks) */
.arch-svg .a-tpath { fill: var(--ink); transition: fill var(--t-line) var(--ease-line); }
.arch-svg .a-tstroke { fill: none; stroke: var(--ink); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.arch-svg .a-timg { filter: grayscale(1) contrast(1.05); opacity: .85; transition: filter var(--t-line) var(--ease-line), opacity var(--t-line) var(--ease-line); }
/* dark: the grey image marks turn light, like the marks drawn in ink; a dark mark (Exa's blue glyph, Anymail
   Finder's navy disc) otherwise all but vanishes on the dark ground (F6, 25 Sep). Hover shows the colours in light mode only. */
@media (prefers-color-scheme: dark) { .arch-svg .a-timg { filter: grayscale(1) invert(.86) contrast(1.05); } }
@media (hover: hover) {
  .arch:hover .a-tpath { fill: var(--brand); }
  .arch:hover .a-timg { filter: none; opacity: 1; }
}
/* dark mode: a picture logo keeps its light treatment on hover; with the filter removed, a dark logo (Exa) sat dark on dark (Raian, 27 Sep 2026: 'on dark mode several of the icons are dark on dark') */
@media (hover: hover) and (prefers-color-scheme: dark) { .arch:hover .a-timg { filter: grayscale(1) invert(.86) contrast(1.05); } }
.arch-svg .a-gh-mark { fill: var(--ink); transition: fill var(--t-line) var(--ease-line); }
.arch-svg .a-hit { fill: transparent; }
.arch-svg a.a-gh:hover .a-gh-mark, .arch-svg a.a-gh:focus-visible .a-gh-mark { fill: var(--accent); }
.arch-svg a.a-gh:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* /tools/: the push grid, name flush right in the left column like the years in Experience */
.tools-intro { max-width: 44rem; }
.tools { list-style: none; display: flex; flex-direction: column; gap: 2.2rem; }
.tool { display: grid; grid-template-columns: calc(var(--centerMargin) - var(--innerPad)) var(--innerPad) minmax(0, 1fr); align-items: baseline; }
.tool-name { grid-column: 1; justify-self: end; font-size: var(--size-m); font-weight: 600; }
.tool-text { grid-column: 3; max-width: 44rem; }
.tool-text .meta-line { margin-block-start: .35em !important; }
.tools-link { margin-block-start: calc(var(--vertGap) * .9); }
.row {
  display: grid;
  grid-template-columns: calc(var(--centerMargin) - var(--innerPad)) var(--innerPad) minmax(0, 1fr);
  align-items: center;
}
.row-media { grid-column: 1; }
.row-text { grid-column: 3; max-width: 44rem; }
.row-title { font-size: clamp(2rem, 2.9vw, var(--size-l)); line-height: 1.18; margin-block-end: .5em; text-wrap: balance; }
.row p { font-size: 1.25rem; }
.figure-line { font-size: var(--size-s) !important; margin-block-start: 1.1em !important; max-width: 36rem; }
.figure-line strong { font-weight: 700; margin-inline-end: .25em; }
.actions { font-size: var(--size-s) !important; margin-block-start: 1.3em !important; display: flex; flex-wrap: wrap; gap: .4em 1.8em; align-items: center; }
.actions a { font-weight: 500; display: inline-flex; align-items: center; min-height: 44px; }
.actions a::before { bottom: 11px !important; }
.actions .bracket { min-height: 44px; display: inline-flex; align-items: center; }

/* title link: underline wipes in under the title on hover */
.title-link { background-image: linear-gradient(currentColor, currentColor); background-size: 0 2px; background-repeat: no-repeat; background-position: 0 100%; transition: background-size var(--t-hover) var(--ease-out); }
@media (hover: hover) { .title-link:hover, .row:hover .title-link, .card:hover .title-link { background-size: 100% 2px; } }

/* a framed artifact: no mat, no hairline. The artifact itself is the print, resting on the ground.
   The Flip Education colours stay inside it. */
.frame {
  display: block; position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--print-radius); box-shadow: var(--print-shadow);
  transition: box-shadow var(--t-hover) var(--ease-out), transform var(--t-hover) var(--ease-out);
}
.frame::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; border-radius: inherit;
  box-shadow: inset 0 0 0 1px var(--print-ring); mix-blend-mode: darken;
}
.frame video { border-radius: inherit; }
.frame img, .frame video { filter: var(--print-dim); }
/* cut-out cards on a transparent ground (the editor replies): no frame box, no ring; each card is its own
   print and casts the print shadow through its alpha (G3 critic F8, 25 Sep: the grey tray read as a mat) */
.frame.bare, .frame.bare .crop { overflow: visible; }
.frame.bare, .row:hover .frame.bare, .card:hover .frame.bare, a.full-link:hover .frame.bare { box-shadow: none; border-radius: 0; }
.frame.bare::after { content: none; }
.frame.bare img { filter: var(--print-drop); }
.frame .crop { position: relative; overflow: hidden; aspect-ratio: var(--ratio, 4 / 3); }
.frame .crop img { width: 100%; height: 100%; object-fit: cover; object-position: var(--pos, center); }
.frame .crop.tall img { height: auto; object-fit: fill; transition: transform var(--t-hover) var(--ease-out); }
@media (hover: hover) {
  .row:hover .crop.tall img, .card:hover .crop.tall img { transform: translate3d(0, -7%, 0); }
  /* a print you can open lifts off the table by two pixels */
  .row:hover .frame, .card:hover .frame, a.full-link:hover .frame { box-shadow: var(--print-shadow-lift); transform: translate3d(0, -2px, 0); }
}

/* the number set as the picture, for showcases with no artifact yet */
.figure-plate { grid-column: 1; justify-self: end; text-align: right; max-width: 20rem; }
.figure-plate .v { display: block; font-size: clamp(2.6rem, 4.4vw, 4.5rem); font-weight: 400; line-height: 1.02; letter-spacing: -.035em; font-variant-numeric: tabular-nums; }
.figure-plate .k { display: block; font-size: var(--size-s); color: var(--ink-2); margin-block-start: .6em; }
.row .figure-plate { align-self: start; padding-block-start: .3em; }
.rows-figures .row { align-items: start; }

/* ---------- experience: the dot timeline ---------- */
.thread { max-width: 44rem; }
.cv { display: flex; flex-direction: column; margin-block-start: calc(var(--vertGap) * .6); }
.exp { display: flex; align-items: baseline; gap: var(--innerPad); }
.exp .time { min-width: calc(var(--centerMargin) - var(--innerPad)); text-align: right; white-space: nowrap; font-size: var(--size-s); font-variant-numeric: tabular-nums; }
.exp .details { position: relative; flex: 1; padding-block-end: var(--cvGap); max-width: 44rem; }
.exp .details::before { content: ""; position: absolute; top: .7em; bottom: -.7em; width: 2px; left: calc((var(--innerPad) - 1px) / -2); background: var(--hair); }
.cv > li:last-child .details::before { display: none; }
.exp h3 { font-size: var(--size-m); position: relative; padding-block-end: .3em; }
/* company marks, as on the old record: small, grey, colour on hover (the brand never leaks into the chrome at rest) */
.org-logo { display: inline-block; width: 1.05em; height: 1.05em; border-radius: 5px; vertical-align: -0.14em; margin-inline-end: .38em;
  background: var(--logo-tile); padding: var(--logo-pad); object-fit: contain; filter: grayscale(1) contrast(1.05); opacity: .82; transition: filter var(--t-line) var(--ease-line), opacity var(--t-line) var(--ease-line); }
@media (hover: hover) { .exp:hover .org-logo { filter: none; opacity: 1; } }
.exp h3::before {
  content: ""; position: absolute; top: calc((var(--size-m) * 1.2 - var(--dot)) / 2);
  left: calc((var(--innerPad) + var(--dot) - 3px) / -2);
  width: var(--dot); height: var(--dot); border-radius: 50%;
  background: var(--ground); border: 2px solid var(--ink); z-index: 2;
}
.cv > li:first-child h3::before { background: var(--accent); border-color: var(--accent); }
.exp h3 .at { font-weight: 400; }
.exp p { font-size: var(--size-s); color: var(--ink); }
.exp.early .time, .exp.early h3, .exp.early p { color: var(--ink-2); }
.exp.early h3::before { border-color: var(--ink-2); }

/* ---------- notes ---------- */
.notes-list { margin-block-start: 1.2em; display: flex; flex-direction: column; gap: .7em; }
.notes-list li { display: flex; gap: 1.2em; align-items: baseline; }
.notes-list .when { font-size: var(--size-s); color: var(--ink-2); min-width: 7.5em; flex: none; }
.notes-list a { font-size: var(--size-m); line-height: 1.3; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em; text-decoration-color: currentColor; transition: text-decoration-color var(--t-line) var(--ease-line); padding-block: .1em; }
@media (hover: hover) { .notes-list a:hover { text-decoration-color: transparent; } }

/* ---------- contact + footer ---------- */
.contact .mail { font-size: var(--size-l); font-weight: 700; line-height: 1.3; }
.contact .mail a { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .16em; transition: text-decoration-color var(--t-line) var(--ease-line); }
@media (hover: hover) { .contact .mail a:hover { text-decoration-color: transparent; } }
footer { padding-block-end: var(--innerPad); }
footer .wrap { display: flex; align-items: center; padding-block-start: 1.6em; position: relative; gap: 1.5em; }
footer .wrap::before { content: ""; position: absolute; top: 0; left: var(--outerPad); right: var(--outerPad); height: 1px; background: var(--hair); }
footer p { font-size: var(--size-s); white-space: nowrap; }
footer p a { display: inline-flex; align-items: center; min-height: 44px; }
footer p a::before { bottom: 11px !important; }
footer ul { display: flex; flex: 1; justify-content: flex-end; flex-wrap: wrap; gap: 0 1.5em; }
footer ul a { font-size: var(--size-s); display: inline-flex; align-items: center; min-height: 44px; }
footer ul a::before { bottom: 11px !important; }

/* ---------- signature: the bracketed link that splits, then opens the real thing ---------- */
.bracket { white-space: nowrap; }
.bracket .split { white-space: normal; vertical-align: bottom; }
.split {
  position: relative; display: inline-block; font-weight: 500; line-height: 1.2; text-align: left;
  padding: 0 .06em; z-index: 1; transition: transform .17s ease;
}
.split .label { position: relative; z-index: 3; }
.split .label::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: currentColor; transform-origin: center left; transition: transform var(--t-line) var(--ease-line); }
.split .fx { position: absolute; inset: -.24em -.62em; border-radius: .43em; z-index: 1; opacity: 0; pointer-events: none; }
.split .fx i {
  position: absolute; inset: 0; border-radius: inherit; background: var(--chip);
  transform: scale(.93); transition: transform .4s var(--ease-out) .04s;
}
.split.active .fx i { background: var(--panel); }
@media (hover: hover) {
  .split:hover .fx, .split.active .fx { opacity: 1; transition: opacity .16s ease .04s; }
  .split:hover .fx i, .split.active .fx i { transform: none; }
  .split:hover .label::after, .split.active .label::after { transform: scaleX(0); transform-origin: center right; }
}
.split:active { transform: scale(.97); }

.curtain { position: fixed; inset: 0; z-index: 90; background: var(--curtain); opacity: 0; pointer-events: none; transition: opacity .42s ease; }
.having-fun .curtain { opacity: 1; pointer-events: auto; }
.having-fun { overflow: hidden; }
.having-fun .split.active { z-index: 100; }
.reveal {
  position: fixed; z-index: 95; background: var(--panel); overflow: hidden; border-radius: 6px;
  box-shadow: var(--shadow-open); opacity: 0; pointer-events: none;
  transform: perspective(1500px) rotateY(0deg) translate3d(2.4em, 0, 0);
  transform-origin: 100% 50%;
  transition: opacity .2s ease, transform .45s var(--ease-out);
}
.reveal.open { opacity: 1; pointer-events: auto; transform: perspective(1500px) rotateY(9.3deg) translate3d(0, 0, 0); transition: opacity .24s ease .12s, transform .45s var(--ease-out) .12s; }
.reveal img, .reveal video { width: 100%; height: 100%; object-fit: cover; }
.reveal video { background: #000; object-fit: contain; }
.reveal-note { position: fixed; z-index: 96; font-size: var(--size-s); max-width: 26rem; opacity: 0; pointer-events: none; transition: opacity .3s ease .36s; background: var(--ground); padding: .5em .9em .3em; margin-inline-start: -.9em; }
.reveal-note.open { opacity: 1; pointer-events: auto; }
.reveal-note .cap { display: block; }
.reveal-note .row-actions { display: flex; flex-wrap: wrap; gap: 0 1.4em; margin-block-start: .3em; }
.reveal-note .row-actions a, .reveal-note .row-actions button { display: inline-flex; align-items: center; min-height: 44px; font-weight: 500; color: var(--ink); }
.reveal-note .row-actions button { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em; }
.reveal-note .row-actions a::before { bottom: 11px; }
.reveal-note .hint { color: var(--ink-2); }
.tether { position: fixed; z-index: 96; height: 1px; background: var(--ink); transform-origin: right center; transform: scaleX(0); transition: transform .2s var(--ease-out) .42s; }
.tether.open { transform: scaleX(1); }
.tether::after { content: ""; position: absolute; right: calc(var(--dot) / -2); top: calc(var(--dot) / -2 + .5px); width: var(--dot); height: var(--dot); border-radius: 50%; background: var(--accent); border: 2px solid var(--ink); }

/* ---------- work index (gallery page) ---------- */
.mast.plain h1 { padding-inline-end: 0; padding-block: calc(var(--innerPad) + 1.5rem) var(--innerPad); }
/* on the gallery page the group title and its intro share one row, so the cards reach the first screen */
.page-work main { padding-top: calc(var(--vertGap) * .6); }
.page-work .group { display: grid; grid-template-columns: calc(var(--centerMargin) - var(--innerPad)) var(--innerPad) minmax(0, 1fr); align-items: baseline; }
.page-work .group > h2 { grid-column: 1; margin-block-end: calc(var(--vertGap) * .5); }
.page-work .group > p.push { grid-column: 3; margin-inline-start: 0; max-width: 44rem; margin-block-end: calc(var(--vertGap) * .5); }
.page-work .group > .cards { grid-column: 1 / -1; }
/* the GTM / Ops areas (each a heading and its cards) span the whole group grid, like the home gallery;
   without this they auto-placed into the 84px gutter column (G3 critic F1, 25 Sep) */
.page-work .group > .area { grid-column: 1 / -1; }
.cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(var(--vertGap) * .7) var(--innerPad); align-items: start; }
.card { display: flex; flex-direction: column; }
.card .frame { margin-block-end: 1.4rem; }
.card .frame .crop { --ratio: 16 / 10; }
.card .figure-plate { justify-self: auto; text-align: left; max-width: none; margin-block-end: 1.6rem; padding: 1.1rem 0 0; display: flex; flex-direction: column; justify-content: flex-start; box-shadow: 0 -1px 0 var(--hair); }
.card .figure-plate .v { font-size: clamp(3rem, 5vw, 5.25rem); }
.card .figure-plate .k { max-width: 24rem; font-size: 1.125rem; }
.card-title { font-size: var(--size-m); line-height: 1.25; margin-block-end: .45em; text-wrap: balance; }
.card p { font-size: 1.125rem; }
.card .figure-line { margin-block-start: .9em !important; }
.card .figure-line strong { font-size: 1.125rem; }

/* ---------- showcase page ---------- */
.mast.case .wrap { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: var(--innerPad); align-items: end; padding-block: calc(var(--vertGapLarge) - var(--size-l) + 1.5rem) calc(var(--innerPad) + 1rem); }
.mast.case h1 { padding: 0; font-size: clamp(2.75rem, 4.3vw, 70px); }
.case-hero { position: relative; z-index: 2; }
/* a picture to be read (editor replies): full width under the title, so its text lands at reading size */
.mast.case.wide .wrap { grid-template-columns: minmax(0, 1fr); align-items: start; }
.mast.case.wide h1 { max-width: 16em; }
.frame .crop.has-narrow picture { display: contents; }
.case-hero .frame video { width: 100%; aspect-ratio: 16 / 9; background: #000; }
.case-hero .figure-plate { justify-self: start; text-align: left; max-width: 26rem; }
.case-hero .figure-plate .v { font-size: clamp(3.5rem, 7vw, 7.5rem); }
.case-hero .figure-plate .k { font-size: 1.125rem; }
.case-intro .card-line { font-weight: 500; }
/* the opening as the page's lead: from the left edge like the title, larger type, a reading measure of ~70
   characters (Raian, 25 Sep 2026: indented under an empty column it read as a side note) */
.case-intro.lead { max-width: none; }
.standfirst { font-size: clamp(1.375rem, 1.05rem + .75vw, 1.75rem) !important; line-height: 1.45; color: var(--ink); max-width: 34em; text-wrap: pretty; }
.standfirst + .standfirst { margin-block-start: .7em; }
.case-intro.lead .status { margin-block-start: 1.6em !important; }
.case-intro .status { font-size: var(--size-s) !important; color: var(--ink-2); margin-block-start: 1.2em !important; }
.back { font-size: var(--size-s); font-weight: 500; display: inline-flex; align-items: center; gap: .45em; min-height: 44px; margin-block-start: .8em; }
.arrow { width: .95em; height: .95em; flex: none; }

.figures { display: flex; flex-direction: column; gap: 1.6rem; }
.figures li { display: grid; grid-template-columns: calc(var(--centerMargin) - var(--innerPad)) var(--innerPad) minmax(0, 1fr); align-items: baseline; }
.figures .v { grid-column: 1; text-align: right; font-size: var(--size-l); font-weight: 400; line-height: 1.1; letter-spacing: -.025em; font-variant-numeric: tabular-nums; }
.figures .k { grid-column: 3; font-size: var(--size-m); max-width: 40rem; }

.decide { gap: 0; margin-block-start: 0; }
.decide .exp .details { padding-block-end: .7em; }
.decide .exp.because .details { padding-block-end: 3.2em; }
.cv.decide > li:last-child .details::before { display: block; }
.cv.decide > li:last-child .exp.because .details::before { display: none; }
.decide .time { color: var(--ink-2); }
.decide .chose .time { color: var(--accent); font-weight: 700; }
.decide .exp h3 { font-size: var(--size-m); }
.decide .exp h3::before { display: none; }
.decide .chose h3::before { display: block; background: var(--accent); border-color: var(--accent); }
.decide .could p { color: var(--ink-2); font-size: 1.25rem; }
.decide .because p { font-size: 1.25rem; }
.decide .exp:not(.chose) .time { position: relative; top: .15em; }

.chapter h2 { margin-block-end: calc(var(--vertGap) * .35); }
.chapter p { max-width: 44rem; }

.work-groups { display: flex; flex-direction: column; gap: calc(var(--vertGap) * .7); }
.work-group h3 { font-size: var(--size-m); margin-block-end: 1.1rem; }
.shelf { display: flex; flex-wrap: wrap; gap: 2.4rem; align-items: flex-start; }
.shelf figure { flex: 0 1 auto; max-width: 100%; }
.shelf .frame .crop { aspect-ratio: auto; height: var(--cap, 620px); }
.shelf .frame .crop img { height: auto; object-fit: fill; }
.shelf figure.open .frame .crop { height: auto; }
.shelf .crop.mid img { position: relative; top: 50%; transform: translateY(-50%); }
.shelf figure.open .crop.mid img { top: 0; transform: none; }
/* a tall print is cut clean at the cap, like a cropped print: no fade (a fade to white left a white band
   on the beige prints, and a fade to the ground left a shadow round an empty patch). "See the full image"
   says there is more. */
.strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 1.2rem; }
.strip .frame .crop { --ratio: 16 / 9; }
.justified { display: flex; flex-direction: column; gap: 2.4rem; }
.justified .line { display: flex; gap: 1.6rem; align-items: flex-start; }
.justified figure { flex: var(--a) 1 0; min-width: 0; } /* grow in proportion to the aspect ratio from a zero basis: paired prints come out the same height */
.justified .frame .crop { aspect-ratio: var(--ar); }
figcaption { font-size: var(--size-s); color: var(--ink-2); margin-block-start: 1.05em; } /* clears the print's shadow */
figcaption .more { color: var(--ink); font-weight: 500; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em; min-height: 44px; display: inline-flex; align-items: center; margin-inline-start: .2em; }
.full-link { display: block; }
.full-link:active { transform: none; }

.links-list { display: flex; flex-direction: column; gap: .2em; }
.links-list a { font-size: var(--size-m); display: inline-flex; align-items: center; min-height: 44px; }
.links-list a::before { bottom: 8px !important; }
.receipts { font-size: var(--size-s) !important; color: var(--ink-2); max-width: 44rem; }
.receipts strong { color: var(--ink); }
.sources { max-width: 44rem; font-size: var(--size-s); color: var(--ink-2); }
.sources summary { cursor: pointer; font-weight: 500; color: var(--ink); min-height: 44px; display: inline-flex; align-items: center; gap: .6em; list-style: none; }
.sources summary::-webkit-details-marker { display: none; }
.sources summary::after { content: ""; width: .45em; height: .45em; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-.15em) rotate(45deg); transition: transform var(--t-line) var(--ease-out); }
.sources[open] summary::after { transform: translateY(.1em) rotate(-135deg); }
.colophon { display: flex; flex-direction: column; gap: 2.2rem; max-width: 44rem; }
.sources ol { list-style: decimal; padding-inline-start: 1.2em; margin-block-start: .6em; display: flex; flex-direction: column; gap: .5em; }
.sources li strong { color: var(--ink); font-weight: 500; }
/* the one block at the end of a work page: receipts, the source of each number, the open code (27 Sep 2026) */
.sources-block { display: flex; flex-direction: column; gap: .9rem; max-width: 44rem; font-size: var(--size-s); color: var(--ink-2); border-top: 1px solid var(--hair); padding-block-start: 1.4rem; }
.sources-block h2 { font-size: var(--size-s); font-weight: 600; color: var(--ink); margin: 0; line-height: 1.4; }
.sources-block .receipts { margin: 0; }
.sources-block .num-sources { list-style: decimal; padding-inline-start: 1.2em; margin: 0; display: flex; flex-direction: column; gap: .5em; }
.sources-block .num-sources strong { color: var(--ink); font-weight: 500; }
.sources-block .repo-links { margin: 0; font-size: var(--size-s); color: var(--ink); gap: .1rem 1.4rem; }
.sources-block .repo-links svg { width: 16px; height: 16px; }
.sources-block .repo-links .all-tools { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em; font-weight: 400; color: var(--ink-2); }

/* the signup box (Raian, 28 Sep 2026): once, in the footer, one row: the line, the field, the button, and a small
   privacy link. It sat at the end of each piece too until he saw it live: "it seems like it's been bolted on top ...
   appears twice". The field is a line to write on, like the site's links, never a boxed card. */
.subscribe { margin: 0; }
.subscribe .sub-lead { margin: 0; font-size: var(--size-s); font-weight: 500; color: var(--ink); }
.subscribe .sub-row { display: flex; align-items: stretch; gap: 1em; }
.subscribe input[type="email"] { flex: 1; min-width: 0; min-height: 44px; font: inherit; font-size: var(--size-s); color: var(--ink); background: transparent; border: 0; border-bottom: 1px solid var(--ink-2); border-radius: 0; padding: 0 .1em; }
.subscribe input[type="email"]::placeholder { color: var(--ink-2); opacity: 1; }
.subscribe input[type="email"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-bottom-color: var(--accent); }
.subscribe button { min-height: 44px; padding: 0 1.1em; font-size: var(--size-s); font-weight: 500; color: var(--ground); background: var(--ink); border-radius: 2px; transition: background var(--t-line) var(--ease-line); }
.subscribe button:hover { background: var(--accent); }
.subscribe button:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.subscribe .sub-note { margin: 0; font-size: var(--size-s); color: var(--ink-2); }
.subscribe .sub-note a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em; color: var(--ink-2); }
footer .sub-wrap { display: block; padding-block: 1.6em 1.2em; }
footer .subscribe.at-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .6em 1.5em; }
footer .subscribe.at-foot .sub-row { flex: 0 1 26rem; }
footer .subscribe p { white-space: normal; }
footer .subscribe .sub-note a { display: inline-flex; align-items: center; min-height: 44px; }
footer .sub-wrap + .wrap::before { display: none; }

.next { display: grid; grid-template-columns: calc(var(--centerMargin) - var(--innerPad)) var(--innerPad) minmax(0, 1fr); align-items: baseline; padding-block-start: calc(var(--vertGap) * .5); position: relative; }
.next::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px; background: var(--hair); }
.next .lab { grid-column: 1; text-align: right; font-size: var(--size-s); color: var(--ink-2); }
.next .go { grid-column: 3; }
.next .go a { font-size: var(--size-l); font-weight: 700; line-height: 1.25; display: inline; }
.next .go .all { display: inline-flex; margin-block-start: 1.2em; font-size: var(--size-s); font-weight: 500; min-height: 44px; align-items: center; }
.next .go .all::before { bottom: 11px !important; }

/* writer's text sections: the source's rhythm, a statement at pull width and the reading text on the push line */
.nut { max-width: 44rem; }
.text-section .body { max-width: 44rem; }
/* a titled section sits on ONE row: heading in the left column, text in the right, first lines level
   (the source's stepped heading-then-text-a-row-lower left an empty band; Raian flagged it, 24 Sep) */
.text-section, .chapter {
  display: grid; grid-template-columns: calc(var(--centerMargin) - var(--innerPad)) var(--innerPad) minmax(0, 1fr);
  align-items: baseline;
}
.text-section > h2, .chapter > h2 { grid-column: 1; width: auto; margin: 0; }
.text-section > p, .chapter > p { grid-column: 3; margin-inline-start: 0; max-width: 44rem; }
.contact-lead { max-width: 40rem; }
.contact-lead .mail-inline { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .2em; font-weight: 500; white-space: nowrap; transition: text-decoration-color var(--t-line) var(--ease-line); }
@media (hover: hover) { .contact-lead .mail-inline:hover { text-decoration-color: transparent; } }
.notes-intro { margin-block-start: .6em; color: var(--ink-2); font-size: 1.25rem !important; max-width: 40rem; }
.skip:focus { position: fixed; left: 16px; top: 16px; width: auto; height: auto; clip: auto; z-index: 300; background: var(--panel); padding: .6em 1em; }

/* ---------- tablet ---------- */
@media (max-width: 1023px) {
  .pull { width: 100%; }
  .mast h1, .mast-sub { padding-inline-end: 34%; }
  .site-head .wrap { grid-template-columns: auto minmax(0, 1fr); column-gap: 2.4rem; }
  .nav { justify-content: flex-end; gap: 0 1.4rem; }
  .cards { grid-template-columns: 1fr 1fr; gap: 4rem 2.4rem; }
  .mast.case .wrap { grid-template-columns: 1fr; }
}

/* ---------- phone ---------- */
@media (max-width: 767px) {
  :root { --size-l: 2.1rem; --size-m: 1.25rem; --headerPadTop: 1.25rem; --vertGap: 5rem; --outerPad: 24px; --innerPad: 2rem; }
  html { scroll-padding-top: 1.5rem; }
  .push { margin-inline-start: 0; }
  p { font-size: 1.125rem; }

  .site-head { position: absolute; padding-block: var(--headerPadTop) 0; }
  .scrolled .site-head { transform: none; }
  .scrolled .site-head::before { opacity: 0; }
  .site-head .wrap { display: block; }
  .me { font-size: 1.5rem; padding-block: .3em; }
  .nav { justify-content: flex-start; gap: 0 1.25rem; font-size: 1rem; margin-block-start: .1rem; }

  .mast, .mast.home { min-height: 0; display: block; padding-block-start: calc(min(52svh, 480px) + 1.5rem); }
  .portrait-plane { inset: 0 0 auto 0; height: 52svh; min-height: 360px; max-height: 480px; }
  .portrait {
    height: calc(100% - 3.4rem); right: -18%; bottom: auto; top: 3.6rem;
    --portrait-mask: radial-gradient(ellipse 52% 47% at 48% 47%, #000 50%, rgba(0,0,0,.5) 74%, transparent 100%);
  }
  .mast h1 { font-size: 2.1rem; padding: 0; max-width: 21rem; }
  .mast-sub { padding: 1.2rem 0 2.4rem; max-width: none; }
  .group-head, .text-section, .chapter { display: block; }
  .tool { display: block; } .tool-name { display: inline-flex; min-height: 44px; align-items: center; }
  a.tool-name::before { bottom: 11px; } /* under the word, not at the foot of the 44px tap box (F10) */
  .area-head { display: block; } /* the grid's first column is too narrow on a phone: 'Go-to- / market' */
  .text-section > p, .chapter > p { margin-block-start: 1rem; }
  .standfirst { font-size: 1.3rem !important; line-height: 1.45; }
  .group-head p { margin-block-start: 1rem; }
  .mast::after { left: 0; }
  main { padding-top: 2rem; }

  .row { grid-template-columns: minmax(0, 1fr); gap: 1.6rem; }
  .row-media, .row-text, .figure-plate { grid-column: 1; }
  .row-title { font-size: 1.6rem; }
  .row p { font-size: 1.125rem; }
  .figure-plate { justify-self: start; text-align: left; }
  .figure-plate .v { font-size: 2.75rem; }

  .exp { flex-direction: column; gap: .3em; margin-inline-start: 40px; }
  .exp .details { order: 1; padding-block-end: .2em; }
  .exp .time { order: 2; text-align: left; min-width: 0; color: var(--ink-2); padding-block-end: 1.6em; }
  .exp .details::before { left: -27px; bottom: calc(-1.6em - 2.6em); }
  .exp h3::before { left: -32px; }
  .notes-list li { flex-direction: column; gap: .1em; }
  .notes-list a { font-size: 1.2rem; }
  .contact .mail { font-size: 1.5rem; }
  footer .wrap { flex-direction: column; align-items: flex-start; gap: .3em; }
  footer ul { justify-content: flex-start; }

  .mast.plain { min-height: 0; padding-block-start: 7.5rem; }
  .mast.plain h1 { padding-block: 0 2.5rem; }
  .page-work .group { display: block; }
  .page-work .group > h2 { margin-block-end: 1.2rem; }
  .cards { grid-template-columns: minmax(0, 1fr); gap: 3.5rem; }
  .card .figure-plate { aspect-ratio: auto; padding-block: 1rem .5rem; }

  .mast.case { min-height: 0; padding-block-start: 7.5rem; }
  .mast.case .wrap { padding-block: 0 2.5rem; gap: 2rem; }
  .mast.case h1 { font-size: 2.1rem; }
  .frame .crop.has-narrow { aspect-ratio: auto; }
  .frame .crop.has-narrow img { height: auto; object-fit: fill; }
  .arch figcaption, .shot-fig figcaption { margin-inline-start: 0; } /* on the text edge, like every other block on a phone (F2) */
  /* the scroller runs to the screen edges (at rest the diagram still starts on the text edge): more of it shows */
  .arch-scroll { margin-inline: calc(-1 * var(--outerPad)); padding-inline: var(--outerPad); }
  .figures li { grid-template-columns: minmax(0, 1fr); }
  .figures .v, .figures .k { grid-column: 1; text-align: left; }
  .figures .v { font-size: 2.1rem; }
  .figures .k { font-size: 1.125rem; }
  .decide .exp { flex-direction: row; gap: .9em; margin-inline-start: 22px; }
  .decide .exp .time { order: 0; min-width: 4.8em; padding-block-end: 0; font-size: 1rem; }
  .decide .exp .details { order: 1; }
  .decide .exp .details::before { display: none; }
  .decide .chose h3::before { left: -22px; top: .35em; width: 10px; height: 10px; }
  .decide .could p, .decide .because p { font-size: 1.05rem; }
  .decide .exp h3 { font-size: 1.15rem; }
  .decide .exp.because .details { padding-block-end: 2.2em; }
  .shelf { gap: 1.6rem; }
  .shelf figure { width: 100% !important; }
  .shelf .frame .crop { height: 480px; }
  .justified .line { flex-direction: column; gap: 1.6rem; }
  .justified figure { flex: none; width: 100%; }
  .strip { grid-template-columns: 1fr 1fr; gap: .8rem; }
  .next { grid-template-columns: minmax(0, 1fr); }
  footer .subscribe.at-foot .sub-row { flex-basis: 100%; }
  .next .lab { text-align: left; grid-column: 1; }
  .next .go { grid-column: 1; }
  .next .go a { font-size: 1.6rem; }
}
/* phone tap targets: every link and button at least 44 px tall without moving the layout */
@media (max-width: 767px) {
  .me { display: inline-flex; align-items: center; min-height: 44px; padding-block: 0; }
  .title-link, .contact-lead .mail-inline, .next .go .title-link { padding-block: max(.4em, 10px); }
  .bracket .split { padding-block: 13px; margin-block: -13px; }
  .bracket .split .fx { inset: calc(13px - .24em) -.62em; }
  .notes-list a { padding-block: 10px; margin-block: -10px; }
}
@keyframes arrowDrift { from { transform: translateY(0); } to { transform: translateY(.5em); } }

/* ---------- reduced motion: nothing moves; everything still answers, by fading ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; }
  .js .drift { transform: none !important; transition: opacity .2s ease !important; }
  .js .rise .w > span { transform: none !important; transition: none !important; }
  .js .rise .w { overflow: visible; }
  .portrait { transform: none !important; }
  .site-head, .scrolled .site-head { transition: none; }
  .reveal, .reveal.open { transform: none !important; transition: opacity .16s ease !important; }
  .tether { transition: opacity .16s ease .1s !important; transform: scaleX(1); opacity: 0; }
  .tether.open { opacity: 1; }
  .reveal-note { transition: opacity .16s ease .1s !important; }
  .split .fx i { transition: none !important; }
  .frame .crop.tall img, .row:hover .crop.tall img, .card:hover .crop.tall img { transform: none !important; }
  .frame, .row:hover .frame, .card:hover .frame, a.full-link:hover .frame { transform: none !important; transition: box-shadow .16s ease; }
  .title-link { transition: background-size .12s ease; }
  a:active, button:active, .split:active { transform: none; }
}
/* the diagram's edge fades follow the reader's own scroll, nothing moves by itself: they stay under reduced motion */
@media (prefers-reduced-motion: reduce) {
  @supports (animation-timeline: scroll()) {
    .arch-scroll { animation: arch-fades linear both !important; animation-timeline: scroll(self inline) !important; }
  }
}

/* dark mode on phones: the cut-out keeps its linear shoulder fade (after the phone rule so it wins) */
@media (max-width: 767px) and (prefers-color-scheme: dark) {
  .portrait { --portrait-mask: linear-gradient(to bottom, #000 58%, rgba(0,0,0,.5) 78%, transparent 95%); }
}


/* the open code behind a work piece, under its opening (25 Sep 2026) */
.repo-links { display: flex; flex-wrap: wrap; gap: .25rem 1.6rem; margin-block-start: 1.1rem; font-size: 1.0625rem; font-weight: 500; }
.repo-links a { display: inline-flex; align-items: center; gap: .5rem; min-height: 44px; }
.repo-links a span:first-of-type { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em; }
.repo-links svg { width: 20px; height: 20px; fill: currentColor; flex: none; }

/* ---------- the bento gallery: home "Selected work" and the top of /work/ (28 Sep 2026) ----------
   Direction A, round 2, Raian's pick ("Gallery looks good"). Spec: the approved prototype and its state list, Drive
   "raianpollock.com Redesign/gates/home-gallery/A/" (index.html, NOTES.md, STATES.md). Structure recreated from the
   Vercel Geist design system's Grid component (https://vercel.com/geist/grid, CSS read 27 Sep 2026): modules, cells
   that span columns and rows, one padding for every cell, small crosses on chosen intersections (21 / 15 / 11 px).
   Own code, no Vercel code copied. Round 2: 16px gutters of page ground; each tile its own lighter surface with a
   hairline edge and the print shadow; "See the work" on every tile; hover lifts 3px. Placement: _macros.html bento()
   writes each tile's grid lines (--gc, --gr) for four columns; narrower layouts use spans by size class only.
   Measured (WCAG ratio): light tile vs ground 1.14, hovered 1.21, edge vs ground 1.52; dark 1.15, 1.34, 2.20. */
.bento {
  --pad: 28px;        /* one padding for every tile, as Geist does */
  --row: 22rem;       /* module height on wide screens */
  --xs: 21px;         /* cross size, Geist's wide-screen value */
  --gap: 1rem;        /* gutter of page ground between tiles */
  --tile-radius: 6px; /* the site's own panel radius (.reveal) */
  --cue-h: 3.25rem;
  --tile: #f3f9f6;    /* 65% --panel + 35% --ground */
  --tile-hi: #ffffff; /* --panel: hover, focus, press and the rising panel */
  --pic-edge: rgba(22, 32, 27, .14);
  --ease-out-3: cubic-bezier(.33, 1, .68, 1); /* motion-floor.md */
  --ease-out-4: cubic-bezier(.25, 1, .5, 1);
  --ease-in-3: cubic-bezier(.32, 0, .67, 0);
  position: relative;
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-auto-rows: var(--row);
}
@media (prefers-color-scheme: dark) {
  .bento { --tile: #1b2520; --tile-hi: #27312c; --pic-edge: rgba(0, 0, 0, .35); } /* dark --panel; 94% --panel + 6% --ink */
}
.bento > .tile { grid-column: var(--gc, auto); grid-row: var(--gr, auto); }
.group-head.bento-head { margin-block-end: calc(var(--vertGap) * .5); }
.page-work .group > .bento { grid-column: 1 / -1; }
/* the filter above the mosaic (Raian, 28 Sep 2026: "a way to segment or filter it by GTM and Ops"): the look of the
   org chart / systems buttons on the search program page. site.js shows it, so without JavaScript the whole gallery
   simply shows; each view's tile places come from tools/bento.py */
.bento-filter { display: flex; flex-wrap: wrap; margin: 0 0 1.5rem; }
.no-js .bento-filter { display: none; }  /* the buttons need site.js; without it the whole gallery shows */
.page-work .group > .bento-filter { grid-column: 1 / -1; }
.bento-filter button { min-height: 44px; padding: 0 1.1em; font: inherit; font-size: var(--size-s); font-weight: 500; line-height: 1.2;
  color: var(--ink-2); border: 1px solid var(--hair); border-radius: 2px; background: transparent; position: relative; cursor: pointer;
  transition: background-color var(--t-line) var(--ease-line), color var(--t-line) var(--ease-line), border-color var(--t-line) var(--ease-line); }
.bento-filter button + button { margin-inline-start: -1px; }
.bento-filter button[aria-pressed="true"] { background: var(--panel); color: var(--ink); border-color: var(--ink-2); z-index: 1; }
@media (hover: hover) { .bento-filter button:hover { color: var(--ink); border-color: var(--ink-2); z-index: 1; } }
.bento-filter button:focus-visible { z-index: 2; }
.bento > .tile[hidden], .bento > .x[hidden] { display: none; }

/* crosses on intersections of the gutters: two 1px lines, as Geist draws them */
.bento > .x { position: absolute; z-index: 7; width: var(--xs); height: var(--xs); pointer-events: none; }
.bento > .x::before, .bento > .x::after { content: ""; position: absolute; background: var(--ink-2); }
.bento > .x::before { left: calc(50% - .5px); top: 0; bottom: 0; width: 1px; }
.bento > .x::after { top: calc(50% - .5px); left: 0; right: 0; height: 1px; }
.bento > .x-tl { top: calc(var(--xs) / -2 - var(--gap) / 2); left: calc(var(--xs) / -2 - var(--gap) / 2); }
.bento > .x-tr { top: calc(var(--xs) / -2 - var(--gap) / 2); right: calc(var(--xs) / -2 - var(--gap) / 2); }
.bento > .x-bl { bottom: calc(var(--xs) / -2 - var(--gap) / 2); left: calc(var(--xs) / -2 - var(--gap) / 2); }
.bento > .x-br { bottom: calc(var(--xs) / -2 - var(--gap) / 2); right: calc(var(--xs) / -2 - var(--gap) / 2); }
/* the big tile's inner corner: its grid lines come from bento() */
.bento > .x-in { top: calc(var(--xs) / -2 - var(--gap) / 2); left: calc(var(--xs) / -2 - var(--gap) / 2); }

/* a tile: a surface lighter than the page, a hairline edge, the site's resting print shadow */
.bento .tile {
  position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0;
  padding: var(--pad) var(--pad) 0;
  background-color: var(--tile);
  border: 1px solid var(--hair); border-radius: var(--tile-radius);
  box-shadow: var(--print-shadow);
  overflow: hidden; overflow: clip; isolation: isolate;
  cursor: pointer;
  transition: transform 200ms var(--ease-in-3), box-shadow 200ms var(--ease-in-3), background-color 200ms var(--ease-in-3);
}
.bento .tile-title { font-size: 1.25rem; line-height: 1.2; text-wrap: balance; max-width: 30rem; }
.bento .tile-wide .tile-title { font-size: var(--size-m); max-width: 24em; }
.bento .tile-big .tile-title { font-size: clamp(1.875rem, 2.5vw, 2.5rem); line-height: 1.12; letter-spacing: -.005em; max-width: 13em; }

/* the whole tile opens the piece: the title link stretches over it (one tab stop per tile). The stretched link sits
   under the text (every word stays readable and measurable) and over the picture; the panel and the cue let clicks
   fall through to it. */
.bento .tile .title-link { position: static; }
.bento .tile .title-link::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.bento .tile .title-link:focus-visible { outline: none; }
.bento .tile .title-link:focus-visible::after { z-index: 8; outline: 2px solid var(--accent); outline-offset: -4px; border-radius: calc(var(--tile-radius) - 1px); }

/* the picture: flat inside the tile (the tile carries the shadow), a hairline edge so white charts keep their shape */
.bento .media { position: relative; flex: 1 1 auto; min-height: 5rem; margin-top: 1.1rem; }
.bento .print { position: absolute; inset: 0; overflow: hidden; border-radius: var(--print-radius); }
.bento .print::after { content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; box-shadow: inset 0 0 0 1px var(--pic-edge); }
.bento .print picture { display: contents; }
.bento .print img { width: 100%; height: 100%; object-fit: cover; object-position: var(--pos, 50% 0); transform-origin: var(--pos, 50% 0); filter: var(--print-dim); }
.bento .print.tall img { height: auto; object-fit: fill; }

/* the cue: the site's own "See the work" line, drawn like every site link, at the foot of every tile */
.bento .cue {
  position: relative; z-index: 6; pointer-events: none;
  display: flex; align-items: center; min-height: var(--cue-h);
  margin-inline: calc(var(--pad) * -1); padding-inline: var(--pad);
  background-color: inherit;
  font-size: 1rem !important; font-weight: 500; line-height: 1.2;
}
.bento .cue span { position: relative; }
.bento .cue span::before {
  content: ""; position: absolute; left: 0; bottom: -2px; width: 100%; height: 1px;
  background: currentColor; transform-origin: center left; transition: transform var(--t-line) var(--ease-line);
}

/* the panel: the card line and the piece's first number */
.bento .panel { position: relative; z-index: 5; pointer-events: none; }
.bento .panel-line { font-size: 1rem; line-height: 1.4; }
.bento .fig .v { display: block; font-size: 2rem; font-weight: 400; line-height: 1.05; letter-spacing: -.03em; font-variant-numeric: tabular-nums; }
.bento .fig .k { display: block; font-size: 1rem; line-height: 1.35; color: var(--ink-2); margin-block-start: .3em; }
.bento .panel .meta-line { font-size: 1rem !important; line-height: 1.35; color: var(--ink-2); margin-block-start: 0 !important; }
.bento .panel > * + * { margin-block-start: .85rem !important; }
.bento .figs { display: grid; gap: .85rem 1.6rem; }
.bento .figs > p { margin: 0; }
.bento .tile-big .panel-line { font-size: 1.25rem; }
.bento .tile-big .fig .v { font-size: var(--size-l); }
.bento .fig .v.v-long, .bento .tile-big .fig .v.v-long { font-size: 1.75rem; }
.bento .fig .v .nw { white-space: nowrap; }
.bento .figs:has(.v-long) .fig .v { font-size: 1.75rem; } /* the pair stays one size */
.bento .tile-big .figs { grid-template-columns: 1fr 1fr; }
.bento .fig-sentence { margin: 0; font-size: 1rem; line-height: 1.4; color: var(--ink-2); } /* a writer's one-line result in the panel (prototype A) */
.bento .tile.tight .panel-line { display: none; } /* set by site.js when the panel would cover the title */
.bento .tile-big .panel > * + * { margin-block-start: 1.5rem !important; }

/* the tools line, the site's own link after the gallery, fills the spare module */
.bento .tile-tools { padding-bottom: var(--pad); position: relative; overflow: hidden; isolation: isolate; }
/* his real year of GitHub contributions behind the tools line (tools/github_calendar.py; Raian, 30 Sep 2026: "a little
   nice GitHub art, kind of in the background"): newest weeks at the bottom right, fading out towards the words */
.bento .tile-tools .gh-art { position: absolute; right: var(--pad); bottom: var(--pad); width: calc(100% - 2 * var(--pad)); height: 5.5rem;
  z-index: -1; pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 45%); mask-image: linear-gradient(to right, transparent, #000 45%); }
@media (max-width: 767px) { .bento .tile-tools .gh-art { display: none; } }
.bento .tile-tools .gh-art rect { fill: var(--accent); }
.bento .tile-tools .gh-art .l0 { fill: var(--hair); opacity: .55; }
.bento .tile-tools .gh-art .l1 { opacity: .16; }
.bento .tile-tools .gh-art .l2 { opacity: .3; }
.bento .tile-tools .gh-art .l3 { opacity: .46; }
.bento .tile-tools .gh-art .l4 { opacity: .64; }
.bento .tile-tools p { font-size: 1.25rem; font-weight: 500; line-height: 1.3; }
.bento .tile-tools a { display: inline; }
.bento .tile-tools a.line { position: static; }
.bento .tile-tools a.line::before { display: none; }
.bento .tile-tools a span { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .22em; transition: text-decoration-color var(--t-line) var(--ease-line); }
.bento .tile-tools a::after { content: ""; position: absolute; inset: 0; z-index: 1; }
.bento .tile-tools a:focus-visible { outline: none; }
.bento .tile-tools a:focus-visible::after { z-index: 8; outline: 2px solid var(--accent); outline-offset: -4px; border-radius: calc(var(--tile-radius) - 1px); }

/* press: every screen */
.bento .tile:active { transform: scale(.98); background-color: var(--tile-hi); transition-duration: 120ms; }

/* hover and keyboard focus (wide screens with a pointer) */
@media (hover: hover) and (min-width: 768px) {
  .bento .tile:hover, .bento .tile:focus-within {
    transform: translate3d(0, -3px, 0); box-shadow: var(--print-shadow-lift); background-color: var(--tile-hi);
    transition: transform 200ms var(--ease-out-3), box-shadow 200ms var(--ease-out-3), background-color 200ms var(--ease-out-3);
  }
  .bento .tile:hover:active { transform: translate3d(0, -1px, 0) scale(.98); transition-duration: 120ms; }
  .bento .panel {
    position: absolute; left: 0; right: 0; bottom: var(--cue-h); z-index: 5;
    padding: 1.1rem var(--pad) .35rem;
    background: var(--tile-hi); box-shadow: 0 -1px 0 var(--hair);
    transform: translate3d(0, calc(100% + var(--cue-h)), 0); visibility: hidden;
    transition: transform 240ms var(--ease-in-3), visibility 0s linear 240ms;
  }
  .bento .panel > * { transform: translate3d(0, .75rem, 0); transition: transform 200ms var(--ease-in-3); }
  .bento .tile:hover .panel, .bento .tile:focus-within .panel { transform: none; visibility: visible; transition: transform 380ms var(--ease-out-4), visibility 0s; }
  .bento .tile:hover .panel > *, .bento .tile:focus-within .panel > * {
    transform: none;
    transition: transform 380ms var(--ease-out-4) calc(60ms + var(--i, 0) * 60ms);
  }
  .bento .panel > :nth-child(2) { --i: 1; }
  .bento .panel > :nth-child(3) { --i: 2; }
  /* a piece with no picture keeps its panel in place: there is nothing for it to rise over */
  .bento .tile.no-pic .panel { position: relative; bottom: auto; padding: 0; margin-block-start: .85rem; background: none; box-shadow: none; transform: none; visibility: visible; }
  .bento .tile.no-pic .panel > * { transform: none; }
  /* the picture moves slowly: a gentle scale from its own corner, then settles back faster */
  .bento .print img { transition: transform 300ms var(--ease-in-3); }
  .bento .tile:hover .print img, .bento .tile:focus-within .print img { transform: scale(1.05); transition: transform 600ms var(--ease-out-3); }
  .bento .tile:hover .print.tall img, .bento .tile:focus-within .print.tall img { transform: translate3d(0, -9%, 0); }
  .bento .tile:hover .title-link, .bento .tile:focus-within .title-link { background-size: 100% 2px; }
  .bento .tile:hover .cue span::before, .bento .tile:focus-within .cue span::before { transform: scaleX(0); transform-origin: center right; }
  .bento .tile-tools:hover a span, .bento .tile-tools:focus-within a span { text-decoration-color: transparent; }
  /* wide tiles set the card line and the number side by side */
  .bento .tile-wide .panel { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 0 1.6rem; align-items: start; }
  .bento .tile-wide .panel > * + * { margin-block-start: 0 !important; }
  .bento .tile-big .panel { padding-block: 1.5rem .5rem; }
}
@media (hover: hover) and (min-width: 768px) and (prefers-reduced-motion: reduce) {
  /* nothing moves or scales; hover and focus still answer: surface, shadow, underlines, and the panel fading in place */
  .bento .tile, .bento .tile:hover, .bento .tile:focus-within, .bento .tile:active, .bento .tile:hover:active { transform: none !important; transition: box-shadow 120ms ease, background-color 120ms ease !important; }
  .bento .panel, .bento .tile:hover .panel, .bento .tile:focus-within .panel { transform: none !important; }
  .bento .panel { opacity: 0; transition: opacity 120ms ease, visibility 0s linear 120ms !important; }
  .bento .tile:hover .panel, .bento .tile:focus-within .panel, .bento .tile.no-pic .panel { opacity: 1; transition: opacity 120ms ease, visibility 0s !important; }
  .bento .panel > *, .bento .tile:hover .panel > *, .bento .tile:focus-within .panel > * { opacity: 1 !important; transform: none !important; transition: none !important; }
  .bento .print img, .bento .tile:hover .print img, .bento .tile:focus-within .print img { transform: none !important; transition: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .bento .tile:active { transform: none; }
}

/* no hover (phones, touch screens): title, one key detail and the cue always shown */
@media (hover: none), (max-width: 767px) {
  .bento .panel { margin-block-start: .35rem; }
  .bento .panel-line, .bento .fig-2 { display: none; }
  .bento .panel > * + *, .bento .tile-big .panel > * + * { margin-block-start: 0 !important; }
  .bento .fig .v { font-size: 1.75rem; }
  .bento .tile-big .fig .v { font-size: 2.25rem; }
  .bento .tile-big .figs { grid-template-columns: 1fr; }
}
@media (hover: none) and (min-width: 768px) {
  .bento { grid-auto-rows: minmax(var(--row), auto); }
  .bento .media { min-height: 9rem; }
}

/* entrance: the tiles stand still, their contents drift in once (site.js adds .shown, 55ms apart) */
.js .bento .tile .tile-title, .js .bento .tile .media, .js .bento .tile .cue, .js .bento .tile-tools p { opacity: 0; transform: translate3d(var(--drift), 0, 0); transition: transform var(--t-enter) var(--ease-enter) var(--d, 0ms), opacity var(--t-enter) ease var(--d, 0ms); }
.js .bento .tile.shown .tile-title, .js .bento .tile.shown .media, .js .bento .tile.shown .cue, .js .bento .tile-tools.shown p { opacity: 1; transform: none; }
/* the title fades in without the sideways drift: a moved title becomes the box its stretched link's ::after is measured
   from, so when the drift ended the whole-tile click area snapped from the title's size to the tile's, which counts as
   a layout shift (0.22 on the Work page on a slowed phone, 28 Sep 2026). */
.js .bento .tile .tile-title { transform: none; }
/* on phones the big tile's picture is the page's largest paint: it shows at once instead of waiting for its entrance
   (Work page on a slowed phone: 2.6 s, over the 2.5 s bar, 28 Sep 2026) */
@media (hover: none), (max-width: 767px) { .js .bento .tile-big .media { opacity: 1; transform: none; transition: none; } }
@media (hover: none), (max-width: 767px) {
  .js .bento .tile .panel { opacity: 0; transition: opacity var(--t-enter) ease var(--d, 0ms); }
  .js .bento .tile.shown .panel { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .js .bento .tile .tile-title, .js .bento .tile .media, .js .bento .tile .cue, .js .bento .tile-tools p { transform: none !important; transition: opacity .2s ease !important; }
}

/* middle widths: two columns */
@media (max-width: 1359px) {
  .bento { --xs: 15px; --pad: 26px; --row: 20rem; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-flow: row dense; }
  .bento > .tile { grid-column: auto; grid-row: auto; }
  .bento > .tile-big { grid-column: 1 / -1; grid-row: span 2; }
  .bento > .tile-wide { grid-column: 1 / -1; }
  .bento > .x-in { display: none; }
}

/* phones: one column */
@media (max-width: 767px) {
  .bento { --pad: 22px; --xs: 11px; --gap: 14px; grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
  .group-head.bento-head { margin-block-end: 2.25rem; }
  .bento > .tile-big, .bento > .tile-wide { grid-column: 1; grid-row: auto; }
  .bento .tile-title, .bento .tile-wide .tile-title { font-size: 1.375rem; }
  .bento .tile-big .tile-title { font-size: 1.75rem; }
  .bento .tile .title-link { display: inline; padding-block: 10px; }
  /* each picture at its own shape, so nothing is cut; the big tile square, as approved */
  .bento .media { flex: none; aspect-ratio: var(--ar, 4 / 3); min-height: 0; margin-top: 1rem; }
  .bento .tile-big .media { aspect-ratio: 1 / 1; }
  .bento .tile-tools { padding-block: 1.1rem 1.3rem; }
  .bento .tile-tools p { font-size: 1.125rem; }
  .bento .tile-tools a { display: inline-block; padding-block: 10px; }
}
/* a card's own phone picture of another shape (card.phone), only up to 480 px, where its pixels still cover the box; last in the file so it wins over the phone block above */
@media (max-width: 480px) { .bento .media { aspect-ratio: var(--ar-ph, var(--ar, 4 / 3)); } }

/* screenshot sets (showcase artifact type "gallery", grouped per section in .gal-set): a tab per set, then one row of
   first screens that scrolls sideways, each its own print with the homepage tile's hairline edge, 6px corner and resting
   print shadow, page ground between them. The row is at most 33% of the window high, so the block stays under half a
   screen (Raian, 2 Oct 2026: "doesn't take up more than half of the screen"); each opens the whole capture. From 768 px every set fits one row (below). */
.gal-set { margin-block: calc(var(--vertGap) * .2) var(--vertGap); }
.gal-tabs { display: flex; flex-wrap: wrap; margin-block-end: .9rem; }
.gal-tabs[hidden], .gal-panel[hidden] { display: none; }
.gal-tabs button { font: inherit; font-size: var(--size-s); color: var(--ink-2); background: transparent; border: 1px solid var(--hair);
  padding: .55rem .95rem; min-height: 44px; cursor: pointer; position: relative; }
.gal-tabs button + button { margin-inline-start: -1px; }
.gal-tabs button[aria-selected="true"] { background: var(--panel); color: var(--ink); border-color: var(--ink-2); z-index: 1; }
.gal-tabs button:hover { color: var(--ink); border-color: var(--ink-2); z-index: 1; }
.gal-tabs button:focus-visible { z-index: 2; outline: 2px solid var(--accent); outline-offset: 2px; }
.gal-panel { margin: 0; }
.gal-panel + .gal-panel { margin-block-start: 1.5rem; }
.gal-strip { --strip-h: clamp(180px, 33vh, 360px); display: flex; gap: 1.1rem; overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity; scroll-padding-inline: 4px; padding: 4px 4px 22px; margin: -4px -4px 0; scrollbar-width: thin; }
.gal-strip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gal-item { flex: none; display: block; scroll-snap-align: start; }
.gal-strip .frame { border: 1px solid var(--hair); border-radius: 6px; background: var(--panel); }
.gal-strip .frame img { display: block; height: var(--strip-h); width: auto; aspect-ratio: 16 / 10; object-fit: cover; object-position: top; }
.gal-panel figcaption { margin-inline-start: 0; max-width: 44rem; margin-block-start: .4rem; }
/* laptop and up: every set fits one row, nothing to scroll (Raian, 2 Oct 2026: the scrollbar "isn't visible so people
   have to guess to scroll horizontally ... fit the four in a normal 13-inch viewport") */
@media (min-width: 768px) {
  .gal-dots { display: none; }
  .gal-strip { display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); overflow: visible; margin: 0; padding: 0 0 18px; }
  .gal-strip .frame img { width: 100%; height: auto; }
}
/* phones: the row still scrolls, so it shows that it does: the next shot peeks in, and the scrollbar is always drawn */
@media (max-width: 767px) {
  .gal-strip { --strip-h: 180px; gap: .75rem; padding-block-end: 10px; }
  /* phones hide scrollbars whatever the CSS says (iOS draws none), so a dot per shot shows there is more, and where */
  .gal-dots { display: flex; gap: 2px; margin-block: 2px 4px; }
  .gal-dots button { width: 24px; height: 24px; padding: 0; border: 0; background: none; cursor: pointer; position: relative; }
  .gal-dots button::after { content: ""; position: absolute; inset: 8px; border-radius: 50%; border: 1.5px solid var(--ink-2); }
  .gal-dots button.on::after { background: var(--ink-2); }
  .gal-strip .frame img { height: auto; width: 70vw; max-width: 300px; }
  /* one row of tabs that scrolls sideways, never two uneven rows */
  .gal-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-inline: -16px; padding-inline: 16px; }
  .gal-tabs button { flex: none; white-space: nowrap; }
}

/* ---------- Personal projects: the drawing sheet (layout C, Raian 5 Oct 2026) ----------
   One thin ink frame split into cells like the blocks of Cerda's plan: square corners, no fill, no shadow. The
   picture sits in the big cell, the name and links in the small one; every further project adds a row. */
.page-work .group > .sheet { grid-column: 1 / -1; }
.sheet { border: 1px solid var(--ink); }
.sheet-row { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.sheet-row + .sheet-row { border-top: 1px solid var(--ink); }
.sheet-row > div { padding: clamp(16px, 2vw, 28px); }
.sheet-pic { border-right: 1px solid var(--ink); }
.sheet-frame { display: block; aspect-ratio: 16 / 11; overflow: hidden; }
.sheet-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
.sheet-credit { font-size: .875rem; line-height: 1.4; color: var(--ink-2); margin-block-start: .6rem; }
.sheet-text { display: flex; flex-direction: column; justify-content: space-between; gap: 2rem; }
/* the project's own mark above its name (Walkably's Blocks, Raian 6 Oct 2026); light and dark files, never recoloured here */
.sheet-mark { display: block; width: 48px; height: 48px; margin-block-end: 1rem; }
.sheet-mark img { display: block; width: 100%; height: 100%; }
.sheet-name { font-size: clamp(1.875rem, 2.5vw, 2.5rem); line-height: 1.1; letter-spacing: -.005em; }
.sheet-name a { display: inline-flex; align-items: center; min-height: 44px; }
.sheet-line { font-size: 1.125rem; line-height: 1.45; color: var(--ink-2); margin-block-start: .6rem; max-width: 26rem; }
.sheet-links { display: flex; flex-direction: column; align-items: flex-start; gap: .25rem; font-size: 1rem;
  border-top: 1px solid var(--hair); padding-block-start: 1rem; }
.sheet-links a { display: inline-flex; align-items: center; gap: .45rem; min-height: 44px; font-weight: 600; }
.sheet-links .arrow { width: 1rem; height: 1rem; }
/* the 44px tap box is taller than the text: keep the wipe underline under the words, not at the box's foot */
.sheet-links a.line::before { bottom: calc(50% - .85em); }
@media (max-width: 767px) {
  .sheet-row { grid-template-columns: 1fr; }
  .sheet-pic { border-right: 0; border-bottom: 1px solid var(--ink); }
  .sheet-row > div { padding: 12px 12px 16px; }
  .sheet-mark { width: 40px; height: 40px; margin-block-end: .75rem; }
}
