/* ==========================================================================
   Maxwell Yan — Portfolio
   Light off-white canvas, solid colour blocks, zero rounded corners.
   Type: Fustat throughout; the hero name is Dela Gothic One (as vector shapes).
   ========================================================================== */

:root {
  /* Canvas — warm off-white, after the "Graphics by Maxwell Yan" title card */
  --bg: #f7f2ea;
  --bg-2: #efe8dc;
  --bg-3: #e4dbcc;
  --line: #ddd3c3;

  /* Ink */
  --fg: #1c1b19;
  --fg-2: #6b655c;
  --fg-3: #a1988a;

  /* Solid blocks. --ink / --paper are the dark block / light text pair;
     --shade is the charcoal used for text on the light project colours. */
  --paper: #f7f2ea;
  --white: #ffffff;
  --ink: #161514;
  --shade: #161514;
  --surface: #ffffff; /* raised blocks: contact, Beli */
  --ph-ink: #57524a; /* placeholder labels */
  /* hero bars use a difference blend; this colour reads as --fg over --bg
     and as the inverse over the type */
  --negative: #e1ddd6;
  --taupe: #cfc3b1;
  --stone: #b9ac98;
  --red: #dc2f0e; /* the vibrant secondary — use sparingly; white on it passes AA (4.7:1) */

  /* Project blocks */
  --compass: var(--taupe);
  --micdrop: var(--white);
  --explore: var(--stone);
  --play: var(--red);
  --warriors: var(--stone);

  /* Defaults (overridden per page / per block) */
  --accent: var(--taupe);
  --on-accent: var(--shade);

  /* Type */
  --font-display: "Fustat", system-ui, -apple-system, sans-serif;
  --font-text: "Fustat", system-ui, -apple-system, sans-serif;

  --gutter: clamp(16px, 2.4vw, 32px);
  /* the nav floats over the page, so nothing reserves space for it */
  --header-h: 0px;
  --ease: cubic-bezier(0.76, 0, 0.24, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  /* hovers: a gentle, symmetric ease-in-out so they feel calm */
  --ease-hover: cubic-bezier(0.45, 0, 0.55, 1);
}

/* Reset ------------------------------------------------------------------ */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border-radius: 0 !important; /* no rounded corners, anywhere */
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h);
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-text);
  font-optical-sizing: auto;
  font-feature-settings: "ss01", "cv11";
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

ul,
ol {
  list-style: none;
}

::selection {
  background: var(--red);
  color: var(--white);
}

:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 3px;
}

/* keyboard users can jump straight past the nav */
.skip-link {
  position: fixed;
  top: var(--gutter);
  left: var(--gutter);
  z-index: 60;
  padding: 10px 14px;
  background: var(--ink);
  color: var(--paper);
  font-size: 14px;
  font-weight: 600;
  transform: translateY(calc(-100% - var(--gutter) - 8px));
}

.skip-link:focus {
  transform: none;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Type ------------------------------------------------------------------- */
h1, h2, h3 {
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}

/* Main headlines (same family as the body, set heavier) */
.display,
.hero__name,
.section-head h2,
.pp-title {
  font-family: var(--font-display);
}

.display {
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 0.9;
  hyphens: none;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.eyebrow::before {
  content: "";
  width: 8px;
  height: 8px;
  background: var(--red);
  flex: none;
}

.eyebrow--plain::before {
  display: none;
}

.muted {
  color: var(--fg-2);
}

/* Layout ----------------------------------------------------------------- */
.wrap {
  padding-inline: var(--gutter);
}

.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
}

main {
  padding-top: var(--header-h);
}

/* Header ----------------------------------------------------------------- */
/* Nav: a small solid block fixed at the top centre of the screen, on
   every page, always visible. */
.site-header {
  position: fixed;
  top: max(12px, calc(var(--gutter) - 12px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px;
  background: var(--bg);
  border: 1px solid var(--line);
  transition: transform 0.28s var(--ease), opacity 0.2s var(--ease);
}


.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: 15px;
}

.brand {
  padding-left: 3px;
}

.brand__seal {
  width: 34px;
  height: 34px;
}

.site-nav {
  display: flex;
  gap: 4px;
}

.site-nav a {
  position: relative;
  padding: 8px 12px;
  font-size: 14px;
  font-weight: 500;
  overflow: hidden;
  isolation: isolate;
  transition: color 0.2s var(--ease-hover);
}

.site-nav a::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* the hover tint; the current page swaps in ink (below) */
  background: color-mix(in srgb, var(--ink) 10%, transparent);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.2s var(--ease-hover), background-color 0.2s var(--ease-hover);
}

.site-nav a[aria-current="page"] {
  color: var(--paper);
}

/* hover is a light tint rising from the bottom; the current page is ink */
.site-nav a:hover::before {
  transform: scaleY(1);
}

.site-nav a[aria-current="page"]::before {
  transform: scaleY(1);
  background: var(--ink);
}

/* Media / placeholders ------------------------------------------------------
   Every image lives in a [data-ph] box. The box paints a solid placeholder
   (with the expected file path) underneath the <img>. If the image file is
   missing, the img is hidden and the placeholder shows. Drop a real file at
   that path and it appears — no markup changes needed.
   ------------------------------------------------------------------------ */
[data-ph] {
  position: relative;
  overflow: hidden;
  background: var(--ph-bg, var(--bg-3));
  color: var(--ph-fg, var(--ph-ink));
}

[data-ph]::before {
  content: attr(data-ph);
  position: absolute;
  left: 14px;
  bottom: 12px;
  right: 14px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

[data-ph]::after {
  /* small square corner mark so placeholders read as deliberate frames */
  content: "";
  position: absolute;
  top: 14px;
  left: 14px;
  width: 10px;
  height: 10px;
  background: currentColor;
}

[data-ph] > img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

[data-ph].is-empty > img {
  visibility: hidden;
}

.media {
  width: 100%;
  aspect-ratio: var(--ratio, 16 / 9);
}

/* Reveal animations ---------------------------------------------------- */
.js .line {
  display: block;
  overflow: hidden;
}

.js .line > span {
  display: block;
  transform: translateY(105%);
  transition: transform 0.55s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 40ms + 24ms);
}

.js.is-ready .line > span {
  transform: none;
}

.js [data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out);
}

.js [data-reveal="wipe"] {
  opacity: 1;
  transform: none;
  clip-path: inset(100% 0 0 0);
  transition: clip-path 0.55s var(--ease);
}

.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 0 0);
}

/* Page transitions --------------------------------------------------------- */
html.is-arriving::after {
  /* paints before first frame so there is no flash between pages */
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--arrive, var(--paper));
}

/* flipping between projects: keep the new page hidden until it slides in */
html.is-arriving-soft main {
  opacity: 0;
}

.wipe {
  position: fixed;
  inset: 0;
  z-index: 1000;
  pointer-events: none;
}

.wipe__layer {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}

.wipe__col {
  /* overlap by 1px so no hairlines between columns */
  margin-right: -1px;
  transform: scaleY(0);
}

/* Buttons ------------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 16px 22px;
  background: var(--fg);
  color: var(--ink);
  font-weight: 600;
  font-size: 15px;
  transition: background 0.2s var(--ease-hover), color 0.2s var(--ease-hover);
}

.btn:hover {
  background: var(--red);
  color: var(--white);
}

/* Google Material Symbols (outlined, weight 400), inlined as SVG */
.icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  fill: currentColor;
  flex: none;
}

.legal .icon {
  vertical-align: -0.15em;
}

.lightbox__close {
  display: grid;
  place-items: center;
}

.arrow-box {
  display: inline-grid;
  place-items: center;
  width: 56px;
  height: 56px;
  background: var(--ink);
  color: var(--paper);
  font-size: 24px;
  flex: none;
  transition: transform 0.3s var(--ease-hover);
}

/* ==========================================================================
   Home
   ========================================================================== */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: max(520px, calc(100svh - var(--header-h)));
  padding: clamp(20px, 2.4vw, 32px) var(--gutter);
  background: var(--bg);
  color: var(--fg);
}

/* Animated rectangles, drawn in front of the type with a difference
   blend: each bar is the negative of whatever it passes over */
.hero__bars {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  mix-blend-mode: difference;
  pointer-events: none;
}

/* Name lockup. MAXWELL and YAN are vector outlines of Dela Gothic One (built
   from the font file), and each bar is merged into its letter as one shape, so
   they can't drift out of line in any browser. The lead bar runs from far
   off-screen into the M; the tail bar runs out of the N past the right
   edge (the hero clips both). Rows are exactly the letters' height.
   Columns: [lead space] [words] [seal] [rest]. The two outer columns are
   equal, so the whole group (MAXWELL plus the seal) is centred on the
   screen; the bars simply grow to reach the edges. Everything is sized
   from --name. */
.hero__lockup {
  --name: clamp(32px, min(10.5vw, 14svh), 136px);
  --row-h: calc(var(--name) * 0.726);
  position: relative;
  display: grid;
  --seal-gap: calc(var(--name) * 0.22);
  grid-template-columns:
    minmax(calc(var(--gutter) + 0.3em), 1fr)
    auto
    calc(var(--row-h) + var(--seal-gap))
    minmax(0, 1fr);
  row-gap: calc(var(--name) * 0.52);
  margin-inline: calc(var(--gutter) * -1);
  font-size: var(--name);
}

.hero__name {
  display: contents;
  color: var(--fg);
}

.hero__row {
  display: block;
  height: var(--row-h);
  overflow: visible;
  fill: currentColor;
}

.hero__row--top {
  grid-column: 2;
  grid-row: 1;
  width: calc(var(--name) * 6.557);
}

.hero__row--bot {
  grid-column: 2;
  grid-row: 2;
  justify-self: end;
  width: calc(var(--name) * 2.725);
}

/* reveal: each row wipes down into place (the clip reaches far past the
   box so the bars aren't cut off) */
.js .hero__row {
  clip-path: inset(0 -300vw 100% -300vw);
  transition: clip-path 0.55s var(--ease);
}

.js .hero__row--bot {
  transition-delay: 0.06s;
}

.js.is-ready .hero__row {
  clip-path: inset(0 -300vw 0 -300vw);
}

/* the seal sits to the right of MAXWELL, exactly as tall as its row, and
   above the drifting bars so they never invert it */
.hero__seal {
  grid-column: 3;
  grid-row: 1;
  justify-self: start;
  position: relative;
  z-index: 3;
  width: var(--row-h);
  height: var(--row-h);
  margin-left: var(--seal-gap);
}

.js .hero__seal {
  opacity: 0;
  transition: opacity 0.4s var(--ease-out) 0.15s;
}

.js.is-ready .hero__seal {
  opacity: 1;
}

.hero__blurb {
  grid-column: 2;
  grid-row: 2;
  align-self: start;
  justify-self: start;
  /* line the text's ink up with the inner edge of the M's left stem
     (0.2607em into MAXWELL), less the first letter's own side bearing */
  padding-left: calc(var(--name) * 0.2607 - 1em * var(--d-lsb, 0.06));
  /* stay clear of YAN */
  max-width: calc(var(--name) * 3.482);
  font-size: clamp(16px, calc(var(--name) * 0.16), 24px);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--fg-2);
}

/* beside YAN, the blurb mustn't make that row taller than the letters */
@media (min-width: 700px) {
  .hero__blurb {
    height: 0;
    overflow: visible;
  }
}

.hero__blurb strong {
  font-weight: 600;
  color: var(--fg);
}

/* the same line in Traditional Chinese (設計師 · 多倫多), quietly underneath */
.hero__zh {
  display: block;
  margin-top: 0.5em;
  font-family: "Noto Serif TC", "Songti TC", "PMingLiU", serif;
  font-size: 0.72em;
  font-weight: 600;
  letter-spacing: 0.3em;
  color: #8a8278;
}

/* On narrow screens: the stamp sits under MAXWELL, on YAN's row and as
   tall as it, left-aligned with the blurb; the blurb sits under YAN. */
@media (max-width: 699px) {
  .hero__lockup {
    grid-template-columns: minmax(calc(var(--gutter) + 0.3em), 1fr) auto 0 minmax(0, 1fr);
  }

  .hero__seal {
    grid-column: 2;
    grid-row: 2;
    /* same left edge as the blurb: the inner edge of the M's stem */
    margin-left: calc(var(--name) * 0.2607);
  }

  .hero__blurb {
    grid-row: 3;
    grid-column: 2 / 5;
    max-width: 30ch;
    margin-top: calc(var(--name) * 0.1);
    padding-right: var(--gutter);
  }
}

/* Work grid ------------------------------------------------------------- */
.work {
  padding-block: clamp(48px, 6vw, 96px);
}

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 20px;
  margin-bottom: var(--gutter);
  border-bottom: 1px solid var(--line);
}

.section-head h2 {
  font-size: clamp(26px, 3.6vw, 50px);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1;
}

.section-head .count {
  white-space: nowrap;
  font-size: 14px;
  color: var(--fg-2);
  font-variant-numeric: tabular-nums;
}

.work-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--gutter);
}

.card {
  grid-column: span 12;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2vw, 24px);
  padding: clamp(16px, 2vw, 28px);
  background: var(--accent);
  color: var(--on-accent);
  min-height: 0;
  box-shadow: inset 0 0 0 1px rgb(22 21 20 / 0.06);
}

.card__top {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.card .media {
  /* a shade darker than the card, with the card's own text colour, so the
     placeholder label keeps AA contrast on every card colour */
  --ph-bg: color-mix(in srgb, var(--shade) 10%, var(--accent));
  --ph-fg: var(--on-accent);
  aspect-ratio: 4 / 3;
}

.card .media > img {
  transition: transform 0.3s var(--ease-hover);
}

.card:hover .media > img {
  transform: scale(1.04);
}

.card__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
}

.card__title {
  font-size: clamp(26px, 3.6vw, 64px);
}

.card__client {
  margin-top: 10px;
  font-size: 15px;
  font-weight: 500;
}

.card .arrow-box {
  background: var(--on-accent);
  color: var(--accent);
}

/* on hover the box stays put and its arrow turns 45° to point right */
.card:hover .arrow-box,
.card:focus-visible .arrow-box {
  transform: none;
}

@media (min-width: 700px) {
  .card { grid-column: span 6; }

  .card .media {
    aspect-ratio: auto;
    flex: 1;
    min-height: clamp(280px, 36vw, 560px);
  }
}

@media (min-width: 1100px) {
  .card--wide { grid-column: span 7; }
  .card--narrow { grid-column: span 5; }
}

/* a lone last card runs the full width, as a shorter band */
@media (min-width: 700px) {
  .card--full { grid-column: 1 / -1; }
  .card--full .media { min-height: clamp(160px, 16vw, 280px); }
}

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  margin-top: clamp(48px, 6vw, 96px);
}

.contact {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 32px 48px;
  padding: clamp(28px, 5vw, 72px) var(--gutter);
  background: var(--surface);
  color: var(--fg);
  border-top: 1px solid var(--line);
}

.contact__main {
  display: grid;
  gap: 16px;
}

/* the line sits to the right of the links, level with their bottom edge */
.contact__title {
  max-width: 14ch;
  font-size: clamp(28px, 3.6vw, 56px);
  line-height: 1.02;
  text-align: right;
  text-wrap: balance;
}

@media (max-width: 699px) {
  .contact__title {
    max-width: none;
    text-align: left;
  }
}

.contact__links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.contact__links a {
  display: inline-block;
  padding: 10px 14px;
  border: 1px solid var(--ink);
  font-size: 14px;
  font-weight: 500;
  transition: background 0.2s var(--ease-hover), color 0.2s var(--ease-hover);
}

.contact__links a:hover {
  background: var(--ink);
  color: var(--paper);
}

.legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 16px;
  padding: 20px var(--gutter);
  font-size: 13px;
  color: var(--fg-2);
}

.legal a:hover {
  color: var(--fg);
}

/* ==========================================================================
   Project pages — split layout
   Desktop: the page itself never scrolls. Left: a fixed summary panel whose
   type scales with the screen (and is nudged down by main.js if it would
   still overflow). Right: a solid colour block of images that scrolls.
   Small screens: the two simply stack and the page scrolls normally.
   ========================================================================== */
.pp {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

/* Everything in the panel is sized in em from one value. On short screens
   main.js first tightens spacing (--space), then shrinks type (--fit), so
   the panel always fits without scrolling. */
.pp-panel {
  --fit: 1;
  --space: 1;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  /* groups spread out to use the full height; never closer than this */
  justify-content: space-between;
  gap: calc(2.2em * var(--space));
  /* same inset as the image block, so the back button lines up with its
     top edge and the next-project button with its bottom edge */
  padding: var(--gutter);
  font-size: calc(clamp(12px, min(1.02vw, 1.75svh), 17px) * var(--fit));
}

.pp-intro {
  display: flex;
  flex-direction: column;
  gap: calc(1.6em * var(--space));
}

.pp-panel__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1em;
}

.pp-back {
  display: inline-flex;
  align-items: center;
  gap: 0.8em;
  font-size: 0.9em;
  font-weight: 600;
}

.pp-back .arrow-box {
  width: 2.6em;
  height: 2.6em;
  font-size: 1.1em;
}



.pp-index {
  font-size: 0.85em;
  font-weight: 600;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--fg-2);
}

.pp-title {
  display: flex;
  flex-wrap: wrap;
  /* one size on every project: viewport-based, never wider than the panel */
  font-size: min(11cqi, max(3.25vw, 39px));
  letter-spacing: -0.02em;
  line-height: 1;
}

.pp-word {
  display: inline-block;
}

.pp-word + .pp-word {
  margin-left: 0.25em;
}

.pp-lede {
  font-size: 1.3em;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.02em;
  max-width: 26em;
}

.pp-summary {
  display: grid;
  gap: calc(1.1em * var(--space));
  font-size: 1em;
  line-height: calc(1.5 + 0.2 * var(--space));
  max-width: 34em;
  color: var(--fg-2);
}

.pp-summary .eyebrow {
  margin-top: calc(1.5em * var(--space));
  gap: 0.7em;
  font-size: 0.72em;
  color: var(--fg);
}

.pp-summary .eyebrow::before {
  width: 0.7em;
  height: 0.7em;
}

/* headline numbers, above the write-up */
.pp-stats {
  display: grid;
  /* equal columns for however many stats there are */
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 1.2em;
  margin-bottom: calc(0.6em * var(--space));
  padding: calc(1.2em * var(--space)) 0;
  border-block: 1px solid var(--line);
  line-height: 1.25;
}

.pp-stats strong {
  display: block;
  margin-bottom: 0.3em;
  font-family: var(--font-display);
  font-size: 1.35em;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--fg);
  white-space: nowrap;
}

.pp-stats span {
  display: block;
  font-size: 0.78em;
}

.pp-meta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1.6em;
}

.pp-meta div {
  padding: calc(0.9em * var(--space)) 0;
  border-top: 1px solid var(--line);
}

/* long values, and an odd one out, take the full row (see build) */
.pp-meta .is-wide {
  grid-column: 1 / -1;
}

.pp-meta dt {
  font-size: 0.7em;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-2);
  margin-bottom: 0.15em;
}

.pp-meta dd {
  font-size: 0.95em;
  font-weight: 500;
}

/* Previous and next project: two quiet text links under a hairline, with
   the same small ink arrow square as "All work" at the top */
.pp-pager {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1em;
  padding-top: calc(1.1em * var(--space));
  border-top: 1px solid var(--line);
}

.pp-next {
  display: flex;
  align-items: center;
  gap: 0.75em;
  min-width: 0;
}

.pp-next:not(.pp-next--prev) {
  justify-content: flex-end;
  text-align: right;
}

.pp-next__label {
  display: flex;
  flex-direction: column;
  gap: 0.2em;
  min-width: 0;
  font-size: 1.05em;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.pp-next__label small {
  font-size: 0.66em;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-2);
}

.pp-next .arrow-box {
  width: 2.4em;
  height: 2.4em;
  font-size: 1em;
}



/* The work */
.pp-media {
  /* a plain vertical stack: each image keeps its full aspect-ratio height
     inside the fixed-height scroll box (a grid here would squash them) */
  display: flex;
  flex-direction: column;
  gap: var(--gutter);
  margin: 0 var(--gutter) var(--gutter);
  padding: var(--gutter);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: inset 0 0 0 1px rgb(22 21 20 / 0.06);
}

.pp-media:focus-visible {
  outline-offset: -4px;
}

.pp-media .media {
  --ph-bg: color-mix(in srgb, var(--shade) 10%, var(--accent));
  --ph-fg: var(--on-accent);
}

.pp-media > * {
  flex: none;
}

.pp-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gutter);
}

@media (min-width: 900px) {
  /* the page is exactly one screen tall and never scrolls */
  html:has(.pp),
  body:has(.pp) {
    height: 100%;
    overflow: hidden;
  }

  .pp {
    grid-template-columns: minmax(320px, 34%) minmax(0, 1fr);
    height: 100svh;
  }

  .pp-panel {
    height: calc(100svh - var(--header-h));
    overflow: hidden;
  }

  .pp-panel.is-overflowing {
    overflow-y: auto;
  }

  /* only the images scroll; same inset as the panel, so the block's top and
     bottom line up with the back and next-project buttons */
  .pp-media {
    height: calc(100svh - var(--header-h) - var(--gutter) * 2);
    margin: var(--gutter) var(--gutter) var(--gutter) 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--on-accent) 35%, transparent) transparent;
  }
}

/* Playground gallery inside the panel */
.pp-gallery {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-flow: dense;
  gap: var(--gutter);
}

.pp-gallery figure {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pp-gallery .media {
  --ratio: 1 / 1;
}

.pp-gallery .g-wide { grid-column: span 2; }
.pp-gallery .g-wide .media { --ratio: 2 / 1; }
.pp-gallery .g-tall .media { --ratio: 4 / 5; }

.pp-gallery figcaption {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 4px 12px;
  font-size: 13px;
}

.pp-gallery figcaption b {
  font-weight: 600;
}

.pp-gallery figcaption span {
  font-weight: 400;
}

/* ==========================================================================
   About
   ========================================================================== */
.profile {
  padding-block: clamp(32px, 5vw, 72px);
  /* room for the floating nav */
  padding-top: calc(var(--gutter) + 72px);
  row-gap: 40px;
  border-bottom: 1px solid var(--line);
}

.profile__photo {
  grid-column: 1 / -1;
  --ratio: 4 / 5;
  --ph-bg: var(--bg-3);
}

.profile__info {
  grid-column: 1 / -1;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  gap: 28px;
}

.profile__name {
  font-size: clamp(36px, 15.5cqi, 170px);
}

.profile__badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  font-size: 15px;
  font-weight: 600;
  background: var(--bg-3);
  color: var(--fg);
}

.badge--role {
  background: var(--ink);
  color: var(--paper);
}

.badge--loc::before {
  content: "";
  width: 10px;
  height: 10px;
  background: var(--red);
}

.badge--status::before {
  content: "";
  width: 10px;
  height: 10px;
  background: var(--red);
  animation: blink 1.6s steps(2, jump-none) infinite;
}

@keyframes blink {
  50% { opacity: 0.2; }
}

.profile__bio {
  display: grid;
  gap: 1em;
  font-size: clamp(17px, 1.7vw, 24px);
  line-height: 1.5;
  letter-spacing: -0.012em;
  color: var(--fg-2);
  max-width: 40em;
}

.profile__bio p:first-child {
  color: var(--fg);
  font-size: 1.25em;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.025em;
}

@media (min-width: 640px) and (max-width: 899px) {
  .profile__photo { grid-column: 1 / span 6; }
  .profile__info { grid-column: 7 / span 6; justify-content: flex-end; }
}

@media (min-width: 900px) {
  .profile__photo { grid-column: 1 / span 5; align-self: start; position: sticky; top: calc(var(--header-h) + var(--gutter)); }
  .profile__info { grid-column: 7 / span 6; justify-content: flex-end; }
}

/* Wide screens: the name sits on one line, sized by main.js to fill the
   column (capped). The two words stay separate boxes so each can be
   optically aligned and keep its reveal. */
@media (min-width: 900px) {
  .profile__name { white-space: nowrap; }
  .js .profile__name .line { display: inline-block; vertical-align: top; }
}

.about-section {
  padding-block: clamp(56px, 7vw, 112px);
}

/* Experience */
.exp-list li {
  border-bottom: 1px solid var(--line);
}

.exp {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(16px, 2.4vw, 32px);
  padding-block: clamp(14px, 1.6vw, 20px);
}

.exp__logo {
  width: clamp(64px, 7vw, 96px);
  aspect-ratio: 1;
  padding: 18%;
  --ph-bg: var(--white);
  --ph-fg: var(--fg-3);
}

.exp__logo[data-ph]::before {
  /* fallback: show the company initial */
  content: attr(data-initial);
  inset: 0;
  display: grid;
  place-items: center;
  font-size: clamp(22px, 2.6vw, 34px);
  font-weight: 800;
  letter-spacing: -0.04em;
  color: var(--shade);
  text-transform: none;
}

.exp__logo[data-ph]::after {
  display: none;
}

.exp__logo > img {
  object-fit: contain;
}

.exp__company {
  font-size: clamp(20px, 2.3vw, 34px);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.1;
}

.exp__role {
  font-size: clamp(15px, 1.3vw, 18px);
  color: var(--fg-2);
  margin-top: 4px;
}

.exp__year {
  font-size: clamp(14px, 1.2vw, 17px);
  color: var(--fg-2);
  font-variant-numeric: tabular-nums;
}

/* Beli */
.beli {
  background: var(--surface);
  color: var(--fg);
  margin-inline: var(--gutter);
  padding: clamp(20px, 3.4vw, 48px) clamp(16px, 3vw, 44px) clamp(24px, 3.4vw, 52px);
}

.beli .section-head .count {
  color: var(--fg);
}

.beli .section-head a {
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 4px;
}

.beli-list {
  display: grid;
  column-gap: var(--gutter);
  counter-reset: beli;
}

.beli-list li {
  display: grid;
  grid-template-columns: clamp(56px, 6vw, 88px) 1fr auto;
  align-items: center;
  gap: clamp(10px, 1.6vw, 16px);
  padding-block: 14px;
  border-bottom: 1px solid var(--line);
  counter-increment: beli;
}

.beli-list li::before {
  content: counter(beli, decimal-leading-zero);
  font-size: clamp(28px, 3.2vw, 48px);
  font-weight: 800;
  letter-spacing: -0.05em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--red);
}

.beli-list h3 {
  font-size: clamp(18px, 1.7vw, 24px);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.15;
}

.beli-list p {
  font-size: 14px;
  color: var(--fg-2);
}

.beli-score {
  display: grid;
  place-items: center;
  width: clamp(44px, 4vw, 52px);
  height: clamp(44px, 4vw, 52px);
  background: var(--bg-2);
  color: var(--ink);
  font-weight: 700;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}

@media (min-width: 900px) {
  .beli-list {
    grid-template-columns: 1fr 1fr;
    grid-auto-flow: column;
    grid-template-rows: repeat(5, auto);
  }
}

/* Toolkit: compact rows, icon beside the name */
.tools {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr));
  gap: 8px;
}

.tool {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px;
  background: var(--bg-2);
}

.tool__icon {
  flex: none;
  width: 40px;
  aspect-ratio: 1;
  --ph-bg: var(--tool-bg);
  --ph-fg: var(--tool-fg);
}

.tool__icon[data-ph]::before {
  content: attr(data-abbr);
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.03em;
  text-transform: none;
}

.tool__icon[data-ph]::after {
  display: none;
}

.tool__name {
  font-size: 15px;
  overflow-wrap: break-word;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

.tool__use {
  font-size: 13px;
  line-height: 1.3;
  color: var(--fg-2);
  margin-top: 2px;
}

/* Motion preferences --------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* Small screens ------------------------------------------------------------ */
@media (max-width: 520px) {
  .site-nav a { padding: 8px 9px; }
  .legal { flex-direction: column; }
}

/* Education follows Experience directly */
.about-section--tight {
  padding-top: 0;
}

.pp-summary strong {
  font-weight: 600;
  color: var(--fg);
}

/* straight after the stats, the first section doesn't need its extra lead-in */
.pp-stats + .eyebrow {
  margin-top: 0;
}

/* Case study blocks: headings, captions, before/after ------------------ */
.pp-block {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.pp-cap {
  font-size: 0.875rem;
  line-height: 1.45;
  color: color-mix(in srgb, var(--on-accent) 78%, transparent);
  max-width: 60ch;
}

/* "more coming soon": an empty frame the size of a board, drawn in the
   block's own on-colour so it sits quietly under the real work */
.pp-soon {
  aspect-ratio: var(--ratio);
  max-width: 100%;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  border: 1px dashed color-mix(in srgb, var(--on-accent) 55%, transparent);
  color: var(--on-accent);
  text-align: center;
}

.pp-soon__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid color-mix(in srgb, var(--on-accent) 55%, transparent);
}

.pp-soon__icon .icon {
  width: 22px;
  height: 22px;
}

.pp-soon__title {
  margin: 0;
  font-size: clamp(1.125rem, 1.6vw, 1.5rem);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.pp-sec {
  padding-top: calc(var(--gutter) * 0.75);
}

.pp-sec__eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--on-accent) 70%, transparent);
}

.pp-sec__title {
  margin-top: 4px;
  font-size: clamp(1.25rem, 1.6vw, 1.625rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.pp-zoom {
  cursor: zoom-in;
}

/* drag slider: the before image is clipped to the handle's position */
.cmp {
  --pos: 50%;
  position: relative;
  aspect-ratio: var(--ratio, 16 / 9);
  overflow: hidden;
  user-select: none;
}

.cmp img,
.cmp__before {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cmp__before {
  clip-path: inset(0 calc(100% - var(--pos)) 0 0);
}

.cmp__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--pos);
  width: 2px;
  margin-left: -1px;
  background: #fff;
  box-shadow: 0 0 0 1px rgb(22 21 20 / 0.15);
  pointer-events: none;
}

.cmp__handle::after {
  content: "\2194";
  position: absolute;
  top: 50%;
  left: 50%;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--shade);
  color: #fff;
  font-size: 18px;
  transform: translate(-50%, -50%);
  box-shadow: 0 4px 14px rgb(0 0 0 / 0.25);
}

.cmp__tag {
  position: absolute;
  bottom: 12px;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--shade);
  color: #fff;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  pointer-events: none;
}

.cmp__tag--b { left: 12px; }
.cmp__tag--a { right: 12px; }

.cmp__range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: ew-resize;
  -webkit-appearance: none;
  appearance: none;
}

.cmp:has(.cmp__range:focus-visible) .cmp__handle::after {
  outline: 2px solid #fff;
  outline-offset: 3px;
}

/* tabs: when before and after differ in size, flip between them */
.tabs__top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.tabs__label {
  font-size: 0.9375rem;
  font-weight: 600;
}

.tabs__bar {
  display: inline-flex;
  padding: 3px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--on-accent) 10%, transparent);
}

.tabs__bar button {
  padding: 6px 14px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: inherit;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}

.tabs__bar button[aria-selected="true"] {
  background: var(--shade);
  color: #fff;
}

.tabs__stage {
  display: grid;
}

.tabs__stage > img {
  grid-area: 1 / 1;
  justify-self: center;
  align-self: start;
  max-width: 100%;
  max-height: 78svh;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s, visibility 0.25s;
}

.tabs__stage > img.is-on {
  opacity: 1;
  visibility: visible;
}

/* click to zoom */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  overflow: auto;
  padding: 48px 16px;
  background: rgb(22 21 20 / 0.92);
  cursor: zoom-out;
  overscroll-behavior: contain;
}

.lightbox img {
  display: block;
  width: auto;
  max-width: min(100%, 1600px);
  height: auto;
  margin: 0 auto;
}

.lightbox__close {
  position: fixed;
  top: 12px;
  right: 12px;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  color: var(--shade);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

/* a little extra air between groups of boards */
.pp-gap {
  height: calc(var(--gutter) * 0.5);
}

/* pan covers: the screen sits low and runs off the bottom edge, then
   slides up a little on hover */
.card .media.pan {
  position: relative;
  overflow: hidden;
  background: var(--pan-bg);
}

.pan__in {
  position: absolute;
  top: var(--pan-top);
  left: 50%;
  display: flex;
  gap: 4%;
  width: var(--pan-w);
  transform: translate(-50%, 0);
  transition: transform 0.7s var(--ease-out);
}

.card .media.pan .pan__in > img {
  position: static;
  flex: 1 1 0;
  min-width: 0;
  width: 100%;
  height: auto;
  object-fit: fill;
  align-self: flex-start;
  /* the global reset squares every corner; covers opt back in */
  border-radius: var(--pan-r) var(--pan-r) 0 0 !important;
  filter: drop-shadow(0 24px 40px rgb(0 0 0 / 0.35));
  transform: none;
}

.card:hover .media.pan .pan__in,
.card:focus-visible .media.pan .pan__in {
  transform: translate(-50%, -6%);
}

@media (prefers-reduced-motion: reduce) {
  .pan__in { transition: none; }
}

/* switch: one board, several states, flipped with a small pill switch that
   sits in the board's top-right corner, level with its heading */
.sw {
  container-type: inline-size;
  position: relative;
  aspect-ratio: var(--ratio);
  background: #fff;
}

.sw > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.3s var(--ease-out);
}

.sw > img.is-on {
  opacity: 1;
}

.sw__bar {
  position: absolute;
  /* boards keep 5% padding on every side; the switch sits in the right
     padding line, its bottom level with the heading's baseline */
  top: 9.5cqi;
  right: 5cqi;
  transform: translateY(-100%);
  display: flex;
  gap: 2px;
  padding: clamp(2px, 0.4cqi, 3px);
  background: #efefec;
}

.sw__bar button {
  padding: 0.45em 1em;
  border: 0;
  background: none;
  color: #5d5d59;
  font: inherit;
  font-size: clamp(8px, 1.6cqi, 13px);
  font-weight: 600;
  letter-spacing: 0.04em;
  cursor: pointer;
}

/* same motion as the nav: an ink block rises from the bottom behind the
   label, and the label turns white */
.sw__bar button {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: color 0.2s var(--ease-hover);
}

.sw__bar button::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgb(22 21 20 / 0.1);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.2s var(--ease-hover);
}

.sw__bar button[aria-pressed="true"] {
  color: #fff;
}

/* as in the nav: hover is a light tint, the selected option is ink */
.sw__bar button:hover::before {
  transform: scaleY(1);
}

.sw__bar button[aria-pressed="true"]::before {
  transform: scaleY(1);
  background: #161514;
}

.sw__bar button {
  color: #161514;
  font-weight: 500;
  letter-spacing: 0;
}

.sw__bar button:focus-visible {
  outline: 2px solid #161514;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .sw > img { transition: none; }
}

/* a plain colour block in place of a cover image */
.card .media.solid {
  background: var(--solid);
}

/* on narrow cards a full desktop screen gets too small to read: show it
   larger, anchored to its left edge, so the sidebar and main content fill
   the frame */
.card .media.pan {
  container-type: inline-size;
}

@container (max-width: 520px) {
  .pan--screen .pan__in {
    left: 8%;
    width: 150%;
    transform: none;
  }

  .card:hover .pan--screen .pan__in,
  .card:focus-visible .pan--screen .pan__in {
    transform: translateY(-6%);
  }
}

/* a card with no image: just its colour, with the title sitting at the bottom */
.card--bare {
  display: flex;
  flex-direction: column;
}

.card--bare .card__bottom {
  margin-top: auto;
}

/* Playground: a scrolling gallery, images first, very little text --------- */
.pg {
  max-width: 1360px;
  margin: 0 auto;
  padding: calc(var(--gutter) + 8px) var(--gutter) calc(var(--gutter) * 2);
}

.pg-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.pg-intro {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px 40px;
  margin: clamp(48px, 9vw, 120px) 0 clamp(40px, 6vw, 80px);
}

.pg-title {
  font-size: clamp(3.5rem, 13vw, 11rem);
  line-height: 0.85;
  letter-spacing: -0.04em;
  color: var(--red);
}

.pg-intro p {
  max-width: 100%;
  color: var(--fg-2);
  font-size: 0.95rem;
  line-height: 1.45;
}

.pg-group + .pg-group {
  margin-top: clamp(56px, 8vw, 112px);
}

.pg-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 12px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--line);
}

.pg-head h2 {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.pg-head p {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-2);
  text-align: right;
}

/* justified rows: every image in a row shares one height, widths follow
   each image's own proportions */
.pg-row {
  display: flex;
  gap: 14px;
}

.pg-row + .pg-row {
  margin-top: 14px;
}

.pg-item {
  flex: calc(var(--w) / var(--h)) 1 0;
  min-width: 0;
}

.pg-item img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: var(--w) / var(--h);
}

.pg-pager {
  margin-top: clamp(64px, 9vw, 120px);
}

@media (max-width: 640px) {
  .pg-row {
    gap: 8px;
  }

  .pg-row + .pg-row {
    margin-top: 8px;
  }

  .pg-head {
    flex-direction: column;
    gap: 2px;
  }

  .pg-head p {
    text-align: left;
  }
}

.pg-pager {
  --space: 1;
}

@media (max-width: 700px) {
  /* clear the nav */
  .pg-top {
    margin-top: 56px;
  }
}

/* About: one narrow, newspaper-style column with small, skimmable type -- */
.ab {
  max-width: 1000px;
  margin: 0 auto;
  padding: calc(var(--gutter) * 4) var(--gutter) calc(var(--gutter) * 3);
  font-size: 15px;
}

.ab-name {
  font-size: clamp(2.5rem, 7vw, 3.75rem);
  line-height: 0.95;
  letter-spacing: -0.03em;
}

.ab-intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 22%;
  align-items: end;
  gap: 40px;
}

.ab-name {
  margin-bottom: 18px;
}

.ab-copy p {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--fg-2);
}

.ab-copy .ab-lead {
  font-size: 1.15rem;
  line-height: 1.45;
  font-weight: 600;
  color: var(--fg);
}

.ab-copy p + p {
  margin-top: 12px;
}

.ab .ab-photo {
  width: 100%;
  aspect-ratio: 1 / 1;
}

.ab-sec {
  margin-top: 40px;
}

.ab-label {
  padding-bottom: 8px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--line);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* experience and education: compact rows */
.ab .exp {
  gap: 14px;
  padding: 14px 0;
}

.ab .exp__logo {
  width: 40px;
  height: 40px;
  padding: 0;
  overflow: hidden;
  font-size: 14px;
  box-shadow: inset 0 0 0 1px var(--line);
}

.ab .exp__logo > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ab .exp__company {
  font-size: 1rem;
}

.ab .exp__role {
  font-size: 0.85rem;
  margin-top: 2px;
}

.ab .exp__year {
  font-size: 0.8rem;
}

/* toolkit: two tidy columns */
.ab .tools {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-top: 12px;
}

.ab .tool {
  padding: 10px;
}

.ab .tool__name {
  font-size: 0.875rem;
}

.ab .tool__use {
  font-size: 0.75rem;
}

/* eating list: a plain numbered list */
.ab .beli-list {
  grid-template-columns: 1fr;
  grid-auto-flow: row;
  grid-template-rows: none;
  gap: 0;
  margin-top: 0;
}

.ab .beli-list li {
  grid-template-columns: 32px 1fr auto;
  gap: 12px;
}

.ab .beli-score {
  width: 34px;
  height: 34px;
  font-size: 0.8rem;
}

.ab .exp__logo[data-ph]::before {
  font-size: 15px;
}

.ab .beli-list li {
  padding: 10px 0;
}

.ab .beli-list li::before {
  font-size: 0.85rem;
  min-width: 2ch;
}

.ab .beli-list h3 {
  font-size: 0.95rem;
}

.ab .beli-list p {
  font-size: 0.8rem;
}

@media (max-width: 560px) {
  .ab {
    padding-top: 104px;
  }

  .ab-intro {
    grid-template-columns: 1fr;
    gap: 24px;
  }

  .ab .ab-photo {
    order: -1;
    width: 60%;
  }

  .ab .tools {
    grid-template-columns: 1fr;
  }
}

@media (min-width: 900px) {
  .ab .tools {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* keeps each card the height it had with a 4:3 cover image */
.card .card__space {
  background: none;
}

/* About: no rules between list items */
.ab .exp-list li,
.ab .beli-list li {
  border: 0;
}

/* eating list: two columns of five, numbered down each column */
.ab .beli-list {
  grid-template-columns: 1fr;
  column-gap: 40px;
}

@media (min-width: 700px) {
  .ab .beli-list {
    grid-template-columns: 1fr 1fr;
    grid-auto-flow: column;
    grid-template-rows: repeat(5, auto);
  }
}

.ab .beli-list li {
  grid-template-columns: 32px 1fr;
  align-items: start;
}

.ab .beli-list h3 a {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 3px;
  transition: text-decoration-color 0.2s var(--ease-hover);
}

.ab .beli-list h3 a:hover {
  text-decoration-color: currentColor;
}


/* Home hero: the drifting diagonal lines are switched off */
.hero__bars {
  display: none;
}

/* Home card previews: the project's hero, tinted to the card colour; it
   shows in its true colours on hover */
.card .card__cover {
  position: relative;
  overflow: hidden;
  background: var(--accent);
}

.card .card__cover > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card .card__tint {
  filter: grayscale(1) contrast(0.9);
  mix-blend-mode: luminosity;
  /* how strongly the preview shows through the card colour (lower = lighter
     on a white card) */
  opacity: var(--tint, 0.85);
}

.card .card__true {
  opacity: 0;
  transition: opacity 0.3s var(--ease-hover), transform 0.3s var(--ease-hover);
}

.card:hover .card__true,
.card:focus-visible .card__true {
  opacity: 1;
}

/* Mobile nav: the logo and a menu button; the links drop down below ------ */
.nav-toggle {
  display: none;
}

@media (max-width: 699px) {
  .nav-toggle {
    display: inline-grid;
    place-items: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 0;
    background: var(--ink);
    color: var(--paper);
    font-size: 24px;
    cursor: pointer;
  }

  /* block-level so the icon sits dead centre, not on a text baseline */
  .nav-toggle__open,
  .nav-toggle .icon {
    display: block;
  }

  .nav-toggle__close,
  .site-header.is-open .nav-toggle__open {
    display: none;
  }

  .site-header.is-open .nav-toggle__close {
    display: block;
  }

  /* on phones the nav sits in the top right corner */
  .site-header {
    left: auto;
    right: var(--gutter);
    transform: none;
  }

  .pp-panel__top {
    margin-top: 56px;
  }

  .site-nav {
    position: absolute;
    top: calc(100% + 6px);
    right: -1px;
    flex-direction: column;
    gap: 2px;
    min-width: 180px;
    padding: 5px;
    background: var(--bg);
    border: 1px solid var(--line);
    box-shadow: 0 12px 30px rgb(22 21 20 / 0.12);
    visibility: hidden;
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity 0.2s var(--ease), transform 0.2s var(--ease), visibility 0s 0.2s;
  }

  .site-header.is-open .site-nav {
    visibility: visible;
    opacity: 1;
    transform: none;
    transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
  }

  .site-nav a {
    padding: 12px 14px;
    font-size: 16px;
  }

  /* previous / next project stays docked at the bottom of the screen */
  .pp-pager {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    margin: 0;
    padding: 12px var(--gutter) calc(12px + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--bg) 85%, transparent);
    -webkit-backdrop-filter: blur(18px) saturate(1.4);
    backdrop-filter: blur(18px) saturate(1.4);
    border-top: 1px solid var(--line);
    font-size: 14px;
  }

  main.pp,
  main.pg {
    padding-bottom: calc(76px + env(safe-area-inset-bottom));
  }
}

/* inline screen recordings in a case study */
.pp-video {
  background: #121316;
}

.pp-video video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.pp-video {
  position: relative;
}

.pp-video__full {
  position: absolute;
  right: 14px;
  bottom: 14px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: rgb(255 255 255 / 0.92);
  color: var(--ink);
  font-size: 24px;
  cursor: pointer;
  transition: transform 0.2s var(--ease-hover);
}

.pp-video__full:hover {
  transform: scale(1.06);
}

.pp-video__full .icon {
  display: block;
}

/* in full screen, show the whole frame */
.pp-video video:fullscreen {
  object-fit: contain;
  background: #121316;
}

/* film grain over the home card previews; it eases away on hover */
.card .card__cover::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.5 0 0 0 0 0.5 0 0 0 0 0.5 0 0 0 1.6 -0.3'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
  mix-blend-mode: overlay;
  opacity: 0.25;
  transition: opacity 0.6s var(--ease);
}

.card:hover .card__cover::after,
.card:focus-visible .card__cover::after {
  opacity: 0;
}

/* tablets and phones: the stacked project panel uses the full width */
@media (max-width: 899px) {
  .pp-lede,
  .pp-summary {
    max-width: none;
  }
}

/* the preview's true colours fade in slowly on hover (this selector beats
   the generic `.card .media > img` transition, which only covered scale) */
.card .card__cover > img.card__true {
  transition: opacity 0.3s var(--ease-hover), transform 0.3s var(--ease-hover);
}

.card .card__cover::after {
  transition: opacity 0.3s var(--ease-hover);
}


/* Arrow buttons, everywhere: the box never moves or changes colour; on
   hover the arrow nudges a few pixels the way it points */
.arrow-box .icon,
.legal a .icon {
  transition: transform 0.25s var(--ease-hover);
}

.card:hover .arrow-box .icon,
.card:focus-visible .arrow-box .icon {
  transform: translate(3px, -3px);
}

.pp-back:hover .arrow-box .icon,
.pp-next--prev:hover .arrow-box .icon {
  transform: translateX(-3px);
}

.pp-next:not(.pp-next--prev):hover .arrow-box .icon {
  transform: translateX(3px);
}

.legal a:hover .icon {
  transform: translateY(-2px);
}

/* the copyright line is part of the white contact block */
.site-footer {
  background: var(--surface);
}

.legal {
  background: var(--surface);
  padding-top: 0;
  padding-bottom: calc(var(--gutter) + 4px);
}

/* Nav stows away into a small handle once the page is scrolled, and grows
   back into the full bar when the pointer is over it (main.js). The bar is
   solid, with no backdrop blur: re-blurring the
   moving page behind it every frame is what made the morph choppy. The
   surface (::before) and the handle (::after, the stroke's colour) shrink together using
   transform and opacity only, which stay on the GPU. main.js sets --sx/--sy
   to the handle's size as a fraction of the bar. Desktop and tablet only. */
@media (min-width: 700px) {
  .site-header {
    --morph: var(--ease-hover);
    background: none;
    border: 0;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    padding: 6px;
  }

  .site-header::before,
  .site-header::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    transform-origin: 50% 0;
    transform: translateZ(0);
    transition: transform 0.35s var(--morph), opacity 0.3s var(--morph);
    will-change: transform, opacity;
  }

  .site-header::before {
    background: var(--bg);
    border: 1px solid var(--line);
  }

  .site-header::after {
    background: var(--line);
    opacity: 0;
  }

  .site-header > * {
    transition: opacity 0.2s var(--ease-hover) 0.1s;
  }

  .site-header.is-stowed::before,
  .site-header.is-stowed::after {
    transform: scale(var(--sx, 0.15), var(--sy, 0.12)) translateZ(0);
  }

  .site-header.is-stowed::after {
    opacity: 1;
  }

  .site-header.is-stowed > * {
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.1s var(--ease-hover);
  }
}

@media (min-width: 700px) and (prefers-reduced-motion: reduce) {
  .site-header::before,
  .site-header::after,
  .site-header > * {
    transition: none;
  }
}
