  :root{
    --paper:#ffffff;
    --paper-2:#f2f1ef;
    --ink:#161616;
    --ink-soft:#5c5c5c;
    --rule:#e3e2e0;
    --measure:68ch;
    --sans:"Inter",ui-sans-serif,-apple-system,"Helvetica Neue",Arial,sans-serif;
  }

  *{box-sizing:border-box;margin:0;padding:0}

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

  body{
    background:var(--paper);
    color:var(--ink);
    font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,"Times New Roman",serif;
    font-size:17px;
    line-height:1.65;
    -webkit-font-smoothing:antialiased;
    overflow-x:hidden;
  }

  .wrap{max-width:1240px;margin:0 auto;padding:0 32px}

  /* ---------- type ---------- */
  h1,h2,h3{font-weight:400;letter-spacing:-0.02em;line-height:1.08}
  h1{font-size:clamp(2.6rem,6.4vw,5.4rem)}
  h2{font-size:clamp(1.9rem,3.4vw,3rem)}
  h3{font-size:clamp(1.15rem,1.7vw,1.5rem);letter-spacing:-0.01em}

  .eyebrow{
    font-family:ui-sans-serif,-apple-system,"Helvetica Neue",Arial,sans-serif;
    font-size:.7rem;
    letter-spacing:.18em;
    text-transform:uppercase;
    color:var(--ink-soft);
  }

  .lede{font-size:clamp(1.15rem,1.9vw,1.5rem);line-height:1.5;color:var(--ink)}
  p{color:var(--ink-soft);max-width:var(--measure)}
  p + p{margin-top:1.1em}

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

  /* ---------- nav ---------- */
  header{
    position:fixed;inset:0 0 auto 0;z-index:50;
    background:transparent;
    /* opacity and transform are scrubbed frame-by-frame from scroll position
       in the script below — deliberately NOT transitioned here, since a
       transition would lag behind the scrub and fight it */
    /* starting state: hidden above the fold until the script measures scroll */
    opacity:0;
    transform:translateY(-100%);
    pointer-events:none;
    will-change:opacity,transform;
  }

  /* header spans the full viewport so the wordmark sits near the left edge,
     rather than being inset by the centred 1240px content container */
  header .wrap{max-width:none;padding:0 clamp(22px,3.2vw,48px)}

  nav{display:flex;align-items:center;justify-content:space-between;height:74px;gap:24px}

  /* left cluster: wide gap pushes the links toward centre */
  .nav-left{display:flex;align-items:center;gap:clamp(64px,11vw,180px)}

  .brand{
    font-family:var(--sans);
    font-weight:600;
    font-size:1.1rem;
    letter-spacing:-0.01em;
    color:var(--ink);
  }

  .nav-links{
    display:flex;gap:clamp(22px,2.6vw,38px);
    font-family:var(--sans);
    font-weight:600;
    font-size:.94rem;letter-spacing:0;
  }
  .nav-links a,.nav-cta{position:relative;padding-bottom:3px;color:var(--ink);transition:opacity .25s}
  .nav-cta{
    font-family:var(--sans);
    font-weight:600;
    font-size:.94rem;letter-spacing:0;color:var(--ink);
    /* nav is space-between, so this would otherwise sit hard against the
       right padding edge. Pulls it inboard, scaling with the viewport so
       it doesn't collide with the nav links on narrower screens. */
    margin-right:clamp(0px,5vw,110px);
  }
  .nav-links a::after,.nav-cta::after{
    content:"";position:absolute;left:0;bottom:0;height:1px;width:100%;
    background:var(--ink);transform:scaleX(0);transform-origin:right;
    transition:transform .38s cubic-bezier(.4,0,.2,1);
  }
  .nav-links a:hover,.nav-cta:hover{opacity:.6}
  .nav-links a:hover::after,.nav-cta:hover::after{transform:scaleX(1);transform-origin:left}

  /* mobile-only duplicate of the CTA — see Header.astro. Hidden here, and
     switched on inside the responsive block below. */
  .nav-cta-mobile{display:none}

  .nav-toggle{display:none;background:none;border:0;font:inherit;font-size:.94rem;font-weight:600;color:var(--ink);cursor:pointer;font-family:var(--sans)}

  /* ---------- hero ---------- */
  .hero{
    position:relative;min-height:100vh;
    display:flex;align-items:flex-end;
    padding-bottom:clamp(28px,5vh,56px);
    overflow:hidden;
  }
  /* Dark ground, sampled from the footage's own mean tone. It matters for more
     than the join: the wordmark over this is white, so if the video and its
     poster both fail to load, paper-2 would leave white type on near-white. */
  .hero-media{position:absolute;inset:0;z-index:0;background:#21180f}
  /* img and video share this: the hero was a photograph and is now footage,
     and either has to fill the same box the same way. */
  .hero-media img,
  .hero-media video{
    width:100%;height:100%;display:block;
    object-fit:cover;
    /* keeps the subject's face in frame as the viewport gets taller */
    object-position:50% 38%;
  }
  /* Scrim for white type. The lower left is already dark (mean 77/255) but
     the wall behind her runs bright, so the gradient is angled — heavier on
     the right where the background is lightest, lighter over the figure. */
  .hero-media::after{
    content:"";position:absolute;inset:0;
    background:
      linear-gradient(180deg,
        rgba(0,0,0,0) 42%,
        rgba(0,0,0,.18) 68%,
        rgba(0,0,0,.40) 88%,
        rgba(0,0,0,.52) 100%),
      linear-gradient(100deg,
        rgba(0,0,0,.22) 0%,
        rgba(0,0,0,.06) 38%,
        rgba(0,0,0,0) 62%);
  }
  /* hero text aligns to the same left edge as the header wordmark */
  .hero .wrap{
    position:relative;z-index:1;
    max-width:none;width:100%;margin:0;
    padding:0 clamp(22px,3.2vw,48px);
    text-align:left;
  }
  .hero h1{
    font-family:var(--sans);
    font-weight:600;
    font-size:clamp(3.2rem,11vw,11rem);
    line-height:.92;
    letter-spacing:-0.035em;
    color:#fff;
    max-width:none;
    text-align:left;
    margin:0;
  }

  /* ---------- statement: centred title + subtitle ---------- */
  .statement{
    min-height:88vh;
    display:flex;flex-direction:column;
    align-items:center;justify-content:center;
    text-align:center;
    padding:clamp(80px,12vh,140px) 0;
  }
  .statement h2{
    font-family:var(--sans);
    font-weight:600;
    font-size:36px;
    line-height:1.2;
    letter-spacing:-0.02em;
    color:var(--ink);
    max-width:26ch;
  }
  .statement p{
    font-size:35px;
    line-height:1.25;
    letter-spacing:-0.012em;
    color:var(--ink);
    max-width:34ch;
    margin:.2em auto 0;
  }

  /* contact page: longer copy than the home page's one-liner, so both
     sizes come down 2px to stop the block dominating the viewport */
  .statement--compact h2{font-size:34px}
  .statement--compact p{font-size:33px}

  /* Mobile. These apply to BOTH variants — the compact overrides above are
     desktop-only, so the two pages share one set of phone sizes rather
     than drifting apart.

     The big change here isn't type, it's space. `min-height:88vh` made the
     statement own almost a full screen, which reads as generous on a wide
     monitor and as a page of nothing on a phone: a couple of short lines
     marooned in emptiness, with the next section pushed off-screen. Height
     goes back to whatever the content needs, and the padding comes down
     with it. */
  @media (max-width:860px){
    /* Two 15% reductions from the desktop values, so ~72% of the original:
       88vh -> 64vh, and clamp(80,12vh,140) -> clamp(58,8.7vh,101).
       Kept proportional rather than picking fresh numbers, so the mobile
       section still reads as the same piece of design, just smaller. */
    .statement{
      min-height:64vh;
      padding:clamp(58px,8.7vh,101px) 0;
    }
    .statement h2,
    .statement--compact h2{font-size:19px;line-height:1.25}
    .statement p,
    .statement--compact p{font-size:18px;line-height:1.32;margin-top:.4em}
  }
  @media (max-width:480px){
    .statement h2,
    .statement--compact h2{font-size:17px}
    .statement p,
    .statement--compact p{font-size:16px}
  }

  /* ---------- sections ---------- */
  section{padding:clamp(84px,13vh,150px) 0}
  section.tight-top{padding-top:clamp(44px,6vh,72px)}
  .rule{height:1px;background:var(--rule);border:0}

  /* full-bleed media band */
  .bleed{width:100vw;margin-left:calc(50% - 50vw);background:var(--paper-2);line-height:0}
  /* natural aspect ratio on narrow screens; on wide ones max-height clamps the
     band and object-fit crops it, so it never eats a whole desktop screen */
  .bleed img{
    width:100%;height:auto;display:block;
    max-height:82vh;
    object-fit:cover;
    object-position:50% 34%;   /* protects the heads when it does crop */
  }

  /* ---------- about: label left, lede right, body beneath ---------- */
  /* about block runs full width, aligned to the same left edge as the header */
  .about-section{padding:clamp(18px,2.4vh,30px) 0 clamp(60px,9vh,110px)}
  .about-section .wrap{max-width:none;width:100%;margin:0;padding:0 clamp(22px,3.2vw,48px)}

  .about-grid{
    display:grid;
    grid-template-columns:minmax(120px,1fr) 3.4fr;
    column-gap:clamp(24px,4vw,64px);
    row-gap:6px;
    align-items:start;
  }
  .about-grid .about-label{grid-column:1;grid-row:1}
  .about-grid .about-lede{grid-column:2;grid-row:1}
  .about-grid .about-body{grid-column:1 / -1;grid-row:2}

  /* about typography — all Inter Semi Bold, per spec */
  .about-label{
    font-family:var(--sans);
    font-weight:700;
    font-size:16px;
    letter-spacing:0;
    text-transform:none;
    color:var(--ink);
  }
  .about-lede{
    font-family:var(--sans);
    font-weight:700;
    font-size:22px;
    line-height:1.28;
    letter-spacing:-0.01em;
    color:var(--ink);
    max-width:46ch;
    margin:0;
  }
  .about-body{margin-top:2px}
  /* matched to .showcase-text p — the two are the same kind of running
     copy, so they share a size, weight and rhythm. The lede above stays
     larger; that contrast is what makes it read as a lede. */
  .about-body p{
    font-family:var(--sans);
    font-weight:600;
    font-size:16px;
    line-height:1.36;
    letter-spacing:-0.003em;
    color:var(--ink);
    /* 78ch at 16px is about the same measured width 62ch was at 20px, so
       the block keeps its shape on the page while the type gets smaller.
       Without a cap it would span the full grid and run past 150
       characters a line on a wide screen. */
    max-width:78ch;
  }
  .about-body p + p{margin-top:.5em}

  /* ---------- showcase: offset image with text to its right ---------- */
  .showcase{padding:clamp(40px,6vh,72px) 0 clamp(60px,9vh,110px)}
  .showcase .wrap{max-width:none;width:100%;margin:0;padding:0 clamp(22px,3.2vw,48px)}
  .showcase-grid{
    display:grid;
    grid-template-columns:26fr 49fr 25fr;
    column-gap:clamp(18px,2.2vw,34px);
    align-items:start;
  }
  .showcase-rule{
    grid-column:2 / -1;grid-row:1;
    height:1px;background:var(--rule);border:0;
    margin:0 0 clamp(14px,2vh,22px);
  }
  .showcase-fig{grid-column:2;grid-row:2;margin:0;background:var(--paper-2)}
  /* portrait source in a portrait slot, so it runs at its natural ratio;
     the cap only bites on very wide screens where the column gets large */
  .showcase-fig img{
    width:100%;height:auto;display:block;
    max-height:94vh;
    object-fit:cover;
    object-position:50% 38%;
  }
  .showcase-text{grid-column:3;grid-row:2}
  .showcase-text p{
    font-family:var(--sans);
    font-weight:600;
    font-size:16px;
    line-height:1.36;
    letter-spacing:-0.003em;
    color:var(--ink);
    max-width:none;
  }
  .showcase-text p + p{margin-top:.5em}

  .split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(40px,7vw,110px);align-items:center}

  .figure{position:relative;background:var(--paper-2);overflow:hidden}
  .figure svg{width:100%;height:auto;display:block}
  .figure figcaption{
    font-family:ui-sans-serif,-apple-system,sans-serif;
    font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;
    color:var(--ink-soft);padding-top:12px;
  }

  .section-head{display:flex;justify-content:space-between;align-items:baseline;gap:40px;margin-bottom:56px}

  /* ---------- services ---------- */
  /* runs full width on the same left edge as the header, About and Showcase */
  .services{padding:clamp(40px,6vh,72px) 0 clamp(60px,9vh,110px)}
  .services .wrap{max-width:none;width:100%;margin:0;padding:0 clamp(22px,3.2vw,48px)}

  /* same 26/49/25 column rhythm as .showcase-grid, so the description column
     lines up vertically with the showcase text above it */
  .service{
    display:grid;
    grid-template-columns:26fr 49fr 25fr;
    column-gap:clamp(18px,2.2vw,34px);
    align-items:start;
    padding:34px 0 54px;
    position:relative;   /* anchor for the hover preview */
  }
  /* hairline above every row, including the first; nothing below the last */
  .service{border-top:1px solid var(--rule)}

  .service .num{
    font-family:var(--sans);
    font-weight:600;
    font-size:14px;
    line-height:1.3;
    letter-spacing:0;
    color:var(--ink);
    /* optical nudge: lines the digits' cap-height up with the 26px title */
    padding-top:3px;
  }
  .service h3{
    font-family:var(--sans);
    font-weight:500;
    font-size:26px;
    line-height:1.18;
    letter-spacing:-0.015em;
    color:var(--ink);
    /* shrink-wraps the heading so its hover area is the text itself,
       not the full width of the grid cell */
    justify-self:start;
    transition:transform .4s cubic-bezier(.4,0,.2,1);
  }
  .service h3:hover{transform:translateX(9px)}

  /* The title and its proof-of-work links share the middle column. min-width:0
     lets the link grid shrink inside it rather than force the column wider. */
  .service-head{min-width:0}
  /* No longer a grid item, so justify-self can't shrink-wrap the title any more;
     fit-content keeps its hover area to the text, as before. */
  .service-head h3{width:fit-content}

  /* Proof of work: up to four across, further rows beneath. Columns fit their
     names rather than splitting the column evenly, which keeps the grid tucked
     under a short title — but minmax(0, …) lets them give way when four long
     names won't fit, so a name ends in "…" instead of pushing past the column. */
  .service-proof{
    list-style:none;
    margin:14px 0 0;
    display:grid;
    grid-template-columns:repeat(4,minmax(0,max-content));
    column-gap:24px;
    row-gap:8px;
  }
  .service-proof li{min-width:0}
  .service-proof a,
  .service-proof span{
    display:block;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
    font-family:var(--sans);
    font-weight:500;
    font-size:14px;
    line-height:1.5;
    color:var(--ink);
  }
  /* A border rather than a text underline: text-decoration isn't drawn under
     an inline SVG, so the line would stop short of the arrow. Inline-block so
     the border runs the width of this name, not of its whole grid column. */
  .service-proof a{
    display:inline-block;
    max-width:100%;
    vertical-align:top;
    padding-bottom:2px;
    border-bottom:1px solid var(--rule);
    transition:border-color .2s;
  }
  .service-proof a:hover{border-bottom-color:var(--ink)}
  .service-proof a:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
  /* Drawn rather than typed: the ↗ character takes its shape from whatever
     font is showing it, and Inter's is a long hairline diagonal. This is the
     compact, corner-headed arrow, the same on every device. */
  .service-proof .proof-arrow{
    width:.68em;height:.68em;
    margin-left:.32em;
    fill:none;
    stroke:currentColor;
    stroke-width:1.5;
  }
  /* Folded state, set by the script. The 5 here is PROOF_CAP + 1 in
     ServiceList.astro — change the two together. */
  .service-proof.is-collapsed li:nth-child(n+5){display:none}

  .service-proof-more{
    margin-top:10px;
    padding:0;border:0;background:none;cursor:pointer;
    font-family:var(--sans);
    font-weight:500;
    font-size:14px;
    line-height:1.5;
    color:var(--ink-soft);
  }
  .service-proof-more:hover{color:var(--ink)}
  .service-proof-more:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

  /* hover preview: floats above the page and trails the cursor, but only
     while the pointer is over the title text itself (see the script below).
     z-index sits below the header (50) so the nav always stays on top. */
  .service-media{
    position:fixed;top:0;left:0;z-index:40;
    width:clamp(200px,19vw,290px);
    pointer-events:none;
    transform:translate3d(-9999px,-9999px,0);
    will-change:transform;
  }
  /* scale/opacity live on the inner wrapper so the outer transform stays
     free for cursor tracking — transitioning both on one element would fight */
  .service-media-inner{
    background:var(--paper-2);
    line-height:0;
    opacity:0;
    transform:scale(.94);
    transition:opacity .45s cubic-bezier(.4,0,.2,1),transform .6s cubic-bezier(.4,0,.2,1);
  }
  .service.hovering .service-media-inner{opacity:1;transform:scale(1)}
  .service-media img{width:100%;height:auto;display:block}

  @media (prefers-reduced-motion:reduce){
    .service-media{display:none}
  }
  .service p{
    font-family:var(--sans);
    font-weight:500;
    font-size:16px;
    line-height:1.45;
    letter-spacing:0;
    color:var(--ink);
    max-width:none;
    /* smaller nudge than the number — 16px type already sits closer to the title's cap line */
    padding-top:1px;
  }

  /* ---------- quote ---------- */
  .quote{text-align:center;padding:clamp(90px,15vh,170px) 0}
  .quote blockquote{font-size:clamp(1.5rem,3.1vw,2.5rem);line-height:1.28;max-width:22ch;margin:0 auto;letter-spacing:-0.02em}
  .quote .eyebrow{margin-top:32px;display:block}

  /* ---------- contact ---------- */
  .contact{display:grid;grid-template-columns:1fr 1fr;gap:clamp(40px,7vw,110px)}
  .field{border-bottom:1px solid var(--rule);padding:14px 0;margin-bottom:26px}
  .field label{
    display:block;font-family:ui-sans-serif,-apple-system,sans-serif;
    font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-soft);margin-bottom:8px;
  }
  .field input,.field textarea{
    width:100%;background:none;border:0;font-family:inherit;font-size:1rem;color:var(--ink);resize:none;
  }
  .field input:focus,.field textarea:focus{outline:none}
  .btn{
    display:inline-block;border:1px solid var(--ink);padding:14px 34px;
    font-family:ui-sans-serif,-apple-system,sans-serif;font-size:.78rem;
    letter-spacing:.13em;text-transform:uppercase;cursor:pointer;background:none;color:var(--ink);
    transition:background .3s,color .3s;
  }
  .btn:hover{background:var(--ink);color:var(--paper)}

  .detail-list dt{
    font-family:ui-sans-serif,-apple-system,sans-serif;
    font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-soft);
  }
  .detail-list dd{margin:6px 0 28px}

  /* ---------- footer ---------- */
  /* same full-width left edge as the header, About, Showcase and Services */
  footer{border-top:1px solid var(--rule);padding:34px 0 40px}
  footer .wrap{max-width:none;width:100%;margin:0;padding:0 clamp(22px,3.2vw,48px)}
  .foot-row{
    display:flex;justify-content:space-between;align-items:baseline;
    flex-wrap:wrap;gap:18px;
    font-family:var(--sans);
    font-weight:500;
    font-size:14px;
    line-height:1.3;
    letter-spacing:0;
    color:var(--ink);
  }

  /* ---------- scroll reveal ---------- */
  .reveal{opacity:0;transform:translateY(22px);transition:opacity .9s cubic-bezier(.4,0,.2,1),transform .9s cubic-bezier(.4,0,.2,1)}
  .reveal.in{opacity:1;transform:none}

  @media (prefers-reduced-motion:reduce){
    .reveal{opacity:1;transform:none;transition:none}
    html{scroll-behavior:auto}
  }

  /* ---------- responsive ---------- */
  @media (max-width:860px){
    .wrap{padding:0 22px}
    .nav-links{
      display:none;position:absolute;top:74px;left:0;right:0;
      background:var(--paper);flex-direction:column;gap:0;
      border-bottom:1px solid var(--rule);
    }
    .nav-links.open{display:flex}
    .nav-links a{padding:16px 22px;border-top:1px solid var(--rule)}
    .nav-toggle{display:block}
    .nav-cta{display:none}
    /* last item in the dropdown, below Recent Works */
    .nav-cta-mobile{display:block}
    .about-grid{grid-template-columns:1fr;row-gap:20px}
    .about-grid .about-label,
    .about-grid .about-lede,
    .about-grid .about-body{grid-column:1;grid-row:auto}
    .showcase-grid{grid-template-columns:1fr;row-gap:20px}
    .showcase-rule,
    .showcase-fig,
    .showcase-text{grid-column:1;grid-row:auto}
    .split,.contact{grid-template-columns:1fr;gap:40px}
    .service{grid-template-columns:1fr;row-gap:10px;padding:26px 0 34px}
    .service .num,.service .service-head,.service p{grid-column:1;padding-top:0}
    .service h3{font-size:23px}
    /* four across leaves a name about 70px on a phone — two rows of two instead */
    .service-proof{grid-template-columns:repeat(2,minmax(0,max-content))}
    .service-media{display:none}
    .hero{min-height:78vh}
  }

  /* ---------- approach: label left, two columns of running text right ---------- */
  .approach{padding:clamp(30px,4vh,48px) 0 clamp(60px,9vh,110px)}
  .approach .wrap{max-width:none;width:100%;margin:0;padding:0 clamp(22px,3.2vw,48px)}
  .approach-grid{
    display:grid;
    grid-template-columns:2fr 1fr 1fr;
    column-gap:clamp(18px,2.2vw,34px);
    align-items:start;
  }
  .approach-col p{
    font-family:var(--sans);
    font-weight:600;
    font-size:16px;
    line-height:1.36;
    letter-spacing:-0.003em;
    color:var(--ink);
    max-width:none;
  }
  /* continuous text: paragraphs run on, marked by a first-line indent
     rather than a blank line — the editorial convention */
  .approach-col p + p{margin-top:0;text-indent:1.7em}

  /* shared label style for the ruled blocks on the About page */
  .block-label{
    font-family:var(--sans);
    font-weight:700;
    font-size:16px;
    letter-spacing:0;
    color:var(--ink);
  }

  /* hairline above a block, with breathing room beneath it */
  .ruled{
    border-top:1px solid var(--rule);
    padding-top:clamp(22px,3vh,34px);
  }

  /* ---------- cross-document page transitions ---------- */
  /* the browser cross-fades between documents on same-origin navigation;
     where unsupported this rule is ignored and you get a normal page load */
  @view-transition{navigation:auto}
  ::view-transition-old(root),
  ::view-transition-new(root){
    animation-duration:.42s;
    animation-timing-function:cubic-bezier(.4,0,.2,1);
  }
  @media (prefers-reduced-motion:reduce){
    ::view-transition-old(root),
    ::view-transition-new(root){animation:none}
  }

  @media (max-width:860px){
    .approach-grid{grid-template-columns:1fr;row-gap:18px}
    .approach-col p + p{text-indent:0;margin-top:.8em}
  }

  /* ---------- credits: date, institution, qualification ---------- */
  /* same 26/49/25 rhythm as .service and .showcase-grid, so the three
     columns line up with every other three-column block on the site */
  .credits{padding:clamp(30px,4vh,48px) 0 clamp(60px,9vh,110px)}
  .credits .wrap{max-width:none;width:100%;margin:0;padding:0 clamp(22px,3.2vw,48px)}

  .credit{
    display:grid;
    grid-template-columns:26fr 49fr 25fr;
    column-gap:clamp(18px,2.2vw,34px);
    align-items:start;
    padding:34px 0 54px;
    border-top:1px solid var(--rule);
  }
  .credit-date,
  .credit-note{
    font-family:var(--sans);
    font-weight:700;
    font-size:14px;
    line-height:1.35;
    letter-spacing:0;
    color:var(--ink);
    max-width:none;
    /* optical nudge, matching the services rows */
    padding-top:3px;
  }
  .credit-name{
    font-family:var(--sans);
    font-weight:500;
    font-size:26px;
    line-height:1.18;
    letter-spacing:-0.015em;
    color:var(--ink);
    margin:0;
  }

  @media (max-width:860px){
    .credit{grid-template-columns:1fr;row-gap:8px;padding:26px 0 34px}
    .credit-date,.credit-note{padding-top:0}
    .credit-name{font-size:23px}
  }

  /* ---------- anchor targets ---------- */
  /* the header is fixed and 74px tall, so a plain jump would land the
     section underneath it — this stops the scroll just clear of it */
  #top,
  #about,
  #work,
  #services{scroll-margin-top:84px}

  /* ---------- enquiry: image left, form right ---------- */
  /* full-bleed split. align-items:stretch lets the photograph match the
     form's height however long the form gets. */
  .enquiry{padding:0}
  .enquiry-grid{
    display:grid;
    grid-template-columns:1fr 1fr;
    align-items:stretch;
    width:100vw;
    margin-left:calc(50% - 50vw);
  }

  .enquiry-media{position:relative;background:var(--paper-2);min-height:clamp(420px,58vh,760px)}
  .enquiry-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
  /* Radial scrim rather than a vertical one, because the heading now sits
     dead centre. The middle of this photograph averages 36/255 but carries
     a specular highlight up at 253 — a flat wash would leave that spot
     under 3:1 against white, so the scrim is densest where the type is. */
  .enquiry-media::after{
    content:"";position:absolute;inset:0;
    background:radial-gradient(ellipse at center,
      rgba(0,0,0,.55) 0%,
      rgba(0,0,0,.40) 45%,
      rgba(0,0,0,.26) 100%);
  }
  /* the h2 itself is the centring box; the span holds the measure */
  .enquiry-media h2{
    position:absolute;inset:0;z-index:1;
    display:flex;
    align-items:center;
    justify-content:center;
    padding:clamp(28px,5vh,56px) clamp(22px,3.2vw,48px);
    margin:0;
    text-align:center;
    font-family:var(--sans);
    font-weight:600;
    font-size:clamp(1.5rem,2.4vw,2.3rem);
    line-height:1.14;
    letter-spacing:-0.02em;
    color:#fff;
  }
  .enquiry-media h2 span{max-width:14ch}

  .enquiry-form{
    background:var(--paper-2);
    padding:clamp(34px,4.2vw,66px) clamp(22px,3.2vw,56px);
  }

  /* scoped so these beat the older generic .field rules further up */
  .enquiry-form .field{border:0;padding:0;margin:0 0 clamp(18px,2.3vh,26px)}
  .enquiry-form .field label{
    display:block;
    font-family:var(--sans);
    font-weight:600;
    font-size:14px;
    letter-spacing:0;
    text-transform:none;
    color:var(--ink);
    margin-bottom:5px;
  }
  .enquiry-form .field input,
  .enquiry-form .field textarea,
  .enquiry-form .field select{
    width:100%;
    background:transparent;
    border:0;
    border-bottom:1px solid var(--rule);
    border-radius:0;
    font-family:var(--sans);
    font-weight:500;
    font-size:16px;
    line-height:1.4;
    color:var(--ink);
    padding:9px 0;
    transition:border-color .25s;
  }
  .enquiry-form .field textarea{resize:vertical;min-height:120px}
  .enquiry-form .field input::placeholder,
  .enquiry-form .field textarea::placeholder{color:var(--ink-soft);opacity:.75}
  .enquiry-form .field input:focus,
  .enquiry-form .field textarea:focus,
  .enquiry-form .field select:focus{outline:none;border-bottom-color:var(--ink)}

  /* native select chrome removed, caret drawn back in */
  .enquiry-form .field select{
    appearance:none;-webkit-appearance:none;
    background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='7' viewBox='0 0 11 7'%3E%3Cpath d='M1 1l4.5 4.5L10 1' fill='none' stroke='%23161616' stroke-width='1.4'/%3E%3C/svg%3E");
    background-repeat:no-repeat;
    background-position:right 2px center;
    padding-right:22px;
    cursor:pointer;
  }

  /* ---------- chips ---------- */
  .chips{display:flex;flex-wrap:wrap;gap:8px;margin-top:7px}
  /* the real input stays in the DOM for keyboard and form semantics,
     but is hidden — the label is what you see and click */
  .chips input{position:absolute;opacity:0;width:0;height:0;pointer-events:none}
  .chips label{
    display:inline-block;cursor:pointer;
    font-family:var(--sans);
    font-weight:500;
    font-size:14px;
    line-height:1;
    padding:10px 16px;
    border:1px solid var(--rule);
    border-radius:999px;
    background:var(--paper);
    color:var(--ink);
    transition:background .25s,border-color .25s,color .25s;
  }
  .chips label:hover{border-color:var(--ink-soft)}
  .chips input:checked + label{background:var(--ink);border-color:var(--ink);color:var(--paper)}
  .chips input:focus-visible + label{outline:2px solid var(--ink);outline-offset:2px}

  /* ---------- checkboxes ---------- */
  .check{
    display:flex;align-items:flex-start;gap:10px;
    margin-bottom:9px;
    font-family:var(--sans);
    font-weight:500;
    font-size:15px;
    line-height:1.4;
    color:var(--ink);
    cursor:pointer;
  }
  .check input{flex:none;width:15px;height:15px;margin-top:3px;accent-color:var(--ink);cursor:pointer}

  .enquiry-form .group-label{
    display:block;
    font-family:var(--sans);
    font-weight:600;
    font-size:14px;
    color:var(--ink);
    margin-bottom:2px;
  }
  .enquiry-form fieldset{border:0;padding:0;margin:0 0 clamp(20px,2.6vh,28px)}

  /* chips look identical whether they're radios or checkboxes, so the
     multi-select group says so rather than leaving people to guess.
     Sits on its own line under the label, matching .field-note. */
  .enquiry-form .legend-hint{
    margin:2px 0 0;
    font-family:var(--sans);
    font-weight:500;
    font-size:13px;
    line-height:1.4;
    letter-spacing:0;
    color:var(--ink-soft);
    max-width:none;
  }

  /* ---------- solid button ---------- */
  .btn-solid{
    display:inline-flex;align-items:center;gap:10px;
    background:var(--ink);color:var(--paper);
    border:1px solid var(--ink);
    font-family:var(--sans);
    font-weight:600;
    font-size:15px;
    letter-spacing:0;
    text-transform:none;
    padding:15px 28px;
    cursor:pointer;
    transition:background .3s,color .3s;
  }
  .btn-solid:hover{background:transparent;color:var(--ink)}

  .form-note{
    margin-top:14px;
    font-family:var(--sans);
    font-weight:500;
    font-size:14px;
    color:var(--ink-soft);
    max-width:none;
  }

  @media (max-width:860px){
    .enquiry-grid{grid-template-columns:1fr}
    .enquiry-media{min-height:52vh}
    .enquiry-media h2 span{max-width:20ch}
  }

  /* ---------- column set: equal columns, no numbering ---------- */
  /* Used on the contact page. Same left edge and gap as every other
     section; four equal columns rather than the 26/49/25 of .service. */
  .colset{padding:clamp(30px,4vh,48px) 0 clamp(60px,9vh,110px)}
  .colset .wrap{max-width:none;width:100%;margin:0;padding:0 clamp(22px,3.2vw,48px)}

  .colset-grid{
    display:grid;
    grid-template-columns:repeat(4,1fr);
    column-gap:clamp(18px,2.2vw,34px);
    align-items:start;
    border-top:1px solid var(--rule);
    padding-top:clamp(22px,3vh,34px);
  }

  .col h3{
    font-family:var(--sans);
    font-weight:700;
    font-size:16px;
    line-height:1.3;
    letter-spacing:0;
    color:var(--ink);
    margin:0 0 5px;
  }
  .col p{
    font-family:var(--sans);
    font-weight:500;
    font-size:16px;
    line-height:1.45;
    letter-spacing:0;
    color:var(--ink);
    max-width:none;
  }

  /* four narrow columns stop working well before the mobile breakpoint,
     so they fold to two first, then one */
  @media (max-width:1180px){
    .colset-grid{grid-template-columns:repeat(2,1fr);row-gap:clamp(26px,3.4vh,40px)}
  }
  @media (max-width:860px){
    .colset-grid{grid-template-columns:1fr;row-gap:26px}
  }

  /* helper note sitting under a form field */
  .enquiry-form .field-note{
    margin-top:7px;
    font-family:var(--sans);
    font-weight:500;
    font-size:13px;
    line-height:1.4;
    letter-spacing:0;
    color:var(--ink-soft);
    max-width:none;
  }

  /* in-flight state: the button is already non-interactive via the disabled
     attribute — this just makes that visible, so it stops inviting clicks */
  .btn-solid:disabled{
    opacity:.5;
    cursor:not-allowed;
  }
  .btn-solid:disabled:hover{
    background:var(--ink);
    color:var(--paper);
  }
  /* fields stay readable but clearly inert while sending */
  .enquiry-form[aria-busy="true"] .field,
  .enquiry-form[aria-busy="true"] fieldset{
    opacity:.6;
    pointer-events:none;
    transition:opacity .2s ease;
  }

  /* ==================================================================
     RECENT WORKS PAGE
     ================================================================== */

  /* ---------- intro sequence ---------- */
  /* Fixed overlay above everything. `hidden` by default in the markup —
     the script removes that attribute only when it decides to play, so
     reduced-motion users and repeat visitors never see this at all. */
  .intro{
    position:fixed;
    inset:0;
    z-index:200;
    display:flex;
    align-items:center;
    justify-content:center;
    background:var(--paper);
  }
  .intro[hidden]{display:none}

  .intro-stack{
    position:relative;
    display:flex;
    flex-direction:row;
    align-items:center;
    justify-content:center;
    gap:0.28em;
    line-height:1;
    white-space:nowrap;
    /* one step down from the original clamp(22px,5.6vw,74px) — 6px off
       both ends, with the vw rate eased to match so the curve between
       them stays smooth rather than kinking at the clamp boundaries */
    font-size:clamp(16px,5.1vw,68px);
  }

  .intro-word{
    font-family:var(--sans);
    font-weight:600;
    /* deliberately smaller than the brand. Quira is the thing being
       introduced, so it should be the largest element on screen —
       "Recent Works" is context around it, not a peer. */
    font-size:0.72em;
    letter-spacing:-0.025em;
    color:var(--ink);
    /* the two words start side by side, reading as one line */
    transform:translateX(0);
    transition:transform .85s cubic-bezier(.16,1,.3,1);
  }

  /* shell takes no part in the column's layout, so the two words sit
     adjacent at rest and the brand simply waits behind them */
  .intro-brand-shell{
    position:absolute;
    left:0;right:0;
    top:50%;
    transform:translateY(-50%);
    text-align:center;
    pointer-events:none;
  }
  .intro-brand{
    display:inline-block;
    font-family:var(--sans);
    font-weight:600;
    font-size:1em;          /* same clamp as the words, via .intro-stack */
    letter-spacing:-0.025em;
    line-height:1;
    color:var(--ink);
    opacity:0;
    transform-origin:left top;
    transition:opacity .5s ease;
  }

  /* phase 1 — the two words draw apart sideways.
     These em values are relative to the WORD's font size, which is now
     0.72em of the stack — so the travel had to grow from 1.72 to 2.38 to
     open the same physical gap. 2.38 × 0.72 × 2, plus the 0.28em flex gap,
     leaves about 3.7em for a wordmark roughly 2.55em wide: comfortable
     clearance on both sides at every viewport. */
  .intro--split .intro-word[data-intro-left]{transform:translateX(-2.38em)}
  .intro--split .intro-word[data-intro-right]{transform:translateX(2.38em)}

  /* phase 2 — Quira fades up into the gap they left */
  .intro--brand .intro-brand{opacity:1}

  /* phase 3 — the words retire, leaving Quira alone to make the trip */
  .intro--handoff .intro-word{opacity:0;transition:opacity .4s ease,transform .85s cubic-bezier(.16,1,.3,1)}

  /* phase 4 — the whole overlay clears. The brand element is transformed
     by JS at this point (it needs runtime measurements), so only the
     backdrop is animated here. */
  .intro--clear{
    opacity:0;
    pointer-events:none;
    transition:opacity .5s ease .25s;
  }

  /* the brand's flight path is set inline by the script (it needs runtime
     measurements); this just supplies the easing */
  .intro-brand{will-change:transform,opacity}
  .intro--handoff .intro-brand{
    transition:transform .9s cubic-bezier(.5,0,.2,1),opacity .5s ease;
  }

  /* while the intro runs, the real header stays out of the way so the
     travelling brand appears to become it */
  body.intro-running #site-header{opacity:0 !important}
  body.intro-running{overflow:hidden}

  /* ---------- page heading ---------- */
  .work-head{padding:clamp(96px,15vh,150px) 0 clamp(24px,3.4vh,42px)}
  .work-head .wrap{max-width:none;width:100%;margin:0;padding:0 clamp(22px,3.2vw,48px)}
  .work-title-main{
    font-family:var(--sans);
    font-weight:600;
    font-size:clamp(30px,5vw,54px);
    line-height:1.1;
    letter-spacing:-0.025em;
    color:var(--ink);
  }

  /* ---------- carousel ---------- */
  .works{padding:0 0 clamp(40px,6vh,72px)}

  .works-viewport{padding:0 clamp(22px,3.2vw,48px)}

  .works-track{
    display:grid;
    grid-auto-flow:column;
    /* three across on desktop, with the gutter subtracted so the cards
       line up with every other section's left edge */
    grid-auto-columns:calc((100% - 2 * clamp(14px,1.6vw,24px)) / 3);
    gap:clamp(14px,1.6vw,24px);
    overflow-x:auto;
    scroll-snap-type:x mandatory;
    scroll-behavior:smooth;
    /* native scrollbar hidden — the progress bar below replaces it */
    scrollbar-width:none;
  }
  .works-track::-webkit-scrollbar{display:none}
  .works-track:focus-visible{outline:2px solid var(--ink);outline-offset:4px}

  .work-card{
    position:relative;
    display:block;
    scroll-snap-align:start;
    aspect-ratio:3 / 4;
    overflow:hidden;
    background:var(--paper-2);
    text-decoration:none;
  }
  /* The card is the link now, so keyboard users need to see where they are.
     Offset sits just outside the photograph rather than on top of it. */
  a.work-card:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

  .work-card img{
    position:absolute;
    inset:0;
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
    transition:transform 1.1s cubic-bezier(.16,1,.3,1);
  }
  /* a slow push-in on hover, no zoom-and-snap */
  .work-card:hover img{transform:scale(1.04)}

  /* both labels sit over the photograph, so each gets a gradient scrim
     rather than a flat overlay — the image stays readable and the text
     gets a dark base to sit on. Densities are a starting point: they
     need measuring against the real project images once those land,
     the way the hero scrim was. */
  .work-card::before,
  .work-card::after{
    content:"";
    position:absolute;
    left:0;right:0;
    height:38%;
    pointer-events:none;
  }
  .work-card::before{
    top:0;
    background:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0));
  }
  .work-card::after{
    bottom:0;
    background:linear-gradient(to top,rgba(0,0,0,.55),rgba(0,0,0,0));
  }

  .work-title{
    position:absolute;
    top:clamp(18px,2.4vw,30px);
    left:0;right:0;
    z-index:2;
    text-align:center;
    font-family:var(--sans);
    font-weight:500;
    font-size:clamp(15px,1.5vw,22px);
    letter-spacing:.12em;
    text-transform:uppercase;
    color:#fff;
  }
  .work-caption{
    position:absolute;
    bottom:clamp(18px,2.4vw,30px);
    left:clamp(16px,2vw,28px);
    right:clamp(16px,2vw,28px);
    z-index:2;
    text-align:center;
    font-family:var(--sans);
    font-weight:500;
    font-size:clamp(13px,1.05vw,16px);
    line-height:1.35;
    letter-spacing:0;
    color:#fff;
  }

  /* ---------- carousel controls ---------- */
  .works-controls{
    display:flex;
    align-items:center;
    justify-content:center;
    gap:clamp(16px,2vw,28px);
    margin-top:clamp(22px,3vh,36px);
  }
  .works-arrow{
    display:inline-flex;
    align-items:center;
    justify-content:center;
    width:42px;height:42px;
    border:1px solid var(--rule);
    border-radius:999px;
    background:var(--paper);
    color:var(--ink);
    font-size:15px;
    cursor:pointer;
    transition:border-color .25s,opacity .25s;
  }
  .works-arrow:hover{border-color:var(--ink)}
  .works-arrow:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
  .works-arrow:disabled{opacity:.3;cursor:default}
  .works-arrow:disabled:hover{border-color:var(--rule)}

  .works-progress{
    position:relative;
    width:clamp(120px,18vw,240px);
    height:1px;
    background:var(--rule);
  }
  .works-progress-bar{
    position:absolute;
    top:0;left:0;
    height:1px;
    width:33%;
    background:var(--ink);
    transition:left .3s ease,width .3s ease;
  }

  /* ---------- responsive ---------- */
  @media (max-width:860px){
    /* 2 x 2 on mobile — four cards visible at once.
       grid-template-rows makes the auto-flow fill two rows before starting
       a new column, so each "column" is a stacked pair and the carousel
       still scrolls sideways. Note this means reading order runs down then
       across: 1 and 2 on the left, 3 and 4 on the right. */
    .works-track{
      grid-template-rows:repeat(2,auto);
      grid-auto-columns:calc((100% - clamp(10px,2.4vw,16px)) / 2);
      gap:clamp(10px,2.4vw,16px);
    }
    /* Title and caption move together so the hierarchy survives the
       shrink — drop only the caption and the two end up near-identical,
       which reads as a mistake rather than a pair.
       Tracking eases off too: .12em is generous at 22px and starts
       breaking long titles like "GIFT CARDS" apart at 13px. */
    .work-title{
      font-size:13px;
      letter-spacing:.07em;
      top:clamp(12px,3vw,18px);
    }
    .work-caption{
      font-size:11px;
      line-height:1.3;
      bottom:clamp(12px,3vw,18px);
      left:clamp(10px,2.6vw,16px);
      right:clamp(10px,2.6vw,16px);
    }
  }

  @media (prefers-reduced-motion:reduce){
    .works-track{scroll-behavior:auto}
    .work-card img{transition:none}
    .work-card:hover img{transform:none}
    .intro,.intro *{transition:none !important;animation:none !important}
  }

  /* ---------- enquiry: success state ---------- */
  /* The submitted answers stay visible but recede — they're a receipt now,
     not something to read. Controls are `disabled` in JS, so this is purely
     the visual half; it isn't relied on to prevent input. */
  .enquiry-form.is-done .field,
  .enquiry-form.is-done fieldset{
    opacity:.4;
    transition:opacity .3s ease;
  }
  .enquiry-form.is-done .btn-solid{opacity:.4}

  .enquiry-done{
    margin-top:clamp(20px,3vh,30px);
    padding:clamp(20px,3vw,28px);
    border:1px solid var(--ink);
    background:var(--paper);
  }
  .enquiry-done[hidden]{display:none}

  .enquiry-done h3{
    font-family:var(--sans);
    font-weight:600;
    font-size:clamp(17px,1.7vw,21px);
    line-height:1.25;
    letter-spacing:-0.01em;
    color:var(--ink);
    margin:0 0 6px;
  }
  .enquiry-done #enquiry-done-email{font-weight:600;word-break:break-word}
  .enquiry-done p{
    font-family:var(--sans);
    font-weight:500;
    font-size:15px;
    line-height:1.45;
    letter-spacing:0;
    color:var(--ink);
    max-width:none;
    margin:0;
  }
  .enquiry-done-note{
    margin-top:8px !important;
    font-size:13px !important;
    color:var(--ink-soft) !important;
  }
