    /* ---------- tablet ----------
   The desktop architecture is one uniform scale of the 1280x800 canvas:
   u = min(100vw/1280, 100dvh/800). It holds while that scale is generous —
   at 1366x1024 (12.9" landscape) it is 1.07, at 1180x820 it is 0.92. It
   fails at u < 0.9, where the 10px labels drop under 9px and the body copy
   under 10px; that is 1152px wide. Below that the type unit is pinned and
   the boxes carrying type size to their content, so the composition stops
   being a shrinking miniature and becomes a layout at its own scale, while
   the frame keeps scaling with the viewport. At the boundary both units are
   0.9 and every content-sized box resolves to its desktop width, so the
   architectures meet without a visible step. */
    @media (max-width: 1152px) {
      :root {
        --u: clamp(.8px, min(100vw / 1280, 100vh / 800), 1.1px);
        --u: clamp(.8px, min(100vw / 1280, 100dvh / 800), 1.1px);
        /* type grows fluidly as the viewport narrows: 0.9 at the breakpoint,
       matching the desktop scale exactly, up to 1.12 where the phone block
       takes over at the same value — both boundaries are stepless */
        --t: max(var(--u), clamp(.9px, calc(.9px + (1152px - 100vw) * .00042), 1.12px));
      }

      /* pills and the CTA size to their label instead of to a fixed canvas width;
     the paddings are the reference's own internal measurements, so at the
     breakpoint these resolve to 87/90/190 units exactly as before */
      .resume {
        width: auto;
        padding: 0 calc(19*var(--t)) 0 calc(17*var(--t))
      }

      .cta {
        width: auto;
        padding: 0 calc(19*var(--t))
      }

      /* the dock's cells become content-aware; the dividers become their edges,
     landing on the same 116/139 offsets at the breakpoint */
      .dock {
        display: flex;
        justify-content: space-between;
        align-items: stretch
      }

      .dock .div {
        display: none
      }

      .talk {
        padding: 0 min(calc(24*var(--t)), 6vw) 0 min(calc(20*var(--t)), 5vw);
        border-left: var(--hair) solid rgba(255, 255, 255, .21)
      }

      /* touch targets grow inside the existing boxes — nothing moves */
      .links {
        gap: calc(17*var(--t));
        align-self: stretch
      }

      .links a {
        display: flex;
        align-items: center;
        align-self: stretch
      }
    }

    /* The hero image is 16:10. Once the viewport is narrower than ~6/5 the frame
   crops the mountains away and the index rail loses the dark ground it reads
   against, so the rail moves up into the sky band and the hero takes the full
   width below it. Above that ratio the rail keeps its centred desktop
   position and the hero reserves its column. */
    @media (max-width: 1152px) and (min-aspect-ratio: 6/5) {
      .hero {
        padding-inline: calc(150*var(--t))
      }
    }

    @media (max-width: 1152px) and (max-aspect-ratio: 6/5) {
      .hero {
        padding-inline: calc(22*var(--t))
      }
    }

    /* ---------- navigation collapse ----------
   The bar holds logo + links + both pills while the gap between the wordmark
   and the first link stays above an eighth of the frame width. With the type
   growing as the viewport narrows that gap closes at ~830px, so from there
   the same nav set becomes a panel hung off the MENU pill — the site's own
   dots icon is the burger. No markup is duplicated: .navset is
   display:contents in the bar and a flex panel here. */
    @media (max-width: 830px) {
      .navset {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        position: absolute;
        top: calc(52*var(--t));
        right: 0;
        min-width: calc(196*var(--t));
        padding: calc(16*var(--t)) calc(20*var(--t)) calc(18*var(--t));
        gap: calc(4*var(--t));
        background: rgba(11, 16, 26, .74);
        -webkit-backdrop-filter: blur(calc(16*var(--t)));
        backdrop-filter: blur(calc(16*var(--t)));
        clip-path: polygon(0 0, calc(100% - 15*var(--t)) 0, 100% calc(15*var(--t)), 100% 100%,
            calc(15*var(--t)) 100%, 0 calc(100% - 15*var(--t)));
        opacity: 0;
        visibility: hidden;
        transform: translateY(calc(-6*var(--t)));
        transition: opacity .34s ease, transform .34s cubic-bezier(.22, .61, .36, 1), visibility .34s;
        z-index: 6;
      }

      .nav-open .navset {
        opacity: 1;
        visibility: visible;
        transform: none
      }

      .links {
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        margin-right: 0;
        align-self: auto
      }

      .links a {
        padding: calc(9*var(--t)) 0;
        justify-content: flex-start
      }

      .menu {
        display: flex
      }

      .navset .resume {
        width: auto;
        align-self: stretch;
        justify-content: flex-start;
        margin-top: calc(10*var(--t));
        height: calc(38*var(--t));
        padding: 0 calc(16*var(--t));
        background: #0C0C0C
      }
    }


    /* ---------- mobile ----------
   The tablet architecture holds further than a conventional phone breakpoint
   would suggest. Measured down the range: the masthead still has 189px
   between wordmark and menu at 560, the headline keeps its two hand-set
   lines to 487, the dock keeps 200px of slack to 400. What fails first is
   the paragraph — its four hand-set lines need 452px of measure, so at
   549px the block breaks into five ragged lines with an orphan. That is the
   real breaking point, so mobile begins at 548.

   The architecture here: the hand-set breaks are released so the copy finds
   its own measure, the wordmark becomes fluid so it never crowds the menu,
   the frame margins tighten proportionally, the rail climbs clear of the
   subject as the frame crops to it, and the type scale simply carries over
   from the tablet boundary rather than shrinking — a phone is held closer,
   not read at arm's length. */
    @media (max-width: 548px) {
      :root {
        --u: clamp(.62px, min(100vw / 500, 100vh / 820), 1.1px);
        --u: clamp(.62px, min(100vw / 500, 100dvh / 820), 1.1px);
        /* 1.12 at the breakpoint, matching tablet exactly, easing to a 1.06 floor */
        --t: clamp(1.06px, calc(100vw / 489), 1.12px);
      }

      .frame {
        left: calc(22*var(--u));
        right: calc(22*var(--u));
        top: calc(22*var(--u));
        bottom: calc(22*var(--u))
      }

      /* the wordmark rides level with the nav, stroke-only */
      .logo {
        left: calc(9*var(--t));
        top: calc(46*var(--t));
        width: auto;
        aspect-ratio: auto;
        height: calc(41*var(--t))
      }

      .masthead {
        right: calc(9*var(--t));
        top: calc(46*var(--t))
      }

      /* the frame now crops to the subject itself, so the rail stops floating
     beside the composition and docks under the wordmark, in the sky band —
     the one region that stays dark at every phone crop. Its rhythm tightens
     just enough to clear the stone, and the inactive items carry slightly
     more weight to hold up against a brighter backdrop. */
      .hero {
        bottom: max(9%, calc(59*var(--t)));
        padding-inline: calc(18*var(--t))
      }

      .headline {
        text-wrap: balance
      }

      .blurb {
        max-width: calc(400*var(--t))
      }

      .blurb br {
        display: none
      }

      /* the headline wraps freely here, so it lifts as one block instead of per line */
      .headline .hrow {
        display: inline;
        overflow: visible
      }

      .headline .hrise {
        display: inline
      }

      .anim .headline .hrise {
        animation: none
      }

      .anim .headline {
        animation: settle .8s var(--e-mask) .42s both
      }

      .hero .headline {
        transition: opacity .4s ease
      }

      .swapping .headline {
        opacity: 0
      }
    }

    /* ---------- phone compression — the hero content is taller than the
    first screen on most hand-built devices; scale the stack down so the
    name clears the wordmark and the cue still meets the dock ---------- */
    @media (max-width: 548px) {
      .name {
        font-size: min(calc(38*var(--t)), 8.2vw)
      }

      .role {
        font-size: calc(20*var(--t))
      }

      .hero-core {
        gap: calc(6*var(--t))
      }

      .stack {
        margin-top: calc(6*var(--t))
      }

      .stack-icon {
        width: calc(46*var(--t));
        height: calc(46*var(--t));
        border-radius: calc(9*var(--t))
      }

      .stack-icon svg {
        width: calc(80*var(--t));
        height: calc(80*var(--t))
      }

      .summary {
        margin-top: calc(8*var(--t));
        font-size: clamp(.9rem, 2.6vw, 1.35rem);
        line-height: 1.55
      }

      .hero-socials {
        margin-top: calc(12*var(--t));
        margin-bottom: calc(16*var(--t))
      }

      .hero-socials .contact-icon {
        width: calc(40*var(--t));
        height: calc(40*var(--t));
        border-radius: calc(10*var(--t))
      }

      .hero-socials .contact-icon svg {
        width: calc(31*var(--t));
        height: calc(31*var(--t))
      }

      .scroll-cue {
        gap: calc(8*var(--t));
        padding-bottom: calc(14*var(--t))
      }

      .scroll-label.lbl {
        font-size: calc(11*var(--t));
        letter-spacing: calc(1*var(--t))
      }

      .shred-arrow {
        width: calc(13*var(--t));
        height: calc(22*var(--t))
      }
    }

    /* ---------- narrow mobile ----------
   Measured: the dock's three cells hold one row down to 365px, where the
   centre cue meets the contact control. Below that the cue takes a row of
   its own — the two controls split the row above it, keeping the same
   hairline language — rather than the labels being shrunk or dropped. */
    @media (max-width: 370px) {
      .dock {
        height: auto;
        flex-wrap: wrap
      }

      .scroll {
        position: static;
        transform: none;
        order: 1;
        flex: 1 0 100%;
        justify-content: center;
        height: calc(40*var(--t));
        border-top: var(--hair) solid rgba(255, 255, 255, .13)
      }

      .anim .scroll {
        animation-name: settle
      }

      .hero {
        bottom: calc(96*var(--t))
      }
    }

    /* last resort only: on a screen too short to hold the whole composition the
   supporting paragraph steps aside rather than the layout clipping */
    @media (max-height: 560px),
    (max-width: 370px) and (max-height: 640px) {
      .summary,
      .blurb {
        display: none
      }
    }

