/* ============================================================
   Natnael Ashebir — portfolio
   Editorial, scroll-driven layout. Fixed chrome, one live stage.
   ============================================================ */

:root {
  --bg: #ececec;
  --ink: #111112;
  --ink-soft: #6f6f72;
  --ink-faint: #b6b6b8;
  --line: #d3d3d4;
  --accent: #2b59ff;                  /* the one accent colour */
  --black: #0b0b0c;

  /* Surfaces the two themes paint differently. */
  --paper: #fff;                       /* loader */
  --ghost: #fbfbfb;                    /* the huge pale words on about / contact */
  --ghost-ink: rgba(17, 17, 18, .17);
  --count-a: #a3b8ff;                  /* the big work counter: light blue, fading down */
  --count-b: #d3ddff;
  --shot: #e2e2e2;                     /* image placeholder while loading */
  --shadow: rgba(0, 0, 0, .5);
  --haze: 236, 236, 239;               /* ribbon fade, as r, g, b for the canvas */
  --tile: #dcdce1;                     /* ribbon tile before its image lands */
  color-scheme: light;

  --pad: 28px;
  --topbar: 118px;
  --sans: "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --serif: "Instrument Serif", "Times New Roman", Times, serif;

  --ease: cubic-bezier(.22, 1, .36, 1);
}

html[data-theme="dark"] {
  --bg: #0e0e0f;
  --ink: #ececec;
  --ink-soft: #8d8d91;
  --ink-faint: #4b4b4f;
  --line: #2a2a2d;
  --paper: #0b0b0c;
  --ghost: #18181a;
  --ghost-ink: rgba(236, 236, 236, .12);
  --count-a: rgba(160, 185, 255, .7);
  --count-b: rgba(160, 185, 255, .3);
  --shot: #1a1a1c;
  --shadow: rgba(0, 0, 0, .9);
  --haze: 14, 14, 15;
  --tile: #1e1e21;
  --accent: #4f7bff;                  /* a touch lighter so it holds up on black */
  color-scheme: dark;
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.45;
  letter-spacing: -0.01em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background-color .4s var(--ease), color .4s var(--ease);
}

body.is-locked { overflow: hidden; }

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
[hidden] { display: none !important; }

::selection { background: var(--accent); color: #fff; }

/* ============================================================
   Intro loader
   ============================================================ */
.loader {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  background: var(--paper);
  overflow: hidden;
}
/* the same heavy sans as the page-change titles, one reel per letter */
.loader-name {
  position: relative;
  margin: 0;
  font-weight: 700;
  color: var(--accent);
  font-size: clamp(44px, 8.5vw, 140px);
  line-height: .9;
  letter-spacing: -0.06em;
  text-align: center;
  display: grid;
  justify-items: center;
}
.loader-name > span { display: block; white-space: nowrap; }
.loader-name > span:nth-child(2) { --d: .1s; }

@keyframes nameUp { to { opacity: 1; transform: none; } }

/* Roller: each letter is a short reel of random letters that spins up and
   lands on the real one, left to right, like a slot machine settling.
   Only the last letter takes up width; the spinning ones overflow centred. */
.reel {
  display: inline-block;
  height: 1em;
  line-height: 1;
  overflow: hidden;
  vertical-align: top;
}
.reel-in {
  display: flex;
  flex-direction: column;
  /* capped, so even a long title settles quickly (the page change waits for it) */
  animation: reelSpin calc(.45s + min(var(--i), 12) * 12ms) cubic-bezier(.3, 0, 0, 1) calc(var(--d, 0s) + min(var(--i), 12) * 18ms) both;
}
.reel-in > span { display: block; height: 1em; }
.reel-in > span:not(:last-child) { width: 0; align-self: center; display: flex; justify-content: center; }
.reel-gap { display: inline-block; width: .28em; }
@keyframes reelSpin { from { transform: translateY(0); } to { transform: translateY(calc(var(--n) * -1em)); } }

/* first visit: photo, name and a line of bio before the site opens */
.loader.is-intro { cursor: pointer; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; touch-action: none; }
.loader.is-held { cursor: grabbing; }
.intro {
  display: grid;
  justify-items: center;
  gap: clamp(14px, 2.6vh, 28px);
  padding: 0 16px;
  text-align: center;
}
.is-intro .loader-name { font-size: clamp(40px, 7vw, 104px); }
.is-intro .loader-name > span { --d: .25s; }
.is-intro .loader-name > span:nth-child(2) { --d: .38s; }
.intro-pic {
  position: relative;
  margin: 0;
  width: clamp(104px, 17vh, 170px);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--ghost);
  opacity: 0;
  transform: scale(.82);
  transition: opacity .7s var(--ease), transform 1s var(--ease);
}
.intro-pic.in { opacity: 1; transform: none; }
.intro-pic img { position: absolute; filter: grayscale(1) contrast(1.1); }
/* the same blue print as hovering the photo on About, arriving near the end */
.intro-pic::after {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--accent) 50%, #fff);
  mix-blend-mode: multiply;
  opacity: 0;
  animation: introFade .9s 2.4s var(--ease) forwards;
}
.intro-bio {
  margin: 0;
  max-width: 44ch;
  font-size: clamp(15px, 2.1vh, 19px);
  line-height: 1.45;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.intro-bio span {
  display: inline-block;
  opacity: 0;
  transform: translateY(.45em);
  animation: nameUp .6s var(--ease) forwards;
  animation-delay: calc(.85s + var(--i) * 32ms);
}
.intro-skip {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 26px;
  text-align: center;
  font-size: 12px;
  color: var(--ink-soft);
  opacity: 0;
  animation: introFade .6s 1.8s forwards;
}
.intro-bar {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  animation: introBar var(--d) linear forwards;
}
@keyframes introFade { to { opacity: 1; } }
@keyframes introBar { to { transform: scaleX(1); } }

.loader.done { animation: loaderOut .75s .35s var(--ease) forwards; }
@keyframes loaderOut {
  to { transform: translateX(-101%); visibility: hidden; }
}

/* ============================================================
   Page transition wipe
   ============================================================ */
.wipe {
  --wave: 12vh;
  position: fixed;
  inset: 0;
  z-index: 150;
  background: var(--accent);
  display: grid;
  place-items: center;
  /* parked below the screen, wave and all */
  transform: translateY(calc(100% + var(--wave) + 2px));
  pointer-events: none;
}
.wipe.in  { animation: wipeIn .62s cubic-bezier(.7, 0, .3, 1) forwards; }
.wipe.out { animation: wipeOut .62s cubic-bezier(.7, 0, .3, 1) forwards; }
@keyframes wipeIn  { from { transform: translateY(calc(100% + var(--wave) + 2px)); } to { transform: none; } }
@keyframes wipeOut { from { transform: none; } to { transform: translateY(calc(-100% - var(--wave) - 2px)); } }

/* A wave rides the panel's edge: on the top as it rolls up over the page,
   on the bottom as it rolls on and off the top. Each is a strip of sine
   twice the screen wide, sliding sideways so the crests travel. */
.wipe-wave {
  position: absolute;
  left: 0;
  width: 200%;
  height: var(--wave);
  fill: var(--accent);
}
.wipe-wave.top { bottom: calc(100% - 1px); }
.wipe-wave.bottom { top: calc(100% - 1px); transform: scaleY(-1); }
.wipe.run .wipe-wave { animation: waveRoll 1.1s linear infinite; }
@keyframes waveRoll { to { translate: -50% 0; } }

/* the destination, rising in letter by letter */
.wipe-label { position: relative; z-index: 1; display: grid; justify-items: center; gap: 10px; text-align: center; }
.wipe-num { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: rgba(255, 255, 255, .7); }
.wipe-name {
  margin: 0;
  display: flex;
  overflow: hidden;
  padding: 0 .05em .06em;
  font-size: clamp(44px, 8.5vw, 140px);
  font-weight: 700;
  line-height: .9;
  letter-spacing: -0.06em;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
}
.wipe-name { --d: .5s; }   /* the letters start rolling once the wave has nearly covered the screen */
.wipe.run .wipe-num { animation: wipeNum .5s var(--ease) .15s both; }
@keyframes wipeNum { from { opacity: 0; transform: translateY(6px); } }

/* Opening a project from the work page: blue squares pop in at random,
   the name rolls in, then they pop out. See openProject() in main.js. */
.ofx {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: grid;
  place-items: center;
  overflow: hidden;
  pointer-events: none;
}
.ofx-grid {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(var(--cols), var(--size));
  grid-auto-rows: var(--size);
}
.ofx-grid i { background: var(--accent); transform: scale(0); }
.ofx.in .ofx-grid i { animation: pixIn .3s calc(var(--r) * .4s) steps(3) forwards; }
.ofx.out .ofx-grid i { transform: scale(1.02); animation: pixOut .3s calc(var(--r) * .4s) steps(3) forwards; }
@keyframes pixIn { from { transform: scale(0); } to { transform: scale(1.02); } }
@keyframes pixOut { from { transform: scale(1.02); } to { transform: scale(0); } }

.ofx-label { position: relative; z-index: 2; display: grid; justify-items: center; gap: 10px; text-align: center; opacity: 0; }
.ofx.in .ofx-label { opacity: 1; }
.ofx.out .ofx-label { opacity: 0; transition: opacity .25s; }
.ofx-cat { font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: rgba(255, 255, 255, .75); }
.ofx.in .ofx-cat { animation: wipeNum .5s var(--ease) .35s both; }
.ofx-name {
  --d: .45s;
  margin: 0;
  display: flex;
  overflow: hidden;
  padding: 0 .05em .06em;
  font-size: clamp(44px, 8.5vw, 140px);
  font-weight: 700;
  line-height: .9;
  letter-spacing: -0.06em;
  color: #fff;
  white-space: nowrap;
}

/* ============================================================
   Fixed chrome
   ============================================================ */
.chrome {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  padding: var(--pad) var(--pad) 0;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 24px;
  align-items: center;
  pointer-events: none;
}
.chrome > * { pointer-events: auto; }

/* --- icons: Hugeicons from the sprite in index.html --- */
.hi {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -0.22em;
}
/* the "go" arrow: on hover it flies out of the corner and comes back in from
   the opposite one, like it went somewhere */
.hi-go { overflow: hidden; }
a:hover > .hi-go, a:focus-visible > .hi-go { animation: hiGo .55s var(--ease); }
@keyframes hiGo {
  0%   { transform: none; }
  45%  { transform: translate(70%, -70%); opacity: 0; }
  46%  { transform: translate(-70%, 70%); opacity: 0; }
  100% { transform: none; opacity: 1; }
}

/* --- wordmark: portrait + name, doubling as a live "is he online" status --- */
.brand-wrap { position: relative; z-index: 30; justify-self: start; display: inline-flex; align-items: flex-start; }
.brand {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  line-height: 1;
}
.brand-ava { position: relative; display: block; flex: none; }
.brand img {
  display: block;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.2);
  background: var(--ghost);
  transform: scale(var(--beat, 1));
  transition: opacity .6s;
}
/* status dot on the portrait's corner: blue while online, with a ripple that
   leaves it on every heartbeat; grey and still offline. Driven from main.js */
.brand-ava::before,
.brand-ava::after {
  content: "";
  position: absolute;
  right: -1px; bottom: -1px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--accent);
  pointer-events: none;
  transition: background .6s;
}
.brand-ava::before { box-shadow: 0 0 0 2px var(--bg); z-index: 1; }
.brand-ava::after { transform: scale(var(--ripple, 1)); opacity: var(--ripple-o, 0); }

.brand-name {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
  white-space: nowrap;
  transition: color .2s;
}
.brand:hover .brand-name { color: var(--accent); }

/* the status, set like the little numbers beside the menu items; it's also
   the button that opens the card, so it works without hover (phones) */
.brand-state {
  margin: 5px 0 0 5px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: .02em;
  line-height: 1;
  color: var(--accent);
  cursor: pointer;
  white-space: nowrap;
  transition: color .6s;
}
.brand-state i { font-style: normal; opacity: .6; transition: opacity .2s; }
.brand-state:hover i, .brand-wrap.is-open .brand-state i { opacity: 1; text-decoration: underline; text-underline-offset: 2px; }

/* offline: the ring goes quiet and grey, the portrait fades a little */
.brand:not([data-presence="online"]) .brand-ava::before { background: var(--ink-faint); }
.brand-wrap:not([data-presence="online"]) .brand-state { color: var(--ink-soft); }
.brand[data-presence="offline"] img { opacity: .6; }

/* the hover card: drops in under the wordmark and stays while the cursor
   travels down into it (its top padding bridges the gap), so the DM link
   is reachable */
.brand-tip {
  position: absolute;
  left: -8px; top: 100%;
  padding-top: 12px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .25s, transform .35s var(--ease), visibility 0s .25s;
}
.brand-tip:empty { display: none; }
.brand-card {
  display: grid;
  gap: 10px;
  width: max-content;
  max-width: 240px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--ink);
  color: var(--bg);
  font-size: 11.5px;
  line-height: 1.4;
}
.brand-card b { font-weight: 600; }
.brand-card { gap: 12px; min-width: 230px; }
/* the way to reach him: an X row — logo tile, handle, and a go arrow */
.brand-dm {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 -6px -6px;
  padding: 7px 10px 7px 7px;
  border-radius: 9px;
  background: color-mix(in srgb, var(--bg) 10%, transparent);
  transition: background .25s;
}
.brand-dm:hover { background: color-mix(in srgb, var(--bg) 18%, transparent); }
.brand-dm-x {
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border-radius: 8px;
  background: var(--bg);
  color: var(--ink);
  transition: transform .4s var(--ease);
}
.brand-dm:hover .brand-dm-x { transform: rotate(-8deg) scale(1.06); }
.brand-dm-x .hi { width: 16px; height: 16px; }
.brand-dm-t { display: grid; gap: 2px; flex: 1; }
.brand-dm-t b { font-weight: 600; }
.brand-dm-t small { font-size: 10.5px; opacity: .55; }
.brand-dm .hi-go { width: 17px; height: 17px; opacity: .8; }

@media (hover: hover) {
  .brand-wrap:hover .brand-tip { opacity: 1; visibility: visible; transform: none; transition: opacity .25s, transform .35s var(--ease), visibility 0s; }
}
.brand-wrap.is-open .brand-tip,
.brand-wrap:focus-within .brand-tip {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity .25s, transform .35s var(--ease), visibility 0s;
}

/* --- menu: one row, numbered, an accent dot under the current page --- */
.nav { position: relative; justify-self: center; }
.nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 26px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
}
.nav-list a { display: inline-block; transition: color .25s; }
.nav-list sup {
  margin-left: 3px;
  font-size: 8px;
  font-weight: 400;
  letter-spacing: .02em;
  color: var(--ink-soft);
  vertical-align: 5px;
  transition: color .25s;
}
.nav-list a:hover, .nav-list a.on { color: var(--accent); }
.nav-list a:hover sup, .nav-list a.on sup { color: var(--accent); }
.nav-dot {
  position: absolute;
  left: -2.5px;
  top: 0;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  pointer-events: none;
}
.nav-dot.is-on { opacity: 1; }
.nav-dot.ready { transition: transform .55s var(--ease), opacity .3s; }

/* --- clock: one quiet line, beside the theme switch --- */
.clock { font-size: 12px; color: var(--ink-soft); white-space: nowrap; }
.clock b { font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; }

/* --- right side --- */
.inquiries {
  justify-self: end;
  display: flex;
  gap: 14px;
  align-items: center;
  font-size: 12px;
}

/* --- the call button, on every page --- */
.book-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: center;
  height: 44px;
  padding: 0 20px;
  border-radius: 0;
  background: var(--accent);
  color: #fff;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: transform .3s var(--ease), opacity .25s;
}
.book-cta .hi { width: 1.2em; height: 1.2em; }
.book-cta .hi-go { margin-left: 2px; }
.book-cta:hover { opacity: .9; }

/* the top-bar copy is only for project pages; the others carry their own */
body:not(.on-project) .chrome .book-cta { display: none; }
.cta-work { position: absolute; right: calc(40px + 348px / 2); transform: translateX(50%); bottom: 48px; z-index: 5; height: 44px; padding: 0 20px; font-size: 15px; }
.cta-about { margin-top: 18px; }
.cta-work-m { margin: 0 0 22px; justify-self: start; }

/* the phone version of the work page: a plain stacked list */
.work-m { padding: calc(var(--topbar) + 12px) var(--pad) 12vh; display: grid; grid-template-columns: minmax(0, 1fr); }
.work-m > * { min-width: 0; }
.work-m-head { display: flex; justify-content: space-between; margin-bottom: 14px; font-size: 11px; color: var(--ink-soft); }
.wm-card { display: grid; gap: 6px; padding: 0 0 34px; }
.wm-card img { display: block; width: 100%; max-width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; background: var(--shot); margin-bottom: 8px; }
.wm-card .w-cat { font-size: 11px; color: var(--ink-soft); }
.wm-card .w-title { margin: 0; font-size: 26px; font-weight: 600; line-height: 1; letter-spacing: -0.045em; text-transform: uppercase; }
.wm-card .w-rule { margin: 6px 0; }
.wm-card .w-desc { margin: 0; max-width: none; font-size: 13px; color: var(--ink-soft); }
.about-right { margin-left: auto; display: grid; justify-items: start; }
.play-foot {
  position: fixed;
  left: var(--pad);
  bottom: calc(var(--pad) + 26px);
  width: 210px;
  display: grid;
  justify-items: start;
  gap: 14px;
}
.play-foot .play-note { position: static; }

/* --- light / dark switch --- */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--ink-soft);
  transition: color .25s;
}
.theme-toggle:hover { color: var(--ink); }
.tt-ico { position: relative; display: inline-grid; width: 15px; height: 15px; }
.tt-ico .hi {
  grid-area: 1 / 1;
  width: 15px; height: 15px;
  transition: transform .5s var(--ease), opacity .3s;
}
.tt-ico .hi:last-child { opacity: 0; transform: rotate(-90deg) scale(.5); }
html[data-theme="dark"] .tt-ico .hi:first-child { opacity: 0; transform: rotate(90deg) scale(.5); }
html[data-theme="dark"] .tt-ico .hi:last-child { opacity: 1; transform: none; }
.theme-toggle:hover .tt-ico { transform: rotate(-12deg); }
.tt-ico { transition: transform .4s var(--ease); }
.theme-toggle b { font-weight: 500; }

/* --- bottom chrome --- */
.chrome-foot {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 60;
  padding: 0 var(--pad) calc(var(--pad) - 6px);
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  font-size: 12px;
  color: var(--ink-soft);
  pointer-events: none;
}
.chrome-foot > * { pointer-events: auto; }
.scroll-hint { transition: opacity .4s; }
.scroll-hint.hide { opacity: 0; }

/* dark chrome (project intro / playground header) */
.on-dark .chrome,
.on-dark .chrome-foot { color: #f2f2f2; }

/* ============================================================
   WORK — scroll-driven stage
   ============================================================ */
.stage { display: block; }
.stage-spacer { width: 1px; }

.stage-fixed {
  position: fixed;
  inset: 0;
  z-index: 10;
  pointer-events: none;
}
.stage-fixed > * { pointer-events: auto; }

/* --- left meta --- */
.w-meta {
  position: absolute;
  left: var(--pad);
  top: 50%;
  transform: translateY(-50%);
  width: 296px;
  display: grid;
  gap: 34px;
  font-size: 16px;
  line-height: 1.38;
  letter-spacing: -0.015em;
}
.w-meta-row { display: grid; grid-template-columns: 96px 1fr; gap: 12px; align-items: start; }
.w-meta-row > span { color: var(--ink-faint); }
.w-meta-row > div { display: grid; gap: 2px; }
.w-meta.swap { opacity: 0; transform: translateY(calc(-50% + 6px)); }
.w-meta { transition: opacity .35s var(--ease), transform .35s var(--ease); }

/* --- centre media: the coiled ribbon --- */
.w-media {
  position: absolute;
  inset: 0;
}
/* One canvas. The strip is drawn sliver by sliver so the surface curves
   instead of creasing — see renderWorkStage in main.js. */
.coil {
  position: absolute;
  inset: 0;
  display: block;
  /* the strip is painted opaque; this is what fades it out before it reaches
     the header and the footer line */
  -webkit-mask-image: linear-gradient(to bottom, transparent 4%, #000 22%, #000 80%, transparent 96%);
  mask-image: linear-gradient(to bottom, transparent 4%, #000 22%, #000 80%, transparent 96%);
}

/* --- right list --- */
/* .cta-work (above) centres on this column — keep its right/width in sync */
.w-list {
  position: absolute;
  right: 40px;
  top: 50%;
  width: 348px;
  text-align: center;
}
.w-item {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  will-change: transform, opacity;
  cursor: pointer;
}
.w-cat {
  display: block;
  font-size: 11px;
  color: var(--ink-soft);
  margin-bottom: 4px;
}
.w-title {
  font-family: var(--sans);
  /* --f is 1 on the project in focus and 0 on its neighbours, so the name
     grows and thickens with it, up to the 600 every other headline uses.
     The font is loaded as a weight range (400..700), so the in-between
     weights are real rather than faked by the browser. */
  font-weight: calc(420 + var(--f, 0) * 180);
  font-size: calc(22px + var(--f, 0) * 16px);
  line-height: 1;
  letter-spacing: -0.045em;
  margin: 0;
  text-transform: uppercase;
  text-wrap: balance;
}
.w-rule {
  display: block;
  width: 16px;
  height: 1px;
  background: currentColor;
  margin: 11px auto;
  opacity: .5;
}
.w-desc { margin: 0; font-size: 12px; line-height: 1.4; max-width: 27ch; margin-inline: auto; }
.w-item.is-active .w-title { color: var(--ink); }

/* --- counter --- */
.w-counter {
  position: absolute;
  left: var(--pad);
  bottom: 62px;
  display: flex;
  align-items: center;
  color: var(--ink-soft);
  font-size: 12px;
  pointer-events: none;
}
.w-counter .big {
  font-size: 92px;
  line-height: .78;
  font-weight: 600;
  letter-spacing: -0.06em;
  /* the gradient only paints inside the box, and the tight line-height and
     tracking make the box smaller than the digits — pad it out on every side
     (and pull the margins back) so no stroke gets clipped */
  padding: .16em .14em .12em .1em;
  margin: -.16em calc(2px - .14em) -.12em calc(14px - .1em);
  /* the open project's number in a soft wash of the accent blue, fading down */
  color: var(--count-a);
  background: linear-gradient(180deg, var(--count-a), var(--count-b));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ============================================================
   TESTIMONIALS
   ============================================================ */
.kw {
  height: 100vh;
  box-sizing: border-box;
  padding: var(--topbar) var(--pad) var(--pad);
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr) 220px;
  gap: 4vw;
}
/* nothing added yet: one calm line in the middle */
.kw-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 14px;
}
.kw-empty .kw-mark { position: static; line-height: .5; margin-bottom: -4vh; }
.kw-empty h2 { margin: 0; font-size: clamp(26px, 3.4vw, 48px); font-weight: 500; letter-spacing: -0.035em; line-height: 1.1; }
.kw-empty p { margin: 0; max-width: 40ch; font-size: 14px; color: var(--ink-soft); }
.kw-empty a { display: inline-flex; align-items: center; gap: 5px; margin-top: 6px; font-weight: 500; color: var(--accent); }
.kw-empty a .hi { width: 14px; height: 14px; transition: transform .3s var(--ease); }
.kw-empty a:hover .hi { transform: translate(2px, -2px); }
.kw-side { display: flex; flex-direction: column; min-height: 0; }
.kw-side h3 { margin: 0 0 8px; font-size: 12px; font-weight: 400; color: var(--ink-soft); }
.kw-side p { margin: 0; max-width: 24ch; font-size: 13px; line-height: 1.4; }

/* the middle column: the testimonial, then its one line of navigation,
   both as wide as the video so their edges line up */
.kw-main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  max-width: calc(52vh * 16 / 9);
  justify-self: center;
  min-height: 0;
}
.kw-stage { position: relative; margin: 0; }
.kw-mark {
  position: absolute;
  left: -.04em;
  top: -.36em;
  font-family: var(--serif);
  font-size: clamp(140px, 24vh, 260px);
  line-height: 1;
  color: var(--count-a);
  opacity: .55;
  pointer-events: none;
  animation: introFade .8s var(--ease) both;
}
.kw-stage blockquote {
  position: relative;
  margin: 0;
  max-width: 22em;
  font-size: clamp(22px, min(2.6vw, 4.4vh), 40px);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.035em;
  text-wrap: balance;
}
.kw-stage.is-long blockquote { font-size: clamp(17px, min(1.8vw, 3vh), 26px); line-height: 1.3; }
/* a long quote stops after a few lines until "Read more" */
.kw-stage blockquote.is-clamped {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
}
.kw-stage.has-video blockquote.is-clamped { -webkit-line-clamp: 3; }
.kw-more {
  margin-top: 10px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  color: var(--accent);
  cursor: pointer;
}
.kw-more:hover { text-decoration: underline; }
.kw-nav {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 4vh;
  padding-top: 16px;
  font-size: 13px;
}
.kw-of { color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.kw-up {
  margin-left: 2px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--ink-soft);
  cursor: pointer;
}
.kw-up b { font-weight: 500; color: var(--ink); transition: color .25s; }
.kw-up .hi { width: 16px; height: 16px; color: var(--accent); transition: transform .3s var(--ease); }
.kw-up:hover b { color: var(--accent); }
.kw-up:hover .hi { transform: translateX(3px); }
/* words rise in one after another, capped so a long quote doesn't drag */
.kw-stage blockquote span {
  display: inline-block;
  opacity: 0;
  transform: translateY(.4em);
  animation: nameUp .7s var(--ease) forwards;
  animation-delay: calc(min(var(--i), 45) * 16ms);
}
.kw-stage figcaption {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 4.5vh;
  opacity: 0;
  animation: introFade .7s .35s var(--ease) forwards;
}
.kw-stage.has-video:not(.is-portrait) figcaption { margin-top: 0; }
.kw-ava {
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.1);
}
.kw-ava.is-initials {
  display: grid;
  place-items: center;
  filter: none;
  background: var(--accent);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
}
.kw-stage figcaption b { display: block; font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.kw-stage figcaption small { display: block; font-size: 13px; color: var(--ink-soft); }

/* video testimonials: the clip above the quote, or beside it when it's
   portrait; a blue play button until it's started, then native controls */
.kw-stage.has-video { display: grid; gap: 3.5vh; }
.kw-stage.has-video.is-portrait { grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 4vw; }
.kw-video {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 18px;
  overflow: hidden;
  background: var(--black);
  animation: introFade .7s var(--ease) both;
}
.is-portrait .kw-video { width: auto; height: min(62vh, 640px); aspect-ratio: 9 / 16; max-width: none; }
.kw-video video { display: block; width: 100%; height: 100%; object-fit: cover; }
.kw-video.is-on video { object-fit: contain; }
.kw-play {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 68px;
  height: 68px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  transform: translate(-50%, -50%);
  transition: transform .4s var(--ease);
}
.kw-play .hi { width: 24px; height: 24px; margin-left: 3px; }
.kw-play:hover { transform: translate(-50%, -50%) scale(1.08); }
.kw-video.is-on .kw-play { display: none; }
/* the quote mark is positioned against the words, not the whole stage */
.kw-words { position: relative; }
.has-video .kw-mark { font-size: clamp(100px, 16vh, 180px); }
.has-video:not(.is-portrait) .kw-mark { display: none; }
.kw.is-playing .kw-bar i { animation-play-state: paused !important; }

.kw-btn {
  margin-left: auto;
  width: 32px;
  height: 32px;
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: none;
  color: var(--ink);
  cursor: pointer;
  transition: background .25s, color .25s, border-color .25s;
}
.kw-btn .hi { width: 16px; height: 16px; }
.kw-btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
/* the hairline along the top of the nav line doubles as the timer */
.kw-bar { position: absolute; top: 0; left: 0; right: 0; height: 1px; overflow: hidden; background: var(--line); }
.kw-bar i { position: absolute; inset: 0; background: var(--accent); transform: scaleX(0); transform-origin: left; }
.kw-main:hover .kw-bar i { animation-play-state: paused !important; }
@keyframes kwBar { to { transform: scaleX(1); } }
.cta-kw { margin-top: auto; align-self: flex-start; }

@media (max-width: 860px) {
  .kw { height: auto; min-height: 100vh; grid-template-columns: minmax(0, 1fr); gap: 36px; padding-top: calc(var(--topbar) + 24px); }
  .kw-main { max-width: none; }
  .cta-kw { margin-top: 20px; }
  .kw-stage { padding-top: 48px; }
  .kw-mark { top: -.12em; font-size: 130px; }
  .kw-stage blockquote { font-size: 24px; }
  .kw-stage.is-long blockquote { font-size: 19px; }
  .kw-stage.has-video.is-portrait { grid-template-columns: 1fr; }
  .is-portrait .kw-video { height: 58vh; justify-self: center; }
}

/* ============================================================
   PROJECT detail
   ============================================================ */
.project { padding-bottom: 20vh; }

.proj-side {
  position: fixed;
  left: var(--pad);
  top: 46%;
  transform: translateY(-46%);
  width: 300px;
  z-index: 20;
  display: grid;
  gap: 26px;
  font-size: 11.5px;
}
.proj-side .row { display: grid; grid-template-columns: 62px 1fr; gap: 10px; align-items: start; }
.proj-side .row > span { color: var(--ink-faint); }
.proj-side .row p { margin: 0; max-width: 24ch; line-height: 1.42; }
.proj-side .pairs { display: grid; grid-template-columns: 52px 1fr 48px 1fr; gap: 6px 8px; }
.proj-side .pairs > span { color: var(--ink-faint); }

/* Fills the space between the fixed info column (left) and the thumbnail
   rail (right): 78% of that gap, centred, capped at 900px on wide screens. */
.proj-stream {
  --left: calc(var(--pad) + 392px); /* clears the fixed menu by ~40px */
  --right: 100px;
  --room: calc(100% - var(--left) - var(--right));
  width: min(900px, calc(var(--room) * .78));
  margin-left: calc(var(--left) + (var(--room) - min(900px, calc(var(--room) * .78))) / 2);
  padding-top: var(--topbar);
  display: grid;
  gap: 54px;
}
.proj-stream figure { margin: 0; }
.proj-stream img {
  width: 100%;
  background: var(--shot);
  box-shadow: 0 20px 50px -34px var(--shadow);
}

.proj-rail {
  position: fixed;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 20;
  display: grid;
  gap: 6px;
  width: 46px;
}
.proj-rail button {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  opacity: .42;
  transition: opacity .3s;
  outline: 0;
}
.proj-rail button img { width: 100%; height: 100%; object-fit: cover; }
.proj-rail button.on,
.proj-rail button:hover { opacity: 1; }

.proj-outro {
  margin-top: 16vh;
  text-align: center;
  display: grid;
  gap: 18px;
  justify-items: center;
}
.proj-outro .next-k { color: var(--ink-soft); font-size: 12px; }
.proj-outro a {
  font-family: var(--sans);
  font-weight: 600;
  font-size: clamp(28px, 4.6vw, 64px);
  line-height: 1.05;
  text-transform: uppercase;
  letter-spacing: -0.035em;
  color: var(--accent);
  transition: opacity .25s;
}
.proj-outro a:hover { opacity: .65; }

/* ============================================================
   ABOUT
   ============================================================ */
/* One screen, no scrolling: the type is sized against viewport height as
   well as width so the whole page shrinks to fit rather than overflowing. */
.about { height: 100vh; padding: 0 var(--pad); overflow: hidden; }

.about-hero {
  height: 100%;
  display: grid;
  grid-template-rows: 1fr auto;
  padding: var(--topbar) 0 var(--pad);
  box-sizing: border-box;
}
.about-stack {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 0;
}
.about-facts {
  /* margin, not justify-self: these sit in a plain wrapper, not directly in
     the grid, so justify-self has nothing to act on. It has to be the
     shorthand too — a separate margin: 0 below would wipe it out. */
  margin: 0 0 0 auto;
  text-align: left;
  padding: 0;
  list-style: none;
  color: var(--accent);
  font-size: clamp(13px, min(1.7vw, 2.1vh), 26px);
  font-weight: 650;
  line-height: 1.28;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  max-width: 44ch;
}

/* experience on the left, the accent-coloured facts on the right */
.about-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 40px; }
/* a plain list, set like the small lists in the footer band */
.about-exp { width: min(360px, 32vw); }
.about-exp h3 { margin: 0; font-size: 11px; font-weight: 400; color: var(--ink-soft); }

/* heading row: title + live count on the left, discipline filters on the right,
   with a hairline that draws itself in under them */
.xp-head {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  padding-bottom: 8px;
  margin-bottom: 8px;
}
.xp-head::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--line);
  transform-origin: left;
  animation: xpDraw .9s var(--ease) .35s both;
}
@keyframes xpDraw { from { transform: scaleX(0); } }
.xp-count {
  display: inline-block;
  min-width: 2ch;
  font-size: 9px;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.xp-count.is-tick { animation: xpTick .45s var(--ease); }
@keyframes xpTick { from { opacity: 0; transform: translateY(-5px); } }

.xp-filters { display: flex; gap: 10px; }
.xp-filters button {
  position: relative;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 11px;
  color: var(--ink-faint);
  cursor: pointer;
  transition: color .25s;
}
.xp-filters button:hover,
.xp-filters button:focus-visible { color: var(--ink); outline: none; }
.xp-filters button[aria-pressed="true"] { color: var(--ink); }
/* a small accent underline that grows under the active filter */
.xp-filters button::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -3px;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transition: transform .35s var(--ease);
}
.xp-filters button[aria-pressed="true"]::after { transform: scaleX(1); }

/* rows touch (padding, not gap) so the cursor never falls between them and dims them all */
.xp-list { list-style: none; margin: 0; padding: 0; display: grid; }
.xp-row {
  position: relative;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 1.5px 0;
  font-size: clamp(11px, 1.3vh, 12px);
  line-height: 1.35;
  color: var(--ink-soft);
  cursor: default;
  transition: opacity .3s, color .3s, transform .45s var(--ease);
  animation: xpIn .7s var(--ease) backwards;
  animation-delay: calc(.4s + var(--i) * 45ms);
}
@keyframes xpIn { from { opacity: 0; transform: translateY(8px); filter: blur(3px); } }
.xp-row b { font-weight: 500; color: var(--ink); transition: color .3s; }
.xp-row time {
  flex: none;
  font-variant-numeric: tabular-nums;
  transform-origin: left center;
  transition: color .3s, transform .45s var(--ease);
}
.xp-where, .xp-when { display: inline-block; }

/* the name slides over to make room for an accent dot */
.xp-main {
  display: inline-flex;
  align-items: center;
  transform-origin: left center;
  transition: transform .45s var(--ease);
}
.xp-dot {
  width: 5px; height: 5px;
  margin-left: -5px; margin-right: 0;
  border-radius: 50%;
  background: var(--accent);
  transform: scale(0);
  transition: transform .4s var(--ease), margin .45s var(--ease);
}
.xp-role { white-space: pre; }

/* an accent hairline sweeps under the hovered row */
.xp-row::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform .5s var(--ease);
}

/* spotlight: hovering one row quiets the rest */
@media (hover: hover) {
  .xp-list:hover .xp-row { opacity: .35; }
  .xp-list:hover .xp-row:hover { opacity: 1; }
  /* the hovered row grows: the name from the left, and the date steps out past
     the column's right edge into the empty space so the two never meet */
  .xp-row:hover { z-index: 1; }
  .xp-row:hover .xp-main { transform: translateX(10px) scale(1.3); }
  .xp-row:hover time { transform: translateX(18px) scale(1.3); }
  /* its neighbours step aside to make room */
  .xp-row:has(+ .xp-row:hover) { transform: translateY(-3px); }
  .xp-row:hover + .xp-row { transform: translateY(3px); }
  .xp-row:hover .xp-dot { transform: scale(1); margin-right: 7px; }
  .xp-row:hover b, .xp-row:hover time { color: var(--accent); }
  .xp-row:hover::after { transform: scaleX(1); transform-origin: left; }
}

/* filtering: matches keep their dot, the rest fade back */
.is-filtered .xp-row:not(.is-muted) .xp-dot { transform: scale(1); margin-right: 7px; }
.xp-row.is-muted { opacity: .25; }
.xp-row.is-muted b { color: var(--ink-soft); }
@media (hover: hover) {
  .xp-list:hover .xp-row.is-muted { opacity: .15; }
  .xp-list:hover .xp-row.is-muted:hover { opacity: .7; }
}

.about-name {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 1.2vh 0;
}
.about-name b {
  font-size: clamp(56px, min(19vw, 22vh), 320px);
  font-weight: 700;
  line-height: .78;
  letter-spacing: -0.06em;
  color: var(--ghost);
}
/* The portrait between NAT and NAEL: a big plain circle.
   It's taller than the letters, so negative margins let it overhang the row
   instead of pushing the page down. Grey and muted while the clip loops, full
   colour once someone turns the sound on. */
.face-orbit {
  position: relative;
  flex: none;
  width: clamp(90px, min(14vw, 20.5vh), 240px);
  aspect-ratio: 1;
  margin: -10vh 0 -4vh;
  display: grid;
  place-items: center;
}
/* a disc of page colour behind the portrait, so the divider line below
   passes behind the circle rather than through it */
.face-orbit::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--bg);
}
.face-video {
  position: relative;
  z-index: 1;
  margin: 0;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--ghost);
  cursor: pointer;
  transition: transform .6s var(--ease);
}
.face-orbit:hover .face-video { transform: scale(1.03); }
.face-video video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.1);
  transition: filter .4s var(--ease);
}
.face-video.is-live video { filter: none; }
/* hover: tint the grey photo blue. "multiply" with a light blue keeps every
   shadow and detail of the photo and lays the blue over the lights, so it
   reads as a blue print of the picture, neither washed out nor dyed solid */
.face-video::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  background: color-mix(in srgb, var(--accent) 50%, #fff);
  mix-blend-mode: multiply;
  opacity: 0;
  pointer-events: none;
  transition: opacity .5s var(--ease);
}
.face-orbit:hover .face-video::after { opacity: 1; }
.face-video.is-live::after { display: none; }
.fv-sound { z-index: 2; }
.face-video img { display: block; width: 100%; height: 100%; object-fit: cover; filter: grayscale(1) contrast(1.1); }
.face-video.is-empty { cursor: default; }
.face-video.is-empty .fv-sound { display: none; }
.fv-sound {
  position: absolute;
  left: 50%;
  bottom: 9%;
  transform: translateX(-50%);
  white-space: nowrap;
  padding: 5px 10px;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  font: inherit;
  font-size: clamp(9px, 1.1vh, 11px);
  cursor: pointer;
  backdrop-filter: blur(6px);
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.face-video:hover .fv-sound { background: var(--accent); }

.about-name .face {
  width: clamp(80px, min(16vw, 19vh), 240px);
  aspect-ratio: 1;
  border-radius: 50%;
  object-fit: cover;
  filter: grayscale(1) contrast(1.2);
}

.about-statement {
  color: var(--accent);
  /* sentence case and a size closer to the bio beside it */
  font-size: clamp(14px, min(1.35vw, 1.9vh), 22px);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.02em;
  max-width: 30ch;
  margin: 0;
  align-self: start;
}

.about-foot {
  border-top: 1px solid var(--line);
  padding: 12px 0 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr)) 1.5fr 1.7fr 118px;
  gap: 24px;
  align-items: start;
}
.about-foot h3 {
  margin: 0 0 clamp(16px, 4.4vh, 46px);
  font-size: clamp(10px, 1.25vh, 11.5px);
  font-weight: 400;
  color: var(--ink-soft);
}
.about-foot ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  font-size: clamp(10px, 1.25vh, 11.5px);
  line-height: 1.34;
}
.about-foot a { text-decoration: underline; text-underline-offset: 3px; }
.about-foot a:hover { color: var(--accent); }
.about-foot .muted { color: var(--ink-soft); }

/* The contact links carry the page, so they are sized like the email on the
   contact page rather than like the lists beside them. */
.about-foot .big-links {
  gap: 4px;
  font-size: clamp(14px, min(1.5vw, 2vh), 26px);
}
.about-foot .big-links a {
  color: var(--accent);
  font-weight: 650;
  letter-spacing: -0.03em;
  text-underline-offset: 5px;
  transition: opacity .25s var(--ease);
}
.about-foot .big-links a:hover { color: var(--accent); opacity: .6; }
.about-foot .trusted { text-align: right; }
/* The about band is just the links and the statement now; keep them in the
   columns they had beside the old lists. */
/* the bio is the one thing people come here to read: a touch above body
   size, and most of the band's width */
.about .about-bio { grid-column: 1 / span 4; }
.about-bio p {
  margin: 0 0 .7em;
  max-width: 58ch;
  font-size: 13px;
  line-height: 1.55;
  letter-spacing: -0.01em;
  text-wrap: pretty;
}
/* the links sit at the right-hand end of the band */
.about .about-bio + div { grid-column: 5 / -1; justify-self: end; text-align: right; }
.about .about-bio + div .big-links { justify-items: end; }


/* ============================================================
   PLAYGROUND
   ============================================================ */
.play {
  padding: var(--topbar) var(--pad) 16vh;
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 28px;
}
.play-aside { position: relative; }
.play-aside .count {
  position: sticky;
  top: 34vh;
  font-size: clamp(90px, 11vw, 168px);
  font-weight: 600;
  line-height: .78;
  letter-spacing: -0.06em;
  color: var(--ghost);
}
.play-note {
  position: fixed;
  left: var(--pad);
  bottom: calc(var(--pad) + 26px);
  width: 210px;
  font-size: 11px;
  color: var(--ink-soft);
  line-height: 1.45;
}
.play-grid {
  columns: 3;
  column-gap: 12px;
}
.play-grid figure {
  margin: 0 0 12px;
  break-inside: avoid;
  background: var(--shot);
  cursor: zoom-in;
  overflow: hidden;
}
.play-grid img {
  width: 100%;
  transition: transform .6s var(--ease);
}
.play-grid figure:hover img { transform: scale(1.03); }

/* lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 140;
  background: rgba(8, 8, 9, .93);
  display: grid;
  place-items: center;
  padding: 5vh 5vw;
  cursor: zoom-out;
}
.lightbox img { max-height: 90vh; max-width: 100%; width: auto; object-fit: contain; }
.lightbox.tall { display: block; place-items: normal; overflow-y: auto; overscroll-behavior: contain; }
.lightbox.tall img { max-height: none; width: min(860px, 100%); margin: 0 auto; cursor: default; }
.lb-close {
  position: fixed;
  top: 22px;
  right: 26px;
  z-index: 1;
  color: #fff;
  font-size: 13px;
  opacity: .7;
  transition: opacity .2s;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.lb-close:hover { opacity: 1; }
.lb-close .hi { transition: transform .4s var(--ease); }
.lb-close:hover .hi { transform: rotate(90deg); }

/* The project's details, in the same column as on its own page. */
.lightbox:has(.lb-info) { padding-left: calc(var(--pad) + 340px); background: rgba(8, 8, 9, .97); }
.lb-info { color: #fff; cursor: default; }
.lb-info .row > span, .lb-info .pairs > span { color: rgba(255, 255, 255, .42); }
.lb-title {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.1;
  text-transform: uppercase;
  max-width: 14ch;
}

/* ============================================================
   CONTACT — the about page's layout, with a call button where
   the portrait would be.
   ============================================================ */
.contact { height: 100vh; padding: 0 var(--pad); overflow: hidden; }
.contact-hero {
  height: 100%;
  display: grid;
  grid-template-rows: 1fr auto;
  padding: var(--topbar) 0 var(--pad);
  box-sizing: border-box;
}
.contact-stack {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 0;
}
.contact-mark {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 1.2vh 0;
}
.contact-mark b {
  font-size: clamp(56px, min(19vw, 22vh), 320px);
  font-weight: 700;
  line-height: .78;
  letter-spacing: -0.06em;
  color: var(--ghost);
}

/* the accent-coloured button, with its label running round it */
.ct-call {
  position: relative;
  flex: none;
  width: clamp(110px, min(18vw, 22vh), 260px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  color: #fff;
}
.ct-call-c {
  position: relative;
  width: 64%;
  aspect-ratio: 1;
  display: grid;
  place-content: center;
  border-radius: 50%;
  background: var(--accent);
  text-align: center;
  font-size: clamp(12px, min(1.5vw, 1.9vh), 22px);
  font-weight: 650;
  line-height: 1;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  transition: transform .5s var(--ease);
}
.ct-call-c .ct-go {
  justify-self: center;
  width: 1.5em;
  height: 1.5em;
  margin-top: .3em;
  stroke-width: 1.8;
  transition: transform .5s var(--ease);
}
.ct-call:hover .ct-call-c { transform: scale(1.08); }
.ct-call:hover .ct-call-c .ct-go { transform: translate(3px, -3px); }
.ct-call:focus-visible { outline: none; }
.ct-call:focus-visible .ct-call-c { box-shadow: 0 0 0 3px var(--bg), 0 0 0 4px var(--accent); }

/* the footer is just the links and the statement, so give them the width */
.contact-foot { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1.8fr); }
/* the links matter most here, so they get the statement's voice */
.contact .contact-foot .big-links {
  gap: 0;
  font-size: clamp(15px, min(1.9vw, 2.4vh), 34px);
  line-height: 1.28;
  text-transform: uppercase;
}
.contact .contact-foot .big-links a { letter-spacing: -0.02em; text-underline-offset: 4px; }
.ct-info { justify-self: end; max-width: 46ch; }
.ct-info p { margin: 0 0 1em; font-size: clamp(11px, 1.35vh, 13px); line-height: 1.45; }
.ct-info .muted { color: var(--ink-soft); }
@media (max-width: 1100px) { .contact .ct-info { justify-self: start; grid-column: 1 / -1; order: -1; } }
@media (max-width: 1100px) { .contact .contact-foot { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 860px) {
  .contact .contact-foot { grid-template-columns: 1fr; gap: 28px; }
  .contact .contact-foot .big-links { font-size: 22px; }
}
/* availability: one solid blue pill with a live dot, one quiet line under it */
.ct-open { margin-left: auto; display: grid; justify-items: end; gap: 10px; text-align: right; }
.ct-open-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 36px;
  padding: 0 16px 0 14px;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.ct-open-dot { position: relative; width: 8px; height: 8px; border-radius: 50%; background: #fff; }
.ct-open-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #fff;
  animation: ctPing 1.8s var(--ease) infinite;
}
@keyframes ctPing { to { transform: scale(2.8); opacity: 0; } }
.ct-open p { margin: 0; font-size: 13px; color: var(--ink-soft); }
@media (prefers-reduced-motion: reduce) { .ct-open-dot::after { animation: none; } }

.contact-now { margin: 0 0 3vh; font-size: 13px; color: var(--ink-soft); }
.contact-now b { color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }

/* ============================================================
   Small screens
   ============================================================ */
@media (max-width: 1100px) {
  /* Narrower than this the bottom band has to stack, which makes it far too
     tall for one screen — so let the page scroll from here down. */
  .about, .contact { height: auto; overflow: visible; }
  .about-hero, .contact-hero { height: auto; padding-bottom: 12vh; }
  .about-stack, .contact-stack { display: block; }
  .about-name, .contact-mark { margin: 6vh 0; }
  .about-foot { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .about-foot .about-statement { grid-column: 1 / -1; order: -1; max-width: none; margin-bottom: 28px; }
  .about-foot .trusted { text-align: left; }
  .about .about-bio { grid-column: 1 / -1; }
  .about .about-bio + div { grid-column: auto; justify-self: start; text-align: left; }
  .about .about-bio + div .big-links { justify-items: start; }
  .play-grid { columns: 2; }
  .w-meta { display: none; }
  .w-shot { width: 38vw; }
}

@media (max-width: 860px) {
  :root { --pad: 16px; --topbar: 132px; }

  .chrome {
    grid-template-columns: 1fr auto;
    gap: 10px 12px;
    align-items: center;
  }

  .nav { grid-column: 1 / -1; order: 3; }
  .nav-list { gap: 6px 18px; }

  .nav { justify-self: start; }
  .inquiries { font-size: 11px; gap: 10px; align-items: center; }
  .clock { display: none; }
  .chrome .book-cta { height: 32px; padding: 0 12px; font-size: 12px; }
  .book-cta { height: 42px; padding: 0 18px; font-size: 14px; }

  .chrome-foot { display: none; }

  .wm-card .w-title { font-size: 26px; }


  .proj-side {
    position: static;
    transform: none;
    width: auto;
    padding: var(--topbar) var(--pad) 34px;
    gap: 20px;
  }
  .proj-side .row p { max-width: none; }
  .proj-stream { width: auto; margin: 0; padding: 0 var(--pad); gap: 26px; }
  .proj-rail { display: none; }
  .lightbox:has(.lb-info) { padding-left: 5vw; }
  .lightbox .lb-info { padding: 40px 0 28px; }
  .proj-outro a { font-size: clamp(30px, 9vw, 54px); }

  .play { grid-template-columns: 1fr; gap: 14px; padding-bottom: 12vh; }
  .play-aside { display: grid; gap: 10px; }
  .play-aside .count { position: static; font-size: 76px; }
  .play-note { position: static; width: auto; }
  .play-grid { columns: 2; }

  .about-hero, .contact-hero { padding-top: var(--topbar); }
  .about-facts, .about-statement { margin-left: 0; max-width: none; }
  .ct-open { margin-left: 0; justify-items: start; text-align: left; }
  .about-top { flex-direction: column-reverse; gap: 28px; }
  .about-right { margin-left: 0; }
  .play-foot { position: static; margin-top: 18px; width: auto; }
  .cta-work { bottom: 24px; }
  .about-exp { width: 100%; }
  .about-name { gap: 6px; margin: 4vh 0; }
  .about-name b, .contact-mark b { font-size: 56px; }
  .ct-call { width: 104px; }
  .ct-call-c { font-size: 11px; }
  .about-name .face { width: 84px; }
  /* too narrow to sit between the letters: float it, centred, over them */
  .about-name { position: relative; margin: 96px 0; }
  .face-orbit { position: absolute; left: 50%; top: 50%; width: 120px; margin: 0; transform: translate(-50%, -50%); }
  .about-foot { grid-template-columns: 1fr 1fr; gap: 22px; }
  .about-foot .trusted { text-align: left; }

}

/* Shorter than this and no amount of shrinking fits the page in one screen,
   so let it scroll rather than clip the columns off the bottom. */
@media (max-height: 640px) {
  .about, .contact { height: auto; overflow: visible; }
  .about-hero, .contact-hero { height: auto; padding-bottom: 40px; }
  .about-stack, .contact-stack { display: block; }
  .about-name, .contact-mark { margin: 4vh 0; }
}

@media (min-width: 1600px) {
  .play-grid { columns: 4; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}
