/* v8 "Studio Triple" - the re-skin sheet. Direction B, gated 2026-07-29 with
   one amendment: Karrik replaces Le Murmure on the display face.

   The system in one breath: a riso studio print. One sheet, one key plate and
   three constant inks. A left rail carries the wordmark, the ink-chip contents
   and the edition switch. The landing index is not a list any more, it is a
   printed block: three full-width ink bands with the route names reversed out
   in knockout cream, each band edged with a permanent 2px keyline so it keeps
   its boundary on a dark sheet. No folio numerals, no kickers, no terrain wash,
   no grain.

   Two faces. Karrik (static, 400) sets the H1 and the three route-band names
   and nothing else. Bricolage Grotesque (variable, opsz 12-36 / wght 300-700 /
   wdth 87.5-100) sets everything else, with all three axes pinned on every
   rule because the trimmed file's fvar defaults clamp to opsz 36 / wght 700.
   There is no italic file and none is coming: font-synthesis is off and the
   eleven v7 italic runs are restyled as roman register shifts.

   TWO-TIER REGISTER INK. The three route inks are edition-invariant when they
   are GROUNDS: a band is #a3243f / #0f6d4b / #33569f whichever edition the
   reader is in, because in a riso job the ink belongs to the plate, not to the
   reader. Those same inks as TEXT fail on the night sheet (2.58 / 2.96 / 2.66),
   so --register carries a second, per-edition tier: the paper set is the band
   inks themselves, the night set is a riso tint of the same three hues (55% ink
   into the knockout cream, mixed in oklab). Pages with no dossier class fall
   back to --register:var(--key), a deliberate neutral rather than v7's
   accidental campaigns blue.

   --------------------------------------------------------------------------
   INK CHECK  (python3 tests/ink-check.py <ground> <ink...>, portfolio root)
   --------------------------------------------------------------------------
   1) NIGHT SHEET  #0d1218
        key             #f2ecdf   15.97  AA body
        muted           #97a0a6    7.07  AA body
        register text   editorial #cf8587 6.59 | ai #81a78e 7.03 | campaigns #879cc2 6.77
        line            #39424a    1.84  rules only, never text
        hairline        #1d2530    1.22  rules only, never text
        chart bed       #181814    1.06  which is why the plate is given an edge
        band grounds    #a3243f 2.58 | #0f6d4b 2.96 | #33569f 2.66
        band at full ink 1.59 / 1.78 / 1.68. The tool calls the inks FAIL
        because it reads them as text. They are grounds. Band separability is
        why every band carries a permanent knockout keyline.

   2) PAPER SHEET  #f7f2e7
        key             #17140f   16.45  AA body
        muted           #59524a    6.89  AA body
        register text   editorial #a3243f 6.53 | ai #0f6d4b 5.68 | campaigns #33569f 6.33
        line            #b8b0a0    1.93  rules only
        hairline        #ded6c6    1.29  rules only

   3) REVERSED-OUT TYPE ON EVERY BAND STATE, both editions (knockout #f7f2e7)
        rest  editorial  6.53 | ai  5.68 | campaigns  6.33
        full  editorial 10.58 | ai  9.49 | campaigns 10.04
      All six clear AA body for the route name and the description line, and
      hover only ever raises the ratio.

      The fourth band state is the KEY PLATE, which the one uninked route at
      the foot of each dossier takes. Its type is the sheet, so it inverts
      with the edition and its hover mixes the key 84% into the sheet in
      oklab:
        night rest   ground #f2ecdf, type #0d1218   15.97  AA body
        night hover  ground #c8c4bb, type #0d1218   10.81  AA body
        paper rest   ground #17140f, type #f7f2e7   16.45  AA body
        paper hover  ground #35312b, type #f7f2e7   11.57  AA body

   4) PLATES AND VEILS (edition-invariant)
        chart bed  #181814 with cream labels #f7f2e7   15.95
        sheet veil #080706 with knockout    #f7f2e7    18.03
        an opened .sheet-page pins the paper set in both editions:
        #f7f2e7 ground, #17140f 16.45, muted #59524a 6.89

   5) PRINT, true white #ffffff
        key #17140f 18.37 | muted #4a443c 9.62
        band inks as line work and as text: 7.29 / 6.35 / 7.06

   MOTION INVENTORY (Phase 8 rebuilds motion-check from this list)
     page motion, exactly one:  .index-home a background-color .28s
     state changes on approach: link underline draw, --ink weight on wordmark
       / reading-list titles / colophon address, ticker and stage-rail rule
       colour, plate and summary border colour
     press feedback on :active:  border-bottom-width, --t-press
     disclosure:                 details::details-content block-size, marker rotate
     component:                  theme-knob slide
     Retired from v7: masthead-drift (40s), terrain drift (theme.js still
     writes --terrain-y on :root; this sheet never reads it), the --spring
     overshoot easing, every backdrop-filter.
   ========================================================================== */

@layer reset, tokens, base, furniture, dossier, essay, print;

/* Karrik is static. Every Karrik rule sets font-variation-settings:normal so
   the body's Bricolage axis pins cannot inherit onto it. */
@font-face{
  font-family:"Karrik";
  src:url("assets/fonts/karrik-latin.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap;
}
/* The production Bricolage was instanced to opsz 12-36 / wght 300-700 /
   wdth 87.5-100, which clamped its fvar defaults to opsz 36 / wght 700 and
   set usWeightClass 700. Declaring the real ranges here is what stops the
   browser picking that default, and every rule below pins all three axes. */
@font-face{
  font-family:"Bricolage Grotesque";
  src:url("assets/fonts/bricolagegrotesque-latin.woff2") format("woff2");
  font-weight:300 700;font-stretch:87.5% 100%;font-style:normal;font-display:swap;
}

/* Registered so weight can interpolate. It is read on the element that sets
   it, so it must not inherit: a pseudo-element inherits from its originating
   element, which is the trap that silently kills the move. v7 also registered
   --draw; nothing ever consumed it, so it does not come across. */
@property --ink{syntax:"<number>";inherits:false;initial-value:400}

@layer reset{
  *,*::before,*::after{box-sizing:border-box}
  body,h1,h2,h3,p,figure,blockquote,table{margin:0}
  img{display:block;max-width:100%;height:auto}
  table{border-collapse:collapse}
  button{font:inherit;color:inherit;background:none;border:0}
}

@layer tokens{
  :root{
    /* Paper is the initial/default edition. The sheet is a warm press cream. */
    --sheet:#f7f2e7;
    --key:#17140f;
    --muted:#59524a;
    --line:#b8b0a0;
    --hair:#ded6c6;

    /* the register ink AS TEXT. */
    --register:var(--key);

    /* Constants. These do not flip with the edition, because the ink and the
       knockout are properties of the plate, not of the reader. */
    --ko:#f7f2e7;          /* the knockout: sheet cream reversed out of ink */
    --plate-dark:#181814;  /* backing for charts drawn in cream ink */
    --veil:#080706;        /* the backdrop behind an opened sheet */
    --veil-text:var(--ko);

    /* the three plates, at riso saturation, and the same three with the key
       plate laid on top (rest multiplied per channel by #9c988e) */
    --ink-ed:#a3243f;      --ink-ed-full:#6b1727;
    --ink-ai:#0f6d4b;      --ink-ai-full:#0a4830;
    --ink-cam:#33569f;     --ink-cam-full:#223a68;
    --ink-wr:#6d3f7a;      --ink-wr-full:#4a2a53;

    --statement-ed:#a3243f;
    --statement-ai:#0f6d4b;
    --statement-cam:#33569f;
    --statement-wr:#6d3f7a;

    --grain-a:.03;         --grain-f:invert(1);
    --rail-sheet:#eee7d4;  --rail-topo-a:.075;  --rail-topo-f:invert(1);

    color-scheme:light;

    --display:"Karrik",Georgia,serif;
    --text:"Bricolage Grotesque","Helvetica Neue",Arial,sans-serif;
    --spine-display:80px;
    --spine-h1:50px;
    --spine-h2:31px;
    --spine-h3:19px;

    --step--1:clamp(.78rem,.74rem + .16vw,.88rem);
    --step-0:clamp(1rem,.96rem + .2vw,1.11rem);
    --step-1:clamp(1.2rem,1.1rem + .5vw,1.5rem);
    --step-2:clamp(1.6rem,1.3rem + 1.4vw,2.4rem);
    --step-3:clamp(2rem,1.4rem + 3vw,3.6rem);   /* route names, route h1 */
    --step-4:clamp(1.9rem,1.1rem + 2.7vw,3.2rem); /* the statement h1 */
    --step-read:clamp(1.06rem,1.02rem + .22vw,1.18rem);

    --space-3xs:.25rem; --space-2xs:.45rem; --space-xs:.75rem;
    --space-s:1rem;     --space-m:1.6rem;   --space-l:2.4rem;
    --space-xl:3.6rem;  --space-2xl:5.2rem; --space-3xl:7.5rem;

    --rail-w:13.5rem;
    --pad:clamp(1.1rem,4vw,3rem);

    --f-text:"opsz" 14,"wght" 400,"wdth" 100;
    --f-read:"opsz" 16,"wght" 400,"wdth" 100;
    --f-small:"opsz" 12,"wght" 400,"wdth" 100;
    --f-label:"opsz" 12,"wght" 700,"wdth" 100;
    --f-quiet:"opsz" 12,"wght" 600,"wdth" 90;
    --f-lead:"opsz" 24,"wght" 400,"wdth" 100;
    --f-mid:"opsz" 24,"wght" 600,"wdth" 100;
    --f-strong:"opsz" 24,"wght" 700,"wdth" 100;

    --bite:cubic-bezier(.2,0,.1,1);
    --t-press:.1s;
    --t-band:.28s;
    --radius-round:50%;
  }

  body.reg-editorial{--register:#a3243f}
  body.reg-ai{--register:#0f6d4b}
  body.reg-campaigns{--register:#33569f}
  body.reg-writing{--register:#6d3f7a}
}

@layer base{
  html{background:var(--sheet)}
  /* the stock's tooth: one fixed tile over the whole screen sheet. On html,
     not body (body is a grid), file path not data: URI (img-src 'self').
     Native popovers live in the top layer and stay above it; the print
     layer's kill list removes it. */
  html::before{
    content:"";position:fixed;inset:0;z-index:40;pointer-events:none;
    background:url(assets/grain.svg);background-size:150px;
    opacity:var(--grain-a);filter:var(--grain-f);
  }
  body{
    background:var(--sheet);
    color:var(--key);
    font-family:var(--text);
    font-size:var(--step-0);
    line-height:1.55;
    font-weight:400;
    font-variation-settings:var(--f-text);
    /* No italic file ships and none is wanted. Nothing obliques silently. */
    font-synthesis:none;
    font-variant-numeric:lining-nums proportional-nums;
    letter-spacing:.012em;
    -webkit-font-smoothing:antialiased;

    /* the frame: the rail is the studio's own margin, the column is the
       press bed. The header is the rail on every page. */
    display:grid;
    grid-template-columns:var(--rail-w) minmax(0,1fr);
    grid-template-rows:1fr auto;
    min-height:100vh;
    min-height:100dvh;
  }
  .site-header{grid-column:1;grid-row:1/-1}
  main{grid-column:2;grid-row:1;min-width:0;padding-bottom:var(--space-2xl)}
  body>footer{grid-column:2;grid-row:2;min-width:0}

  /* the display face, and the only two places it is allowed */
  h1{
    font-family:var(--display);font-weight:400;font-variation-settings:normal;
    font-size:var(--step-3);line-height:1.02;letter-spacing:-.025em;
    text-wrap:balance;
  }
  h2,h3{font-weight:400;letter-spacing:-.025em;text-wrap:balance;font-variation-settings:var(--f-mid)}
  p{text-wrap:pretty}
  /* italic is dropped site-wide: no file, no synthesis, no oblique */
  em,i,cite{font-style:normal}

  .measure{max-width:66ch}
  /* v7's shell was a centred 1180px column. Direction B sets flush left off
     the rail with one gutter, and the things that need a measure carry their
     own. That is what lets a band bleed to the column edge with a negative
     margin instead of viewport arithmetic. */
  .shell{width:100%;margin-inline:0;padding-inline:var(--pad)}

  ::selection{background:var(--key);color:var(--sheet)}

  a{
    color:inherit;text-decoration:none;
    background:linear-gradient(currentColor,currentColor) no-repeat left bottom/0 1px;
    transition:background-size .2s var(--bite);
  }
  a:hover,a:focus-visible{background-size:100% 1px}
  /* a link inside running copy is visible at rest, at half strength, and
     takes full ink on approach */
  p a,figcaption a,.credit a{
    background-size:100% 1px;
    background-image:linear-gradient(color-mix(in oklab,currentColor 45%,transparent),color-mix(in oklab,currentColor 45%,transparent));
  }
  p a:hover,p a:focus-visible,figcaption a:hover,figcaption a:focus-visible,
  .credit a:hover,.credit a:focus-visible{
    background-image:linear-gradient(currentColor,currentColor);
  }
  /* a bare :focus-visible rather than a link-and-button list, so the skip
     link's destination (tabindex="-1") gets a ring too */
  :focus-visible{outline:2px solid var(--key);outline-offset:3px}
  [tabindex="-1"]:focus-visible{outline-offset:6px}
  /* a full-bleed skip target cannot take an outset ring. It already reaches
     both column edges, so at +6px the ring lands under the rail on one side
     and off the sheet on the other, and reads as a bracket. The bleeding
     targets take the band's inset ring instead. */
  .index:focus-visible,main[tabindex="-1"]:focus-visible{outline-offset:-8px}

  .skip-link{
    position:fixed;z-index:50;top:1rem;left:1rem;padding:.6rem .9rem;
    background:var(--key);color:var(--sheet);
    font-variation-settings:var(--f-label);
    transform:translateY(-200%);
  }
  .skip-link:focus{transform:none}
}

@layer furniture{
  /* ------------------------------------------------------------- the rail */
  .site-header{border-right:1px solid var(--hair)}
  /* min-height gives the toggle's margin-top:auto something definite to push
     against; max-height plus overflow-y keeps the lower controls reachable
     when the reader zooms text past the viewport. */
  .site-header .header-row{
    position:sticky;top:0;
    min-height:100vh;max-height:100vh;
    min-height:100dvh;max-height:100dvh;
    overflow-y:auto;
    display:flex;flex-direction:column;align-items:flex-start;
    gap:var(--space-l);
    padding:var(--space-m) var(--space-s) var(--space-m) var(--pad);
    /* the rail's own stock, laid over the bed */
    background:var(--rail-sheet);
    isolation:isolate;
  }
  /* the terrain under the studio margin: the v7 topo wash back as furniture,
     not atmosphere. Static; the drift died with v8 and stays dead. */
  .site-header .header-row::before{
    content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
    background:url(assets/topo.svg) center/220% auto;
    opacity:var(--rail-topo-a);filter:var(--rail-topo-f);
  }
  /* Bricolage, not Karrik: the display face is reserved for the H1 and the
     three route names. The ink saturates on approach, the way it does on the
     reading-list titles and the colophon address. */
  .wordmark{
    font-size:var(--step-0);line-height:1;
    background:none;cursor:pointer;width:max-content;
    --ink:500;
    font-variation-settings:"opsz" 18,"wght" var(--ink),"wdth" 90;
    letter-spacing:-.01em;
    transition:--ink .2s var(--bite);
  }
  /* :active is not decoration here. It is the only form of this a thumb ever
     receives, and cursor:pointer makes iOS Safari paint it on tap. */
  .wordmark:hover,.wordmark:focus-visible,.wordmark:active{--ink:700}

  /* the contents, as ink chips. Each route sits beside its own plate. */
  .ticker{
    display:flex;flex-direction:column;align-items:flex-start;
    gap:var(--space-xs);
    font-size:var(--step--1);
    font-variation-settings:"opsz" 12,"wght" 500,"wdth" 100;
    font-variant-numeric:lining-nums;
  }
  .ticker a{
    display:flex;align-items:center;gap:.55rem;
    background:none;color:var(--muted);
    transition:color .14s var(--bite);
  }
  .ticker a::before{
    content:"";width:.74rem;height:.74rem;flex:0 0 auto;background:var(--muted);
  }
  .ticker a:first-child::before{background:var(--key)}
  .ticker a[href*="editorial"]::before{background:var(--ink-ed)}
  .ticker a[href*="ai-production"]::before{background:var(--ink-ai)}
  .ticker a[href*="campaigns"]::before{background:var(--ink-cam)}
  .ticker a[href*="writing"]::before{background:var(--ink-wr)}
  .ticker a:hover,.ticker a:focus-visible,.ticker a[aria-current]{color:var(--key)}

  /* ------------------------------------------------ the garnish furniture */
  .kicker-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--space-3xs) var(--space-m)}
  .status{
    display:flex;align-items:center;
    font-size:var(--step--1);color:var(--key);
    letter-spacing:.09em;text-transform:uppercase;
    font-variation-settings:var(--f-label);
  }
  /* the register bar: the three plates this sheet is printed from, drawn as
     one strip of chips with the registration gaps left open */
  .status::before{
    content:"";display:inline-block;width:2.6em;height:.62em;margin-right:.6em;
    background:linear-gradient(90deg,
      var(--ink-ed) 0 30%,transparent 30% 35%,
      var(--ink-ai) 35% 65%,transparent 65% 70%,
      var(--ink-cam) 70% 100%);
  }

  /* the three-ink registration bar that opened the landing contents (v7 to
     the 2026-09-07 build) is gone at his call; the books section opens on
     the same hairline as every other section. */

  /* the spec row: a dotted leader, the grammar of a colophon spec table */
  .spec{margin:var(--space-m) 0 var(--space-l);max-width:44rem}
  .spec>div{display:flex;align-items:baseline;gap:var(--space-s);padding:.4rem 0}
  .spec dt{
    flex:1;display:flex;align-items:baseline;gap:var(--space-s);
    font-size:var(--step--1);letter-spacing:.09em;text-transform:uppercase;
    color:var(--muted);font-variation-settings:var(--f-label);
  }
  .spec dt::after{content:"";flex:1;border-bottom:1px dotted var(--line);transform:translateY(-.3em)}
  .spec dd{margin:0;font-size:var(--step-0);text-align:right;max-width:34ch;transition:color .2s var(--bite)}
  /* the answer takes the register on approach; weight stays put */
  .spec>div:hover dd{color:var(--register)}

  .section-rule{
    display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-m);
    border-top:2px solid var(--key);
    padding-top:var(--space-xs);
    margin-bottom:var(--space-m);
    position:relative;z-index:1;
  }
  .section-rule h2{
    font-size:var(--step--1);letter-spacing:.1em;text-transform:uppercase;
    font-variation-settings:var(--f-label);
  }
  .section-rule p{
    font-size:var(--step--1);color:var(--muted);letter-spacing:.02em;
    font-variation-settings:var(--f-small);
  }

  .standfirst{
    font-size:var(--step-1);line-height:1.34;max-width:44ch;
    font-variation-settings:var(--f-lead);
  }

  /* the pull quote keeps its size and its register rule and loses the italic.
     Register carries it: a wider measure, a rule in the dossier ink, and the
     curly quotes already in the copy. */
  blockquote{
    font-size:var(--step-2);line-height:1.32;
    font-variation-settings:"opsz" 24,"wght" 350,"wdth" 100;
    border-left:2px solid var(--register);padding-left:var(--space-s);
    margin-block:var(--space-m);max-width:48ch;
  }
}

@layer dossier{
  /* the hero is flat on the sheet. v7 floated it on a frosted, bevelled
     legend card over the terrain wash; there is no wash to read through and
     no glass in this direction, so the card and its whole --frost / --emboss
     / --card-fill family are retired. */
  .route-hero{margin-top:var(--space-l);padding:0 0 var(--space-m)}
  .route-hero h1{margin:var(--space-2xs) 0 var(--space-m);max-width:20ch}
  .route-hero .standfirst{margin-bottom:var(--space-s)}
  /* A sentence-length h1 reads as a statement, not a title. Its three inks
     drift like a slow split fountain: colour moving through paper, with no
     bright sweep or synthetic sheen. */
  .route-hero h1.statement{font-size:var(--step-4);line-height:1.04;max-width:30ch}
  @supports ((background-clip:text) or (-webkit-background-clip:text)){
    .route-hero h1.statement{
      color:transparent;-webkit-text-fill-color:transparent;
      background-image:linear-gradient(105deg,
        var(--statement-ed) 0%,var(--statement-wr) 50%,
        var(--statement-ed) 100%);
      background-size:180% 100%;background-position:0% 50%;
      background-clip:text;-webkit-background-clip:text;
      animation:statement-ink-drift 22s ease-in-out infinite alternate;
    }
  }
  @keyframes statement-ink-drift{
    to{background-position:100% 50%}
  }

  .case-section{padding:var(--space-xl) 0 var(--space-2xl)}
  .case-section p+p,.route-hero p+p{margin-top:var(--space-s)}
  .case-layout{
    display:grid;grid-template-columns:minmax(0,1.15fr) minmax(18rem,.85fr);
    gap:clamp(2rem,5vw,5rem);align-items:start;max-width:76rem;
  }
  .case-layout>*{min-width:0}

  h3{
    font-size:var(--step-2);margin:var(--space-l) 0 var(--space-2xs);
    font-variation-settings:var(--f-mid);
  }
  h3:first-child{margin-top:0}

  .eyebrow{
    font-size:var(--step--1);letter-spacing:.09em;text-transform:uppercase;
    color:var(--muted);margin-bottom:var(--space-3xs);
    font-variation-settings:var(--f-label);
  }
  /* the kicker class was removed from the markup on 2026-07-14 and the three
     route pages still ship a plain <p> where it was. Nothing dresses it. */

  /* ---------------------------------------- plates that open, not figures */
  .plate{border:0;padding:0;background:none;display:block;width:100%}
  .plate-open{
    display:block;width:100%;cursor:zoom-in;text-align:left;
    border:1px solid var(--line);
    padding:var(--space-2xs);
    transition:border-color var(--t-press) var(--bite);
  }
  .plate-open img{width:100%}
  .plate-open:hover,.plate-open:focus-visible{border-color:var(--key)}
  .plate-open:active{border-bottom-width:3px;border-bottom-color:var(--key);padding-bottom:calc(var(--space-2xs) - 2px)}

  /* the cue chip: a plate must say it opens. v7 typed the mark as U+2295 and
     got it from a system serif; neither Karrik nor Bricolage carries that
     codepoint, so the mark is drawn instead. A circled cross is a
     registration target, which is the right mark for this sheet anyway. It
     takes currentColor, so it follows the cue's own hover. */
  .plate-cue{
    display:flex;justify-content:space-between;align-items:center;gap:var(--space-2xs);
    margin-top:var(--space-2xs);padding-top:.3rem;
    border-top:1px solid var(--line);
    font-size:.66rem;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);
    font-variation-settings:var(--f-label);
    transition:color .14s var(--bite),border-top-color .14s var(--bite);
  }
  .plate-cue::after{
    content:"";flex:0 0 auto;width:.95rem;height:.95rem;
    border:1px solid currentColor;border-radius:var(--radius-round);
    background:
      linear-gradient(currentColor,currentColor) center/1px 62% no-repeat,
      linear-gradient(currentColor,currentColor) center/62% 1px no-repeat;
  }
  .plate-open:hover .plate-cue,.plate-open:focus-visible .plate-cue{
    color:var(--key);border-top-color:var(--key);
  }

  .plate figcaption{
    padding:var(--space-xs) var(--space-3xs) var(--space-3xs);
    font-size:var(--step--1);color:var(--muted);line-height:1.45;
    font-variation-settings:var(--f-small);
  }
  /* the block-label idiom. The markup carries no separator between the label
     and the sentence after it, so display:block is load-bearing everywhere
     it appears below. */
  .plate figcaption b{
    display:block;font-size:var(--step--1);
    letter-spacing:.09em;text-transform:uppercase;color:var(--key);
    margin-bottom:var(--space-3xs);
    font-variation-settings:var(--f-label);
  }
  .plate figcaption a{color:inherit}
  .plate-stack{position:sticky;top:var(--space-m);display:grid;gap:var(--space-m)}
  .plate-row{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-s);margin-top:var(--space-m)}
  .plate-row.two{grid-template-columns:repeat(2,1fr);max-width:56rem}
  .wall{margin-top:var(--space-l)}
  .plate-wide{max-width:56rem;margin-top:var(--space-s)}
  .plate-shelf{display:grid;grid-template-columns:repeat(5,1fr);gap:var(--space-s);margin-top:var(--space-m);align-items:start}
  /* jackets differ a few percent in proportion, so at equal column width the
     frames stop at unequal heights. Pin every cover to a single 2:3 box. */
  .plate-shelf .plate-open img{aspect-ratio:1/1.5;object-fit:cover}
  /* editions wall: the four posts arrive in three aspects (1:1, 3:4, and the
     reel's trim), which staggered every caption below them. One fixed frame,
     content letterboxed. contain, not cover: these are data slides, a crop
     would eat axes and numbers. The band colour lives in the unlayered
     lit-sheet zone with the other bed exceptions; a layered background here
     would lose to it. */
  #editions .plate-open img{aspect-ratio:3/4;object-fit:contain}
  /* the landing gallery: the shelf bled to the column edges, same arithmetic
     as the ink bands. Hairline gaps, one shared crop box, no wrap: five
     jackets as one printed strip, decorative at any width (the readable
     copies live on the editorial route). Beats the 900px 3-column fallback
     on specificity, which is the point: the strip never breaks its row. */
  .plate-shelf.bleed{
    margin-inline:calc(-1*var(--pad));
    grid-template-columns:repeat(8,1fr);
    gap:var(--space-3xs);
  }
  .plate-shelf.bleed img{width:100%;aspect-ratio:1/1.55;object-fit:cover}

  /* the opened sheet. Top layer, light dismiss, Escape, focus return: all
     native. :popover-open, ::backdrop, @starting-style and the two
     allow-discrete transitions are one mechanism, not four options. */
  .sheet{
    border:0;padding:0;background:none;max-width:min(94vw,1150px);width:100%;
    position:fixed;inset:0;margin:auto;height:max-content;max-height:94dvh;overflow:auto;
    opacity:1;
    transition:opacity .18s var(--bite),overlay .18s allow-discrete,display .18s allow-discrete;
  }
  .sheet:not(:popover-open){opacity:0}
  @starting-style{.sheet:popover-open{opacity:0}}
  .sheet::backdrop{background:color-mix(in oklab,var(--veil) 94%,transparent)}
  /* a sheet for a plate cut at 598px: open at natural size, never upscaled */
  .sheet-narrow{max-width:min(94vw,600px)}
  .sheet img{width:100%;border:1px solid var(--veil-text)}
  .sheet-foot{
    display:flex;justify-content:space-between;align-items:baseline;gap:var(--space-s);
    padding-top:var(--space-2xs);
    font-size:var(--step--1);color:var(--veil-text);
    font-variation-settings:var(--f-small);
  }
  .sheet-foot a{color:inherit}
  .sheet-close{
    font-size:var(--step--1);letter-spacing:.09em;text-transform:uppercase;
    color:var(--veil-text);cursor:pointer;padding:.2rem 0 .1rem;
    font-variation-settings:var(--f-label);
    border-bottom:1px solid color-mix(in oklab,var(--veil-text) 50%,transparent);
    transition:border-bottom-width var(--t-press) var(--bite),border-bottom-color var(--t-press) var(--bite);
  }
  .sheet-close:hover,.sheet-close:focus-visible{border-bottom-color:var(--veil-text)}
  .sheet-close:active{border-bottom-width:3px}

  /* a sheet that opens to a page rather than a plate: the jacket beside the
     blurb that went to print on it. It pins the paper set in both editions,
     because opening a plate puts a sheet of stock on the table. The five
     blurbs are verbatim published artefacts and read as print. */
  .sheet-page{
    display:grid;grid-template-columns:minmax(9rem,.45fr) 1fr;gap:var(--space-m);
    padding:var(--space-m);align-items:start;
    --sheet:#f7f2e7;--key:#17140f;--muted:#59524a;--line:#b8b0a0;
    background:var(--sheet);color:var(--key);
    /* the plate edge: the dossier's register ink misprinting past the
       stock, so an opened sheet reads as a pull from the same press. One
       hard shadow, no blur; forced-colors drops it and keeps the border. */
    box-shadow:.45rem .45rem 0 var(--register);
  }
  /* the edge is ink on the roller, a plate property: it pins the saturated
     plate ink in both editions, the way the sheet pins the paper stock. The
     night text tier's tint is for reading, not for rollers. */
  body.reg-editorial .sheet-page{--register:var(--ink-ed)}
  body.reg-ai .sheet-page{--register:var(--ink-ai)}
  body.reg-campaigns .sheet-page{--register:var(--ink-cam)}
  .sheet-page img{border:1px solid var(--line)}
  /* the blurbs are the one place italic was already cancelled in v7 */
  .sheet-page .blurb{
    font-style:normal;font-size:var(--step-0);line-height:1.55;
    font-variation-settings:var(--f-text);
    border:0;padding:0;margin:0;max-width:58ch;
  }
  .sheet-page .blurb p{margin-bottom:var(--space-xs)}
  .sheet-page h3{margin-top:0;font-size:var(--step-1)}
  .sheet-page .byline{color:var(--muted);font-size:var(--step--1);margin-bottom:var(--space-s)}
  .sheet-page .credit{
    font-size:var(--step--1);color:var(--muted);
    font-variation-settings:var(--f-small);
    border-top:1px solid var(--line);padding-top:var(--space-2xs);margin-top:var(--space-2xs);
  }

  /* a sheet that opens to a strip: the carousel as it ran, slide by slide */
  .sheet-strip{
    display:grid;grid-auto-flow:column;grid-auto-columns:min(76vw,22rem);
    gap:var(--space-2xs);overflow-x:auto;
    scroll-snap-type:x mandatory;padding-bottom:var(--space-2xs);
  }
  .sheet-strip img{scroll-snap-align:center}

  /* --------------------------------------------------------- the book run */
  /* The chain a title walks from manuscript to print, drawn: six stages on
     one spine, the fifth forking into two lanes that rejoin for the print
     order. Every connector is a border rule and every arrowhead a border
     triangle, so it prints whole and needs no arrow glyph. The flow runs in
     the dossier's register ink; the boxes and the return bracket are the key
     plate. */
  .book-run{
    list-style:none;margin:var(--space-l) auto var(--space-l);padding:0;
    counter-reset:run;max-width:44rem;
    --flow:var(--register);--fan-gap:var(--space-m);
  }
  .book-run>li{
    counter-increment:run;position:relative;
    width:fit-content;min-width:min(26rem,100%);max-width:100%;
    margin-inline:auto;
    border:1px solid var(--key);
    padding:var(--space-2xs) var(--space-s) var(--space-xs);
  }
  .book-run>li+li{margin-top:var(--space-l)}
  .book-run>li+li::before{
    content:"";position:absolute;left:calc(50% - 1px);top:calc(-1*var(--space-l));height:2rem;
    border-left:2px solid var(--flow);
  }
  .book-run>li+li::after{
    content:"";position:absolute;left:50%;top:-.4rem;transform:translateX(-50%);
    border:.32rem solid transparent;border-bottom:0;border-top:.4rem solid var(--flow);
  }
  .book-run>li>b{
    display:block;font-size:var(--step--1);
    letter-spacing:.08em;text-transform:uppercase;color:var(--key);
    margin-bottom:var(--space-3xs);
    font-variation-settings:var(--f-label);
  }
  /* the numbering lives in CSS, not in the markup */
  .book-run>li>b::before{
    content:counter(run,decimal-leading-zero);
    color:var(--register);margin-right:.7rem;letter-spacing:.05em;
    font-variant-numeric:lining-nums tabular-nums;
  }
  .book-run p{font-size:var(--step--1);color:var(--muted);font-variation-settings:var(--f-small);max-width:52ch}
  .book-run>li.run-print{border-width:2px}

  /* stage five: a header on the spine, a bus, two lanes, a rejoin */
  .book-run>li.run-fork{border:0;padding:0;text-align:center;width:100%;min-width:0}
  .book-run>li.run-fork>b{
    display:inline-block;margin-bottom:0;
    border:1px solid var(--key);padding:var(--space-2xs) var(--space-s);
  }
  .run-split{display:grid;grid-template-columns:1fr 1fr;gap:var(--fan-gap);text-align:left}
  .run-split>div{border:1px solid var(--key);padding:var(--space-2xs) var(--space-s) var(--space-xs)}
  .run-split b{
    display:block;font-size:var(--step--1);
    letter-spacing:.08em;text-transform:uppercase;color:var(--key);
    margin-bottom:var(--space-3xs);
    font-variation-settings:var(--f-label);
  }
  .run-split p+p{margin-top:0}

  /* the back-and-forth on the passes stage: a return bracket on the key
     plate, the same mark as the engine's correction loop opposite */
  .run-loop{
    position:absolute;left:calc(100% + .4rem);top:.55rem;bottom:.55rem;width:1.4rem;
    border:1px solid var(--key);border-left:0;
  }
  .run-loop::before{
    content:"";position:absolute;left:0;bottom:-.27rem;
    border:.26rem solid transparent;border-left:0;border-right:.36rem solid var(--key);
  }

  .run-fan{
    display:grid;grid-template-columns:repeat(2,1fr);column-gap:var(--fan-gap);
    position:relative;height:2.4rem;margin-top:var(--space-3xs);
  }
  .run-fan::after{
    content:"";position:absolute;
    left:calc((100% - var(--fan-gap))/4);right:calc((100% - var(--fan-gap))/4);
    border-top:2px solid var(--flow);
  }
  .run-fan.out::after{top:1rem}
  .run-fan.in::after{top:calc(100% - 1rem)}
  .run-fan>i{position:relative}
  .run-fan>i.mid{position:absolute;inset:0}
  .run-fan.out>i::before{content:"";position:absolute;left:calc(50% - 1px);top:1rem;bottom:.4rem;border-left:2px solid var(--flow)}
  .run-fan.out>i::after{
    content:"";position:absolute;left:50%;bottom:0;transform:translateX(-50%);
    border:.32rem solid transparent;border-bottom:0;border-top:.4rem solid var(--flow);
  }
  .run-fan.out>i.mid::before{left:calc(50% - 1px);top:0;height:1rem;bottom:auto}
  .run-fan.out>i.mid::after{display:none}
  .run-fan.in>i::before{content:"";position:absolute;left:calc(50% - 1px);top:0;height:calc(100% - 1rem);border-left:2px solid var(--flow)}
  .run-fan.in>i::after{display:none}
  .run-fan.in>i.mid::before{top:calc(100% - 1rem);height:auto;bottom:.4rem}
  .run-fan.in>i.mid::after{
    display:block;content:"";position:absolute;left:50%;bottom:0;transform:translateX(-50%);
    border:.32rem solid transparent;border-bottom:0;border-top:.4rem solid var(--flow);
  }
  .run-fan.in{margin-top:0}
  .run-fork .run-split{margin-top:0}
  .book-run>li.run-fork+li{margin-top:0}
  .book-run>li.run-fork+li::before,.book-run>li.run-fork+li::after{display:none}
  .run-stake{
    margin-top:var(--space-m);max-width:56ch;
    font-size:var(--step-0);line-height:1.5;
    font-variation-settings:"opsz" 18,"wght" 500,"wdth" 100;
  }

  /* ----------------------------------------------------------- the engine */
  /* Three lanes on one grid: the /match-note bypass on the left, the trunk in
     the middle, the correction loop on the right. Trunk items auto-place in
     column two; only the side lanes pin their rows. */
  .engine{
    display:grid;
    grid-template-columns:minmax(8rem,10rem) minmax(0,1fr) 2rem;
    column-gap:var(--space-m);
    margin-top:var(--space-l);
    --flow:var(--register);
    --fan-gap:var(--space-s);
  }
  .engine>*{grid-column:2;min-width:0}
  .engine b{
    display:block;font-size:var(--step--1);
    color:var(--register);letter-spacing:.03em;
    font-variation-settings:var(--f-label);
    font-variant-numeric:lining-nums;
  }
  .engine span{
    display:block;font-size:var(--step--1);color:var(--muted);
    font-variation-settings:var(--f-small);line-height:1.45;margin-top:.1rem;
    text-wrap:balance;
  }

  .eng-node{
    justify-self:center;text-align:left;max-width:36ch;
    border:1px solid var(--key);padding:var(--space-2xs) var(--space-s);
  }
  .eng-input{border-color:var(--line)}
  .eng-post{border-width:2px;padding-inline:var(--space-l)}
  .eng-post b{color:var(--key)}

  /* a file is a ledger strip, not a box: rules above and below, no sides */
  .eng-chit{
    justify-self:center;text-align:left;max-width:40ch;
    border-block:1px solid var(--line);padding:.35rem var(--space-s);
  }
  .eng-chit b{color:var(--key)}
  .eng-stamp{border:2px solid var(--register);padding:var(--space-2xs) var(--space-s)}
  .eng-stamp b{color:var(--register)}

  .eng-band{border:1px solid var(--key);padding:var(--space-2xs) var(--space-s)}
  .eng-band>b+span{max-width:52ch}
  /* the gates catch both lanes, so the band runs under the bypass as well */
  .eng-gates{grid-column:1/3;text-align:left;padding-block:0}
  .eng-gates>div{
    display:grid;grid-template-columns:minmax(8.5rem,10rem) 1fr;gap:var(--space-s);
    padding:var(--space-2xs) 0;border-top:1px solid var(--line);
  }
  .eng-gates>div:first-child{border-top:0}
  .eng-gates span{max-width:56ch}

  .eng-flow{display:block;position:relative;height:var(--space-l)}
  .eng-flow::before{
    content:"";position:absolute;left:calc(50% - 1px);top:0;bottom:.34rem;
    border-left:2px solid var(--flow);
  }
  .eng-flow::after{
    content:"";position:absolute;left:50%;bottom:0;transform:translateX(-50%);
    border:.32rem solid transparent;border-bottom:0;border-top:.4rem solid var(--flow);
  }
  .eng-thin::before{border-left-width:1px}

  /* the dispatch fan: bus and drops share the workers' column tracks, so the
     three lines land dead centre on the three boxes at any width or zoom */
  .eng-fan{
    display:grid;grid-template-columns:repeat(3,1fr);column-gap:var(--fan-gap);
    height:3rem;position:relative;
  }
  .eng-fan::after{
    content:"";position:absolute;
    left:calc((100% - 2*var(--fan-gap))/6);right:calc((100% - 2*var(--fan-gap))/6);
    border-top:2px solid var(--flow);
  }
  .eng-fan.out::after{top:1.1rem}
  .eng-fan.in::after{top:calc(100% - 1.1rem)}
  .eng-fan>i{position:relative}
  .eng-fan>i::before{content:"";position:absolute;left:calc(50% - 1px);border-left:2px solid var(--flow)}
  .eng-fan.out>i::before{top:1.1rem;bottom:.34rem}
  .eng-fan.out>i:nth-child(2)::before{top:0}
  .eng-fan.out>i::after{
    content:"";position:absolute;left:50%;bottom:0;transform:translateX(-50%);
    border:.32rem solid transparent;border-bottom:0;border-top:.4rem solid var(--flow);
  }
  .eng-fan.in>i::before{top:0;height:calc(100% - 1.1rem)}
  .eng-fan.in>i:nth-child(2)::before{height:auto;bottom:.34rem}
  .eng-fan.in>i:nth-child(2)::after{
    content:"";position:absolute;left:50%;bottom:0;transform:translateX(-50%);
    border:.32rem solid transparent;border-bottom:0;border-top:.4rem solid var(--flow);
  }

  .eng-workers{
    list-style:none;margin:0;padding:0;
    display:grid;grid-template-columns:repeat(3,1fr);column-gap:var(--fan-gap);
  }
  .eng-workers li{border:1px solid var(--line);padding:.4rem .3rem;text-align:center}

  .eng-lane{
    grid-column:1;grid-row:3/11;
    display:grid;grid-template-rows:auto minmax(1.6rem,1fr);min-height:0;
  }
  .eng-lane-head{border:1px solid var(--key);padding:var(--space-2xs) var(--space-xs)}
  .eng-lane-rule{position:relative;min-height:1.6rem}
  .eng-lane-rule::before{
    content:"";position:absolute;left:calc(50% - .5px);top:0;bottom:.3rem;
    border-left:1px solid var(--flow);
  }
  .eng-lane-rule::after{
    content:"";position:absolute;left:50%;bottom:0;transform:translateX(-50%);
    border:.28rem solid transparent;border-bottom:0;border-top:.36rem solid var(--flow);
  }

  /* the correction loop: verdicts send the work back up. A margin bracket on
     the key plate, meeting the two bands on their shoulders. */
  .eng-loop{
    grid-column:3;grid-row:7/12;
    margin:var(--space-m) 0 var(--space-l) calc(-1*var(--space-m));
    border:1px solid var(--key);border-left:0;
    position:relative;display:grid;align-items:center;justify-items:end;
  }
  .eng-loop::before{
    content:"";position:absolute;left:0;top:-.33rem;
    border:.32rem solid transparent;border-left:0;border-right:.44rem solid var(--key);
  }
  .eng-loop span{
    writing-mode:vertical-rl;margin:0 .3rem 0 0;
    font-size:.68rem;letter-spacing:.09em;text-transform:uppercase;color:var(--key);
    font-variation-settings:var(--f-label);
  }

  /* -------------------------------------------------------- turn it over */
  details{border-block:1px solid var(--line);margin-top:var(--space-l)}
  summary{
    display:flex;justify-content:space-between;align-items:center;gap:var(--space-s);
    padding:var(--space-xs) 0;cursor:pointer;list-style:none;
    font-size:var(--step--1);letter-spacing:.09em;text-transform:uppercase;
    font-variation-settings:var(--f-label);
    border-bottom:1px solid transparent;
    transition:border-bottom-width var(--t-press) var(--bite),border-bottom-color var(--t-press) var(--bite);
  }
  summary::-webkit-details-marker{display:none}
  /* the pen approaches, then bites: no rule at rest, a hairline on hover, a
     thick rule under a press. The same three beats on every control. */
  summary:hover,summary:focus-visible{border-bottom-color:var(--line)}
  summary:active{border-bottom-width:3px;border-bottom-color:var(--key);padding-bottom:calc(var(--space-xs) - 2px)}
  summary .marker{
    color:var(--key);font-family:var(--text);font-size:1.3rem;line-height:1;
    font-variation-settings:"opsz" 24,"wght" 300,"wdth" 100;
    transition:transform .22s var(--bite),color var(--t-press) var(--bite);
  }
  details[open] summary .marker{color:var(--register);transform:rotate(45deg)}
  .reveal{
    padding:0 0 var(--space-m);display:grid;
    grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));gap:var(--space-m);
  }
  /* the flow rule's p+p top margin survives into grid cells, where margins
     don't collapse: column two sat 16px lower than column one. The gap owns
     the spacing here, so the cells own none. The second selector outguns
     .case-section p+p, which beats a bare .reveal p on specificity. */
  .reveal p,.case-section .reveal p+p{margin:0;font-size:var(--step--1);color:var(--muted);font-variation-settings:var(--f-small)}
  .reveal b{
    display:block;font-size:var(--step--1);
    letter-spacing:.08em;text-transform:uppercase;color:var(--key);margin-bottom:var(--space-3xs);
    font-variation-settings:var(--f-label);
  }
  /* Chrome only, and it degrades to the jump every other browser does today */
  @supports selector(::details-content){
    details::details-content{
      block-size:0;overflow:clip;
      transition:block-size .3s var(--bite),content-visibility .3s allow-discrete;
    }
    details[open]::details-content{block-size:auto}
  }

  /* ------------------------------------------------ the receipt, steppable */
  /* Four stages of one documented run, in source order. The rail is the
     control: the checked stage stands full and the other three fold to their
     running heads. Native radios and :has() only; print unfolds everything,
     and a browser without :has() keeps all four open. The #st-1 to #st-4 ids
     are CSS-coupled: renaming one kills the fold. */
  .stages{margin-top:var(--space-s)}
  .stage-rail{display:flex;flex-wrap:wrap;gap:0 var(--space-s);border-bottom:1px solid var(--line)}
  .stage-rail input{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
  .stage-rail label{
    font-size:.7rem;letter-spacing:.09em;text-transform:uppercase;
    font-variation-settings:var(--f-label);
    padding:.45rem .1rem .35rem;cursor:pointer;color:var(--muted);
    border-bottom:2px solid transparent;margin-bottom:-1px;
    transition:color .14s var(--bite),border-bottom-color .14s var(--bite),border-bottom-width var(--t-press) var(--bite);
  }
  .stage-rail label:hover{color:var(--key)}
  .stage-rail label:active{border-bottom-width:4px;border-bottom-color:var(--key)}
  .stage-rail input:checked + label{color:var(--key);border-bottom-color:var(--register)}
  .stage-rail input:focus-visible + label{outline:2px solid var(--key);outline-offset:2px}

  .stage{
    position:relative;
    border-left:2px solid var(--line);
    padding-left:var(--space-s);margin-top:var(--space-m);
    transition:border-left-color .2s var(--bite);
  }
  /* a folded card is a click target in its own right: a stretched label
     covers it, and disappears once the stage is open so the copy stays
     selectable. Lives inside the fold guard below. */
  .stage-hit{display:none}
  .stage h3{font-size:var(--step-1);margin-top:0}
  .stage blockquote{font-size:var(--step-1);margin-block:var(--space-xs)}
  .stages:has(#st-1:checked) .stage-1,
  .stages:has(#st-2:checked) .stage-2,
  .stages:has(#st-3:checked) .stage-3,
  .stages:has(#st-4:checked) .stage-4{border-left-color:var(--register)}
  .stages:has(#st-1:checked) .stage-1 .eyebrow,
  .stages:has(#st-2:checked) .stage-2 .eyebrow,
  .stages:has(#st-3:checked) .stage-3 .eyebrow,
  .stages:has(#st-4:checked) .stage-4 .eyebrow{color:var(--register)}
  /* the fold. Guarded so a browser without :has() can never trap content. */
  @supports selector(.stages:has(input:checked)){
    .stage>*:not(.eyebrow):not(h3):not(.stage-hit){display:none}
    .stage h3{color:var(--muted);transition:color .2s var(--bite)}
    .stage-hit{display:block;position:absolute;inset:0;cursor:pointer}
    .stage:has(.stage-hit:hover) h3{color:var(--key)}
    .stages:has(#st-1:checked) .stage-1>*,
    .stages:has(#st-2:checked) .stage-2>*,
    .stages:has(#st-3:checked) .stage-3>*,
    .stages:has(#st-4:checked) .stage-4>*{display:block}
    .stages:has(#st-1:checked) .stage-1 h3,
    .stages:has(#st-2:checked) .stage-2 h3,
    .stages:has(#st-3:checked) .stage-3 h3,
    .stages:has(#st-4:checked) .stage-4 h3{color:var(--key)}
    .stages:has(#st-1:checked) .stage-1 .stage-hit,
    .stages:has(#st-2:checked) .stage-2 .stage-hit,
    .stages:has(#st-3:checked) .stage-3 .stage-hit,
    .stages:has(#st-4:checked) .stage-4 .stage-hit{display:none}
  }

  /* the reading list: the contents grammar at reading size */
  .reading-list{border-top:2px solid var(--key);margin-top:var(--space-s)}
  .reading-list a{
    display:block;padding:var(--space-s) 0;border-bottom:1px solid var(--line);background:none;cursor:pointer;
    transition:border-bottom-width var(--t-press) var(--bite),border-bottom-color var(--t-press) var(--bite);
  }
  .reading-list a strong{
    display:block;font-size:var(--step-1);letter-spacing:-.01em;
    --ink:480;
    font-variation-settings:"opsz" 24,"wght" var(--ink),"wdth" 100;
    width:max-content;max-width:100%;
    transition:--ink .2s var(--bite),color .2s var(--bite);
  }
  .reading-list a span{display:block;color:var(--muted);font-size:var(--step--1);max-width:60ch;margin-top:var(--space-3xs)}
  .reading-list a:hover strong,.reading-list a:focus-visible strong,.reading-list a:active strong{color:var(--register);--ink:660}
  .reading-list a:active{border-bottom-width:3px;border-bottom-color:var(--key);padding-bottom:calc(var(--space-s) - 2px)}

  /* --------------------------------------------------------- the ink bands */
  /* The landing index is a printed block: three full-width bands, flush, in
     the three plate inks, with the route names reversed out in knockout
     cream. No folio numerals: the ink is the index. The keyline is permanent,
     because on the night sheet a band at full ink is 1.6:1 against the sheet
     and would lose its own edge. */
  /* The same block runs twice: as the landing contents, and at the foot of
     each dossier as the other routes. One grammar, both places. */
  .index{
    margin-top:var(--space-2xl);
    /* bleed to the column edge. The shell is flush left with one gutter, so
       this is exact arithmetic and needs no viewport unit. */
    margin-inline:calc(-1*var(--pad));
    border-bottom:2px solid var(--ko);
  }
  /* the landing markup carries style="margin-top:0;border-top:0" inline on
     its nav, so the block's top keyline is drawn by the first band instead */
  .index a:first-child{border-top:2px solid var(--ko)}
  .index a{
    display:block;position:relative;
    padding:clamp(1.15rem,2.4vw,1.9rem) var(--pad);
    cursor:pointer;
    border-bottom:2px solid var(--ko);
    /* an uninked route is the key plate itself, which is the ink the index
       carries in the rail */
    background-color:var(--key);color:var(--sheet);
    transition:background-color var(--t-band) var(--bite);
  }
  /* tooth rides ABOVE the flat ink as an overlay, so the audited band values
     underneath stay honest. White flecks read as the paper starving the ink:
     the riso tell. Print and forced-colors kill it. */
  .index a::after{
    content:"";position:absolute;inset:0;pointer-events:none;
    background:url(assets/grain.svg);background-size:150px;
    opacity:.14;
  }
  .index a:last-child{border-bottom:0}
  /* THE ONE MOTION: hover and focus lay the key plate on the colour and the
     band takes full ink. Nothing else on the landing moves. */
  .index a.ink-editorial{background-color:var(--ink-ed);color:var(--ko)}
  .index a.ink-ai{background-color:var(--ink-ai);color:var(--ko)}
  .index a.ink-campaigns{background-color:var(--ink-cam);color:var(--ko)}
  .index a.ink-writing{background-color:var(--ink-wr);color:var(--ko)}
  .index a:hover,.index a:focus-visible{background-color:color-mix(in oklab,var(--key) 84%,var(--sheet))}
  .index a.ink-editorial:hover,.index a.ink-editorial:focus-visible{background-color:var(--ink-ed-full)}
  .index a.ink-ai:hover,.index a.ink-ai:focus-visible{background-color:var(--ink-ai-full)}
  .index a.ink-campaigns:hover,.index a.ink-campaigns:focus-visible{background-color:var(--ink-cam-full)}
  .index a.ink-writing:hover,.index a.ink-writing:focus-visible{background-color:var(--ink-wr-full)}
  /* the ring sits inset on the ink instead of disappearing into it */
  .index a:focus-visible{outline:2px solid currentColor;outline-offset:-8px}

  .index a strong{
    display:block;
    font-family:var(--display);font-weight:400;font-variation-settings:normal;
    font-size:var(--step-3);line-height:1.02;letter-spacing:-.005em;
    color:inherit;
  }
  .index a>span{
    display:block;margin-top:var(--space-2xs);max-width:46ch;
    font-size:var(--step--1);color:inherit;
    font-variation-settings:"opsz" 13,"wght" 400,"wdth" 100;
  }

  /* the folio numerals and the specimen strip are cut in this direction: the
     ink indexes the routes, and the jackets belong to a shelf of their own.
     Phase 6 removes the markup; until then the CSS carries the decision. */
  .index-home .num,.index-home .spec-wrap{display:none}
  .index-home .route-body{
    display:block;margin:0;max-width:none;color:inherit;font-size:inherit;
  }
  .index-home .desc{
    display:block;margin-top:var(--space-2xs);max-width:46ch;
    font-size:var(--step--1);color:inherit;
    font-variation-settings:"opsz" 13,"wght" 400,"wdth" 100;
  }
  /* the go affordance is a drawn corner riding the last word, so a wrapped
     title never strands it. No U+2192 anywhere on the sheet. */
  .index-home .go-w{
    display:inline;white-space:nowrap;margin:0;max-width:none;
    font-size:inherit;color:inherit;
  }
  .index-home .go-w::after{
    content:"";display:inline-block;
    width:.42em;height:.42em;margin-left:.42em;vertical-align:.06em;
    border-top:2px solid currentColor;border-right:2px solid currentColor;
    transform:rotate(45deg);
  }

  /* The specimen strip sits inside the hidden .spec-wrap above, so none of
     this paints today. The classes are live markup and Phase 6 lifts the
     jackets out into a shelf of their own, so they are dressed here rather
     than left to render raw the moment the wrapper comes off. */
  .spec-label{
    display:block;margin-top:.25rem;
    font-size:.66rem;letter-spacing:.09em;text-transform:uppercase;color:var(--muted);
    font-variation-settings:var(--f-label);
  }
  .specimen{display:flex;flex-wrap:wrap;gap:var(--space-2xs);margin-top:var(--space-2xs)}
  .specimen img{height:6.4rem;width:auto;border:1px solid var(--line)}
  .specimen img.wide{height:auto;width:100%;max-width:24rem}

  /* ------------------------------------------------------------- colophon */
  /* Built around the email: a real mailto at display scale in the dossier's
     register ink, with the name quiet in the meta row. v7 crossed the address
     over the rule as an overprint (screen after dark, multiply on paper);
     that is gone. See the note in the moodboard: with the crossing rule on
     the key plate, both blends cancel the address exactly where they meet. */
  .colophon{
    border-top:1px solid var(--hair);
    margin-top:var(--space-3xl);padding-bottom:var(--space-2xl);
  }
  .colophon .crossing{border-top:2px solid var(--key);margin-top:var(--space-l)}
  .colophon .mail{
    display:block;width:max-content;max-width:100%;
    font-size:clamp(1.35rem,.6rem + 3.4vw,3.4rem);
    line-height:1.1;letter-spacing:-.02em;
    color:var(--register);
    --ink:500;
    font-variation-settings:"opsz" 36,"wght" var(--ink),"wdth" 90;
    margin-top:var(--space-s);
    background:linear-gradient(currentColor,currentColor) no-repeat left bottom/0 .05em;
    transition:--ink .25s var(--bite),background-size .22s var(--bite);
  }
  .colophon .mail:hover,.colophon .mail:focus-visible{--ink:700;background-size:100% .05em}
  .colophon .mail:active{--ink:700;background-size:100% .12em}
  .colophon .meta{
    display:flex;justify-content:space-between;flex-wrap:wrap;gap:var(--space-s);
    margin-top:var(--space-m);border-top:1px solid var(--line);padding-top:var(--space-xs);
    font-size:var(--step--1);color:var(--muted);letter-spacing:.03em;
    font-variation-settings:var(--f-small);
  }
  /* the essay room keeps its narrower shell and a smaller address */
  .colophon-essay{margin-top:var(--space-2xl)}
  .colophon-essay .mail{font-size:clamp(1.2rem,.7rem + 2vw,2.4rem)}

  /* the aside note: muted, with a rule in the margin. It was italic in v7. */
  .aside-note{
    color:var(--muted);
    border-left:2px solid var(--line);padding-left:var(--space-s);
    font-variation-settings:var(--f-small);
  }
}

/* Utilities that retired the markup's inline style attributes (v9 P1). */
@layer dossier{
  .flush-top{margin-top:0;border-top:0}
  .gap-top{margin-top:var(--space-xl)}
  .plate-narrow{max-width:12rem}
  .img-outlined{border:1px solid var(--line)}
  .plate-slim{max-width:8rem}
}

/* The long-read layer for the three IPL essays. The essay bodies are verbatim
   artefacts; this layer only sets the room they are read in. */
@layer essay{
  .article-shell{width:min(760px,calc(100% - 2rem));margin-inline:auto}
  /* the dossier index bleeds by -var(--pad) against the shell gutter; the
     article shell has no gutter, so the onward bands sit flush instead */
  .article-shell .index{margin-inline:0}
  /* flat, like the route hero. No card, no frost, no bevel. */
  .article-header{margin-top:var(--space-l);padding:0 0 var(--space-m)}
  .article-header h1{
    font-size:var(--step-4);line-height:1.04;
    margin:var(--space-2xs) 0 var(--space-m);
  }
  .section-number{
    font-size:var(--step--1);letter-spacing:.1em;text-transform:uppercase;
    color:var(--register);
    font-variation-settings:var(--f-label);
    border-top:2px solid var(--key);padding-top:var(--space-xs);
  }
  .provenance{
    font-size:var(--step--1);color:var(--muted);
    font-variation-settings:var(--f-small);
    border-block:1px solid var(--line);padding:var(--space-s) 0;
  }
  .article-body{padding-bottom:var(--space-3xl)}
  .article-body>p{font-size:var(--step-read);line-height:1.62;margin-bottom:var(--space-s);font-variation-settings:var(--f-read)}
  /* the --ink weight interpolation extends to section headings: 600 at
     rest, the full 700 on approach. Same idiom as the wordmark and the
     reading-list titles, not a new one. */
  .article-body h2,.carousel-pair h2{
    --ink:600;
    font-variation-settings:"opsz" 24,"wght" var(--ink),"wdth" 100;
    transition:--ink .2s var(--bite);
    width:max-content;max-width:100%;
  }
  .article-body h2:hover,.carousel-pair h2:hover{--ink:700}
  .article-body h2{
    font-size:var(--step-2);line-height:1.08;margin:var(--space-xl) 0 var(--space-s);
  }
  /* the datelines and source notes. Five of them, one per essay standfirst or
     methods note, each the whole paragraph. Italic in v7; here they step down
     and take the margin colour, which is what a dateline is. */
  .article-body em{
    display:block;color:var(--muted);
    font-size:var(--step--1);letter-spacing:.04em;
    font-variation-settings:var(--f-quiet);
  }
  .article-body hr{border:0;border-top:1px solid var(--line);margin:var(--space-l) 0}
  /* full bleed inside the column, never past it */
  .article-chart{
    width:min(1060px,calc(100vw - var(--rail-w) - 2rem));
    margin:var(--space-xl) 50%;transform:translateX(-50%);
  }
  .article-chart img{width:100%;border:1px solid var(--line)}
  /* FILENAME CONTRACT. The Iyer and KKR charts are transparent PNGs drawn
     with cream labels for a dark ground, so the plate carries its own bed and
     that bed is an edition constant. The cluster map is drawn for paper and
     takes the knockout backing. The CSK SVGs take it too, but never show it:
     each paints its own full-canvas dark ground (P3 finding, 2026-08-05).
     Renaming a chart file changes its backing. This is the first of three
     sites; the other two are the unlayered artefact block and the print
     layer. */
  .article-chart img[src$="_embed_dark.png"]{
    background:var(--plate-dark);
    /* #181814 on #0d1218 is 1.06:1, so the plate is given a drawn edge or it
       has no boundary at all on the night sheet */
    border-color:var(--line);
    padding:clamp(.6rem,2vw,1.4rem);
  }
  .article-chart figcaption{
    font-size:var(--step--1);color:var(--muted);margin-top:var(--space-2xs);line-height:1.45;
    font-variation-settings:var(--f-quiet);
  }
  .carousel-pair{border-top:2px solid var(--key);padding:var(--space-xl) 0 var(--space-2xl);margin-top:var(--space-2xl)}
  .carousel-pair h2{font-size:var(--step-2);margin:var(--space-2xs) 0 var(--space-xs)}
  .carousel-strip{
    display:flex;overflow-x:auto;gap:var(--space-s);
    scroll-snap-type:x mandatory;margin-top:var(--space-m);padding-bottom:var(--space-2xs);
  }
  .carousel-strip img{width:min(70vw,340px);scroll-snap-align:start;border:1px solid var(--line)}
  /* Verse. The two poems carry their own lineation; the source DOCX is
     authoritative for indent depth and the packet's lineation.json records
     it. Every line is its own block so a turnover can hang: a wrapped long
     line must never read as the next line of the poem. */
  .verse{margin:var(--space-l) 0;--v-step:2.6ch;--v-hang:1.6em}
  .verse .stanza{margin:0 0 var(--space-m)}
  .verse .v{
    display:block;
    font-size:var(--step-read);line-height:1.5;
    font-variation-settings:var(--f-read);
    padding-left:calc(var(--v-in,0)*var(--v-step) + var(--v-hang));
    text-indent:calc(-1*var(--v-hang));
  }
  .verse .i1{--v-in:1}
  .verse .i2{--v-in:2}
  .verse .i3{--v-in:3}
  body>footer .article-shell{padding:var(--space-l) 0 var(--space-2xl)}
}

/* ==========================================================================
   THE UNLAYERED ZONE. Everything below is deliberately outside @layer and
   must stay there. Paper is the base/no-JS default in @layer tokens, and the
   explicit [data-theme] blocks override it on screen when chosen by the
   reader. The responsive collapses, the artefact backing, reduced motion,
   forced colours and the toggle component sit here for the same reason: they
   override layered rules by position, not by specificity. Tidying any of this
   into a layer silently breaks the toggle.
   ========================================================================== */

/* ------------------------------------------------------ the rail folds ---- */
@media (max-width:60rem){
  :root{--rail-w:0px}
  body{grid-template-columns:minmax(0,1fr);grid-template-rows:auto 1fr auto}
  .site-header{
    grid-column:1;grid-row:1;
    border-right:0;border-bottom:1px solid var(--hair);
  }
  main{grid-column:1;grid-row:2}
  body>footer{grid-column:1;grid-row:3}
  .site-header .header-row{
    position:static;min-height:0;max-height:none;overflow:visible;
    flex-direction:row;flex-wrap:wrap;align-items:center;
    gap:var(--space-s) var(--space-m);
    padding:var(--space-s) var(--pad);
  }
  /* the wordmark bookends the switch on the first line and the contents run
     under both, rather than the switch orphaning on a line of its own */
  .wordmark{order:1}
  .theme-toggle{order:2}
  .ticker{order:3;flex-basis:100%;flex-direction:row;flex-wrap:wrap;gap:var(--space-s) var(--space-m)}
}

@media(max-width:900px){
  .case-layout{grid-template-columns:1fr}
  .plate-stack{position:static}
  .plate-row,.plate-row.two{grid-template-columns:1fr}
  .plate-shelf{grid-template-columns:repeat(3,1fr)}
  .plate-shelf.bleed{grid-template-columns:repeat(4,1fr)}
  .sheet-page{grid-template-columns:1fr}
  .sheet-page img{max-width:12rem}
}
@media(max-width:640px){
  .section-rule{flex-direction:column;align-items:flex-start;gap:.3rem}
  /* narrow sheets: the verse indents compress but never vanish */
  .verse{--v-step:1.4ch;--v-hang:1.1em}
  /* the dotted leader is a wide-page grammar; the rows stack instead */
  .spec>div{display:block}
  .spec dt::after{display:none}
  .spec dd{text-align:left;margin-top:.15rem;max-width:none}
  .plate-shelf{grid-template-columns:repeat(2,1fr)}
  .plate-shelf.bleed{grid-template-columns:repeat(2,1fr)}
  /* the fork stacks: a bracket on the left binds the two concurrent lanes,
     fed by a stub down from the header and rejoining into print, so stage
     five still reads as parallel. The desktop drop-lines drawn on the fan's
     <i> children are switched off and the whole thing is redrawn on the fans'
     own pseudo-elements with every inset stated, so no desktop value leaks
     in and the corners stay square. */
  .run-split{grid-template-columns:1fr;gap:var(--space-s);position:relative;padding-left:1.5rem}
  .run-split::before{content:"";position:absolute;left:.4rem;right:auto;top:0;bottom:0;width:auto;border:0;border-left:2px solid var(--flow)}
  .run-split>div{position:relative}
  .run-split>div::before{content:"";position:absolute;left:-1.1rem;right:auto;top:1.15rem;bottom:auto;width:.66rem;height:auto;border:0;border-top:2px solid var(--flow)}
  .run-split>div::after{
    content:"";position:absolute;left:-.5rem;right:auto;top:.85rem;bottom:auto;width:0;height:0;
    border:.3rem solid transparent;border-right:0;border-left:.4rem solid var(--flow);
  }
  .run-fan{height:1rem;margin-top:0;position:relative}
  .run-fan>i::before,.run-fan>i::after{display:none}
  .run-fan.out::before{content:"";display:block;position:absolute;left:calc(50% - 1px);right:auto;top:0;bottom:0;width:auto;height:auto;border:0;border-left:2px solid var(--flow)}
  .run-fan.out::after{content:"";display:block;position:absolute;left:.4rem;right:calc(50% - 1px);top:auto;bottom:0;width:auto;height:auto;border:0;border-top:2px solid var(--flow)}
  .run-fan.in::before{content:"";display:block;position:absolute;left:.4rem;right:calc(50% - 1px);top:0;bottom:auto;width:auto;height:auto;border:0;border-top:2px solid var(--flow)}
  .run-fan.in::after{content:"";display:block;position:absolute;left:calc(50% - 1px);right:auto;top:0;bottom:.34rem;width:auto;height:auto;border:0;border-left:2px solid var(--flow)}
  .run-fan.in>i.mid{position:static;display:block}
  .run-fan.in>i.mid::after{
    content:"";display:block;position:absolute;left:50%;right:auto;top:auto;bottom:0;width:0;height:0;
    transform:translateX(-50%);border:.32rem solid transparent;border-bottom:0;border-top:.4rem solid var(--flow);
  }
  /* the engine narrows: the bypass lane becomes a spine, its head set the way
     a title runs down a book's spine; the trunk keeps the desktop geometry */
  .engine{grid-template-columns:2.6rem minmax(0,1fr) 1.5rem;column-gap:var(--space-xs)}
  .engine .eng-lane{grid-template-rows:auto minmax(1.6rem,1fr)}
  .engine .eng-lane-head{border:0;padding:0;justify-self:center;writing-mode:vertical-rl}
  .engine .eng-lane-head b{display:inline;margin:0}
  .engine .eng-lane-head span{display:none}
  .run-loop{display:none}
  .eng-gates>div{grid-template-columns:1fr;gap:.1rem}
  .eng-loop{margin-left:calc(-1*var(--space-xs))}
  .eng-node,.eng-band{padding-inline:var(--space-xs)}
  .specimen img{height:4.4rem}
  /* "communications" has fourteen letters; the display size must clear it on
     a narrow screen without breaking the word */
  .route-hero h1,.article-header h1,.index a strong{font-size:clamp(1.9rem,9.5vw,2.9rem)}
  /* a sentence-length h1 runs to five lines at the title size, so it takes a
     step down of its own. These two rules are unlayered and beat the
     dossier layer whatever their specificity, which is why the statement
     needs its own line here. */
  .route-hero h1.statement{font-size:clamp(1.7rem,7.6vw,2.4rem)}
}

/* artefacts keep a lit sheet behind them. On the paper edition the backing is
   invisible (cream on cream); after dark it is the lamplight that stops a
   transparent PNG from sinking into the ground. The Iyer plates keep their
   own dark bed instead: their labels are cream. The order of these two rules
   is the contract. */
.plate img,.plate-open img,.specimen img,.sheet img,.sheet-strip img,
.carousel-strip img,.article-chart img{background:var(--ko)}
.article-chart img[src$="_embed_dark.png"]{background:var(--plate-dark)}
/* the editions wall letterboxes mixed-aspect slides (dossier owns the frame);
   the bands take the chart bed, not the lit sheet — the slides are dark
   artifacts and a cream band would stripe them in the paper edition. */
#editions .plate-open img{background:var(--plate-dark)}
/* P3 finding, 2026-08-05: the CSK SVGs need no bed rule at all. Each one
   paints its own full-canvas dark ground (.bg fill #14110E, cream ink) —
   they are dark-plate artifacts like the _embed_dark PNGs, not paper-drawn
   charts, whatever the @layer essay comment used to claim. The P2 "dark bed
   night-only" call is met by the artifact itself in both editions; putting
   them on cream would need re-inking, which the pane review declined. */

@media screen and (prefers-color-scheme:light){
  /* Image lift on light OS canvas: against bright screens pixels read muted
     by chromatic induction. The lift gives back what a dark surround grants
     for free. This is purely perceptual thumbnail contrast adjustment, not
     theme selection. Charts are excluded: their ink is data and must stay true. */
  .plate img,.plate-open img,.specimen img,.sheet img,.sheet-strip img,
  .carousel-strip img{filter:saturate(1.45) contrast(1.08) brightness(1.03)}
}

@media(prefers-reduced-motion:reduce){
  /* Every state still changes. It just arrives. */
  *,*::before,*::after{transition-duration:.01ms!important;animation-duration:.01ms!important}
  html{scroll-behavior:auto}
  .index a{transition:none}
  .route-hero h1.statement{animation:none}
  details[open] summary .marker{transform:none}
  .sheet-strip{scroll-snap-type:none}
}

@media(forced-colors:active){
  /* the texture overlays are url() backgrounds the UA keeps; on a forced
     canvas they are noise over repainted grounds, so they go */
  html::before,.site-header .header-row::before,.index a::after{display:none}
  .plate-open{border:1px solid}
  /* the UA repaints the grounds, so the ink no longer separates the bands.
     Each one gets a real border and the system palette does the rest. */
  .index a{border:1px solid;forced-color-adjust:auto}
  .ticker a::before,.status::before{border:1px solid CanvasText}
  .plate-cue::after{border-color:CanvasText}
  .index .go-w::after{border-top-color:CanvasText;border-right-color:CanvasText}
  /* the dark charts are transparent PNGs drawn in cream ink. Repainted onto a
     forced light Canvas their labels vanish, so the plate keeps its own bed. */
  .article-chart img[src$="_embed_dark.png"]{forced-color-adjust:none;border:1px solid CanvasText}
  .theme-knob,.theme-track{border:1px solid CanvasText}
  .route-hero h1.statement{
    color:CanvasText;-webkit-text-fill-color:CanvasText;
    background:none;animation:none;
  }
}

/* ------------------------------------------------ manual edition toggle */
/* Paper is the base/no-JS default in @layer tokens. When an explicit reader
   choice is stored, theme.js sets data-theme on <html> before first paint.
   These [data-theme] blocks are the explicit overrides and win on screen by
   being unlayered. They are wrapped in @media screen so @layer print's paper
   pin is never overridden: a Night reader who prints still gets paper. */
@media screen{
  :root[data-theme="dark"]{
    color-scheme:dark;
    --sheet:#0d1218; --key:#f2ecdf; --muted:#97a0a6;
    --line:#39424a; --hair:#1d2530;
    --statement-ed:#cf8587; --statement-ai:#81a78e; --statement-cam:#879cc2; --statement-wr:#b192bd;
    --grain-a:.05;         --grain-f:none;
    --rail-sheet:#161410;  --rail-topo-a:.055;  --rail-topo-f:none;
  }
  :root[data-theme="dark"] body.reg-editorial{--register:#cf8587}
  :root[data-theme="dark"] body.reg-ai{--register:#81a78e}
  :root[data-theme="dark"] body.reg-campaigns{--register:#879cc2}
  :root[data-theme="dark"] body.reg-writing{--register:#b192bd}

  :root[data-theme="light"]{
    color-scheme:light;
    --sheet:#f7f2e7; --key:#17140f; --muted:#59524a;
    --line:#b8b0a0; --hair:#ded6c6;
    --statement-ed:#a3243f; --statement-ai:#0f6d4b; --statement-cam:#33569f; --statement-wr:#6d3f7a;
    --grain-a:.03;         --grain-f:invert(1);
    --rail-sheet:#eee7d4;  --rail-topo-a:.075;  --rail-topo-f:invert(1);
  }
  :root[data-theme="light"] body.reg-editorial{--register:#a3243f}
  :root[data-theme="light"] body.reg-ai{--register:#0f6d4b}
  :root[data-theme="light"] body.reg-campaigns{--register:#33569f}
  :root[data-theme="light"] body.reg-writing{--register:#6d3f7a}
  :root[data-theme="light"] .plate img,
  :root[data-theme="light"] .plate-open img,
  :root[data-theme="light"] .specimen img,
  :root[data-theme="light"] .sheet img,
  :root[data-theme="light"] .sheet-strip img,
  :root[data-theme="light"] .carousel-strip img{
    filter:saturate(1.45) contrast(1.08) brightness(1.03);
  }
  /* and the night edition takes the lift back off, for the cross case */
  :root[data-theme="dark"] .plate img,
  :root[data-theme="dark"] .plate-open img,
  :root[data-theme="dark"] .specimen img,
  :root[data-theme="dark"] .sheet img,
  :root[data-theme="dark"] .sheet-strip img,
  :root[data-theme="dark"] .carousel-strip img{filter:none}
}

/* the switch itself: a square track and a square knob, the same geometry as
   the ink chips. Flat inks, no shadow, no glow. It sits at the foot of the
   rail and slides across on the edition. */
.theme-toggle{
  --tw:2.1rem; --th:1.05rem; --knob:.55rem; --tpad:2px;
  flex:0 0 auto;display:inline-flex;align-items:center;gap:var(--space-xs);
  margin-top:auto;padding:.35rem 0;background:none;cursor:pointer;line-height:0;
}
.theme-label{
  color:var(--muted);font-size:.66rem;line-height:1;
  letter-spacing:.09em;text-transform:uppercase;
  font-variation-settings:var(--f-label);white-space:nowrap;
}
.theme-paper,.theme-night{transition:color .2s var(--bite)}
:root[data-theme="light"] .theme-paper,:root[data-theme="dark"] .theme-night{color:var(--key)}
.theme-track{
  position:relative;display:block;width:var(--tw);height:var(--th);
  border:1px solid var(--line);
  transition:border-color .2s var(--bite);
}
.theme-knob{
  position:absolute;top:50%;left:var(--tpad);
  width:var(--knob);height:var(--knob);
  background:var(--key);
  transform:translateY(-50%);
  transition:transform .26s var(--bite);
}
:root[data-theme="dark"] .theme-knob{transform:translate(calc(var(--tw) - var(--knob) - 2*var(--tpad)),-50%)}
.theme-toggle:hover .theme-track,.theme-toggle:focus-visible .theme-track{border-color:var(--key)}
.theme-toggle:focus-visible{outline:2px solid var(--key);outline-offset:3px}
@media(prefers-reduced-motion:reduce){.theme-knob{transition:none}}
@media(max-width:60rem){.theme-toggle{margin-top:0;margin-left:auto}}

@layer print{
  @media print{
    @page{margin:2cm}
    /* whatever the screen edition, the printed sheet is paper, and paper is
       pushed to true white: the cream stock is a screen conceit and ink on
       real paper needs that extra step. --ko is redefined to the key so
       nothing tries to reverse out of a flood that is not being printed. */
    :root{
      --sheet:#ffffff;--key:#17140f;--muted:#4a443c;
      --line:#8b8378;--hair:#c9c1b3;
      --ko:#17140f;--register:var(--key);
      --veil:#17140f;--veil-text:#ffffff;
      /* the overlays are display:none'd below; zeroed here as well so no
         zone ever prints texture */
      --grain-a:0;--rail-topo-a:0;--rail-sheet:#ffffff;
      /* the night edition's color-scheme would otherwise ride into the print
         canvas: with background graphics on, the UA paints a dark canvas
         outside the page box and the sheet prints in a black frame. */
      color-scheme:light;
    }
    body.reg-editorial{--register:#a3243f}
    body.reg-ai{--register:#0f6d4b}
    body.reg-campaigns{--register:#33569f}
    body.reg-writing{--register:#6d3f7a}
    html,body{background:#fff;color:#17140f;font-size:10.5pt}
    /* the frame folds: the rail becomes a running head over the page */
    body{display:block;min-height:0}
    .site-header{border-right:0;border-bottom:1px solid var(--hair)}
    .site-header .header-row{
      position:static;min-height:0;max-height:none;overflow:visible;
      flex-direction:row;flex-wrap:wrap;align-items:baseline;
      gap:.5rem 1.4rem;padding:0 0 .5rem;
      /* the running head is the page's own paper, not the rail's stock */
      background:none;
    }
    .ticker{flex-direction:row;flex-wrap:wrap;gap:.4rem 1.2rem}
    /* the chips are backgrounds and drop out with backgrounds off. They are
       decoration and the running head reads without them. */
    .ticker a::before{display:none}
    main{padding-bottom:0}
    /* the toggle's own block is unlayered and outranks this layer's normal
       declarations; the important flag is what puts the print layer back on
       top of the unlayered zone. */
    /* the texture overlays join the kill list: grain, rail topo, band tooth */
    .skip-link,.stage-rail,.plate-cue,.theme-toggle,
    html::before,.site-header .header-row::before,.index a::after{display:none!important}

    /* the landing's contents is the page itself: print it as contents lines.
       A flooded full-width band is a wet sheet and reversed type at
       description size fills in, so each band degrades to a 3px rule in its
       own ink with the route name set in that ink. print-color-adjust is
       scoped to the chart plate alone; the bands are deliberately excluded,
       because their ink is meant to survive as line work, not as a flood. */
    .index{margin-top:var(--space-l);margin-inline:0;border-bottom:0}
    /* the bled shelf re-margins for the same reason the bands do: a print
       sheet has no column edge to bleed to */
    .plate-shelf.bleed{margin-inline:0}
    /* the transition is killed here as well as the flood. background-color is
       a transitioned property on a band, and a running transition sits in a
       higher cascade origin than any layer: without this, switching to print
       media starts a .28s fade from the ink and the sheet can be captured
       mid-flood. */
    .index a,.index a:first-child,.index a:last-child{
      display:block;color:#17140f;
      background:none;background-color:transparent;transition:none;
      border:0;border-top:3px solid;
      padding:.5rem 0 1rem;break-inside:avoid;
    }
    .index a.ink-editorial{border-top-color:var(--ink-ed);color:var(--ink-ed)}
    .index a.ink-ai{border-top-color:var(--ink-ai);color:var(--ink-ai)}
    .index a.ink-campaigns{border-top-color:var(--ink-cam);color:var(--ink-cam)}
    .index a.ink-writing{border-top-color:var(--ink-wr);color:var(--ink-wr)}
    .index a strong{font-size:1.7rem}
    /* the description drops to black, the route name keeps its ink. On the
       landing the name is wrapped in .route-body, which is a direct child
       span, so that wrapper has to be handed the ink back. */
    .index a>span{color:#17140f}
    .index-home .route-body{color:inherit}
    .index-home .desc{color:#17140f}
    .index .go-w::after{display:none}
    .route-hero h1.statement{
      color:#17140f;-webkit-text-fill-color:#17140f;
      background:none;animation:none;
    }

    .colophon{break-inside:avoid;border-top:0}
    .colophon .mail{margin-top:.2rem;font-size:1.8rem;color:var(--register);background:none}
    /* every stage prints unfolded, whatever the rail left on screen */
    .stage{border-left:2px solid #000}
    .stage>*{display:block!important}
    .stage h3{color:#000!important}
    /* the status chips are backgrounds, which print drops by default */
    .status::before{print-color-adjust:exact;-webkit-print-color-adjust:exact}
    /* A closed <details> hides its content with content-visibility:hidden on
       ::details-content. This is the fix, and it is the reason the printed
       dossier is complete. */
    details{border:0}
    details>*{display:block!important}
    details::details-content{
      block-size:auto!important;overflow:visible!important;
      content-visibility:visible!important;
    }
    summary .marker{display:none}
    .reveal{display:block}
    .sheet{display:none!important}
    .plate-open{border:1px solid #000;padding:0}
    /* the lamplight backing is unlayered and reads --ko, which print
       repurposes as the key, so every artefact bed would print near-black.
       Re-pin the beds to the paper; important beats the unlayered zone. */
    .plate img,.plate-open img,.specimen img,.sheet img,.sheet-strip img,
    .carousel-strip img,.article-chart img{background:#ffffff!important}
    /* the dark chart plates keep their bed on paper, or their cream labels
       print invisible. Third and last site of the filename contract. */
    .article-chart img[src$="_embed_dark.png"]{
      background:#181814!important;border-color:#181814;
      print-color-adjust:exact;-webkit-print-color-adjust:exact;
    }
    .article-chart{width:auto;margin-inline:0;transform:none}
    .case-section,table,.stage,.book-run>li{break-inside:avoid}
    /* the KTS wall outgrew one page: an unsatisfiable avoid pushes the whole
       section past a near-blank sheet, so it may break; figures stay whole */
    #kts{break-inside:auto}
    figure:not(.engine){break-inside:avoid}
    .eng-node,.eng-chit,.eng-band,.eng-fan,.eng-workers,.eng-lane-head{break-inside:avoid}
    .eng-flow{height:1.3rem}
    .eng-fan{height:2.2rem}
    .eng-fan.out::after{top:.8rem}
    .eng-fan.in::after{top:calc(100% - .8rem)}
    .eng-fan.out>i::before{top:.8rem}
    .eng-fan.in>i::before{height:calc(100% - .8rem)}
    .engine{--flow:#000}
    .engine b{color:#000}
    .eng-stamp,.eng-post{border-color:#000}
    .book-run{--flow:#000}
    .book-run>li>b::before{color:#000}
    .run-fan,.run-split>div{break-inside:avoid}
    h2,h3{break-after:avoid}
    a{background:none}
    a[href^="http"]::after{content:" (" attr(href) ")";font-size:.85em;color:#444;word-break:break-all}
  }
}

/* ------------------------------------------- continuation, 2026-09-07 */
/* The home shelf is a row of links now, not decoration: each jacket lands on
   its figure on the editing page, and carries title, author and genre under
   it. The practice block is the four-part account of the editing on home and
   on the editing page. The reading-list kicker names form and year above a
   title. All three sit in their own layer so they read after the base. */
@layer continuation{
  /* the home hero is one statement with nothing under it (standfirst cut at
     his call, 2026-09-07), so the air that framed a two-part hero closes up */
  .route-hero:has(> h1.statement:last-child){margin-top:var(--space-m);padding-bottom:0}
  .route-hero:has(> h1.statement:last-child) h1{margin-bottom:var(--space-s)}
  .route-hero:has(> h1.statement:last-child){padding-bottom:var(--space-s)}
  .route-hero:has(> h1.statement:last-child)+.case-section{padding-top:0}
  .shelf-book,.shelf-book:hover,.shelf-book:focus-visible{display:block;color:inherit;background:none}
  .shelf-book img{display:block}
  .shelf-book:focus-visible{outline:2px solid var(--key);outline-offset:3px}
  .shelf-cap{
    display:block;padding:var(--space-xs) var(--space-3xs) 0;
    font-size:var(--step--1);color:var(--muted);line-height:1.4;
    font-variation-settings:var(--f-small);
  }
  .shelf-cap b{
    display:block;color:var(--key);letter-spacing:.02em;
    font-variation-settings:var(--f-label);
    transition:color var(--t-press) var(--bite);
  }
  .shelf-book:hover .shelf-cap b,.shelf-book:focus-visible .shelf-cap b{color:var(--statement-ed)}
  .practice{
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    gap:var(--space-l) var(--space-xl);max-width:76rem;margin-top:var(--space-m);
  }
  .practice>div>b{
    display:block;font-size:var(--step--1);letter-spacing:.09em;text-transform:uppercase;
    color:var(--register);margin-bottom:var(--space-2xs);
    font-variation-settings:var(--f-label);
  }
  .practice p{max-width:52ch}
  /* the shelf bleeds, so the paragraph under it needs its own top margin; the
     closing bands sit under a section rule, not at the foot of a dossier */
  .plate-shelf.bleed+.measure{margin-top:var(--space-m)}
  .index-home{margin-top:var(--space-m)}
  .reading-list .rl-kicker{
    display:block;font-size:var(--step--1);letter-spacing:.1em;text-transform:uppercase;
    color:var(--register);margin-bottom:var(--space-3xs);
    font-variation-settings:var(--f-label);
  }
  @media(max-width:640px){
    .practice{grid-template-columns:1fr;gap:var(--space-m)}
  }
  @media print{
    .shelf-cap b{color:#17140f}
    .practice>div{break-inside:avoid}
  }
}
