/* Post//Mundane brand v2 tokens - ops/brand/tokens/tokens.css is the source
     of truth. Only the subset this page uses is carried here. */
  :root {
    /* Sampled from the reference sheet: a neutral grey ground, deep navy for
       type, and one electric blue doing all the drawing. The scale keeps its
       meaning - 900 is still the strongest mark - so everything downstream
       follows without being touched. */
    --pm-ink-900:#001A5C; --pm-ink-800:#0A2A72; --pm-ink-700:#103593;
    --pm-ink-600:#0247D3; --pm-ink-500:#4A79E8; --pm-ink-400:#7E9DF0;
    --pm-ink-300:#B9C8FA; --pm-ink-200:#D5DFFD;
    --pm-paper-050:#E6E6E6; --pm-paper-200:#DCDCDC;
    --pm-sans:"Helvetica Neue",Helvetica,"Archivo",Arial,sans-serif;
    --pm-mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,"DejaVu Sans Mono",monospace;
    --pm-ls-label:.22em;
    --pm-rule-hair:1px; --pm-rule-off:2px;
    --pm-radius:4px;
    --pm-shadow:none;            /* there is no elevation in this system */
    --pm-grain-opacity:.07;

    /* Plotter speed. Every stroke carries its own --t and --d; this scales
       all of them at once, the copy's --in with them, so the type still
       arrives as the pen finishes rather than after it. Lower is faster. */
    --plot:.38;

    /* One artboard unit in px. The plate cover-crops (xMaxYMid slice), so a
       unit is whichever of the two ratios is larger - exactly what the SVG
       resolves internally. With this, where the elevation begins is CSS
       arithmetic rather than something JS has to measure and keep fresh. */
    --u:max(calc(100vw / 2752), calc(100svh / 1536));
    --gutter:clamp(24px,5vw,72px);
    --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='3' intercept='-1'/%3E%3CfeFuncG type='linear' slope='3' intercept='-1'/%3E%3CfeFuncB type='linear' slope='3' intercept='-1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");

    /* page roles, mapped onto the tokens */
    --mono:var(--pm-mono);
    --sans:var(--pm-sans);
    --ground:var(--pm-paper-050);
    --ground-sub:var(--pm-paper-200);
    --line:var(--pm-ink-600);          /* THE LINE - rules, drawings, wordmark */
    --text:var(--pm-ink-800);          /* running text */
    --text-title:var(--pm-ink-900);
    --label:var(--pm-ink-500);         /* eyebrows, dimension text */
    --hair:var(--pm-ink-300);
  }
  * { box-sizing:border-box; }
  body { margin:0; background:var(--ground); }

  .hero {
    position:relative; width:100%; height:100svh; min-height:520px;
    overflow:hidden; background:var(--ground);
  }
  /* paper grain, generated in-page so nothing external is fetched */
  .hero::after {
    content:"";
    position:absolute; inset:0;
    pointer-events:none;
    background-image:var(--grain);
    background-size:200px 200px;
    mix-blend-mode:multiply;
    opacity:.18;
  }

  .hero__plate {
    position:absolute; inset:0; width:100%; height:100%;
    display:block; color:var(--line);
  }

  /* Every reveal is a white stroke inside a mask, hidden by its own length.
     One technique for all of them — no transforms, which do not apply
     reliably to shapes inside <mask>. */
  #mask path, #maskGrade {
    fill:none; stroke:#fff;
    stroke-linecap:butt; stroke-linejoin:round;
    stroke-dasharray:var(--len); stroke-dashoffset:var(--len);
  }
  #mask path { stroke-width:13; }
  #maskGrade { stroke-width:13; }

  .run #mask path, .run #maskGrade {
    transition-property:stroke-dashoffset;
    transition-duration:calc(var(--t,380ms) * var(--plot));
    transition-timing-function:linear;
    transition-delay:calc(var(--d,0ms) * var(--plot));
    stroke-dashoffset:0;
  }

  /* header sits above the plate and arrives only once the drawing settles */
  /* three tracks so the nav centres on the page, not on the space left over
     beside the lockup */
  .site-head {
    position:absolute; z-index:2; inset:0 0 auto 0;
    display:grid; grid-template-columns:1fr auto 1fr; align-items:center;
    gap:24px;
    padding:clamp(20px,3.2vh,36px) clamp(24px,5vw,72px);
    font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
  }
  .site-head .lockup { justify-self:start; }
  .links { justify-self:center; }
  /* Wordmark A, "Ledger" - mono medium caps at .34em tracking with a midpoint
     separator, sitting on its 2px ruling-off line. The rule is part of the
     mark and never omitted; it spans the type only, never under the monogram.
     Monogram sits at 87.5% of the type's cap-height box, gap = half its width. */
  .lockup { display:flex; align-items:center; gap:.9em; }
  .lockup__mark { height:clamp(19px,1.6vw,25px); width:auto; flex:none; }
  /* Will's call: no ruling-off rule, and the sans rather than the mono.
     Note brand/02-identity.md says the rule "is part of the mark and never
     omitted" - this departs from that on purpose. The tracking stays; it is
     what still reads as a wordmark rather than a word. */
  .lockup__type {
    display:inline-block;
    font-family:var(--sans); font-weight:600;
    color:var(--pm-ink-900);
    font-size:clamp(13px,1.05vw,17px);
    letter-spacing:.30em; text-indent:.30em;
    line-height:1;
  }
  .links { display:flex; gap:clamp(16px,2.3vw,42px); }
  /* no opacity here: `.links a` (0,1,1) would outrank `.rise` (0,1,0) and
     leave the links visible before the drawing finishes */
  /* the nav takes the hero's face: same sans, same weight, same tight
     tracking. The mono label tracking came off with it - .22em is set for
     uppercase mono and reads as a mismatch inside a sans. */
  .links a {
    color:var(--label); text-decoration:none;
    font-family:var(--sans);
    font-weight:500; font-size:clamp(13px,.95vw,15px);
    letter-spacing:-.01em; text-transform:none;
    padding-bottom:3px; border-bottom:1px solid transparent;
    transition:opacity .2s ease, border-color .2s ease;
  }
  .links a:hover, .links a:focus-visible { border-bottom-color:currentColor; }
  .links a:focus-visible { outline:2px solid var(--line); outline-offset:4px; }

  /* ---- video scroll stage ------------------------------------------------
     The frame is pinned in the centre of the screen and grows from a quarter
     size to full as the section scrolls past - the effect Will sent, built
     the way its own description says it works: a direct CSS transform.
     framer-motion only supplied the scroll number, and this page already has
     one of those. */
  .vs { position:relative; height:230vh; background:var(--ground); }
  .vs__stage {
    position:sticky; top:0;
    height:100svh;
    display:grid; place-items:center;
    padding:0 var(--gutter);
  }
  .vs .ambient {
    width:min(1080px, 84vw); margin:0;
    transform:scale(var(--s, .25));
    transform-origin:center center;
    will-change:transform;
  }

  /* AMBIENT VIDEO
     A muted loop with a glow that takes its colour from the frame on screen.
     The colour is sampled by drawing the video to a 1x1 canvas and reading
     that one pixel - the average of the frame, effectively - then used as the
     colour of a large box-shadow. Technique after the Framer AmbientVideo
     component; written natively because that module is React and loads from
     framerusercontent, which the artifact CSP blocks. */
  .ambient {
    margin:0;                     /* figure default, reset here not inline:
                                     an inline margin outranks the media query
                                     that pulls the frame off the elevation */
    position:relative;
    aspect-ratio:16 / 9;
    border-radius:12px;
    isolation:isolate;
  }
  .ambient video {
    position:relative; z-index:1;
    width:100%; height:100%;
    display:block; object-fit:cover;
    border-radius:inherit;
    box-shadow:0 0 28px 6px var(--glow, rgba(100,100,100,.3));
    transition:box-shadow .35s linear;
    background:var(--pm-ink-200);
  }
  .ambient__ph {
    position:relative; z-index:1;
    width:100%; height:100%;
    display:block; border-radius:inherit;
    box-shadow:0 0 28px 6px var(--glow, rgba(100,100,100,.3));
    transition:box-shadow .35s linear;
  }
  @media (prefers-reduced-motion:reduce) {
    .ambient__ph { transition:none; }
  }
  .ambient video[hidden], .ambient__ph[hidden] { display:none; }
  /* TEMPORARY - a third-party YouTube embed standing in for footage.
     Embedded, never re-hosted: the film is Vogue Architects' and an <iframe>
     is the route that credits and links back to them.

     It cannot drive the glow. A cross-origin frame gives no pixel access, so
     the 1x1 canvas read is impossible and the glow is a fixed colour here.
     The scale-and-crop hides YouTube's title and branding overlays, which sit
     outside the visible box; pointer-events:none keeps the hover chrome from
     ever appearing. Replace the whole block when the real file lands. */
  .ambient__yt {
    position:absolute; inset:0; z-index:2;   /* over the canvas fallback */
    overflow:hidden; border-radius:inherit;
    box-shadow:0 0 28px 6px rgba(86,101,58,.42);
    background:var(--pm-ink-800);
  }
  .ambient__yt iframe {
    position:absolute; top:50%; left:50%;
    width:158%; height:158%;   /* crops YouTube title and branding out */
    transform:translate(-50%,-50%);
    border:0; pointer-events:none;
  }
  /* aspect-ratio fixes the figure's height, so a caption in normal flow lands
     INSIDE the media box and disappears behind the video. It hangs below it. */
  .ambient__cap {
    position:absolute; top:100%; left:0; right:0;
    display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap;
    margin-top:.7em; padding-top:.7em;
    border-top:1px solid var(--hair);
    font-family:var(--mono); font-size:9.5px; color:var(--label);
    letter-spacing:var(--pm-ls-label); text-transform:uppercase;
  }
  /* a glow is motion too: hold it still and do not autoplay */
  @media (prefers-reduced-motion:reduce) {
    .ambient video { transition:none; box-shadow:none; }
  }

  /* 901-1199 is the awkward band: too narrow for two columns, but the hero is
     still fixed height with the drawing at full strength, so a stacked frame
     overflows it and gets cropped. Below 900 the hero flows and there is room.
     The frame sits this band out rather than being cropped or shrunk to a

  .rise { opacity:0; transform:translateY(10px); }
  .run .rise {
    opacity:1; transform:none;
    transition:opacity .7s ease calc(var(--in,0ms) * var(--plot)),
               transform .7s cubic-bezier(.2,.7,.3,1) calc(var(--in,0ms) * var(--plot));
  }

  /* The nav used to be hidden here, with the footer's sheet index carrying
     the sections on small screens. That index is Elsewhere links now, so the
     nav has to come back or AI Studio and Approach are unreachable below
     760px. It takes its own row under the lockup. */
  @media (max-width:760px) {
    .site-head {
      grid-template-columns:1fr; justify-items:center; gap:10px;
      padding-top:clamp(16px,2.4vh,26px);
    }
    .site-head .lockup { justify-self:center; }
    .links { flex-wrap:wrap; justify-content:center; gap:6px clamp(12px,4vw,20px); }
    .links a { font-size:12px; }
  }

  /* hero copy in the open paper to the left of the elevation */
  .intro {
    position:absolute; z-index:2;
    left:clamp(24px,5vw,72px);
    top:clamp(120px,17vh,200px);
    /* The annotation ticks begin 517 units in from the artboard's right edge,
       and the artboard is anchored right - so this is the open paper, exactly,
       at every viewport. No measuring, nothing to go stale. */
    width:calc(100vw - 517 * var(--u) - var(--gutter));
    color:var(--line);
  }
  .intro__title {
    margin:0 0 .7em;
    font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
    color:var(--text-title);
    /* a pure-vw preferred value sits on its floor right through the tablet
       range; the rem term keeps it climbing from the small end up */
    font-weight:500;
    /* The column is measured against the drawing, so this reaches two lines
       on the width rather than on the type size. */
    font-size:clamp(1.5rem, .95rem + 2.3vw, 2.45rem);
    line-height:1.12; letter-spacing:-.02em;
    /* pretty, not balance: balance evens the two lines, which left the first
       one short and the paper beside it empty. pretty fills the measure and
       only protects the last line from an orphan - so line one runs the width
       of the column and line two takes the remainder. */
    text-wrap:pretty;
    /* The column runs the full width to the elevation so the sub-line and the
       buttons can use it; the headline keeps its own clearance. This lived in
       a media query that only existed to seat the video beside the copy, and
       went out with it - the headline ran straight into the drawing. */
    padding-right:48px;
  }
  .intro__sub {
    color:var(--text);
    margin:0 0 2em;
    /* the hero's face, a step down from it - the sub-line reads as the
       headline continuing rather than as a caption under it */
    font-family:var(--sans);
    font-weight:400;
    font-size:clamp(14px,1.05vw,17px); line-height:1.55;
    letter-spacing:-.005em;
    /* a sans sets wider per character than the mono did, so the measure comes
       in to hold the line length steady */
    max-width:48ch; opacity:.88;
  }
  /* reads as a link, but stays a button - it opens a dialog rather than
     navigating, and that is what a screen reader should announce */
  .lnk {
    display:inline-flex; align-items:center; gap:.6em;
    background:none; border:0; padding:0; cursor:pointer;
    color:var(--line); font-family:var(--sans);
    font-weight:500; font-size:clamp(12px,.85vw,14px);
    letter-spacing:-.005em; line-height:1;
  }
  .lnk span {
    text-decoration:underline;
    text-decoration-style:dotted;
    text-decoration-thickness:1px;
    text-underline-offset:4px;
  }
  .lnk:hover span, .lnk:focus-visible span { text-decoration-style:solid; }
  .lnk:focus-visible { outline:2px solid var(--line); outline-offset:4px; }
  .lnk__arrow { flex:none; height:1.05em; width:auto; opacity:.85; }

  /* the letter now lives inside its own sheet */
  .letter {
    color:var(--text);
    font-family:var(--sans);
    font-size:clamp(15px,1.05vw,17px);
    line-height:1.62;
    letter-spacing:-.005em;
    /* 82ch was a mono measure. A sans sets wider, and this is the longest
       read on the site - it needs a shorter line, not the same count. */
    max-width:62ch;
  }
  .letter p { margin:0 0 1.05em; }
  .letter p:last-child { margin-bottom:0; }
  .letter a {
    color:inherit; text-decoration:none;
    border-bottom:1px solid currentColor;
    padding-bottom:1px;
  }
  .letter a:hover, .letter a:focus-visible { background:rgba(2,71,211,.10); }

  /* signature closes the letter — scales with the type so it never overpowers it */
  /* signature closes the letter — scales with the type so it never overpowers it */
  .letter .sig { line-height:0; }
  .sig__mark { display:block; width:clamp(74px, 10em, 128px); height:auto; }


  /* sit in the band below grade; JS pins the exact offset to the line */
  /* the buttons now sit in the copy, under Open letter, rather than in the
     band below grade - so they are laid out, not pinned */
  .actions {
    margin-top:clamp(26px,3.6vh,44px);
    display:flex; flex-wrap:wrap; gap:12px;
    font-family:var(--mono);
  }
  /* A filled field, a full radius and type at a readable size - the weight
     comes from the field, not from elevation, so no shadow or gradient is
     needed to stop it reading flat. */
  .btn {
    display:inline-flex; align-items:center; justify-content:center;
    text-decoration:none; cursor:pointer;
    background-color:var(--line); color:var(--ground);
    border:1px solid var(--line); border-radius:999px;
    padding:.95em 1.7em;
    font-family:var(--sans); font-weight:500;
    font-size:clamp(13px,.95vw,15px);
    letter-spacing:-.005em; text-transform:none; line-height:1;
    transition:background-color .18s ease, border-color .18s ease,
               color .18s ease, transform .12s ease;
  }
  .btn:hover, .btn:focus-visible {
    background-color:var(--pm-ink-800); border-color:var(--pm-ink-800);
    color:var(--ground);
  }
  .btn:active { transform:translateY(1px); }

  /* the second action reads as the quieter one: same field, drawn not filled */
  .btn--ghost {
    background-color:transparent; color:var(--line);
  }
  .btn--ghost:hover, .btn--ghost:focus-visible {
    background-color:var(--pm-ink-200); border-color:var(--pm-ink-200);
    color:var(--pm-ink-900);
  }

  /* One control, drawn as two shapes. The wrapper carries no .btn: given the
     button skin it paints its own square field behind both shapes and every
     override has to fight the base rule back off. It is a group. */
  .cta {
    display:inline-flex; align-items:center; gap:5px;
    text-decoration:none; cursor:pointer;
    font-family:var(--sans); font-weight:500;
    font-size:clamp(13px,.95vw,15px);
    letter-spacing:-.005em; line-height:1;
    transition:transform .12s ease;
  }
  .cta:active { transform:translateY(1px); }
  .btn__label, .btn__go {
    display:inline-flex; align-items:center; justify-content:center;
    background-color:var(--line); color:var(--ground);
    transition:background-color .18s ease;
  }
  .btn__label { border-radius:999px; padding:.95em 1.7em; }
  .btn__go { border-radius:50%; width:3.05em; height:3.05em; flex:none; }
  .btn__go svg { width:1.05em; height:1.05em; display:block; }
  .cta:hover .btn__label, .cta:hover .btn__go,
  .cta:focus-visible .btn__label, .cta:focus-visible .btn__go {
    background-color:var(--pm-ink-800);
  }
  .cta:focus-visible { outline:2px solid var(--line); outline-offset:4px; border-radius:999px; }
  /* the old outlined button's hover lived here and, being later in the sheet,
     was quietly winning over the new .btn:hover and .btn--ghost:hover above -
     it is what painted a square field behind the split control */
  .btn:focus-visible { outline:2px solid var(--line); outline-offset:3px; }

  /* This block sits after .actions on purpose: placed before it, the base
     position:absolute wins on source order and the override does nothing. */
  /* A headline at this size cannot live in a fixed-height hero on a phone:
     it was being clipped by overflow:hidden at 360x640 and running through
     the CTA row everywhere narrow. Below 900px the drawing is a 22% backdrop
     anyway, so the hero flows with its content instead of cropping it. */
  @media (max-width:900px) {
    .hero {
      height:auto; min-height:100svh;
      padding-bottom:clamp(32px,6vh,64px);
    }
    .hero__plate { opacity:.22; }
    .intro {
      position:static; width:auto;
      margin:clamp(88px,14vh,140px) clamp(24px,5vw,72px) 0;
    }
  }


  /* ---- contact sheet ---------------------------------------------------- */
  /* A plain fixed overlay rather than <dialog>.showModal(): sandboxed
     iframes (the published artifact among them) block modal dialogs, and the
     fallback renders in normal flow — uncentred, no backdrop. */
  .overlay {
    position:fixed; inset:0; z-index:100;
    display:flex; align-items:center; justify-content:center;
    background:rgba(0,10,40,.48);
    opacity:0; transition:opacity .22s ease;
  }
  .overlay[hidden] { display:none; }
  .overlay.is-open { opacity:1; }

  .sheet {
    width:75vw; height:75vh;
    padding:0; border:1px solid var(--line);
    background:var(--ground); color:var(--line);
    position:relative; overflow:hidden;
    transform:translateY(8px) scale(.985);
    transition:transform .24s cubic-bezier(.2,.7,.3,1);
  }
  .overlay.is-open .sheet { transform:none; }
  .sheet::after {
    content:""; position:absolute; inset:0; pointer-events:none;
    background-image:var(--grain); background-size:200px 200px;
    mix-blend-mode:multiply; opacity:.18;
  }
  .sheet__inner {
    position:relative; z-index:1;
    height:100%; overflow:auto;
    padding:clamp(28px,4.5vw,64px);
    display:flex; flex-direction:column;
  }
  .sheet__close {
    position:absolute; z-index:2; top:14px; right:18px;
    background:none; border:0; cursor:pointer;
    color:var(--line); font-size:26px; line-height:1; padding:6px 10px;
  }
  .sheet__close:hover { opacity:.65; }
  .sheet__close:focus-visible { outline:2px solid var(--line); outline-offset:2px; }

  .sheet__eyebrow {
    margin:0 0 .9em; font-family:var(--mono); color:var(--label);
    font-size:11px; letter-spacing:var(--pm-ls-label); text-transform:uppercase;
  }
  .sheet__title {
    margin:0 0 .35em;
    font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
    color:var(--text-title);
    font-weight:500; font-size:clamp(1.5rem,2.9vw,2.3rem);
    letter-spacing:-.02em; line-height:1.08;
  }
  .sheet__lede {
    margin:0 0 clamp(24px,3.5vh,44px);
    font-family:var(--sans); font-size:clamp(14px,1vw,16px);
    line-height:1.6; letter-spacing:-.005em;
    max-width:44ch; color:var(--text);
  }

  .form { display:grid; grid-template-columns:1fr 1fr; gap:clamp(16px,2.4vw,30px); }
  .field--wide, .form__foot { grid-column:1 / -1; }
  .field { display:flex; flex-direction:column; gap:.55em; }
  .field label {
    font-family:var(--mono); font-size:10.5px;
    letter-spacing:var(--pm-ls-label); text-transform:uppercase; color:var(--label);
  }
  .field input, .field textarea {
    font-family:var(--mono); font-size:clamp(11px,.85vw,13px);
    color:var(--line); background:transparent;
    border:0; border-bottom:1px solid var(--hair);
    padding:.55em 0; resize:vertical;
  }
  .field input:focus, .field textarea:focus {
    outline:none; border-bottom-color:var(--line);
  }
  .form__foot { display:flex; align-items:center; gap:18px; flex-wrap:wrap; margin-top:.6em; }
  .form__note { margin:0; font-family:var(--mono); font-size:11px; letter-spacing:.06em; }
  /* honeypot - moved out of view rather than display:none, which the better
     bots know to skip. Out of the tab order and off the a11y tree. */
  .hp { position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }

  /* margin-top:auto against the flex column - the sheet gets a bottom edge
     instead of ending halfway down, and the space reads as margin */
  .sheet__foot {
    margin-top:auto; padding-top:clamp(16px,2.4vh,24px);
    border-top:1px solid var(--hair);
    display:flex; align-items:baseline; gap:10px clamp(14px,1.8vw,22px);
    flex-wrap:wrap;
    font-family:var(--mono); font-size:10px;
    letter-spacing:var(--pm-ls-label); text-transform:uppercase;
  }
  .sheet__foot span { color:var(--label); }
  .sheet__foot a {
    color:var(--text); text-decoration:none;
    border-bottom:1px solid var(--hair); padding-bottom:2px;
    letter-spacing:.06em; text-transform:none;
    font-size:clamp(10.5px,.8vw,12.5px);
  }
  .sheet__foot a:hover, .sheet__foot a:focus-visible { border-bottom-color:currentColor; }

  @media (max-width:760px) {
    .sheet { width:92vw; height:88vh; }
    .form { grid-template-columns:1fr; }
  }

  /* side panel: slides in from the right, Notion-style peek */
  .overlay--right { justify-content:flex-end; }
  .panel {
    width:min(620px, 46vw); height:100%;
    background:var(--ground); color:var(--line);
    border-left:1px solid var(--line);
    position:relative; overflow:hidden;
    transform:translateX(100%);
    transition:transform .34s cubic-bezier(.22,.75,.3,1);
  }
  .overlay--right.is-open .panel { transform:none; }
  .panel::after {
    content:""; position:absolute; inset:0; pointer-events:none;
    background-image:var(--grain); background-size:200px 200px;
    mix-blend-mode:multiply; opacity:.18;
  }
  /* flex column so the foot sits on the bottom edge: the panel reads as a
     sheet with a margin, not a column that ran out of content halfway */
  .panel__inner {
    position:relative; z-index:1;
    height:100%; overflow:auto;
    padding:clamp(28px,3.6vw,56px);
    display:flex; flex-direction:column;
  }
  .panel__foot {
    flex:none;
    display:flex; align-items:center; justify-content:space-between;
    gap:16px; flex-wrap:wrap;
    margin-top:clamp(30px,5vh,56px);
    padding-top:clamp(14px,2vh,20px);
    border-top:1px solid var(--hair);
    font-family:var(--mono); font-size:9.5px;
    letter-spacing:var(--pm-ls-label); text-transform:uppercase;
  }
  .panel__sheet { color:var(--label); }
  .btn--sm { padding:.8em 1.4em; font-size:clamp(12px,.85vw,13.5px); }
  .panel__body {
    flex:1 1 auto;
    color:var(--text);
    font-family:var(--sans);
    font-size:clamp(14px,1vw,16px); line-height:1.6;
    letter-spacing:-.005em;
  }
  .panel__body p { margin:0 0 1.4em; max-width:46ch; }
  .panel__body ul { list-style:none; margin:0; padding:0; }
  /* :not(.compat__item) - the logo strip is also a ul, and was picking up
     these rules as stray rules above and below each mark */
  .panel__body li:not(.compat__item) {
    padding:1.05em 0;
    border-top:1px solid var(--hair);
  }
  .panel__body li:not(.compat__item):last-child { border-bottom:1px solid var(--hair); }
  /* pinned: the body around it is sans now, and .22em uppercase tracking is
     a mono setting - inherited into a sans it reads as a mistake */
  .panel__body .li__k {
    display:block; font-family:var(--mono);
    letter-spacing:var(--pm-ls-label); text-transform:uppercase;
    font-size:10px; color:var(--label); margin-bottom:.5em;
  }

  /* which tools these are written for */
  .compat {
    display:flex; align-items:center; flex-wrap:wrap; gap:10px 14px;
    margin:0 0 1.9em;
    padding-bottom:1.4em;
    border-bottom:1px solid var(--hair);
  }
  .compat__list { display:flex; flex-wrap:wrap; align-items:center; gap:22px; list-style:none; margin:0; padding:0; }
  .compat__item {
    display:inline-flex; align-items:center;
    font-size:11px; letter-spacing:.04em; line-height:1;
  }
  .compat__item svg { display:block; height:19px; width:auto; }

  /* prompt cards */
  .pr { border-top:1px solid var(--hair); padding:1.3em 0; }
  .pr:last-child { border-bottom:1px solid var(--hair); }
  .pr__head { display:flex; align-items:center; justify-content:space-between; gap:12px; }
  .pr__head .li__k { margin-bottom:0; }
  .pr__use {
    margin:.5em 0 .9em; opacity:.75;
    font-family:var(--sans); letter-spacing:-.005em;
  }
  .pr__text {
    margin:0; padding:1em 1.1em;
    background:rgba(2,71,211,.05);
    border:1px solid var(--hair);
    font-family:var(--mono); font-size:.92em; line-height:1.62;
    white-space:pre-wrap; word-break:break-word;
    max-height:16em; overflow:auto;
  }
  .pr__copy {
    flex:none; cursor:pointer;
    background:none; color:var(--line);
    border:1px solid var(--line);
    padding:.5em 1em;
    font-family:var(--mono); font-size:9.5px;
    letter-spacing:.16em; text-transform:uppercase; line-height:1;
    transition:background .18s ease, color .18s ease;
  }
  .pr__copy:hover { background:var(--line); color:var(--ground); }
  .pr__copy:focus-visible { outline:2px solid var(--line); outline-offset:2px; }
  .pr__copy.is-done { background:var(--line); color:var(--ground); }

  @media (max-width:760px) { .panel { width:92vw; } }

  /* Below grade is where a drawing carries its title block. The band was
     empty ground; it now holds the sheet's identification. */
  /* The title block closes the document, at the foot of the last section.
     It sat inside the hero while the page was one screen; with sections below
     it that put the footer halfway down, which is not where a footer goes.
     Standing on its own again, it paints its own ground and its own grain. */
  .after {
    position:relative;
    padding:clamp(40px,6vh,84px) var(--gutter) clamp(20px,3vh,32px);
    background:var(--ground-sub);
    font-family:var(--mono);
  }
  .after::after {
    content:""; position:absolute; inset:0; pointer-events:none;
    background-image:var(--grain); background-size:200px 200px;
    mix-blend-mode:multiply; opacity:var(--pm-grain-opacity);
  }
  .colophon__in { position:relative; z-index:1; }
  .colophon__in { width:100%; }
  .tblock {
    display:flex; align-items:flex-end; justify-content:space-between;
    gap:clamp(18px,3vw,56px); flex-wrap:wrap;
    border-top:1px solid var(--line);
    padding-top:clamp(11px,1.7vh,18px);
  }
  .tblock__grid { grid-template-columns:repeat(4,auto); }
  .tblock__grid { display:grid; grid-template-columns:repeat(4,1fr); margin:0; }
  .tblock__grid > div {
    padding:0 clamp(10px,1.2vw,20px);
    border-left:1px solid var(--hair);
  }
  .tblock__grid > div:first-child { border-left:0; padding-left:0; }
  .tblock__grid dt {
    color:var(--label); font-size:9.5px;
    letter-spacing:var(--pm-ls-label); text-transform:uppercase;
    margin-bottom:.85em;
  }
  .tblock__grid dd {
    margin:0; color:var(--text); font-size:clamp(10.5px,.8vw,12.5px);
    line-height:1.45; word-break:break-word;
  }
  .tblock__grid a {
    color:inherit; text-decoration:none;
    border-bottom:1px solid var(--hair); padding-bottom:1px;
  }
  .tblock__grid a:hover, .tblock__grid a:focus-visible { border-bottom-color:currentColor; }

  /* A drawing sheet carries an index. Below 760px .links is display:none and
     this is the only way left to reach AI Studio and Approach at all. */
  .tblock__index {
    display:flex; flex-wrap:wrap; align-items:baseline;
    gap:8px clamp(16px,2.2vw,32px);
    margin:clamp(12px,1.8vh,20px) 0 0;
    padding-top:clamp(10px,1.5vh,15px);
    border-top:1px solid var(--hair);
  }
  .tblock__index-k {
    color:var(--label); font-size:9.5px;
    letter-spacing:var(--pm-ls-label); text-transform:uppercase;
  }
  .tblock__index a {
    color:var(--text); text-decoration:none; cursor:pointer;
    font-family:var(--sans);
    font-weight:500; font-size:clamp(13px,.95vw,15px);
    letter-spacing:-.005em;
    border-bottom:1px solid transparent; padding-bottom:2px;
  }
  .tblock__index a:hover, .tblock__index a:focus-visible { border-bottom-color:currentColor; }
  .tblock__index a:focus-visible { outline:2px solid var(--line); outline-offset:3px; }
  .tblock__legal {
    display:flex; justify-content:space-between; gap:16px; flex-wrap:wrap;
    margin:clamp(10px,1.5vh,16px) 0 0; padding-top:10px;
    border-top:1px solid var(--hair);
    color:var(--label); font-size:9.5px;
    letter-spacing:.16em; text-transform:uppercase;
  }

  @media (max-width:760px) {
    .tblock { flex-direction:column; align-items:flex-start; }
    .tblock__grid { grid-template-columns:repeat(2,1fr); row-gap:24px; }
    .tblock__grid > div:nth-child(3) { border-left:0; padding-left:0; }
  }

  /* ---- section pages ---------------------------------------------------
     Projects, AI Studio and Approach are pages now rather than slide-in
     panels. They reuse the panel's own body styles, so the content reads
     identically to where it came from; only the container changes. */
  body { background:var(--ground); }
  .site-head--page {
    position:static;
    border-bottom:1px solid var(--hair);
  }
  .site-head--page .links a[aria-current="page"] {
    color:var(--text-title);
    border-bottom-color:currentColor;
  }
  /* Hangs off the same left margin as the header and the title block, the
     way everything else on the sheet does - a centred column leaves the
     lockup stranded on its own. */
  /* A plate across the head of each section page. Full bleed, cropped to a
     band: these are drawings, already crops of a larger sheet, so taking a
     band out of one costs nothing. The homepage has no banner - its header
     IS the elevation. */
  .page__banner {
    position:relative;
    height:clamp(130px, 20vh, 240px);
    overflow:hidden;
    background:var(--pm-paper-200);
    border-bottom:1px solid var(--hair);
  }
  .page__banner img {
    width:100%; height:100%;
    object-fit:cover; object-position:center 62%;
    display:block;
  }
  .page__banner::after {
    content:""; position:absolute; inset:0; pointer-events:none;
    background-image:var(--grain); background-size:200px 200px;
    mix-blend-mode:multiply; opacity:var(--pm-grain-opacity);
  }

  .page {
    padding:clamp(38px,7vh,84px) var(--gutter) clamp(40px,7vh,90px);
    display:flex; flex-direction:column;
    min-height:calc(100svh - 230px);
  }
  .page__head, .page__body, .page__foot { max-width:70ch; }
  /* the panel measure was set for a 620px drawer; a page is not that */
  .page__body p { max-width:64ch; }
  .page__body .pr__text { max-height:none; }
  .page__head { margin-bottom:clamp(22px,3.4vh,38px); }
  .page__title {
    margin:0;
    font-family:var(--sans); font-weight:500;
    color:var(--text-title);
    font-size:clamp(1.9rem, 1.1rem + 2.4vw, 3rem);
    line-height:1.1; letter-spacing:-.02em;
  }
  .page__body { flex:1 1 auto; }
  .page__foot {
    flex:none;
    display:flex; align-items:center; justify-content:space-between;
    gap:16px; flex-wrap:wrap;
    margin-top:clamp(30px,5vh,56px);
    padding-top:clamp(14px,2vh,20px);
    border-top:1px solid var(--line);
    font-family:var(--mono); font-size:9.5px;
    letter-spacing:var(--pm-ls-label); text-transform:uppercase;
  }


  /* ---- the traverse -----------------------------------------------------
     One continuous spine down the middle, drawn by the scroll, with each
     phase alternating: plate on one side, text on the other. The spine is a
     plain element whose height is the scroll progress - not an SVG path -
     because a straight line has no reason to be a path, and a filled height
     cannot develop the gaps or seams a dashed stroke can.

     Nothing here exists until it is scrolled to: the spine has no track, the
     dots and the copy start at zero. */
  .traverse {
    position:relative;
    padding:clamp(56px,9vh,120px) var(--gutter) clamp(60px,10vh,140px);
    background:var(--ground);
  }
  .traverse::after {
    content:""; position:absolute; inset:0; pointer-events:none;
    background-image:var(--grain); background-size:200px 200px;
    mix-blend-mode:multiply; opacity:var(--pm-grain-opacity);
  }
  .traverse__head { position:relative; z-index:1; max-width:56ch; margin-bottom:clamp(34px,6vh,80px); }
  .traverse__title {
    margin:0 0 .5em; color:var(--text-title);
    font-family:var(--sans); font-weight:500;
    font-size:clamp(1.6rem,1rem + 1.9vw,2.5rem);
    line-height:1.12; letter-spacing:-.02em; text-wrap:pretty;
  }
  .traverse__lede {
    margin:0; color:var(--text); font-family:var(--sans);
    font-size:clamp(14px,1vw,16px); line-height:1.6; letter-spacing:-.005em;
    max-width:52ch;
  }

  .tl { position:relative; z-index:1; }
  .tl__spine {
    position:absolute; top:0; bottom:0; left:50%;
    width:1px; margin-left:-.5px; pointer-events:none;
  }
  .tl__fill {
    display:block; width:100%; height:var(--fill,0%);
    background:var(--line);
  }

  .tl__rows { list-style:none; margin:0; padding:0; }
  .tl__row {
    display:grid;
    grid-template-columns:1fr clamp(56px,7vw,110px) 1fr;
    align-items:center;
    gap:0 clamp(16px,2vw,36px);
    padding:clamp(34px,6vh,70px) 0;
  }
  /* alternating: the plate changes side, the spine does not move */
  .tl__row .tl__fig  { grid-column:1; }
  .tl__row .tl__body { grid-column:3; }
  .tl__row:nth-child(even) .tl__fig  { grid-column:3; }
  .tl__row:nth-child(even) .tl__body { grid-column:1; }

  .tl__dot {
    grid-column:2; justify-self:center;
    width:11px; height:11px; border-radius:50%;
    border:1px solid var(--line); background:var(--ground);
    opacity:0; transition:opacity .3s ease;
  }
  .tl__row.is-on .tl__dot { opacity:1; }

  .tl__fig {
    margin:0; opacity:0; transition:opacity .5s ease;
    border:1px solid var(--hair); background:var(--pm-paper-050);
    padding:clamp(14px,1.6vw,24px);
  }
  .tl__fig img { display:block; width:100%; height:auto; }
  .tl__row.is-on .tl__fig { opacity:1; }

  .tl__body { opacity:0; transition:opacity .45s ease; }
  .tl__row.is-on .tl__body { opacity:1; }
  .tl__n {
    display:block; font-family:var(--mono); color:var(--label);
    font-size:9.5px; letter-spacing:var(--pm-ls-label); text-transform:uppercase;
    margin-bottom:.7em;
  }
  .tl__h {
    margin:0 0 .4em; color:var(--text-title);
    font-family:var(--sans); font-weight:500;
    font-size:clamp(16px,1.25vw,21px); letter-spacing:-.01em; line-height:1.2;
  }
  .tl__p {
    margin:0; color:var(--text); font-family:var(--sans);
    font-size:clamp(13px,.95vw,15px); line-height:1.55; letter-spacing:-.005em;
    max-width:44ch;
  }

  /* Narrow: the spine moves to the left margin and everything stacks beside
     it - a centre line with 40ch either side does not fit a phone. */
  @media (max-width:820px) {
    .tl__spine { left:7px; margin-left:0; }
    .tl__row {
      grid-template-columns:26px minmax(0,1fr);
      align-items:start;
      gap:0 clamp(12px,3vw,20px);
      padding:clamp(26px,4vh,44px) 0;
    }
    .tl__row .tl__fig, .tl__row:nth-child(even) .tl__fig,
    .tl__row .tl__body, .tl__row:nth-child(even) .tl__body { grid-column:2; }
    .tl__dot { grid-column:1; justify-self:start; margin-top:.35em; }
    .tl__fig { margin-bottom:clamp(14px,2.4vh,22px); }
    .tl__p { max-width:none; }
  }

  /* reduced motion drops the fades; the spine still follows the scroll */
  .tl--still .tl__fig, .tl--still .tl__body, .tl--still .tl__dot { transition:none; }

  /* the mark goes home, on every page */
  .lockup__home { display:inline-flex; text-decoration:none; color:inherit; border-radius:2px; }
  .lockup__home:focus-visible { outline:2px solid var(--line); outline-offset:4px; }
  .lockup__home:hover .lockup__type { color:var(--pm-ink-600); }
