/* ============================================================
   BREATHING EXERCISES — animation studio
   Two-voice typography · 12-col modular grid · diegetic navigation
   See DESIGN.md for token contract.
   ============================================================ */

/* ---------- BRAND DISPLAY FONT ---------- */
/* Druk Wide Medium (Commercial Type) — self-hosted, single weight (500), very
   WIDE. The masthead/brand display voice: nav menu, section + film titles,
   project card client/project names. Hierarchy comes from size + tracking +
   case, since only one weight ships. */
@font-face{
  font-family: 'Druk Wide Web';
  src: url('fonts/DrukWide-Medium-Web.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  /* `block` (not swap): the file is tiny and preloaded, so it paints almost
     instantly — and block avoids a flash of the normal-width fallback
     collapsing the wide lockup before Druk arrives. */
  font-display: block;
}

/* ---------- TOKENS ---------- */
:root{
  /* neutrals */
  --paper:        #FFFFFF;   /* page surface — pure white (was #F0EEE9 warm paper) */
  --paper-pure:   #FFFFFF;

  /* sky tints */
  --sky-100:      #E6F1FD;
  --sky-200:      #D5ECFF;
  --sky-300:      #BDE1FF;
  --sky-500:      #1E91F7;

  /* ink */
  --ink:          #0A2540;
  --ink-soft:     #3A4A5E;
  --ink-mute:     #7A8896;

  /* rules — rgba so they read on any surface */
  --rule:         rgba(10, 37, 64, .10);
  --rule-strong:  rgba(10, 37, 64, .24);

  /* fonts */
  /* Two-font brand system: Druk Wide (headings) + Inter (everything else).
     --f-mono keeps its name for existing callers; labels read as labels
     through UPPERCASE + tracking, not a mono face. */
  --f-sans:       'Inter', sans-serif;
  --f-mono:       'Inter', sans-serif;
  --f-druk:       'Druk Wide Web', 'Arial Black', system-ui, sans-serif;

  /* ---- MODULAR TYPE SCALE (base 17px, step ~1.3). Display/section/title are
     the desktop upper bound; CSS clamps them down. Body/lead/meta/label fixed. ---- */
  --t-display:  clamp(2.75rem, 7.5vw, 5.5rem);  /* page title — Druk, the loud moment */
  --t-section:  clamp(1.75rem, 4.6vw, 3.25rem); /* section heading — Druk */
  --t-title:    clamp(1.3rem, 2.4vw, 1.9rem);   /* card / film name — Druk */
  --t-lead:     1.375rem;    /* 22px — intro / sub */
  --t-body:     1.0625rem;   /* 17px */
  --t-meta:     0.8125rem;   /* 13px */
  --t-label:    0.6875rem;   /* 11px — uppercase tracked */
  /* legacy aliases (still referenced: --t-sub by about.html, --t-mono by
     .eyebrow / .nav / footer) */
  --t-sub:      var(--t-lead);
  --t-mono:     var(--t-label);

  /* ---- SPACING (8pt) with a STEEP gap hierarchy: tight inside, big between ---- */
  --s-2xs: .25rem;  /* 4   inline */
  --s-xs:  .5rem;   /* 8   intra-block */
  --s-sm:  1rem;    /* 16  intra-block */
  --s-md:  1.5rem;  /* 24  block padding */
  --s-lg:  2rem;    /* 32  block padding */
  --s-xl:  3rem;    /* 48  between blocks */
  --s-2xl: 4rem;    /* 64  between blocks / page-top */
  --s-3xl: 6rem;    /* 96  between sections */
  --s-4xl: 8rem;    /* 128 between sections (large) */
  --bl:    0.5rem;

  /* layout — 12-column editorial grid */
  --vdg:    max(1.6rem, calc(100vw / 18));
  --gutter: clamp(1rem, 1.6vw, 1.5rem);   /* 16–24px editorial gutter */
  --cols:   12;
  --nav-h:  7.5rem;

  /* motion */
  --ease-out:     cubic-bezier(.22, 1, .36, 1);
  --ease-in:      cubic-bezier(.6, 0, .8, .3);
}

/* ---------- RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: auto; }
body {
  font-family: var(--f-sans);
  font-size: var(--t-body);
  font-weight: 350;
  line-height: 1.4;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100svh;
}
/* Home is a fullscreen scene — lock the viewport so the keyvis fills
   without ever scrolling. Inner pages stay default body-scrollable. */
body[data-page="home"]{
  overflow: hidden;
  height: 100svh;
}
img, video { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; padding: 0; text-align: inherit; }
a { color: inherit; text-decoration: none; }
ul { margin: 0; padding: 0; list-style: none; }
em { font-style: italic; }
::selection { background: var(--ink); color: var(--paper); }

/* ============================================================
   TYPOGRAPHY VOICES
   ============================================================ */
.body{
  font-family: var(--f-sans);
  font-weight: 350;
  font-size: var(--t-body);
  line-height: 1.4;
  letter-spacing: -.005em;
  margin: 0;
  color: var(--ink-soft);
}
.eyebrow{
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  margin: 0;
  font-family: var(--f-mono);
  font-weight: 400;
  font-size: var(--t-mono);
  line-height: 1.3;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.eyebrow .dot{
  width: 7px; height: 7px;
  border-radius: 999px;
  background: var(--sky-500);
  box-shadow: 0 0 0 4px rgba(30,145,247,.18);
  flex-shrink: 0;
}

/* ============================================================
   GRID — shared by home, work, about
   ============================================================ */
.grid{
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
}

/* ============================================================
   NAVIGATION
   ============================================================ */
.nav{
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--nav-h);
  z-index: 90;
  display: grid;
  /* 3-col symmetrical layout: wordmark left, menu center, free col right.
     The right column stays empty — equal weight on both sides keeps the
     menu mathematically centered regardless of wordmark width. */
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 var(--vdg);
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: .14em;
  color: var(--paper-pure);
  pointer-events: none;
}
.nav > * { pointer-events: auto; }
.nav-mark { grid-column: 1; justify-self: start; }
.nav-menu { grid-column: 2; justify-self: center; }

body[data-page="work"] .nav,
body[data-page="about"] .nav{
  color: var(--ink);
  /* No frosted blur. The bar is clean (transparent) at the top of the page;
     a crisp solid-white backing + a single hairline fade in only once content
     scrolls under it (app.js toggles .is-stuck). */
  border-bottom: 1px solid transparent;
  transition: background-color .3s var(--ease-out), border-color .3s var(--ease-out);
}
body[data-page="work"] .nav.is-stuck,
body[data-page="about"] .nav.is-stuck{
  background: var(--paper);
  border-bottom-color: var(--rule);
}

.nav-mark{
  display: inline-flex;
  align-items: center;
  height: 100%;
  gap: .55rem;
}
.nav-logo{
  display: block;
  /* Same size on every page — wordmark scale is consistent across home
     and inner pages. */
  height: clamp(1.7rem, 3.3vw, 3rem);
  aspect-ratio: 1272 / 201;
  background: currentColor;
  -webkit-mask: url('img/logotype.svg') no-repeat center / contain;
          mask: url('img/logotype.svg') no-repeat center / contain;
  transition: opacity .4s var(--ease-out), background-color .4s var(--ease-out);
}
/* Inner pages: tint the wordmark sky-blue so it sits in the same family
   as the active nav link rather than the heavy --ink it would inherit
   from .nav. The .nav-mark anchor sets the color; .nav-logo's
   `background: currentColor` picks it up through the mask. */
body[data-page="work"]    .nav-mark,
body[data-page="about"]   .nav-mark{ color: var(--sky-500); }

.nav-mark:hover .nav-logo{ opacity: .82; }

/* ============================================================
   NAV MENU — top-center: WORK / ABOUT / SAY HI.
   Druk Wide Medium (the brand display face) sets a brutal editorial
   masthead tone. Items are uppercase; Druk's built-in width carries the
   weight, so tracking stays slightly positive (negative would crush the
   wide caps). Tight gap keeps the group at the optical center.
   ============================================================ */
.nav-menu{
  display: inline-flex;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
  gap: clamp(1.1rem, 2.2vw, 2.2rem);
}
.nav-menu li{ display: inline-flex; }
.nav-link{
  position: relative;
  display: inline-block;
  font-family: var(--f-druk);
  font-weight: 500;        /* Druk Wide ships a single weight */
  font-size: clamp(.68rem, .95vw, .98rem);
  /* Druk Wide is, well, wide — its width carries the masthead weight, so a
     hair of positive tracking keeps the caps breathing instead of the
     wordmark's negative lockup. */
  letter-spacing: .03em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--paper-pure);
  padding: .35rem .1rem;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color .25s var(--ease-out), opacity .25s var(--ease-out);
}
/* Underline grows on hover + when route is active. Hairline rule sits
   just below the cap-line, animated from the left so it reads as a
   draw-in rather than a fade-in. */
.nav-link::after{
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 2px;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .35s var(--ease-out);
}
.nav-link:hover::after,
.nav-link.is-current::after{ transform: scaleX(1); }
.nav-link:hover{ color: var(--sky-300); }
.nav-link.is-current{ color: var(--sky-300); }

/* "Say hi" — a mailto action, NOT a route. Set apart by a gap; the nav
   underline is removed and replaced with an outbound ↗ arrow. On the white
   inner pages the whole thing goes accent-blue so it reads clearly as "send
   us a note"; on the keyvis home it stays legible white with the accent
   arrow doing the work. */
.nav-cta{ margin-left: clamp(1rem, 2.4vw, 2.6rem); }   /* extra space from Work / About */
.nav-link-cta{ position: relative; }
.nav-link-cta::after{ display: none; }                 /* not a route — no underline */
.cta-label{
  display: inline-block;
  transition: opacity .3s var(--ease-out), letter-spacing .55s var(--ease-out), transform .5s var(--ease-out);
}
.nav-link-cta .cta-arc{
  display: inline-block;
  margin-left: .3em;
  font-family: var(--f-sans);
  color: var(--sky-500);
  transition: transform .3s var(--ease-out);
}
/* Email morph: on hover "Say hi" softly dissolves and the address fades up
   in its place. The address is absolute so the centred menu never reflows. */
.cta-mail{
  position: absolute;
  left: 0; top: 50%;
  transform-origin: left center;
  transform: translateY(-50%) scale(1.05);
  white-space: nowrap;
  font-family: var(--f-druk);
  font-weight: 500;
  /* Tighten the very wide Druk so the address sits closer in visual weight
     to "Say hi" — the swap reads as a substitution, not a jump in mass. */
  letter-spacing: -.04em;
  text-transform: none;
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s var(--ease-out), transform .55s var(--ease-out);
}
/* Morph handoff: "Say hi" spreads its tracking apart as it dissolves while
   the tightened address settles in — no blur, no slide, reads as a swap. */
.nav-link-cta:hover .cta-label{ opacity: 0; letter-spacing: .3em; }
.nav-link-cta:hover .cta-mail{ opacity: 1; transform: translateY(-50%) scale(1); }
body[data-page="work"] .nav-link.nav-link-cta,
body[data-page="about"] .nav-link.nav-link-cta{ color: var(--sky-500); }
.nav-link-cta:hover .cta-arc{ transform: translate(.18em, -.18em); }

/* ---------- Social — monochrome brand marks in the nav's right slot (home) ---------- */
.nav-social{
  grid-column: 3;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: clamp(.7rem, 1.4vw, 1.15rem);
}
.nav-social a{
  display: inline-flex;
  color: currentColor;
  opacity: .82;
  transition: opacity .25s var(--ease-out), transform .25s var(--ease-out);
}
.nav-social a:hover{ opacity: 1; transform: translateY(-1px); }
.nav-social svg{
  width: clamp(15px, 1.15vw, 18px);
  height: auto;
  display: block;
  fill: currentColor;
}

/* Inner pages: switch palette to dark ink so the menu reads on the
   off-paper backgrounds. */
body[data-page="work"] .nav-link,
body[data-page="about"]    .nav-link{
  color: var(--ink);
}
body[data-page="work"] .nav-link:hover,
body[data-page="about"]    .nav-link:hover,
body[data-page="work"] .nav-link.is-current,
body[data-page="about"]    .nav-link.is-current{ color: var(--sky-500); }

@media (max-width: 720px){
  .nav-logo{ height: clamp(1.35rem, 5.25vw, 1.8rem); }
  .nav-menu{ gap: 1.1rem; }
  .nav-link{ font-size: .6rem; letter-spacing: .04em; }
}

/* ============================================================
   PAGES — each landing page is a standalone document. The body
   inherits scroll behavior from `body[data-page="*"]` rules above;
   .page is a layout slot inside the body, not a stacked overlay.
   ============================================================ */
.page{ display: block; }

/* ============================================================
   HOME — fullscreen scene
   ============================================================ */
.page-home{
  position: relative;
  width: 100%;
  height: 100svh;
  overflow: hidden;
}

.scene{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  /* First paint: the mood's sky/background webp paints instantly (it's
     tiny and preloaded in <head>) while app.js builds the parallax
     layers on top. It also remains the picture's backdrop and the
     reduced-motion still frame. */
  background-color: #9DC2E6;
  background-image: url('img/keyvis/day/background.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
}
[data-mood="sunset"] .scene{ background-image: url('img/keyvis/sunset/background.webp'); }
[data-mood="night"]  .scene{ background-image: url('img/keyvis/night/background.webp'); }

.scene-inner{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform-origin: 50% 50%;
}

/* ============================================================
   KEYVIS — self-hosted parallax composite. Every layer is the same
   2000×1125 pre-aligned artboard; object-fit:cover crops them
   identically so they stay registered at any viewport. A small base
   overscan (scale) gives the parallax room so layer edges never reveal
   during the cursor shift. app.js drives --px/--py per layer; mood
   swaps crossfade one .kv-set over another.
   ============================================================ */
.kv-stage{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  /* Soft reveal: the layers fade up over the instant-painted sky once
     they decode (app.js adds .is-ready). */
  opacity: 0;
  transition: opacity .9s var(--ease-out);
}
.kv-stage.is-ready{ opacity: 1; }
.kv-set{
  position: absolute;
  inset: 0;
  opacity: 1;
  transition: opacity 1.2s var(--ease-out);
}
.kv-set.is-out{ opacity: 0; }
.kv-layer{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0) scale(1.08);
  will-change: transform;
  user-select: none;
  -webkit-user-drag: none;
}
/* Foreground buildings sit a touch larger so their bigger parallax shift
   reads as depth without exposing the artboard edge. */
.kv-layer.kv-left,
.kv-layer.kv-right{
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0) scale(1.12);
}
/* Portrait phones: a 16:9 cover crop on a tall screen keeps only the centre
   sky and drops both edge buildings. Bias the crop toward the right tower —
   the balcony + character are the brand moment. */
@media (max-width: 720px){
  .kv-layer{ object-position: 62% 50%; }
}

/* Reduced-motion / save-data: app.js paints a single static set with no
   ticker; just settle the layers. */
@media (prefers-reduced-motion: reduce){
  .kv-layer{ transform: scale(1.03); }
  .kv-layer.kv-left, .kv-layer.kv-right{ transform: scale(1.05); }
}

.vignette{
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 51;
  background:
    radial-gradient(60% 40% at 22% 100%, rgba(10,37,64,.20), transparent 70%),
    linear-gradient(180deg, rgba(10,37,64,.14) 0%, transparent 14%);
}

/* ============================================================
   HOME MARQUEE — a running ribbon at the nav's bottom edge. Replaces the
   static tagline; home only (inner pages have the scroll-aware nav there).
   Eight identical items + translateX(-50%) = seamless loop at any width.
   ============================================================ */
.home-marquee{
  position: absolute;
  top: var(--nav-h);
  left: 0; right: 0;
  z-index: 60;
  overflow: hidden;
  pointer-events: none;
  /* Dense ticker: solid hairline rules top + bottom, text packed tight
     between them. Borders stay opaque; only the text is dimmed (.mq-item). */
  border-top: 1px solid var(--paper-pure);
  border-bottom: 1px solid var(--paper-pure);
  padding: .4rem 0;
  opacity: .6;          /* borders + text together at 0.6 over the keyvis */
}
.mq-track{
  display: flex;
  width: max-content;   /* content-width, block-level — no inherited line-box height */
  white-space: nowrap;
  will-change: transform;
  animation: mq-scroll 48s linear infinite;
}
.mq-item{
  flex-shrink: 0;
  font-family: var(--f-sans);
  font-size: var(--t-meta);
  letter-spacing: .01em;
  line-height: 1;
  color: var(--paper-pure);
  padding-left: .6rem;
}
.mq-item::before{
  content: '·';
  margin-right: .6rem;
  color: var(--paper-pure);
  font-size: 1em;
  vertical-align: baseline;
}
@keyframes mq-scroll{ to { transform: translateX(-50%); } }

@media (prefers-reduced-motion: reduce){ .mq-track{ animation: none; } }
@media (max-width: 720px){
  .home-marquee{ top: 3.6rem; }
  .mq-item{ font-size: var(--t-label); }
}

/* ============================================================
   TIME TOY — bottom-RIGHT pill (clock + mood), mono, home only
   ============================================================ */
.time-toy{
  position: fixed;
  z-index: 80;
  right: var(--vdg);
  bottom: 1.5rem;
  display: inline-flex;
  align-items: baseline;
  gap: .55rem;
  pointer-events: none;
  color: var(--paper-pure);
  font-family: var(--f-mono);
  font-feature-settings: 'tnum' 1;
  opacity: .8;
  transition: opacity .5s var(--ease-out);
}
[data-page="work"] .time-toy{ opacity: 0; }

.tt-clock{
  font-size: .8125rem;
  font-weight: 500;
  letter-spacing: .04em;
}
.tt-mood{
  font-size: .55rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  opacity: .65;
}

@media (max-width: 720px){
  .time-toy{ right: 1rem; bottom: 1rem; }
}

/* ============================================================
   INNER PAGES — work + about
   ============================================================ */
.page-work, .page-about{
  background: var(--paper);
  color: var(--ink);
  overflow: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-strong) transparent;
}

.inner-frame, .about-frame{
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  column-gap: var(--gutter);
  /* Top padding = nav height + 3rem breathing room. Was 6rem and felt like
     dead space above the eyebrow — the editorial moment should land sooner. */
  padding: calc(var(--nav-h) + var(--s-2xl)) var(--vdg) var(--s-2xl);
  min-height: 100%;
  align-content: start;
  row-gap: var(--s-3xl);   /* 96 — steep gap between header / content / foot */
}

/* ---------- inner-head + about-head + contact-head ---------- */
.inner-head, .about-head{
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  column-gap: var(--gutter);
  row-gap: var(--s-md);
  padding-bottom: var(--s-xl);
  border-bottom: 1px solid var(--rule);
}
.inner-head .eyebrow{ grid-column: 1 / -1; }
.about-head .eyebrow{ grid-column: 1 / -1; }

.body-projects{ grid-column: 1 / span 6; align-self: start; max-width: 62ch; color: var(--ink-soft); }

/* Page title — the display moment (Druk, big). One per inner page. */
.page-title{
  grid-column: 1 / span 10;
  margin: 0;
  font-family: var(--f-druk);
  font-weight: 500;
  font-size: var(--t-display);
  line-height: .86;
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--ink);
}

/* projects head — eyebrow -> display title -> lead, stacked on the 12-col */
.inner-head-simple{ align-items: start; }
.inner-head-simple .eyebrow{ grid-column: 1 / -1; grid-row: 1; }
.inner-head-simple .page-title{ grid-column: 1 / span 10; grid-row: 2; }
.inner-head-simple .body-projects{ grid-column: 1 / span 6; grid-row: 3; align-self: start; }

/* ============================================================
   ABOUT — body copy. The sidebar + team + factsheet layout lives inline
   in about.html (.ab-* classes); only the shared body voice is here.
   ============================================================ */
.body-about{
  grid-column: 1 / span 5;
  align-self: start;
  max-width: 60ch;
  color: var(--ink-soft);
  font-size: var(--t-body);
  font-weight: 350;
  line-height: 1.4;
}

/* ============================================================
   FOOTER (inner pages)
   ============================================================ */
.inner-foot{
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  padding: 2rem 0 .5rem;
  border-top: 1px solid var(--rule);
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.foot-actions{
  display: inline-flex;
  align-items: center;
  gap: 1.5rem;
}
.foot-link, .back-btn{
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  padding: .5rem 0;
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink);
  border-bottom: 1px solid transparent;
  transition: color .35s var(--ease-out), border-color .35s var(--ease-out);
}
.foot-link:hover, .back-btn:hover{
  color: var(--sky-500);
  border-color: var(--sky-500);
}
.foot-link .fl-arc, .back-btn .bb-arc{
  font-family: var(--f-sans);
  font-size: 1rem;
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
  color: var(--sky-500);
}

@media (max-width: 720px){
  .inner-foot{ flex-direction: column; align-items: flex-start; gap: 1.5rem; }
  .foot-actions{ flex-direction: column; align-items: flex-start; gap: 1rem; }
}

/* Inner-page scrollbars — body is the scroll container, but the .page-*
   class still applies in case future content scrolls inside its own
   container (e.g. a long bio block that should scroll independently). */
body[data-page="work"]::-webkit-scrollbar,
body[data-page="about"]::-webkit-scrollbar{ width: 6px; }
body[data-page="work"]::-webkit-scrollbar-thumb,
body[data-page="about"]::-webkit-scrollbar-thumb{ background: var(--rule-strong); border-radius: 999px; }
body[data-page="work"]::-webkit-scrollbar-track,
body[data-page="about"]::-webkit-scrollbar-track{ background: transparent; }

/* ============================================================
   MOBILE — inner page layout
   ============================================================ */
@media (max-width: 720px) {

  /* Outer frames: collapse 12-col grid to single column */
  .inner-frame, .about-frame {
    grid-template-columns: 1fr;
    row-gap: 2.5rem;
    padding-top: calc(var(--nav-h) + 1.5rem);
  }

  /* Subgrid section headers: vertical stack */
  .inner-head, .about-head {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    padding-bottom: 2rem;
  }

  /* Work page: remove horizontal grid offsets, stack eyebrow → title → body */
  .inner-head-simple { gap: 1rem; }
  .inner-head-simple .body-projects { align-self: auto; max-width: 100%; }

  /* Body copy: always full-width */
  .body-about, .body-projects { max-width: 100%; }
}

@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001s !important;
  }
}

/* Visually hidden — accessible to screen readers and search engines */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   MOBILE IMPROVEMENTS — added 27 May 2026
   ============================================================ */

@media (max-width: 720px) {
  /* Work page: tighter padding */
  .inner-frame { padding-bottom: 3rem; }

  /* Nav: tighter on small screens */
  .nav { height: 3.5rem; }
  .nav-menu { gap: .75rem; }

  /* Footer: back button full width */
  .back-btn, .foot-link { font-size: .9rem; }
}

@media (max-width: 390px) {
  /* iPhone SE and similar: reduce page padding */
  .inner-frame, .about-frame {
    padding-left: 1rem;
    padding-right: 1rem;
  }
}
