/* ==========================================================================
   LAYOUT — sections, composition, image treatment
   ========================================================================== */

/* ══ LOADER ═══════════════════════════════════════════════════════════════ */
/* the mark draws itself in the centre, then fills; the wordmark follows.
   Everything sits on transform/opacity/stroke so it stays on the GPU. */
.loader{
  position:fixed; inset:0; z-index:8000;
  background:var(--paper);
  display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  padding:var(--pad);
  clip-path:inset(0 0 0 0);
  will-change:clip-path;
}
.loader__stage{
  flex:1;
  display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  gap:clamp(20px,3vw,34px);
}
.loader__mark{
  display:block;
  width:clamp(112px,15vw,190px);
  color:var(--ink);
  will-change:transform;
}
.loader__mark svg{ width:100%; height:auto; display:block; }
/* a solid logotype reads as fragments if you stroke-draw it — wipe the
   filled shape instead, which is what the mark is actually made of */
.loader__path{ fill:var(--ink); }
.loader__wordmark{
  display:block;
  font-family:var(--f-display);
  font-size:clamp(1rem,1.6vw,1.45rem);
  font-weight:500; letter-spacing:.22em; text-transform:uppercase;
  color:var(--ink);
}
/* one span per character, popped in with a stagger — reads as the name
   being typed out rather than the whole wordmark just fading up */
.loader__wordmark .lt{ display:inline-block; will-change:transform,opacity; }
.loader__wordmark .lt--sp{ white-space:pre; }

.loader__foot{
  width:100%;
  display:flex; align-items:baseline; justify-content:space-between;
  gap:var(--gut);
  padding-bottom:18px;
}
.loader__role{ font-size:var(--t-meta); color:var(--ink-45); }
.loader__count{
  font-size:var(--t-meta); color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.loader__bar{ height:1px; width:100%; background:var(--ink-12); overflow:hidden; }
.loader__bar i{
  display:block; height:100%; width:100%; background:var(--ink);
  transform:scaleX(0); transform-origin:0 50%;
}

/* ══ HEADER ═══════════════════════════════════════════════════════════════ */
.site-head{
  position:fixed; top:0; left:0; right:0; z-index:100;
  height:var(--head-h);
  padding:0 var(--pad);
  display:grid;
  grid-template-columns:calc(var(--col)*3 + var(--gut)*2) 1fr auto auto;
  align-items:center;
  gap:var(--gut);
  /* explicit placement so a page that omits the role keeps everything put */
  /* a real colour switch, not a blend: difference washes the wordmark out to
     mid-grey wherever the photograph underneath is bright */
  color:var(--ink);
  font-size:var(--t-meta);
  line-height:1;
  transition:transform .62s var(--e-snap), opacity .4s var(--e-soft),
             color .45s var(--e-soft), background-color .45s var(--e-soft),
             box-shadow .45s var(--e-soft), backdrop-filter .45s var(--e-soft);
  will-change:transform;
}
.site-head.is-over-media{ color:var(--paper); }
/* once the page has moved, the bar takes a ground of its own so content
   passing beneath it reads as behind, not colliding with, the wordmark.
   Skipped over the hero and the dark interlude, which supply their own. */
.site-head.is-scrolled:not(.is-over-media){
  background:rgba(242,240,235,.86);
  -webkit-backdrop-filter:blur(16px) saturate(120%);
          backdrop-filter:blur(16px) saturate(120%);
  box-shadow:0 1px 0 var(--line);
}
/* gets out of the way going down, comes back the moment you scroll up */
.site-head.is-hidden{ transform:translate3d(0,-120%,0); opacity:0; }
.site-head__brand{ grid-column:1; }
.site-head__role{ grid-column:2; }
.site-head__nav{ grid-column:3; }
.site-head__loc{ grid-column:4; }
.site-head__brand{
  align-items:center; gap:11px;
  font-size:16px; font-weight:500; letter-spacing:-.015em;
}
.site-head__mark{ width:20px; display:block; }
.site-head__mark svg{ width:100%; height:auto; }
.site-head__role{ opacity:.7; }
.site-head__nav{ display:flex; gap:22px; margin-right:26px; }
/* the home/case-study header has no trailing role+loc meta: the nav spans
   the last two tracks so the empty column's gap can't hold it off the
   margin. :nth-last-child(2) rather than :last-child now that the mobile
   .menu-btn always follows the nav as the true last child. */
.site-head__nav:nth-last-child(2){ margin-right:0; grid-column:3 / -1; justify-self:end; }
.site-head__nav a{ position:relative; padding:4px 0; }
.site-head__nav a::after{
  content:""; position:absolute; left:0; bottom:0;
  width:100%; height:1px; background:currentColor;
  transform:scaleX(0); transform-origin:100% 50%;
  transition:transform .55s var(--e-brand);
}
.site-head__nav a:hover::after,
.site-head__nav a.is-current::after{ transform:scaleX(1); transform-origin:0 50%; }
.site-head__loc{ display:flex; align-items:center; opacity:.7; }
.site-head__loc .dot{ background:currentColor; }

/* ── mobile menu toggle — hidden on desktop, shown in responsive.css ────── */
.menu-btn{
  display:none;
  grid-column:4;
  justify-self:end;
  width:34px; height:34px;
  align-items:center; justify-content:center;
  flex-direction:column; gap:6px;
}
.menu-btn__bar{
  display:block;
  width:22px; height:1.6px;
  background:currentColor;
  transition:transform .45s var(--e-brand), opacity .3s var(--e-soft);
}
/* morphs into an X — driven by a class the open/close JS toggles */
.menu-btn.is-open .menu-btn__bar:first-child{ transform:translateY(3.8px) rotate(45deg); }
.menu-btn.is-open .menu-btn__bar:last-child{ transform:translateY(-3.8px) rotate(-45deg); }

/* ── mobile nav overlay ──────────────────────────────────────────────────
   Sits just under the header's own z-index so the toggle button (and its
   X state) stays in place and clickable the whole time the panel is open,
   rather than needing to be re-parented or bumped above it dynamically. */
.mnav{
  position:fixed; inset:0; z-index:90;
  display:flex; flex-direction:column; justify-content:center;
  padding:var(--pad);
  background:var(--ink);
  clip-path:inset(0 0 100% 0);
  opacity:0;
  pointer-events:none;
  will-change:clip-path;
}
.mnav__list{
  display:flex; flex-direction:column;
  gap:clamp(10px,2.4vw,18px);
}
.mnav__list a{
  display:block;
  font-family:var(--f-display);
  font-size:clamp(2.4rem,11vw,3.6rem);
  font-weight:700; font-stretch:108%;
  letter-spacing:-.03em; text-transform:uppercase;
  color:var(--paper);
  opacity:0; transform:translateY(22px);
  transition:color .25s var(--e-soft);
}
.mnav__list a:hover,
.mnav__list a:active,
.mnav__list a:focus-visible{ color:var(--acc); }
.mnav__foot{
  margin-top:clamp(28px,6vw,52px);
  font-size:var(--t-meta);
  color:rgba(242,240,235,.5);
  opacity:0; transform:translateY(14px);
}

/* ══ 01 · HERO ════════════════════════════════════════════════════════════ */
.stage-a{ position:relative; }
/* sticky: the next section rises over the poster instead of pushing it —
   the first of the site's overlap transitions */
.hero{
  position:sticky; top:0; z-index:0;
  height:100svh; min-height:600px;
  overflow:hidden;
}
.hero__stage{
  position:absolute; inset:0;
  overflow:hidden;
  will-change:transform;
}
.hero__media{
  position:absolute; inset:0;
  will-change:transform;
}
.hero__media img{
  width:100%; height:100%;
  object-fit:cover; object-position:50% 44%;
  transform:translate3d(0,0,0) scale(1.04);
}
/* cinematic scrim: a vignette plus a floor gradient, so display type reads
   over the bright keyboard without flattening the photograph */
.hero__scrim{
  position:absolute; inset:0; z-index:2;
  pointer-events:none;
  /* a bare color can only be the LAST layer in a `background` list — as the
     first item this made the whole declaration invalid and the browser
     dropped it entirely, so the scrim had NO background at all until this
     was written as a flat-color gradient instead */
  background:
    linear-gradient(rgba(10,18,14,.30), rgba(10,18,14,.30)),
    linear-gradient(to top, rgba(14,26,20,.82) 0%, rgba(14,26,20,.42) 26%, rgba(14,26,20,0) 58%),
    radial-gradient(118% 96% at 50% 42%, rgba(14,26,20,.22) 26%, rgba(14,26,20,.56) 100%),
    /* the fixed header sits over this top band the whole time the hero is in
       view — it needs to read against anything behind it, light tablet or
       dark mat alike, so this goes near-solid at the very top rather than
       leaning on the photograph to cooperate */
    linear-gradient(to bottom, rgba(8,14,11,.94) 0%, rgba(10,18,14,.72) 7%, rgba(14,26,20,.42) 15%, rgba(14,26,20,0) 30%);
}
/* headline and statement are one centred block in the middle of the frame;
   only the scroll cue and the index stay pinned to the floor */
.hero__center{
  position:absolute; inset:0; z-index:3;
  display:flex; flex-direction:column;
  justify-content:center; align-items:center;
  text-align:center;
  padding:0 var(--pad);
  color:var(--paper);
  pointer-events:none;
}
.hero__type{
  display:flex; flex-direction:column; align-items:center;
  width:100%;
}
.hero__word{
  font-family:var(--f-display);
  font-size:clamp(3rem,13.5vw,12.4rem);
  font-weight:700; font-stretch:110%;
  line-height:.8; letter-spacing:-.045em;
  text-transform:uppercase;
  color:var(--paper);
  will-change:transform;
}
/* CRAFTING / DIGITAL frame the solid EXPERIENCES line as an outline — full
   white, full opacity, so the stroke still reads against the photograph */
.hero__word--a,
.hero__word--b{
  color:transparent;
  -webkit-text-stroke:1.6px var(--paper);
  paint-order:stroke fill;
}
/* line one holds CRAFTING and DIGITAL on one baseline, pushed to the margins;
   line two lands EXPERIENCES full measure underneath */
.hero__row{
  display:flex; align-items:baseline; justify-content:center;
  gap:clamp(18px,4.4vw,64px);
}
.hero__word--a,
.hero__word--b{ font-size:clamp(2.2rem,8.4vw,7.6rem); }
/* a hair of air so the solid line doesn't clip the outlined one above it */
.hero__word--c{
  font-size:clamp(2.6rem,12.2vw,11rem);
  white-space:nowrap;
  margin-top:clamp(5px,1vh,15px);
}

.hero__statement{
  width:75%;
  margin-top:clamp(24px,3.4vh,44px);
  font-size:clamp(1.35rem,2.7vw,2.44rem);
  line-height:1.14; letter-spacing:-.03em;
  text-wrap:balance;
}
.hero__scroll{
  position:absolute; z-index:5;
  left:var(--pad); bottom:calc(var(--pad) + 6px);
  align-items:center; gap:10px;
  font-size:var(--t-meta);
  color:var(--paper);
}
.hero__scroll-line{
  width:34px; height:1px; background:currentColor; display:block;
  transform-origin:0 50%;
  animation:scrollLine 2.6s var(--e-soft) infinite;
}
@keyframes scrollLine{
  0%,100%{ transform:scaleX(1); opacity:1; }
  50%{ transform:scaleX(.4); opacity:.5; }
}
.hero__index{
  position:absolute; z-index:5;
  right:var(--pad); bottom:calc(var(--pad) + 6px);
  font-size:var(--t-meta); color:rgba(242,240,235,.74);
}
.hero__index span{ margin:0 6px; color:rgba(242,240,235,.4); }

/* ══ 02 · MANIFESTO ═══════════════════════════════════════════════════════ */
.manifesto{
  position:relative; z-index:2;
  background:var(--paper);
  min-height:100svh;
  display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  padding:clamp(90px,14vh,170px) var(--pad);
  overflow:hidden;
}
.manifesto__type{
  position:relative; z-index:2;
  text-align:center;
  pointer-events:none;
}
/* two word-groupings for the same statement — a narrow column needs
   different line breaks, not just a narrower wrap of the same ones */
.manifesto__type--mobile{ display:none; }
.mline{
  display:block; overflow:hidden;
  font-family:var(--f-display);
  font-size:var(--t-display);
  font-weight:700; font-stretch:108%;
  line-height:.86; letter-spacing:-.04em;
  text-transform:uppercase;
}
.mline .hl{ color:var(--acc); }
.manifesto__canvas{
  position:absolute; inset:0; z-index:3;
  width:100%; height:100%;
  cursor:grab;
}
.manifesto__canvas:active{ cursor:grabbing; }
.manifesto__hint{
  position:relative; z-index:2;
  margin-top:38px;
  font-size:var(--t-meta); color:var(--ink-45);
  pointer-events:none;
}

/* ══ 03 · INTRO ═══════════════════════════════════════════════════════════ */
.intro{
  padding:clamp(60px,11vh,150px) var(--pad) clamp(80px,13vh,190px);
  display:grid;
  grid-template-columns:repeat(12,1fr);
  gap:var(--gut) var(--gut);
  align-items:start;
}
/* one explicit column so the portrait's height can't stretch the rows and
   blow a gap between the greeting and the note */
.intro__col{ grid-column:1 / 9; }
.intro__lead{ grid-column:auto; }
.intro__greet{
  font-size:var(--t-lead);
  line-height:1.12; letter-spacing:-.03em;
}
/* the left column reads as one continuous statement:
   greeting → note → figures, with no dead air between them */
.intro__note{ margin-top:clamp(26px,3.2vw,48px); }
/* the copy runs the width of its column instead of stopping short of it */
.intro__note p{ font-size:var(--t-body); line-height:1.6; color:var(--ink-70); max-width:66ch; }
.intro__note p + p{ margin-top:1.3em; }

.intro__media{
  grid-column:9 / 13;
  margin-top:clamp(28px,5vw,74px);
}
/* capped so the portrait balances the text column instead of towering over it
   on wide screens, where four grid columns get very wide */
.intro__media-inner{
  position:relative;
  aspect-ratio:4/5;
  max-height:min(72vh,620px);
  overflow:hidden;
  background:var(--paper-2);
  clip-path:inset(0 0 100% 0);
  will-change:clip-path;
}
.intro__media img{
  width:100%; height:118%;
  object-fit:cover; object-position:50% 6%;
  filter:saturate(.82) contrast(1.04);
  will-change:transform;
}
.intro__media figcaption{
  margin-top:12px;
  font-size:var(--t-meta); color:var(--ink-45);
}
.intro__media figcaption span{ margin:0 5px; color:var(--ink-28); }

.stats{
  margin-top:clamp(34px,4.2vw,60px);
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:var(--gut);
  border-top:1px solid var(--line);
  padding-top:20px;
}
.stats li{ display:flex; flex-direction:column; gap:6px; }
.stats__fig{
  font-family:var(--f-display);
  font-size:clamp(2.2rem,4.4vw,3.6rem);
  font-weight:600; font-stretch:104%;
  line-height:.92; letter-spacing:-.04em;
  font-variant-numeric:tabular-nums;
}
.stats__fig--inf{ font-weight:400; }
.stats__lab{ font-size:var(--t-meta); color:var(--ink-45); }

/* ══ 04 · WORK ════════════════════════════════════════════════════════════ */
.work{ padding-bottom:clamp(70px,10vh,140px); }
.work__head{
  padding:0 var(--pad) clamp(28px,4vw,48px);
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:var(--gut);
}
.work__count{ font-size:var(--t-meta); color:var(--ink-45); }
.work__count span{ margin:0 6px; color:var(--ink-28); }

/* two-column gallery. The second column drops half a card so the grid reads
   as a composition rather than a spreadsheet. */
/* three columns: the thumbnails ship at a fixed 382px, so a two-column card
   was stretching them to ~2x their native width and reading as soft/pixel-y */
.work__grid{
  padding:0 var(--pad);
  display:grid;
  grid-template-columns:repeat(3,1fr);
  column-gap:var(--gut);
  row-gap:clamp(40px,5vw,88px);
}
.work__grid .card:nth-child(3n+2){ margin-top:clamp(30px,5vw,84px); }
.work__grid .card:nth-child(3n+3){ margin-top:clamp(14px,2.2vw,36px); }

.card{
  display:block;
  cursor:none;
}
.card__mat{
  position:relative;
  background:var(--tint,var(--paper-2));
  padding:clamp(18px,2.2vw,40px);
  overflow:hidden;
  clip-path:inset(0 0 100% 0);
  will-change:clip-path;
}
/* every gallery thumbnail ships at the same 382×286 export, so the plate is
   sized to that exact ratio — no cropping, and no second layer of letterbox
   stacked on top of the white padding already baked into the artwork */
.card__plate{
  position:relative;
  aspect-ratio:382/286;
  overflow:hidden;
  background:#fff;
  box-shadow:
    0 20px 44px -20px rgba(16,35,27,.34),
    0 3px 10px -3px rgba(16,35,27,.10);
}
.card__plate img{
  width:100%; height:100%;
  object-fit:cover;
  transform:scale(1.04);
  transition:transform 1.1s var(--e-brand);
  will-change:transform;
}
.card:hover .card__plate img{ transform:scale(1.09); }

/* the cue rises out of the mat's bottom edge on hover */
.card__cue{
  position:absolute; left:0; bottom:0;
  padding:11px clamp(18px,2.2vw,40px);
  font-size:10px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--acc-ink); background:var(--acc);
  transform:translate3d(0,100%,0);
  transition:transform .6s var(--e-brand);
}
.card:hover .card__cue,
.card:focus-visible .card__cue{ transform:translate3d(0,0,0); }

/* every cell placed explicitly: a row-spanning item plus baseline alignment
   collapses the two rows into one and the title lands on the category */
.card__meta{
  margin-top:16px;
  padding-top:14px;
  border-top:1px solid var(--line);
  display:grid;
  grid-template-columns:auto 1fr auto;
  grid-template-rows:auto auto;
  column-gap:var(--gut);
  row-gap:6px;
  align-items:start;
  font-size:var(--t-meta);
}
.card__idx{
  grid-area:1 / 1 / 3 / 2;
  color:var(--ink-45); font-variant-numeric:tabular-nums;
  transition:color .45s var(--e-soft);
}
.card:hover .card__idx{ color:var(--acc); }
.card__name{
  grid-area:1 / 2 / 2 / 3;
  font-size:clamp(1rem,1.3vw,1.16rem);
  font-weight:400; letter-spacing:-.025em; line-height:1.2;
  transition:transform .55s var(--e-brand);
}
.card:hover .card__name{ transform:translate3d(6px,0,0); }
.card__year{
  grid-area:1 / 3 / 2 / 4;
  color:var(--ink-45); font-variant-numeric:tabular-nums; text-align:right;
}
.card__cat{ grid-area:2 / 2 / 3 / 3; color:var(--ink-70); }
.card__disc{ grid-area:2 / 3 / 3 / 4; color:var(--ink-45); text-align:right; }

.res{
  grid-column:1 / 13;
  margin-top:clamp(34px,4.6vw,62px);
  display:grid; grid-template-columns:repeat(4,1fr); gap:var(--gut);
  border-top:1px solid var(--line); padding-top:18px;
}
.res li{ display:flex; flex-direction:column; gap:5px; }
.res b{
  font-family:var(--f-display);
  font-size:clamp(1.5rem,2.5vw,2.05rem);
  font-weight:600; font-stretch:104%;
  line-height:1; letter-spacing:-.035em;
}
.res span{ font-size:var(--t-meta); color:var(--ink-45); line-height:1.4; }

/* ══ 05 · INTERLUDE (dark) ════════════════════════════════════════════════ */
/* sized to the viewport so the pinned frame is a composed, centred plate */
.interlude{
  position:relative;
  background:var(--ink);
  color:var(--paper);
  padding:var(--head-h) var(--pad) calc(var(--pad) + 20px);
  height:100svh; min-height:560px;
  display:flex; align-items:center;
  overflow:hidden;
}
.interlude::before{
  content:""; position:absolute; inset:0;
  background:radial-gradient(90% 70% at 20% 30%, rgba(220,75,34,.16), transparent 62%);
  pointer-events:none;
}
.interlude__inner{ position:relative; z-index:2; width:100%; }
.interlude__lab{
  position:absolute; top:var(--head-h); left:var(--pad); z-index:3;
  font-size:11px; letter-spacing:.12em; text-transform:uppercase;
  color:rgba(242,240,235,.58);
}
.interlude__type{
  font-family:var(--f-display);
  font-size:clamp(2.1rem,5.6vw,5rem);
  font-weight:700; font-stretch:106%;
  line-height:.94; letter-spacing:-.038em;
  text-transform:uppercase;
  max-width:19ch;
}
.interlude__type .fw{ color:rgba(242,240,235,.16); transition:color .1s linear; }

/* ══ 06 · CAPABILITIES ════════════════════════════════════════════════════ */
.cap{ padding:clamp(80px,12vh,170px) var(--pad) clamp(60px,9vh,120px); }
.cap__head{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:var(--gut); margin-bottom:clamp(24px,3.4vw,44px);
}
.cap__hint{ font-size:var(--t-meta); color:var(--ink-45); }

.cap__row{ border-top:1px solid var(--line); }
.cap__row:last-child{ border-bottom:1px solid var(--line); }
.cap__btn{
  position:relative;
  width:100%;
  display:grid;
  grid-template-columns:calc(var(--col)*.6) minmax(0,5fr) minmax(0,4fr) 22px;
  gap:var(--gut);
  align-items:center;
  padding:17px 0;
  font-size:var(--t-meta);
  cursor:none;
}
.cap__btn::before{
  content:""; position:absolute; inset:0 calc(var(--pad) * -1);
  background:var(--paper-2);
  transform:scaleY(0); transform-origin:50% 100%;
  transition:transform .5s var(--e-brand);
  z-index:-1;
}
.cap__row:hover .cap__btn::before,
.cap__row.is-open .cap__btn::before{ transform:scaleY(1); transform-origin:50% 0; }
/* hover nudge rides on transform, never on padding */
.cap__i,.cap__n,.cap__d{ transition:transform .55s var(--e-brand); }
.cap__row:hover .cap__i,
.cap__row:hover .cap__n,
.cap__row:hover .cap__d{ transform:translate3d(13px,0,0); }
.cap__i{ color:var(--ink-45); font-variant-numeric:tabular-nums; }
.cap__n em{ font-style:normal; color:var(--ink-45); }
.cap__d{ color:var(--ink-70); }
.cap__chev{
  position:relative; width:11px; height:11px; justify-self:end;
}
.cap__chev::before,.cap__chev::after{
  content:""; position:absolute; top:50%; left:0;
  width:11px; height:1px; background:currentColor;
  transition:transform .5s var(--e-brand);
}
.cap__chev::after{ transform:rotate(90deg); }
.cap__row.is-open .cap__chev::after{ transform:rotate(0deg); }

/* 0fr → 1fr animates the grid track, not the element's height, so the panel
   opens without layout thrash and without JS measuring anything */
.cap__panel{
  display:grid;
  grid-template-rows:0fr;
  overflow:hidden;              /* the child's padding must not escape the 0fr track */
  transition:grid-template-rows .72s var(--e-brand);
}
.cap__row.is-open .cap__panel{ grid-template-rows:1fr; }
/* no padding on the grid item itself — padding survives a 0fr track and
   would leak a sliver of the closed panel. The children carry it instead. */
.cap__panel-in{
  min-height:0; overflow:hidden;
  display:grid;
  grid-template-columns:calc(var(--col)*.6) minmax(0,5fr) minmax(0,4fr) 22px;
  gap:var(--gut);
  padding:0;
}
/* spacing lives on the children, inside the clipped box, so the closed panel
   still measures exactly zero */
.cap__panel-in > *{ padding:16px 0 30px; }
.cap__panel-in p{
  grid-column:2; font-size:var(--t-meta);
  line-height:1.55; color:var(--ink-70); max-width:52ch;
}
.tags{
  grid-column:3;
  display:flex; flex-wrap:wrap; gap:6px; align-content:flex-start;
}
.tags li{
  font-size:10px; letter-spacing:.1em; text-transform:uppercase;
  padding:6px 11px; border:1px solid var(--line); border-radius:99px;
  color:var(--ink-70);
}

/* ══ 07 · PROFILE ═════════════════════════════════════════════════════════ */
.profile{
  padding:clamp(70px,11vh,160px) 0 clamp(30px,4vh,60px);
  overflow:hidden;
}
.profile__name{
  padding:0 var(--pad);
  margin-bottom:clamp(38px,5.5vw,80px);
  pointer-events:none;
}
.pn{
  display:block;
  font-family:var(--f-display);
  /* leaves slack in the measure so the scroll drift never pushes the
     statement past the page edge */
  font-size:clamp(1.75rem,6.6vw,5.9rem);
  font-weight:700; font-stretch:108%;
  line-height:.94; letter-spacing:-.04em;
  text-transform:uppercase;
  will-change:transform;
}
.pn--b{ text-align:right; color:var(--ink-28); }

.profile__grid{
  padding:0 var(--pad);
  display:grid; grid-template-columns:repeat(12,1fr); gap:var(--gut);
  border-top:1px solid var(--line); padding-top:80px;
}
/* the side column is the masthead for the bio, not a footnote to it — the
   eyebrow carries the accent and the role sits at statement size */
.profile__side{ grid-column:1 / 4; }
.profile__side .lab{ color:var(--acc); }
.profile__role{
  margin:16px 0 26px;
  font-size:clamp(1.15rem,1.7vw,1.5rem);
  font-weight:700;
  line-height:1.25; letter-spacing:-.025em;
  color:var(--ink);
}
.profile__role span{
  display:inline-block; margin-top:4px;
  font-weight:400;
  color:var(--ink-45);
}
.profile__side .link-ext{ font-size:var(--t-body); }
.profile__copy{ grid-column:5 / 12; }
.profile__copy p{
  font-size:var(--t-body);
  line-height:1.6; color:var(--ink-70);
  max-width:58ch;
}
.profile__copy p + p{ margin-top:1.5em; }

/* ══ 08 · CONTACT ═════════════════════════════════════════════════════════ */
.contact{
  position:relative;
  min-height:100svh;
  padding:clamp(70px,11vh,150px) var(--pad) clamp(30px,4vw,50px);
  display:flex; flex-direction:column;
  align-items:center; justify-content:center;
  text-align:center;
}
.contact__type{ width:100%; }
.cline{
  display:block; overflow:hidden;
  font-family:var(--f-display);
  font-size:clamp(2.7rem,11.5vw,10.4rem);
  font-weight:700; font-stretch:110%;
  line-height:.85; letter-spacing:-.045em;
  text-transform:uppercase;
}
.cline--hl{ color:var(--acc); }
.contact__row{
  margin-top:clamp(44px,6vw,88px);
  display:flex; flex-direction:column; align-items:center; gap:26px;
  max-width:46ch;
}
.contact__note{
  font-size:var(--t-meta); line-height:1.55; color:var(--ink-70);
}
.contact__mail{
  position:relative;
  font-size:clamp(1.05rem,1.9vw,1.55rem);
  letter-spacing:-.03em;
  padding-bottom:6px;
  overflow:hidden;
}
.contact__mail::after{
  content:""; position:absolute; left:0; bottom:0;
  width:100%; height:1px; background:currentColor;
  transform:scaleX(1); transform-origin:100% 50%;
  transition:transform .6s var(--e-brand);
}
.contact__mail:hover::after{ transform:scaleX(0); }
.contact__mail-in{
  display:inline-block;
  transition:transform .6s var(--e-brand), color .4s var(--e-soft);
}
.contact__mail:hover .contact__mail-in{ transform:translateY(-2px); color:var(--acc); }

/* ══ CONTACT FORM ═════════════════════════════════════════════════════════ */
/* the form fills the measure of the section rather than sitting in a narrow
   strip with dead space beside it; name and email share the first row */
.cf{
  width:100%;
  max-width:min(880px, 100%);
  margin-top:clamp(44px,6vw,80px);
  text-align:left;
  display:grid;
  grid-template-columns:1fr 1fr;
  column-gap:var(--gut);
  row-gap:clamp(20px,2.4vw,28px);
}
.cf > .cf__field:nth-of-type(1){ grid-column:1; }
.cf > .cf__field:nth-of-type(2){ grid-column:2; }
.cf > .cf__field:nth-of-type(3){ grid-column:1 / -1; }
.cf__row{ grid-column:1 / -1; }
.cf__status{ grid-column:1 / -1; }
.cf__field label{
  display:block;
  margin-bottom:9px;
  font-size:var(--t-meta);
  color:var(--ink);
}
.cf__field label b{ font-weight:500; color:var(--acc); }

.cf input,
.cf textarea{
  width:100%;
  padding:15px 18px;
  font-family:inherit;
  font-size:var(--t-body);
  color:var(--ink);
  background:transparent;
  border:1px solid var(--line);
  border-radius:2px;
  transition:border-color .35s var(--e-soft), background-color .35s var(--e-soft);
}
.cf textarea{ resize:vertical; min-height:132px; line-height:1.5; }
.cf input::placeholder,
.cf textarea::placeholder{ color:var(--ink-28); }
.cf input:hover,
.cf textarea:hover{ border-color:var(--ink-28); }
.cf input:focus,
.cf textarea:focus{
  outline:none;
  border-color:var(--ink);
  background:rgba(255,255,255,.4);
}
.cf input:focus-visible,
.cf textarea:focus-visible{ outline:none; }

.cf__field--check input{ max-width:200px; }

/* errors stay in the layout only when they apply, so nothing jumps twice */
.cf__err{
  display:none;
  margin-top:8px;
  font-size:11px; letter-spacing:.1em; text-transform:uppercase;
  color:var(--acc);
}
.cf__field.is-invalid .cf__err{ display:block; }
.cf__field.is-invalid input,
.cf__field.is-invalid textarea{ border-color:var(--acc); }

/* the check and the send button share a baseline. The error is taken out of
   flow so showing it can't shunt the button down a row. */
.cf__row{
  display:flex; align-items:flex-end; flex-wrap:wrap;
  gap:clamp(16px,2.2vw,26px);
}
.cf__row .cf__field--check{ flex:1 1 240px; }
.cf__row .cf__field--check input{ max-width:none; }
.cf__row .cf__field{ margin-top:0; position:relative; }
.cf__row .cf__err{ position:absolute; top:100%; left:0; margin-top:8px; }

.cf__send{
  padding:15px 30px;
  font-size:var(--t-meta); letter-spacing:.08em; text-transform:uppercase;
  text-align:center;   /* the global button reset defaults to left */
  color:var(--paper); background:var(--ink);
  border-radius:999px;
  transition:background-color .4s var(--e-soft), transform .5s var(--e-brand);
}
.cf__send:hover{ background:var(--acc); transform:translate3d(0,-2px,0); }
.cf__send:active{ transform:translate3d(0,0,0); }
.cf__send[disabled]{ opacity:.5; pointer-events:none; }

.cf__status{
  margin-top:22px;
  font-size:var(--t-meta);
  color:var(--ink-70);
  min-height:1.4em;
}
.cf__status.is-ok{ color:var(--ink); }

/* ══ FOOTER ═══════════════════════════════════════════════════════════════ */
.foot{
  display:grid; grid-template-columns:1fr auto 1fr;
  align-items:center; gap:var(--gut);
  padding:0 var(--pad) calc(var(--pad) + 4px);
  font-size:var(--t-meta); color:var(--ink-45);
}
.foot__c{ display:flex; align-items:center; gap:11px; }
.foot__c a{ color:var(--ink); position:relative; padding-bottom:2px; }
.foot__c a::after{
  content:""; position:absolute; left:0; bottom:0; width:100%; height:1px;
  background:currentColor; transform:scaleX(0); transform-origin:100% 50%;
  transition:transform .5s var(--e-brand);
}
.foot__c a:hover::after{ transform:scaleX(1); transform-origin:0 50%; }
.foot__c li[aria-hidden]{ color:var(--ink-28); }
.foot__r{ text-align:right; }
