/* ======================================================================
   FRAME 3.7 · one stylesheet, identical across all twelve pages.
   The families are variable, so every weight declared here truly exists.
   ====================================================================== */

/* `font-display` moves from `optional` to `swap`, and the reason is a visible
   fault. With `optional` the browser uses the system face when the real one is
   not already cached at paint time, and it never swaps it in for that load, so
   the page stays in Georgia for the whole visit. Georgia has no weight 500, so
   the browser picks a nearby one or synthesises it, and that is where the same
   sentence appeared upright on one page and heavy on another, depending on what
   happened to be cached. The rules were never at fault: the four opening
   sentences share weight, size, face, leading and measure, all measured equal.
   With `swap` the real face always arrives, as soon as it is available. The cost
   is a flash of system text on the first load; the gain is that every visit sees
   the typography the site was designed in, which matters on a site whose subject
   is typography. The files are local and load from disc, so the flash lasts a
   few milliseconds. */
@font-face{
  font-family:'Plein';font-weight:300 900;font-style:normal;font-display:swap;
  src:url(../fonts/plein-variable.woff2) format('woff2');
}
/* `font-display` moves from `optional` to `swap`, and the reason is a visible
   fault. With `optional` the browser uses the system face when the real one is
   not already cached at paint time, and it never swaps it in for that load, so
   the page stays in Georgia for the whole visit. Georgia has no weight 500, so
   the browser picks a nearby one or synthesises it, and that is where the same
   sentence appeared upright on one page and heavy on another, depending on what
   happened to be cached. The rules were never at fault: the four opening
   sentences share weight, size, face, leading and measure, all measured equal.
   With `swap` the real face always arrives, as soon as it is available. The cost
   is a flash of system text on the first load; the gain is that every visit sees
   the typography the site was designed in, which matters on a site whose subject
   is typography. The files are local and load from disc, so the flash lasts a
   few milliseconds. */
@font-face{
  font-family:'Plein';font-weight:300 900;font-style:italic;font-display:swap;
  src:url(../fonts/plein-variable-italic.woff2) format('woff2');
}
@font-face{
  font-family:'Bespoke Slab';font-weight:300 800;font-style:normal;font-display:swap;
  src:url(../fonts/bespoke-slab-variable.woff2) format('woff2');
}
@font-face{
  font-family:'Bespoke Slab';font-weight:300 800;font-style:italic;font-display:swap;
  src:url(../fonts/bespoke-slab-variable-italic.woff2) format('woff2');
}
@font-face{
  font-family:'Necto Mono';font-weight:400;font-style:normal;font-display:swap;
  src:url(../fonts/necto-mono-regular.woff2) format('woff2');
}

/* ---------------------------------------------------------------- token */
:root{
  /* Paper and inks. The three new values are --paper-2, --clay and --indigo,
     plus --plate-ink as the plate black. Ratios against Parchment, using the
     WCAG 2 relative luminance formula: clay 3.34 (non-text only), stone 6.61,
     rust 5.45, indigo 8.51, ink 15.71, plate-ink 14.48. */
  --paper:#F4F1EA;
  --paper-2:#EAE4D8;
  
  --clay:#8E8270;   /* Rules, borders and rings on Paper and nowhere else: 3.34 clears the
                       non-text floor and falls short of the text floor */
  --stone:#5C5448;
  --ink:#1A1814;
  --rust:#A8401E;
  --indigo:#1B4A5E;
  --plate-ink:#241F1A;

  --rule:rgba(26,24,20,0.16);

  /* The plate colour of the page. Every page redeclares it; at rest it is black */
  --plate:var(--plate-ink);

  /* The link accent. It is not --plate, because at rest --plate is plate black,
     #241F1A, while --ink is #1A1814, so a heading that moved from ink to plate on
     hover shifted by three points in 255 and read as no change at all. That is why
     clickable headings failed to announce themselves.
     The accent is the rust, already the colour of the site's links, of the button
     and of the focus ring. There is one of it, and that is the point: a cue is
     learned when it holds still. An early attempt varied it with the case colour,
     but of the three cases only two carry a colour that separates from the ink,
     since the CS3 plate is plate black by declared choice. Two rusts and one indigo
     do not read as a code; they read as an oversight. The identity of the case is
     already carried, strongly, by the sign plate beside the title.
     The one variation lives inside a case page, where the contents list takes the
     colour of the page. There it is no exception: it is that page's ink. */
  --accent:var(--rust);

  /* Diameter of the label marker. In the reference drawing the eyelet ring and the
     nodes inside the sign are the same object at the same size, 10 to 11 pixels.
     That detail is what holds the system together, because the marker opening a
     label is literally the node of the diagram. It used to be .74em, that is 8.88
     at size 12, and it drifted with the size of the label. It is now absolute,
     like the node. */
  --nd-d:10px;

  /* The pale paper of the contents band. The site has no white, and putting #FFF
     here would place a cold rectangle inside a warm page: the eye would not read
     it as lighter, it would read it as belonging to another family.
     It is Paper lifted by two thirds of the step that separates Paper from Paper
     two, in the opposite direction. Against the paper of the page it separates
     without ambiguity; set beside a truly white sheet it shows as ivory.
     The text loses nothing: Ink on this field measures 16.4 against 15.7 on Paper,
     and Stone 6.9 against 6.6. */
  --paper-0:#FCFAF5;

  /* `--wash` used to live here, the warm tint of the field. It served a single
     component, the metric register, and 3.9 took that component's fill away, so it
     was left as a colour nobody asked for any more.
     I am not leaving it declared and inert. This frame already carried four
     mechanisms that were declared and never built (the reveal, the reading line,
     the portrait in the recall, the dossier measure), and a live token nobody uses
     is the same fault the other way round. Should the tint ever return, the sum is:
     channel by channel, 0.9 parts Paper plus 0.1 parts the colour of the page,
     written out rather than mixed at runtime, because a computed mix serialises as
     `color(srgb ...)` and a colour the checking tools cannot read is a colour you
     cannot verify. On Rust it gave #E8D5C9. */

  /* The veil on the recall cards: the colour of the page the card opens, at seven
     hundredths of opacity over the paper. It is a different job from the warm tint,
     which is one value for the whole site and serves a field that has to warm up.
     Here the field has to say which page opens, so it carries that colour at very
     low opacity, because a solid colour on a Home card would cover the dark plate
     of the contact hook sitting beneath it. Written in `rgba` rather than mixed, so
     the computed value stays readable and can be verified. */
  --veil:rgba(26,24,20,.05);

  --display:'Bespoke Slab',Georgia,serif;
  --body:'Plein',system-ui,sans-serif;
  --mono:'Necto Mono',ui-monospace,monospace;

  /* weights: every one of these exists on the variable axis */
  --w-book:400;--w-mid:500;--w-semi:600;--w-bold:700;--w-black:800;

  /* Sizes. Every clamp is rem plus vw and none exceeds a ratio of 2.5 between
     maximum and minimum, so resizing text to 200 per cent holds. */
  --fs-body:clamp(1.0625rem, 0.99rem + 0.33vw, 1.1875rem);      /* 17 → 19 */
  --fs-detail:clamp(1rem, 0.95rem + 0.22vw, 1.0625rem);          /* 16 → 17 */
  --fs-caption:clamp(0.875rem, 0.85rem + 0.1vw, 0.9375rem);      /* 14 → 15 */
  --fs-tag:0.75rem;
  --fs-nav:0.9375rem;
  --fs-wordmark:clamp(1.05rem, 1rem + 0.2vw, 1.2rem);
  --fs-h3:clamp(1.25rem, 1.19rem + 0.26vw, 1.375rem);            /* 20 → 22 */
  --fs-h2:clamp(1.75rem, 1.42rem + 1.4vw, 2.25rem);              /* 28 → 36 */
  --fs-cardine:clamp(1.9rem, 1.5rem + 1.7vw, 2.75rem);           /* 30 → 44 */
  --fs-hero:clamp(2.6rem, 1.75rem + 3.6vw, 4.75rem);             /* 42 → 76 */
  --fs-chapnum:clamp(3rem, 2rem + 4.2vw, 5.5rem);                /* 48 → 88 */
  --fs-dominant:clamp(3.25rem, 2rem + 5.2vw, 6rem);              /* 52 → 96 */
  --fs-satellite:clamp(1.9rem, 1.6rem + 1.3vw, 2.5rem);          /* 30 → 40 */
  --fs-quiet:clamp(1.5rem, 1.35rem + 0.55vw, 1.875rem);
  --fs-gloss-cl:clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);
  --fs-deck:clamp(1.125rem, 1.05rem + 0.32vw, 1.3125rem);

  --s1:.5rem;--s2:1rem;--s3:1.5rem;--s4:2rem;--s5:3rem;--s6:4.5rem;--s7:7rem;
  --space-section:clamp(4rem, 2rem + 6vw, 9rem);
  --space-block:clamp(2rem, 1.2rem + 2.2vw, 3.5rem);
  --space-rail:clamp(1.5rem, 1rem + 1.6vw, 2.75rem);
  --label-max:8.25rem;
  --rail-w:calc(var(--label-max) + var(--space-rail));

  --measure:50ch;
  --read:44rem;
  --page:1120px;
  --dossier:min(940px, 92vw);
  --hang:0rem;                    /* hanging margin: rises at a thousand pixels of window */

  --dur-fast:160ms;--dur:240ms;--dur-reveal:280ms;
  --dur-draw:700ms;--dur-wipe:630ms;
  --ease:cubic-bezier(.2,.7,.2,1);
  --ease-wipe:cubic-bezier(.5,0,.5,1);

  /* The opening sentence of the four non-case pages. One size, lower than the hero
     bridge because the band here is wide and the sentence is long: 19 to 22 pixels.
     It used to carry two different values, the bridge on the three sister pages and
     the quiet size on Contact, which is why it shifted every time you changed page. */
  --fs-plate-lead:clamp(1.1875rem, 1.05rem + 0.45vw, 1.375rem);


  

  /* Commands: height and curvature, the second derived from the first.
     The degree of curvature of a rectangle is measured as a fraction of its
     height, because at a radius of half the height the edge is fully rounded: the
     pill is the ceiling. An absolute radius on commands of different heights
     therefore gives different degrees, which is why eight pixels on a 40 pixel
     button and on the 44 pixel Menu were not the same curve.
     Proportion first. The button stood at 44 pixels around a 15 pixel label: a
     ratio of 2.93 between height and size, where a well proportioned text button
     sits between 2.1 and 2.5. It was oversized, and no radius reads well on a
     box out of proportion. That is why the curvature convinced nobody at any of
     the three values tried, and why the radius was the wrong suspect.
     The 44 came from the recommended minimum target for a fingertip. The WCAG 2.2
     threshold is 24, and 44 is a recommendation for touch: on the desktop the nav
     is driven with a pointer, and where a finger really lands, that is the Menu
     button and the mobile panel, the 44 stays declared in place.
     Hence 38: 17.25 of line, plus 9.3 of breathing above and below, plus the
     border, which brings the ratio down to 2.53. The horizontal breathing measures
     2.26 times the vertical, the proportion of a text button rather than a square.
     Then the radius, two fifths of the height, that is 15.2 pixels on 38 and 17.6
     on 44: the degree does not change, the box it is measured against does. At one
     third the short side divided into three equal parts and the curve stayed
     restrained; at two fifths the straight run measures half an arc, so the curve
     dominates the short side without erasing it. As a fraction of the pill it is
     four fifths of the way, and the pill is the ceiling that stays excluded: at a
     radius of half the height the edge is fully rounded, and two fifths is the last
     stop with a straight run still visible.
     The sum lives in the stylesheet, so changing the height carries the curvature
     with it and the degree stays the same on every command. */
  --cmd-h:38px;
  /* The fraction, not the result: a custom property resolves its own var() calls
     where it is declared, so a radius computed here would carry the 38 pixel value
     from :root to every command, and the 44 pixel commands would come out at a
     lower degree. The sum belongs in the rules, where the height is the element's
     own. */
  --r-k:0.4;
  /* The radius of the cards. Commands compute theirs from their own height and
     plates take 7.7 per cent of their width: at the sizes in use both land between
     14 and 18 pixels, and this is that same arc as an absolute value. On a card 500
     wide a percentage would give 38, which is a different shape. */
  --r-card:16px;
}
@media (min-width:1000px){ :root{--hang:2.75rem;}}

*{box-sizing:border-box;}
html{scroll-behavior:smooth;background:var(--paper);color-scheme:light;}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--body);font-weight:var(--w-book);font-size:var(--fs-body);line-height:1.62;
  -webkit-font-smoothing:antialiased;
  font-variant-numeric:oldstyle-nums;
}
h1,h2,h3,h4{font-family:var(--display);}
p{margin:0 0 var(--s2);max-width:var(--measure);text-wrap:pretty;}
strong{font-weight:var(--w-bold);}
em{font-style:italic;}
a{color:var(--rust);}
a:hover,a:focus-visible{color:var(--ink);}
.num{color:var(--ink);font-variant-numeric:tabular-nums;font-weight:var(--w-semi);
  box-shadow:inset 0 -0.34em 0 rgba(168,64,30,.16);}
:focus-visible{outline:2px solid var(--rust);outline-offset:3px;}
::selection{background:rgba(168,64,30,.18);color:var(--ink);}
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;}

/* --------------------------------------------------- wordmarks and chips */
.ip{display:inline-block;border-radius:50%;background:var(--rust);}
.wm{font-family:var(--display);font-weight:var(--w-black);letter-spacing:-.015em;color:var(--ink);text-decoration:none;}
.wm .ip{width:.21em;height:.21em;vertical-align:calc(0.5ex - 0.105em);margin:0 .2em;}
.mono-mark{font-family:var(--display);font-weight:var(--w-bold);color:var(--ink);}
.mono-mark .ip{width:.16em;height:.16em;vertical-align:.27em;margin:0 .11em;}

/* One copy of the chip. The three earlier ones stay on as aliases. */
.chip,.scale-chip,.c-tag,.cl-chip{
  display:inline-flex;align-items:center;gap:.62em;
  font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink);background:none;border:1px solid var(--clay);border-radius:0;
  padding:.46em .78em;line-height:1;
}
.chip::before,.scale-chip::before,.c-tag::before,.cl-chip::before{
  content:"";width:.55em;height:.55em;background:var(--plate);flex:none;
}
.chip.on-plate{color:var(--paper);border-color:rgba(244,241,234,.42);}
.chip.on-plate::before{background:var(--paper);}

/* Short label in mono, with the eyelet ring from the reference */
.eyebrow-node,.sec-label,.contents-label,.ag-head,.nextcase .k,.dlabel,.case-label{
  font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.15em;text-transform:uppercase;
  color:var(--stone);margin:0 0 var(--s2);
}
.sidenote p.case-label{font-size:var(--fs-tag);line-height:1.6;}
.ag-head{display:flex;align-items:center;gap:.7em;margin-bottom:var(--s3);}
.ag-head::before{content:"";width:var(--nd-d);height:var(--nd-d);border:1px solid var(--plate);border-radius:50%;flex:none;}

/* ------------------------------------------------------------------- header */
.site-header{position:sticky;top:0;z-index:20;background:var(--paper);border-bottom:1px solid var(--rule);}
.site-header .bar{max-width:var(--page);margin:0 auto;padding:var(--s3) var(--s4);display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:var(--s3);}
.brand.wm{font-size:var(--fs-wordmark);}
.nav{display:flex;align-items:center;}
.nav .group{display:flex;align-items:center;gap:2.1rem;margin-right:2.6rem;}
.nav a:not(.cta){
  position:relative;text-decoration:none;color:var(--stone);
  font-family:var(--body);font-weight:var(--w-book);font-size:var(--fs-nav);padding:.2em 0;
  white-space:nowrap;transition:color var(--dur-fast) var(--ease);
}
.nav a:not(.cta)::after{
  content:"";position:absolute;left:0;right:0;bottom:-3px;height:2px;background:var(--rust);
  transform:scaleX(0);transform-origin:left;transition:transform var(--dur-fast) var(--ease);
}
.nav a:not(.cta):hover,.nav a:not(.cta):focus-visible{color:var(--rust);}
.nav a:not(.cta):hover::after,.nav a:not(.cta):focus-visible::after{transform:scaleX(1);}
/* The nav carries three states, and they separate without reading the colour on
   its own: available in Stone at weight 400, current in Ink at weight 500 with the
   node beside it, action in Rust with the border. All three used to be Ink at
   weight 500, and the rule for the current state redeclared Ink, so it did
   nothing: the current page was marked by the dot alone. */
.nav a:not(.cta)[aria-current]:not([aria-current="false"]){color:var(--ink);font-weight:var(--w-mid);}
.nav a:not(.cta)[aria-current]:not([aria-current="false"])::before{content:"";position:absolute;left:-.9em;top:50%;transform:translateY(-50%);width:.4em;height:.4em;border-radius:50%;background:var(--rust);}
.nav a:not(.cta)[aria-current]:not([aria-current="false"])::after{transform:scaleX(0);}

/* The button takes the radius of the sign cards. `overflow:hidden` was already
   in the rule for the wipe from the left, so the fill is clipped on the curved
   corner instead of crossing its edge. */
.cta{
  position:relative;overflow:hidden;display:inline-flex;align-items:center;
  box-sizing:border-box;min-height:var(--cmd-h);
  font-family:var(--body);font-weight:var(--w-mid);font-size:var(--fs-nav);line-height:1.15;
  letter-spacing:.01em;
  color:var(--rust);border:1px solid var(--rust);border-radius:calc(var(--cmd-h) * var(--r-k));
  padding:.62em 1.4em;text-decoration:none;
  transition:color var(--dur-fast) var(--ease);
}
.cta > span{position:relative;z-index:1;}
.cta::before{
  content:"";position:absolute;inset:0;background:var(--rust);z-index:0;
  transform:scaleX(0);transform-origin:left;transition:transform var(--dur) var(--ease);
}
.cta:hover,.cta:focus-visible{color:var(--paper);}
.cta:hover::before,.cta:focus-visible::before{transform:scaleX(1);}
.cta:active{color:var(--paper);}
.cta:active::before{transform:scaleX(1);}
/* The mobile panel is driven with a finger: there the target returns to 44, and
   the radius follows on its own because it is a fraction of the command's height */
.mobile-panel .cta{--cmd-h:44px;}
.on-plate .cta{color:var(--paper);border-color:rgba(244,241,234,.55);}
.on-plate .cta::before{background:var(--paper);}
.on-plate .cta:hover,.on-plate .cta:focus-visible,.on-plate .cta:active{color:var(--plate);}
.on-plate .cta:focus-visible{outline-color:var(--paper);}

.nav-toggle{
  display:none;font-family:var(--body);font-weight:var(--w-mid);font-size:var(--fs-nav);
  background:none;border:1px solid var(--clay);border-radius:calc(var(--cmd-h) * var(--r-k));
  color:var(--ink);padding:.62em 1.4em;cursor:pointer;
  --cmd-h:44px;min-height:var(--cmd-h);
}
.mobile-panel{display:none;}
@media (max-width:820px){
  .site-header .bar{padding:var(--s2) var(--s3);}
  .nav{display:none;}
  .nav-toggle{display:inline-flex;align-items:center;}
  .site-header.open .mobile-panel{display:block;border-top:1px solid var(--rule);padding:var(--s2) var(--s3) var(--s3);}
  /* The panel carries the same three-state grammar as the bar: available in Stone
     at book weight, current in Ink at medium weight with the node, action in the
     button */
  .mobile-panel a:not(.cta){display:block;position:relative;font-family:var(--body);
    font-weight:var(--w-book);font-size:var(--fs-body);color:var(--stone);text-decoration:none;
    padding:.85em 0 .85em 1.1em;min-height:44px;border-bottom:1px solid var(--rule);}
  .mobile-panel a:not(.cta)[aria-current]:not([aria-current="false"]){font-weight:var(--w-mid);color:var(--ink);}
  .mobile-panel a:not(.cta)[aria-current]:not([aria-current="false"])::before{content:"";position:absolute;
    left:0;top:50%;transform:translateY(-50%);width:.4em;height:.4em;border-radius:50%;background:var(--rust);}
  .mobile-panel .cta{display:block;text-align:center;margin-top:var(--s3);padding:.9em;color:var(--paper);}
  .mobile-panel .cta::before{transform:scaleX(1);}
}

/* The frame of the page */
/* No vertical padding here: the vertical rhythm below the band is carried by
   the column, which is why the rule that zeroes it takes the columns and not the
   page. A padding-block on .page would put back the second gap that an earlier
   pass removed. */
.page{max-width:var(--page);margin-inline:auto;padding-inline:var(--s4);}
.skip{position:absolute;left:var(--s2);top:-200px;z-index:60;background:var(--ink);color:var(--paper);
  font-family:var(--body);font-size:var(--fs-nav);line-height:1;padding:.6em 1em;
  border-radius:calc(var(--cmd-h) * var(--r-k));--cmd-h:44px;min-height:var(--cmd-h);
  text-decoration:none;box-sizing:border-box;display:inline-flex;align-items:center;}
.skip:focus{top:var(--s2);}
.block[id]{scroll-margin-top:calc(var(--headerH,64px) + var(--s3));}

/* The frame of the article */
.article{max-width:none;margin:0;padding:0;}
.article-main{width:min(var(--read), calc(100% - 2 * var(--s4)));margin-inline:auto;hanging-punctuation:first;}
.hero-ctx{margin-bottom:0;overflow:hidden;}
/* The hero's breathing is sectional, and it belongs here rather than inside a
   width query: the opening has the same air above and below at every window size.
   It used to sit inside the 820 block and was missing on a wide screen. */
.home-hero{padding-block:var(--space-section);}
.hero-ctx + section > .page{padding-block-start:0;}
.hero-ctx + .spine-sec{padding-top:0;}
.hh-inner{display:flex;flex-direction:column;}

/* The statement runs the full span, then the base splits into two fields: the
   text and the object. */
/* The two blocks of the base are equal: same span and same height, because they
   do the same work, which is to explain the statement above them. The prose used
   to be twice the width of the sign, and the sign looked like a postage stamp. */
/* With the fill gone there is no box left to match against the sign, so the
   reading column takes the width it needs and the sign takes the width that is
   enough for it. Aligned at the top, so the first line of prose and the upper
   edge of the plate start at the same level. */
/* The title used to cross the whole span and sit on two lines, which left the
   sign below beside the prose, and below the prose a gap opened up: the sign's
   column was taller than the text's, and that difference was the gap.
   The card now takes BOTH rows of the base and the title sits in the left column,
   so the two columns end at the same level by construction, and the title, in a
   narrower column, wraps onto three lines instead of two. */
.hh-top{display:grid;grid-template-columns:1.7fr 1fr;
  grid-template-areas:"title sign" "body sign";
  column-gap:var(--s6);row-gap:var(--space-block);align-items:start;}

/* THE TITLE. The two sentences run on as a single period: the second is not a
   block of its own. Forcing a break fixed the split at one position, and at any
   window width other than the one it was chosen for it produced an extra line or
   a stub. It now wraps where it needs to, and `text-wrap:balance` evens the lines
   against each other.
   The measure decides how many lines, not the size: 20 characters of column
   against 55 of text make three lines, and the size stays a clamp, so it scales in
   proportion at every width instead of jumping at a threshold. */
.hh-title{grid-area:title;font-family:var(--display);font-weight:var(--w-bold);
  font-size:clamp(2.4rem, 1.5rem + 3.2vw, 3.9rem);line-height:1.06;letter-spacing:-.028em;
  color:var(--ink);margin:0;text-wrap:balance;}
.hh-title .t2s{color:var(--ink);font-style:italic;font-weight:var(--w-mid);}


/* THE PROSE. Two paragraphs, as in the source file: the third came from a break
   I had introduced, and it was the origin of the disorder. One voice throughout,
   same face, same size, same measure, same colour, separated by a gap and by
   nothing else. No rule between the two: a rule between two paragraphs of the same
   argument divides something that should not be divided. */
/* The hero prose carries no fill: it is the caption to the statement, and a
   caption inside a box becomes a panel to be read rather than a sentence to be
   read. Body size, one step below the sentence that opens the other pages, since
   the statement above is already at the top of the scale and the prose can stay
   quiet.
   The two paragraphs separate by voice rather than by scale: the first in medium
   upright, the second in the true Plein italic, same size. It is the same figure
   as the title, which turns from upright to italic at the second sentence. */
.hh-body{grid-area:body;}
.hh-lead,.hh-thesis{font-family:var(--body);font-size:var(--fs-body);
  line-height:1.6;color:var(--ink);max-width:56ch;margin:0;text-wrap:pretty;}
.hh-lead{font-weight:var(--w-mid);}
.hh-thesis{font-weight:var(--w-book);font-style:italic;margin-top:var(--s3);}
.hh-sign{grid-area:sign;align-self:center;display:grid;place-items:center;width:100%;}
/* The hero plate is square, like the other cards on the site. The 1:1.12 ratio
   of the reference applies where a card carries a label beneath the sign; here it
   carries none, so the extra band would be emptiness rather than air. */
/* No aspect-ratio where the pseudo-element carries the proportion: if it stays,
   it is the one that fixes the height and the pseudo-element does nothing. The
   rendered ratio does not change, because this card is square already. */
/* `auto` rather than no declaration at all. It was written to neutralise the
   1 to 1.12 that .plate-45 set on this same element, which would otherwise have
   taken the card from 340 square to 340 by 381; that rule has since been removed
   as a leftover, and `auto` stays because it says plainly that the height comes
   from the pseudo-element and from nowhere else. */
.hh-sign .sign-card{width:min(100%, 340px);display:grid;aspect-ratio:auto;}
/* The position nodes: the cycle runs fourteen seconds, and without an index it
   does not read as a cycle. They carry the diameter of the sign's node. */
@media (max-width:820px){
  /* In a single column: title, text, object. The plate takes a narrow ceiling,
     because at full width on its own it made the section endless. */
  .hh-top{grid-template-columns:1fr;grid-template-areas:"title" "body" "sign";
    column-gap:0;row-gap:var(--space-block);}
  .hh-sign{max-width:230px;margin-inline:auto;}
}

/* ======================================================================
   THE SIGNS
   ====================================================================== */
/* THE SIGNS. A containing ring, an opaque solid, hidden geometry in dashes,
   nodes, and a body in orbit: satellites on CS1, a bar running along the circle on
   CS2, an isometric stack on CS3.
   ONE STROKE WEIGHT AND ONE NODE RADIUS, in units of the viewBox and never
   redeclared per size: that is how they scale in proportion at every measure. The
   node diameter sits at 3.73 stroke weights, the ratio taken from the reference. */
/* THE SCALE OF STROKE WEIGHTS, on the technical drawing series.
   ISO 128 does not use multiples chosen by eye: it uses a geometric series with a
   ratio of the square root of two, and a drawing employs three grades with a two
   to one ratio between the heaviest and the finest. Here:
     object outline        1.414 x   = root two, the inner solid
     frame                 1.000 x   = the container and the nodes
     hidden construction   0.707 x   = one over root two, and dashed
   Each step is the same ratio, so the three grades read as a system rather than as
   three values. The heavy sits at twice the fine, which is the canonical pair.
   They used to be 1.55 and 0.50: the outline weighed more than this one without
   being in series with anything, and the dash was too slight to sit beneath it.
   All are derived from --sw, which is in units of the viewBox, so the ratio is the
   same at every rendered size: it is the scale that scales, not the individual
   threads.
   --sw is 1.15 units on a viewBox of 120, that is 0.96 per cent of the width, the
   value measured on the reference. It used to be 1.7, chosen against the minimum
   of the smallest viewBox because a thread below the pixel breaks up, and so every
   size inherited the compromise of the smallest. The argument did not hold: at 1.7
   the specimen's 18.5 pixel viewBox renders the frame at 0.26, so it goes below
   the pixel anyway. Sub-pixel is solved where it happens, by choosing not to
   render a sign at 18 pixels, rather than by thickening the threads at 408. */
.sgn{display:block;width:100%;height:auto;overflow:visible;
  --sw:1.15;--sign:var(--paper);--field:var(--plate);}
.sgn-ink{--sign:var(--ink);--field:var(--paper);}
.sgn .ln{fill:none;stroke:var(--sign);stroke-width:var(--sw);stroke-linecap:round;stroke-linejoin:round;}
/* THE RHYTHM BETWEEN SOLID AND DASHED. One material throughout: mark 2.2 and
   gap 3.3, a two to three ratio, on a thread that is half the solid. Every run
   comes out even, because each dashed element declares a `pathLength` that is a
   multiple of the period: the pattern closes on the seam instead of colliding with
   itself, and on an open run it begins and ends with a mark. The rendered size
   stays at 2.2 within two and a half per cent, so the dash is the same material on
   all three signs. */
.sgn .hd{fill:none;stroke:var(--sign);stroke-width:calc(var(--sw) * 0.707);
  stroke-linecap:butt;stroke-dasharray:2.2 3.3;}
.sgn .sl{fill:var(--field);stroke:var(--sign);stroke-width:calc(var(--sw) * 1.414);
  stroke-linejoin:miter;stroke-miterlimit:6;stroke-linecap:butt;}
/* The radius stays in the markup, and this time it is out of the stylesheet.
   `r` as a CSS property takes a length, and 2.9 without a unit is not one, so
   WebKit and Gecko rejected the declaration and fell back on the initial value
   of `r`, which is zero. A circle of radius zero is not drawn, which is why no
   node appeared in those two engines however large the page was zoomed.
   The r="2.8" attribute did not save it: a CSS declaration beats a presentation
   attribute, which has the lowest specificity there is, so the moment the
   stylesheet declared `r` the attribute stopped counting. Two rounds were spent
   on the assumption that it was a fallback. It is one only while nothing in CSS
   claims the property. */
.sgn .nd{fill:var(--field);stroke:var(--sign);stroke-width:var(--sw);}
.sgn .nd.rs{fill:var(--sign);stroke:none;}
/* Here stood a rule that filled the nodes of the small signs, added when the
   missing nodes were read as a ring below the pixel: at 71px of sign the ring is
   0.68px, and the correlation with the hero, where it is 2.54px, looked exact.
   It was not the cause. The cause was `r` declared in CSS without a unit, which
   WebKit and Gecko dropped to zero, and the nodes were missing at every size in
   those engines, hero included. With the radius back in the markup the hollow
   node returns everywhere, which is the drawing the system was approved with.
   The ring below the pixel remains an open question and not a settled one: what
   made me believe in it was the observation that r=0 now explains. If the hollow
   nodes read weakly on WebKit at card size, the answer is one line here, either
   `.sgn-s .nd,.sgn-m .nd{fill:var(--sign);stroke:none;}` for a filled disc or a
   heavier ring on the small sizes alone. That call needs those two engines, not
   an argument. */
.sgn .ar{fill:var(--sign);stroke:none;}
.sgn .mtr,.sgn .mtr-i,.sgn .trv,.sgn .chv,.sgn .desc{transform-box:view-box;}
/* The rotation origins are percentages and not lengths. With transform-box:view-box
   a percentage resolves against the view box by definition, whatever the element is
   rendered at; a length in px is a user unit of that box, which is the same thing
   until an engine scales it. Under page zoom WebKit resolves those lengths a second
   time: the bounding box of a rotating group moves to x 151 inside a box that ends
   at 120, and no angle can put it there, since the group sits within a circle of
   radius 45.5 around the centre. It is the same doubling the card heights show, so
   the two faults are one fault reaching the layout twice.
   60 of 120 is 50%, 22 is 18.3333%, 26 is 21.6667%. The two orbit values arrive
   from --orbY, declared on each sign in the markup, and are written there as
   percentages now. */
.sgn .mtr,.sgn .chv{transform-origin:50% 50%;}
.sgn .mtr-i,.sgn .trv{transform-origin:50% var(--orbY,18.3333%);}

/* The plate: solid field, radius from the reference, 7.7 per cent of the width. */
.plate{position:relative;background:var(--plate);border-radius:7.7%;overflow:hidden;
  color:var(--paper);display:grid;place-items:center;}
.plate > .sgn{width:84%;}
/* The card of the hero sign: the ratio rises to 1 to 1.12 */
/* Here stood .plate-45, and both of its declarations were leftovers of a ratio
   that no longer applies. The aspect-ratio never reached the element, because
   .hh-sign .sign-card sets aspect-ratio:auto on the same one with greater
   specificity and the pseudo-element carries the proportion. The radius was
   computed for that ratio: 6.875 per cent is 7.7 divided by 1.12, the figure that
   kept the corner circular on a card 1.12 times as tall as it is wide. The card is
   340 square today, so that figure drew an ellipse instead, 26.18px across against
   23.38px down. With the rule gone the radius falls to .plate, which declares a
   plain 7.7 per cent, and the corner is round again and back in step with the
   register, where a plate curves at 7.7 per cent of its own width. */
/* The proportion on a pseudo-element, for the ones whose width is a share of the
   container and whose height therefore cannot repeat it. */
/* The marker declares its own width in three places, and in one of them the width
   is a share of the container: a height cannot repeat that, because a percentage
   height resolves against the height of the container while a percentage padding
   resolves against its width. The pseudo-element holds for every form the width
   takes, so it carries the proportion for all three. */
.hh-sign .sign-card::before,.sv-sign-plate::before,.c-sign::before{content:"";
  grid-area:1 / 1;width:0;padding-bottom:100%;}
.hh-sign .sign-card > *,.sv-sign-plate > *,.c-sign > *{grid-area:1 / 1;}
/* The tint on the register row. It used to be Paper two: one warm grey across
   all three cases, which made it the only field on the site that did not know
   which page it was on. It is now the colour of the case at eight per cent over
   the pale paper of the band.
   Eight per cent is not chosen by eye: it is the point where the tint reads as an
   alternating row rather than as a coloured fill, and where every contrast ratio
   rises against Paper two instead of falling, because the pale paper of the band
   starts higher than the tint brings it down. Ink goes from 14.00 to 15.10, the
   CS2 label from 7.58 to 8.08, the CS3 one from 12.90 to 13.36.
   The values are written out rather than mixed at runtime: a computed mix
   serialises in a form the checking tools cannot read, and a contrast you cannot
   measure is a contrast you cannot declare. The sum, to redo it: channel by
   channel, 0.92 parts #FCFAF5 plus 0.08 parts the plate. */
.k-cs1{--plate:var(--rust);--row-tint:#F5EBE4;}
.k-cs2{--plate:var(--indigo);--row-tint:#EAECE9;}
.k-cs3{--plate:var(--plate-ink);--row-tint:#EBE8E3;}
.k-open{--plate:var(--stone);}
.k-house{--plate:var(--plate-ink);}

@media (prefers-reduced-motion: no-preference){
  /* Eight seconds a turn. The orbiting body travels around the centre, and inside
     the orbit it counter-rotates, so it stays upright instead of rolling. The stack
     descends continuously: the version with stops, three in eight seconds, read as
     a fault beside two signs that turn without pausing. The stack descends and
     rises along the same arc, so the turn closes on the seam instead of snapping
     back, continuous like the two that rotate. */
  .sgn .mtr{animation:sgn-orb 8s linear infinite;}
  .sgn .mtr-i{animation:sgn-orb-i 8s linear infinite;}
  .sgn .chv{animation:sgn-chv 8s linear infinite;}
  .sgn .trv{animation:sgn-trv 8s var(--ease) infinite;}
  @keyframes sgn-orb{to{transform:rotate(360deg);}}
  @keyframes sgn-orb-i{to{transform:rotate(-360deg);}}
  @keyframes sgn-chv{to{transform:rotate(-360deg);}}
  /* The travelling body used to animate `rx`, an SVG geometry property that
     Blink animates and the other two do not: outside Blink the body kept the
     rx="4.4" of its markup and never changed shape, so the motion the sign is
     built around was missing in two engines out of three.
     It animates `scale` instead, which every engine composites. The body
     contracts and returns along its orbit rather than squaring off, which says
     the same thing about a body under load. Its transform origin already sits
     at its own centre, since the rect is centred on 60,--orbY. */
  @keyframes sgn-trv{0%{scale:1;}44%{scale:.62;}88%{scale:.88;}100%{scale:1;}}
  /* Anything sitting in a list moves on approach: three endless circuits inside a
     list are restless */
  .c-card .sgn [class*="mtr"],.c-card .sgn .chv,.c-card .sgn .trv,
  .cl-card .sgn [class*="mtr"],.cl-card .sgn .chv,.cl-card .sgn .trv{animation-play-state:paused;}
  .c-card:hover .sgn *,.c-card:focus-within .sgn *,.c-card.seen .sgn *,
  .cl-card:hover .sgn *,.cl-card:focus-within .sgn *{animation-play-state:running;}
  .draw-in .ln{stroke-dasharray:var(--len,240);stroke-dashoffset:var(--len,240);
    animation:sgn-draw var(--dur-draw) var(--ease) forwards;}
  @keyframes sgn-draw{to{stroke-dashoffset:0;}}
  .draw-in .hd,.draw-in .sl,.draw-in .nd,.draw-in .ar{opacity:0;
    animation:sgn-fade var(--dur) var(--ease) var(--dur-draw) forwards;}
  @keyframes sgn-fade{to{opacity:1;}}
}

.sign-card{width:100%;}
.sign-card .pl{position:absolute;inset:0;background:var(--plate);display:grid;place-items:center;z-index:0;}
/* The sign centres exactly: the 1.6 per cent offset compensated for the extra
   height of the rectangular card, and on a square card it would push it off centre */
.sign-card .pl > .sgn{width:78%;}
/* In the reference the eyelet ring sits at the top of the card because a label in
   spaced capitals follows it, and the ring is that label's marker. Here the card
   carries no text, and coining some would break the first invariant: a ring alone
   in a corner reads as debris rather than as a marker. The identity between label
   ring and diagram node stays where a label sits beside it, that is on .spine-label
   and on .ag-head, and it is declared on the System sheet. */
.sign-card .pl.is-cur{z-index:1;}
.sign-card .pl.is-in{z-index:2;animation:plate-wipe var(--dur-wipe) var(--ease-wipe) forwards;}
@keyframes plate-wipe{from{clip-path:inset(0 0 0 100%);}to{clip-path:inset(0 0 0 0);}}
/* ======================================================================
   CASE PAGES
   ====================================================================== */
.case-hero{padding:var(--s5) 0 0;}
.hero-signrow{display:flex;align-items:center;gap:var(--s3);margin-bottom:var(--s5);}
/* WebKit resolves height from aspect-ratio a second time under page zoom: at 200%
   the computed style of a card reads aspect-ratio 1/1 with width 96px and height
   192px, which is internally contradictory and is exactly the width times the zoom
   factor. Firefox and Blink are immune, and the two measurements taken on Firefox
   are identical line for line at both zoom levels.
   The remedy is to keep the height off that path. Where the width is a length the
   engine can compute without asking the container, the height repeats it and
   aspect-ratio becomes a statement rather than a computation. Where the width is a
   share of the container a height cannot repeat it, because a percentage height
   resolves against the container's height and not its width: those three carry the
   ratio on a pseudo-element with a percentage padding, which resolves against the
   width by definition and predates aspect-ratio by a decade.
   This is a remedy for an engine fault and not a correction of the stylesheet: the
   declarations it replaces were correct. */
.hero-plate{width:clamp(76px, 4rem + 3vw, 112px);height:clamp(76px, 4rem + 3vw, 112px);aspect-ratio:1;flex:none;}
.hero-plate .sgn{width:84%;}
.case-hero h1{font-family:var(--display);font-weight:var(--w-bold);font-size:var(--fs-hero);
  line-height:1.03;letter-spacing:-.028em;margin:0;max-width:22ch;text-wrap:balance;color:var(--ink);}
.case-hero .thesis{font-family:var(--display);font-weight:var(--w-mid);font-size:var(--fs-quiet);
  line-height:1.26;color:var(--ink);max-width:34ch;margin-top:var(--s4);letter-spacing:-.012em;text-wrap:pretty;}
/* The disciplines of the case. They used to be five labels in Stone separated by
   rings in Clay, a grey on a grey and nearly invisible: flat, because they carried
   neither presence nor colour. Two moves. The words go to ink, which is the
   register of content rather than that of the quiet label, and content is what they
   are: they are the disciplines the case moved across. The dots fill with the
   colour of the case, so the line carries the rust of CS1, the indigo of CS2 and
   the olive of CS3 as a beat rather than as a field. Five dots of five pixels are
   the right quantity of colour for a line of twelve.
   The dot belongs to the discipline rather than to the space between two, so it
   turns from separator into marker. As a separator it sat only between one label
   and the next, and when the line wrapped the second line opened with a dot that
   separated nothing. As a marker each label has one, so every line begins with a
   dot because it begins with a discipline. The line is a flex with gap, so the
   spacing survives a wrap and survives anyone dragging an element. */
.focus-tags{display:flex;flex-wrap:wrap;column-gap:1.75em;row-gap:.45em;margin-top:var(--s5);
  font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.13em;
  text-transform:uppercase;color:var(--ink);line-height:1.7;}
.focus-tags .ft{display:inline-flex;align-items:center;gap:.72em;white-space:nowrap;}
/* A 320px the longest tag, at thirty characters, renders 270px inside a box of
   256: nowrap is right for a chip, and wrong for a chip wider than its column.
   Below 420px the tag wraps and its dot moves to the top of the first line,
   because a dot centred against two lines of text sits in the gap between them. */
@media (max-width:420px){
  .focus-tags .ft{white-space:normal;align-items:flex-start;}
  .focus-tags .ft::before{margin-top:.45em;}
}
.focus-tags .ft::before{content:"";width:.4em;height:.4em;border-radius:50%;
  background:var(--plate);flex:none;}

/* Metadata register: one rule per cell, no boxes.
   A single rule at the top and none at the foot, so the doubled dividers in the
   upper zone disappear by construction. */
/* Metadata register: one rule per cell, no boxes.
   A single rule at the top and none at the foot, so the doubled dividers in the
   upper zone disappear by construction.
   The rule takes the colour of the case rather than Ink: at one pixel Rust and
   Indigo weigh less than the near-black, so the block gains identity and sheds
   noise at the same time. It is the only thing 3.9 changes here. A twelve part
   grid with the widths cut to the content was built and taken out: on narrow
   windows it fragmented the block instead of composing it, and five equal columns
   have a regularity that bespoke widths do not repay. */
.meta-block{display:grid;grid-template-columns:repeat(5,1fr);gap:var(--s3) var(--s3);
  border:none;padding:0;margin:var(--s6) 0 0;}
.meta-block .m{display:flex;flex-direction:column;gap:.35rem;
  border:none;border-top:1px solid var(--plate);padding:var(--s2) var(--s2) 0 0;}
.meta-block .m .k{font-family:var(--mono);font-size:.6875rem;letter-spacing:.16em;text-transform:uppercase;color:var(--stone);}
.meta-block .m .v{font-family:var(--body);font-weight:var(--w-mid);font-size:var(--fs-caption);color:var(--ink);line-height:1.42;}

/* Metric register: a card, not figures hung on the page.
   It was the only element of the case carrying a size larger than the page with
   no seat of its own: two rules and some text in the void. It now has the same
   vocation as the decision card, a Paper two field and a 3 pixel plate rule at the
   head, so it joins the family the case already has instead of inventing one.
   Inside, two zones: the dominant on the left and the four satellites in a two by
   two square, separated by a continuous rule. The two by two sits beside a tall
   figure better than a row of four, which lengthens without composing, and it
   leaves no orphans because the satellites number four.
   The distances are not uniform: the gap between figure and caption is wider under
   the dominant, which is twice as tall. One distance for different sizes is the
   reason the large figure looked glued to its own line. */
/* ======================================================================
   THE METRIC REGISTER · rewritten in 3.9
   ----------------------------------------------------------------------
   What was wrong. It was the only component on the site built with fills inside
   fills: a tint in the colour of the case, and four tiles of solid paper on top.
   Everywhere else the site delimits with rules and registers, never with nested
   surfaces, and that is why this block looked stuck onto the page rather than
   written into it: it spoke a language the rest does not speak.
   And it broke. At 320 px it measured 608 px tall, more than at 1024, where it
   measures 398, because the two columns stacked while the tiles stayed square, and
   the satellites were left with 57 px of text, that is seven characters a line.

   What it is now. A colophon. No fill: a two pixel rule in the colour of the case
   at the head, which is the sign the site already uses to say that a block belongs
   to a case (the decision card carries it too), and a fine rule at the foot to
   close.
   The dominant figure no longer shares its space with a grid of panels: it takes
   all of it, and its caption sits beside it on the same baseline. Larger and more
   alone, therefore stronger, and the block grows shorter in the process.
   The four satellites form a measured band: figures on a single baseline, captions
   all starting at the same height, which is the subgrid already doing that job,
   and vertical rules in the channel, the newspaper convention and the same one the
   contents list uses.

   Contrast gains by it. The dominant sat on the tint and measured 4.71; on the
   paper it measures 5.45. The satellite figures stay at 15.71, because the paper
   of the tiles and the paper of the page are the same colour: the tiles added no
   contrast, they added edges.

   The three sizes. From 861 px the band runs four across; between 620 and 860 it
   runs two, with the horizontal rule separating the pairs; below 620 it is no
   longer a band but a row register, figure on the left in a 4.5rem column with the
   caption beside it, because below that width four columns of numbers are four
   columns of nothing. At 390 px the caption goes from 66 to 238 px of text.
   The thresholds are the ones the frame already uses, 620 and 860, rather than two
   new numbers coined for this component.
   ====================================================================== */
/* ======================================================================
   THE METRIC REGISTER · a single row (3.9, final draft)
   ----------------------------------------------------------------------
   Four failed drafts share the same error at the root: I gave the dominant a
   different treatment, its own row, its own panel, half the bento, and five things
   that ought to read together became two groups stuck side by side. Hence the
   frankenstein, and hence the height, since two stacked groups cost twice one.

   This is a band of figures, the form newspapers have always used for opening
   numbers: five cells in a row, fine rules in the channel, no panels. The size of
   the figures comes down as far as it takes for all of them to fit, which is the
   constraint the author set, and it is also what makes the band a band rather than
   a grid.

   The hierarchy no longer needs separate treatment: the dominant comes first, it
   has a wider column than the others, and its figure carries the colour of the
   case while the others are black. Three signals inside the same form, rather than
   a different form. It is the principle by which a well made table does not frame
   its important row: it distinguishes it while remaining a table.

   The rule at the head carries the colour of the case and the one at the foot is
   fine: the band is delimited like every other register on the site, and it has no
   rounded corners to quarrel with a thick band.

   Below 860 px five columns would become five slivers, so the band lies down into
   a row register, figure on the left and caption beside it, which is the same
   information in the form a narrow window can hold. It is the band turned through
   ninety degrees.
   ====================================================================== */
/* The band sits within the span, like every other block in the upper zone: it is
   a register rather than a backdrop. Running it out to the window with alternating
   fields was tried and taken out, because on five cells the alternation is not
   symmetrical and the band acquired a rhythm the data do not have; and stripping
   every rule to lighten it cost the band its cohesion, reducing five data to five
   things merely near each other.
   What remains is the approved form: five cells in a row, fine rules in the
   channel, no field, the rule of the case at the head and a fine one at the foot.
   The strong delimiter sits at the top because that is where the block begins; at
   the foot a thread is enough, because the page starts again below it.
   Below 860 px five columns would become five slivers, so the band lies down into
   a row register, figure on the left and caption beside it. It is not a fallback,
   it is the band turned through ninety degrees. */
section.metric-register{background:none;border:0;border-radius:0;
  border-top:2px solid var(--plate);border-bottom:1px solid var(--rule);
  padding:0;margin-block:var(--s6);
  display:grid;grid-template-columns:1.45fr repeat(4,1fr);align-items:stretch;}
.sat-grid{display:contents;}

section.metric-register .metric{display:flex;flex-direction:column;min-width:0;
  padding:var(--s4) var(--s3);border:0;border-left:1px solid var(--rule);}
section.metric-register > .metric.dominant{border-left:0;padding-left:0;}

.metric .fig{display:block;font-family:var(--display);font-weight:var(--w-bold);
  font-variant-numeric:tabular-nums;color:var(--ink);
  font-size:clamp(1.5rem, .78rem + 1.5vw, 2.125rem);
  line-height:.92;letter-spacing:-.03em;}
/* The caption rests on the foot: the five cells hold content of differing
   heights, and without this the five captions would sit on five different lines,
   which is what makes a band look crooked. */
.metric .lbl{display:block;margin-top:auto;padding-top:.75rem;
  font-family:var(--body);font-size:var(--fs-caption);color:var(--stone);
  line-height:1.35;text-wrap:pretty;}

/* The dominant: same cell, figure in the colour of the case and one step of size
   above the others. The step is a third rather than double, because above that
   threshold it becomes an element apart again and the band breaks up. */
.metric.dominant .fig{font-size:clamp(2rem, 1rem + 2.1vw, 2.875rem);
  font-weight:var(--w-black);color:var(--plate);line-height:.9;
  letter-spacing:-.04em;white-space:nowrap;}
.metric.dominant .fig .to{font-size:.3em;font-weight:var(--w-mid);
  color:var(--stone);letter-spacing:.02em;}
/* The counting figure keeps its own cage: without it, going from two characters
   to one would shift the cell beside it. */
.metric.dominant .fig .cd{display:inline-block;min-width:2ch;}
.metric.dominant .lbl{font-weight:var(--w-mid);color:var(--ink);}

@media (max-width:860px){
  section.metric-register{display:flex;flex-direction:column;
    grid-template-columns:none;}
  section.metric-register .metric{display:grid;
    grid-template-columns:minmax(4.5rem,auto) minmax(0,1fr);
    column-gap:var(--s3);align-items:baseline;width:100%;
    border-left:0;border-top:1px solid var(--rule);padding:var(--s3) 0;}
  section.metric-register > .metric.dominant{border-top:0;padding-left:0;}
  .metric .lbl{margin-top:0;padding-top:0;}
}

/* Contents: it is navigation, so it takes the detail size rather than a hero's */
/* The contents list sits on a band of pale paper running edge to edge across the
   window. The rule that used to open it is no longer needed: the band separates on
   its own, and a rule above a change of field is belt as well as braces. The band
   leaves the column through a pseudo-element one window wide and centred on the
   block, so it touches no layout anywhere: the content stays where it is, and only
   what is painted behind it changes.
   `isolation` opens a stacking context, otherwise the layer at minus one would
   slip behind the page background and disappear.
   The inner breathing goes from 2 to 4.5rem: a band you can see wants the space of
   a band, and hard against the edge the field would look tight around the
   contents. */
/* The criterion: the band marks the APPARATUS, not the argument.
   A case page has three parts. The header and the metadata say which project this
   is; the contents list and the scan band are the apparatus, that is the two
   things you read to decide whether and how to read the rest; then come the
   chapters, which are the argument; at the foot the pointer to the next case,
   which is apparatus again.
   The bands sit on the apparatus. The contents list and the scan band are adjacent
   and their fields touch, so they become a single field: the case's front matter.
   Then the paper of the page returns, and the whole argument sits on it. At the
   foot a second band closes.
   What comes of it is a rhythm that means something: pale where you navigate,
   paper where you read. And two interruptions in twenty-five thousand pixels of
   page, rather than a stripe every so often.
   The rules that used to open these three blocks all go: a stroke above a change
   of field is belt as well as braces.
   The field leaves the column through a pseudo-element one window wide and centred
   on the block, so it touches no layout anywhere: the content stays where it is,
   and only what is painted behind it changes. `isolation` opens a stacking
   context, otherwise the layer at minus one would slip behind the page background
   and disappear. */
.contents,.scanband,.nextcase{position:relative;isolation:isolate;}
.contents::before,.scanband::before,.nextcase::before{content:"";
  position:absolute;z-index:-1;top:0;bottom:0;
  left:calc(-50vw + 50%);width:100vw;background:var(--paper-0);}
/* The contents list separates from the scan band that follows it. The two fields
   touch, and without a difference they read as one, which was intended while the
   front matter was a single thing. It has not been so since the contents list
   gained its own breathing: two different functions, navigating and summarising,
   now have two different fields.
   The field of the contents list is the tint of the case, the same eight per cent
   the rows of «At a glance» carry, one value across three components rather than
   three similar shades coined separately. It applies only on case pages, because
   only there does a case colour exist: elsewhere `--row-tint` is not declared and
   the fallback keeps the pale paper. */
.contents::before{background:var(--row-tint,var(--paper-0));}

/* Contents list and scan band: no margin between them, so the two fields touch
   and read as one. All the breathing sits in the inner breathing of the two
   blocks. */
/* The breathing between the contents list and what follows it was the sum of two,
   its own at the foot and the band's at the head: 48 plus 48. Inside a single
   field that sum reads as a hole, because no boundary justifies it. It comes down
   to 24 plus 24: half, and the field stays continuous. */
/* The breathing of the contents list is equal above and below. It used to be 72
   at the head and 24 at the foot, that is content resting on the lower edge of its
   own field: an imbalance that went unnoticed while the field was the same as the
   band below, and that shows as soon as the field becomes its own. A block on a
   field of its own belongs centred in that field. */
.contents{margin:var(--s6) 0 0;border:0;padding:var(--s5) 0;}
/* The contents list reads down and then across, rather than by rows. It used to
   be a grid, and a grid lays out by rows: with two columns far apart the eye read
   the whole first column anyway, so the order seen and the order in the document
   did not agree. It is now a set of columns, filling the first to the bottom
   before moving to the second, which brings the order of the document and the
   order of reading back together. Columns balance any number of entries on their
   own, and there are eleven, twelve and ten across the three cases. The rule in
   the channel is the newspaper convention, and it is there to say that you read
   downwards. */
.contents-grid{columns:2;column-gap:var(--s6);column-rule:1px solid var(--rule);}
.contents-grid a{display:grid;grid-template-columns:2.1em 1fr;align-items:baseline;gap:var(--s1);
  text-decoration:none;padding:.42rem 0;border-top:none;break-inside:avoid;}
.contents-grid .c-n{font-family:var(--mono);font-size:var(--fs-tag);color:var(--plate);
  font-variant-numeric:tabular-nums;letter-spacing:.06em;line-height:1.6;}
.contents-grid .c-dot{display:inline-block;width:.44em;height:.44em;border-radius:50%;
  background:none;border:1px solid var(--plate);margin-top:.5em;}
.contents-grid .c-t{font-family:var(--body);font-weight:var(--w-book);color:var(--ink);
  font-size:var(--fs-detail);line-height:1.4;transition:color var(--dur-fast) var(--ease);}
.contents-grid a:hover .c-t,.contents-grid a:focus-visible .c-t{color:var(--plate);
  text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:.16em;}

/* Scan band: no strong rule, the three compartments are labelled */
.scanband{border-top:none;margin:0;padding:var(--s3) 0 var(--s6);}
.s-comp{padding:var(--s5) 0 0;border-bottom:none;scroll-margin-top:calc(var(--headerH,64px) + var(--s3));}
.scan-body p{margin:0 0 var(--s2);max-width:var(--measure);}
.scan-body p:last-child{margin-bottom:0;}
.scan-body p:first-child{font-family:var(--display);font-weight:var(--w-mid);font-size:var(--fs-h3);
  line-height:1.35;max-width:38ch;margin-bottom:var(--s3);}

/* At a glance as a register of alternating rows: the form of the archive */
.ag-register{border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);}
.ag-register .row{display:grid;grid-template-columns:11rem 1fr;gap:var(--s4);
  padding:var(--s3);border-top:none;align-items:start;}
.ag-register .row:nth-child(odd){background:var(--row-tint,var(--paper-2));}
.ag-register .row:first-child,.ag-register .row:last-child{padding-top:var(--s3);padding-bottom:var(--s3);}
.ag-register .k{font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.11em;text-transform:uppercase;
  color:var(--plate);padding-top:.3em;}
.ag-register .v{max-width:none;}
.ag-register .v p{margin:0;max-width:none;font-size:var(--fs-detail);}
.ag-register .v ul{margin:0;padding:0;list-style:none;}
.ag-register .v li{font-size:var(--fs-detail);margin-bottom:.45rem;position:relative;padding-left:1.15em;line-height:1.45;}
.ag-register .v li::before{content:"";position:absolute;left:0;top:.6em;width:.4em;height:.4em;
  border-radius:50%;border:1px solid var(--stone);}
.ag-register .v li:last-child{margin-bottom:0;}

/* Evidence: four solid tabs, the register reversed onto the field of the case */
.evstrip{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s4) var(--s3);}
.evstrip .item{border-top:none;padding-top:0;}
.evstrip .item .k{display:inline-block;background:var(--plate);color:var(--paper);
  font-family:var(--mono);font-weight:var(--w-book);font-size:var(--fs-tag);letter-spacing:.12em;
  text-transform:uppercase;padding:.46em .72em;margin:0 0 var(--s2);line-height:1;}
.evstrip .item p{margin:0;font-size:var(--fs-detail);color:var(--ink);max-width:none;line-height:1.45;}

/* chapters */
.block{padding:var(--s6) 0 0;}
.block:has(.chap-head){padding-top:var(--s7);}
#overview{padding-top:var(--s5);}
.chap-head{margin:0 0 var(--s5);}
.chap-n{display:block;font-family:var(--display);font-weight:var(--w-black);font-size:var(--fs-chapnum);
  line-height:.78;color:var(--plate);font-variant-numeric:tabular-nums;letter-spacing:-.04em;
  margin:0 0 var(--s3) calc(-1 * var(--hang));}
.chap-head h2{font-family:var(--display);font-weight:var(--w-semi);font-size:var(--fs-h2);line-height:1.08;
  margin:0;max-width:26ch;letter-spacing:-.018em;text-wrap:balance;}
.block > h2{font-family:var(--display);font-weight:var(--w-semi);font-size:var(--fs-h2);line-height:1.08;
  margin:0 0 var(--s5);max-width:26ch;letter-spacing:-.018em;text-wrap:balance;
  position:relative;padding-top:var(--s3);}
.block > h2::before{content:"";position:absolute;top:0;left:calc(-1 * var(--hang));width:3.25rem;height:3px;background:var(--plate);}
.subhead{font-family:var(--body);font-weight:var(--w-bold);font-size:var(--fs-h3);line-height:1.3;
  margin:var(--s6) 0 var(--s2);letter-spacing:-.006em;position:relative;}
@media (min-width:1000px){
  .subhead::before{content:"";position:absolute;left:calc(-1 * var(--hang));top:.5em;
    width:.5em;height:.5em;border-radius:50%;border:1.5px solid var(--plate);}
}

/* Pivots: the node resolving itself, carried over into the typography */
.statement,.closer,.wi-statement,.wi-closer{
  position:relative;font-family:var(--display);font-weight:var(--w-mid);
  color:var(--ink);letter-spacing:-.022em;text-wrap:balance;
  border-top:1px solid var(--ink);padding-top:var(--s4);
}
.statement,.closer{font-size:var(--fs-cardine);line-height:1.1;max-width:26ch;margin:var(--s7) 0;}
.closer{margin:var(--s7) 0 var(--s4);}
.statement::before,.closer::before,.wi-statement::before,.wi-closer::before{
  content:"";position:absolute;top:-0.36em;left:0;width:.72em;height:.72em;border-radius:50%;background:var(--plate);
}
.endmark{display:flex;justify-content:center;align-items:center;gap:var(--s3);padding:var(--s5) 0 var(--s2);}
.endmark .mono-mark{font-size:1.5rem;}
.endmark .plate{width:46px;height:46px;aspect-ratio:1;}

/* sidenote, decision, comparison, before and after: dossier cards */
.sidenote{background:var(--paper-2);border:none;border-left:2px solid var(--plate);border-radius:0;
  padding:var(--s4);margin:var(--s6) 0;max-width:var(--measure);}
.sidenote h4,.sidenote h3{font-family:var(--body);font-weight:var(--w-bold);font-size:var(--fs-h3);margin:0 0 var(--s2);line-height:1.3;}
.sidenote p{max-width:none;font-size:var(--fs-detail);}
.sidenote p:last-child{margin-bottom:0;}
.decision{background:var(--paper-2);border:1px solid var(--rule);border-top:3px solid var(--plate);
  border-radius:0;padding:var(--s4);margin:var(--s6) 0;}
.decision h4,.decision h3{font-family:var(--body);font-weight:var(--w-bold);font-size:var(--fs-h3);margin:0 0 var(--s3);line-height:1.3;}
.decision .field{margin-bottom:var(--s3);}
.decision .field:last-child{margin-bottom:0;}
.decision .field .k{font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.11em;text-transform:uppercase;
  color:var(--plate);display:block;margin-bottom:.35rem;}
.decision .field p{margin:0;max-width:none;font-size:var(--fs-detail);}
.comparison{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--s3);margin:var(--s5) 0;}
.comparison .opt{border:1px solid var(--rule);border-radius:0;padding:var(--s3);}
.comparison .opt.chosen{border-color:var(--plate);background:var(--paper-2);box-shadow:inset 0 3px 0 0 var(--plate);}
.comparison .opt .k{font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.11em;text-transform:uppercase;
  color:var(--stone);display:flex;align-items:center;gap:.55em;margin-bottom:var(--s2);}
.comparison .opt.chosen .k{color:var(--plate);}
.comparison .opt.chosen .k::before{content:"";width:.55em;height:.55em;background:var(--plate);flex:none;}
.comparison .opt p{margin:0;max-width:none;font-size:var(--fs-caption);line-height:1.5;}
.beforeafter{display:grid;grid-template-columns:1fr 1fr;gap:var(--s4);margin:var(--s5) 0;}
.beforeafter .ba{border:none;border-top:1px solid var(--ink);border-radius:0;padding:var(--s2) 0 0;}
.beforeafter .ba .k{font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.11em;text-transform:uppercase;
  color:var(--stone);margin-bottom:var(--s1);}
.beforeafter .ba p{margin:0;max-width:none;font-size:var(--fs-detail);line-height:1.45;}
.beforeafter .why{grid-column:1 / -1;font-size:var(--fs-caption);color:var(--stone);max-width:var(--measure);
  padding-left:var(--s3);border-left:1px solid var(--plate);}

/* Shared row registers */
.chan-reg{margin:var(--s5) 0;max-width:var(--measure);border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);}
.chan-reg .row{display:grid;grid-template-columns:11rem 1fr;gap:var(--s4);padding:var(--s3);border-top:none;}
.chan-reg .row:nth-child(odd){background:var(--paper-2);}
.chan-reg .k{font-family:var(--body);font-weight:var(--w-bold);font-size:var(--fs-detail);color:var(--ink);}
.chan-reg .v{max-width:none;}
.chan-reg .v p{margin:0;max-width:none;font-size:var(--fs-detail);}
.chan-reg .v .q{display:block;font-variant-numeric:tabular-nums;color:var(--ink);font-weight:var(--w-semi);margin-bottom:.25rem;}
.chan-reg .v .d{display:block;color:var(--stone);}
.chan-reg.numbered .row{grid-template-columns:4rem 1fr;gap:var(--s3);}
.chan-reg.numbered .k{font-family:var(--mono);font-weight:var(--w-book);font-size:var(--fs-tag);
  letter-spacing:.1em;color:var(--plate);padding-top:.3em;}

/* Quotations: the true slab italic, which a fake oblique flattened */
blockquote.msg{margin:var(--s4) 0;padding:0 0 0 var(--s3);border-left:2px solid var(--plate);max-width:var(--measure);}
blockquote.msg p{margin:0;font-family:var(--display);font-style:italic;font-weight:var(--w-book);
  font-size:var(--fs-detail);line-height:1.5;color:var(--ink);max-width:none;}

/* Figures: the rule of the case on the caption, twelve times a page */
figure.imgslot{margin:var(--s6) 0;}
figure.imgslot img{display:block;width:100%;height:auto;max-width:100%;border-radius:0;
  border:1px solid var(--rule);background:var(--paper-2);}
/* The span figure leaves the reading column, and that is intended: the column
   stands at 44rem and the dossier at 940. A width greater than the containing
   block with no compensating inset does not centre, it only grows to the right,
   and the overflow is the whole excess instead of half of it. At 1100 pixels of
   window: column 704, left edge at 198, figure 940, right edge at 1138, that is 38
   outside.
   The symmetrical inset centres it on the block, and since the block is centred in
   the page the figure stays centred in the page. The dossier is worth at most
   92vw, so 4vw remains on each side: it cannot overflow at any width. */
figure.f-feature{width:var(--dossier);margin-inline:calc((100% - var(--dossier)) / 2);}
figure.f-feature figcaption{max-width:var(--measure);margin-inline:auto;}
/* The tall figure. The ceiling derives its width from the figure's ratio, which
   every figure declares in `--r`. The fault was never the ratio: it was the floor.
   It sat on the WIDTH, `max(20rem, 76svh * --r)`, and a floor on the width cannot
   coexist with a ceiling on the height: where the ratio is narrow the floor wins,
   the width rises above what the ceiling allowed, and the height rises with the
   ratio. The narrowest ratio in the archive is 0.396, on CS2: at 1440 by 700 the
   ceiling asked for 188 pixels of width, the floor at 320 took it to 320, and the
   figure came out at 705 pixels against a 700 pixel viewport.
   The floor now sits on the HEIGHT budget rather than on the width:
   `max(68svh, 22rem) * --r`. The ratio multiplies an already limited height, so
   the rendered height cannot exceed `max(68svh, 22rem)` whatever the ratio, and
   the floor goes on doing its own job on genuinely short viewports, which is to
   prevent a tiny figure in a wide column. The coefficient is 68 rather than 76
   because the ceiling covers the whole figure: the remaining 32 hundredths hold
   the caption and its gap. */
figure.f-tall{max-width:min(100%, max(calc(max(104svh, 32rem) * var(--r, 0.7)), 26rem));margin-inline:auto;}
/* 3.9: the ceiling had the wrong target.
   At 68svh the figure fitted a screen, and to fit one a full page screenshot had
   to shrink: the CS1 homepage before and after rendered at 308 px, the 180 day
   alert at 259, and the CS2 event page, which is the destination of that case, at
   187. Nine figures across the two pages were postage stamps, which is to say they
   proved nothing.
   The criterion is reversed, and it is not new: it is the one the CS3 blueprints
   already apply. A figure may be taller than a screen, and you scroll; it may not
   be narrower than it takes to read it.
   Two numbers, each with its reason.
   The first is the height budget, which rises from 68 to 104 hundredths of a
   screen: the figure overruns slightly, you scroll once, and there is never any
   doubt that it has ended.
   The second is the width floor, 26rem, which is sixty per cent of the reading
   column. Below that threshold a figure no longer reads as a choice, it reads as
   an accident, and no aspect ratio justifies it: if an image is so tall that at
   that budget it would come out narrower, it keeps the floor and becomes tall.
   That is the case of the event page, 1109 by 2800.
   The floor of the budget rises from 22 to 32rem for the same reason: on a short
   window it was the one producing the postage stamps. */
figure.imgslot figcaption{font-family:var(--body);font-size:var(--fs-caption);color:var(--stone);
  margin-top:.9rem;max-width:var(--measure);text-wrap:pretty;line-height:1.5;
  padding-left:var(--s3);border-left:1px solid var(--plate);}

/* next case */
.nextcase{margin-top:var(--s7);padding:var(--s6) 0;border-top:0;
  display:grid;grid-template-columns:auto 1fr;column-gap:var(--s4);row-gap:var(--s3);align-items:start;}
.nextcase .k{grid-column:1 / -1;margin:0;}
.nextcase .nc-row{display:contents;}
.nextcase .plate{width:84px;height:84px;aspect-ratio:1;grid-row:2;}
.nextcase .line{font-family:var(--display);font-weight:var(--w-mid);font-size:var(--fs-h2);
  line-height:1.14;max-width:28ch;letter-spacing:-.018em;grid-row:2;align-self:center;}
.nextcase .cta{grid-column:2;grid-row:3;justify-self:start;margin-top:var(--s3);}

.site-footer{max-width:var(--page);margin:var(--s7) auto 0;padding:var(--s4);border-top:1px solid var(--rule);
  display:flex;justify-content:space-between;align-items:baseline;gap:var(--s4);flex-wrap:wrap;
  font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.06em;color:var(--stone);}
.site-footer > span{flex:none;}
.site-footer .svc{display:inline-flex;gap:var(--s4);}
.site-footer a{color:var(--stone);text-decoration:none;}
.site-footer a:hover{color:var(--rust);}

/* ======================================================================
   EDITORIAL SPINE AND THE HOME BANDS
   ====================================================================== */
.spine-sec{padding-top:var(--space-section);}
.spine{display:grid;grid-template-columns:var(--rail-w) minmax(0,1fr);column-gap:var(--space-rail);}
.spine-rail{border-right:1px solid var(--rule);}
.spine-label{position:sticky;top:calc(var(--headerH,64px) + var(--space-rail));
  display:inline-flex;align-items:center;gap:.6em;
  font-family:var(--mono);font-weight:var(--w-book);font-size:var(--fs-tag);letter-spacing:.15em;
  text-transform:uppercase;line-height:1.6;color:var(--stone);}
.spine-label::before{content:"";width:var(--nd-d);height:var(--nd-d);border:1px solid var(--plate);border-radius:50%;flex:none;}
.spine-col{min-width:0;container-type:inline-size;}
.lbl-2r{text-wrap:nowrap;}
@media (max-width:640px){
  .spine{grid-template-columns:1fr;row-gap:var(--space-rail);}
  .spine-rail{border-right:0;border-top:1px solid var(--rule);width:var(--rail-w);padding-top:var(--space-rail);}
  .spine-label{position:static;}
  .lbl-2r br{display:none;}
}

.c-caphead{font-family:var(--body);font-size:var(--fs-body);color:var(--ink);max-width:52ch;margin:0 0 var(--space-block);}
.c-title{font-family:var(--display);font-weight:var(--w-bold);font-size:var(--fs-h2);line-height:1.1;
  color:var(--ink);display:block;margin-top:var(--s3);letter-spacing:-.018em;text-wrap:balance;}
.c-out{font-family:var(--body);font-weight:var(--w-book);font-size:var(--fs-detail);line-height:1.5;
  color:var(--stone);display:block;margin-top:var(--s3);max-width:56ch;}
.c-deck{font-family:var(--display);font-weight:var(--w-mid);font-size:var(--fs-deck);line-height:1.28;
  color:var(--ink);margin:var(--s2) 0 0;max-width:none;text-wrap:balance;}

.c-list{display:flex;flex-direction:column;gap:0;}
.c-card{position:relative;display:grid;grid-template-columns:var(--card-plate,104px) minmax(0,1fr);
  column-gap:var(--s5);align-items:start;
  border:none;border-top:1px solid var(--ink);border-radius:0;padding:var(--s4) 0 var(--s6);
  background:none;text-decoration:none;color:inherit;cursor:pointer;}
.c-sign{display:grid;place-items:center;width:var(--card-plate,104px);
  background:var(--plate);border-radius:7.7%;}
.c-sign .sgn{width:84%;}
.c-txt{min-width:0;max-width:var(--measure);}
.c-card:focus-visible{outline:2px solid var(--rust);outline-offset:3px;}
.c-card:hover .c-title,.c-card:focus-visible .c-title,.c-card.seen .c-title{color:var(--accent);}
/* Where the whole card is the link, the title is a span, so the rule for link
   titles did not reach it and the underline was missing: same logic here, colour
   and underline together */
a.c-card .c-title{text-decoration:underline;text-decoration-thickness:2px;
  text-underline-offset:.18em;text-decoration-color:transparent;
  transition:color var(--dur-fast) var(--ease),text-decoration-color var(--dur-fast) var(--ease);}
a.c-card:hover .c-title,a.c-card:focus-visible .c-title,a.c-card.seen .c-title{
  text-decoration-color:currentColor;}
@media (prefers-reduced-motion: no-preference){
  .c-sign{transition:transform var(--dur) var(--ease);}
  .c-title{transition:color var(--dur-fast) var(--ease);}
  .c-card:hover .c-sign,.c-card:focus-visible .c-sign,.c-card.seen .c-sign{transform:translateY(-4px);}
}
@container (max-width: 480px){
  .c-card{grid-template-columns:1fr;row-gap:var(--s3);}
  .c-sign{--card-plate:88px;order:1;}
  .c-txt{order:2;}
}

.cl-wrap{container-type:inline-size;}
.cl-grid{display:grid;grid-template-columns:repeat(2, minmax(0,1fr));gap:var(--s5);}
/* The two recalls on the Home carried a one pixel rule and some text: no surface,
   no colour, and the two identical to each other. They are now cards, with the same
   vocation as the metric register and the decision card: a Paper two field and a 3
   pixel plate rule at the head. The rule carries the colour of the page the card
   opens, the indigo of What I think and the plate black of Who I am, so the recall
   says where it leads before you read it. The colour sits in the rule rather than
   in the field: the dark plate of the contact hook is already below, and two solid
   fields in a row would cancel it. */
.cl-card{display:flex;flex-direction:column;border:none;border-top:1px solid var(--ink);
  border-radius:0;padding:var(--s3) 0 0;}
/* The card takes the radius of the family and a band you can see: three pixels on
   a card 300 tall is a thread, not a band. */
.cl-grid > .cl-card{background:var(--veil);border:1px solid var(--rule);
  padding:var(--s4) var(--s5) var(--s5);overflow:hidden;border-radius:var(--r-card);}
/* Each recall carries the same object the page it opens carries, at the size of
   the card: the figure of two offset rings for What I think, the portrait for Who I
   am. They are not two decorations chosen separately; they are the same thing seen
   twice, first small and then at full band. The reading order is that of the case
   cards sitting a little above on the same page: object, title, gloss, command. The
   figure takes the colour of the card's plate, and its field is the tint it rests
   on. */
.cl-obj{width:88px;aspect-ratio:1;height:auto;flex:none;margin-bottom:var(--s3);}
/* The field of the inner solid wants the OPAQUE value of the tint rather than the
   tint itself: a translucent fill lets the hidden geometry through instead of
   covering it, and it is the covering that makes it hidden. These are the same two
   tints resolved onto paper: indigo at seven per cent gives #E5E5E0, plate black
   #E5E2DB. */
.cl-obj .sgn{--sign:var(--plate);--field:var(--veil-op,var(--paper));width:100%;}
/* The portrait is round and framed high: a square centred on a 640 by 800
   original cut off the forehead, because the face sits in the upper half. Vertical
   focus at twelve per cent keeps the whole head inside the circle. */
.cl-obj img{display:block;width:100%;height:100%;object-fit:cover;
  object-position:50% 12%;border-radius:50%;}
.cl-think{--plate:var(--indigo);--veil:rgba(27,74,94,.07);--veil-op:#E5E5E0;}
.cl-about{--plate:var(--plate-ink);--veil:rgba(36,31,26,.07);--veil-op:#E5E2DB;}
.cl-name{font-family:var(--display);font-weight:var(--w-bold);font-size:var(--fs-h2);line-height:1.1;
  color:var(--ink);margin:0;letter-spacing:-.018em;}
.cl-gloss{font-family:var(--body);font-weight:var(--w-book);font-size:var(--fs-gloss-cl);line-height:1.42;
  color:var(--ink);margin:var(--s3) 0 0;max-width:34ch;}
.cl-gloss.vero-corsivo{font-family:var(--display);font-style:italic;font-weight:var(--w-mid);}
.cl-go{margin-top:auto;padding-top:var(--s4);}
@container (max-width: 620px){ .cl-grid{grid-template-columns:1fr;}}

/* Contact hook: a low plate, anticipating the Contact page */
.contact-band .page{padding-block:0;container-type:inline-size;}
.ct-row{background:var(--plate-ink);color:var(--paper);border:none;border-radius:20px;
  padding:calc(var(--s5) * 0.76) var(--s5);flex-direction:row;align-items:center;justify-content:space-between;gap:var(--s5);}
.ct-row .cl-gloss{margin:0;max-width:30ch;color:var(--paper);font-family:var(--display);
  font-weight:var(--w-mid);font-size:var(--fs-quiet);line-height:1.22;letter-spacing:-.015em;}
.ct-row .cl-go{display:contents;}
.ct-row .cta{flex:none;}
@container (max-width: 620px){
  .ct-row{flex-direction:column;align-items:flex-start;gap:var(--s4);}
}

/* ======================================================================
   SISTER PAGES
   ====================================================================== */
.wd-col,.wt-col,.wi-col,.sv-col,.co-col{padding-top:var(--space-block);}
/* The column following an opening band carries no second gap: the band has
   already provided the separation, and the two summed were the emptiness you could
   see. The selector covers both bands, because Contact carries .co-plate. */
:is(.page-plate,.co-plate) + .page :is(.wd-col,.wt-col,.wi-col,.co-col){padding-top:0;}
@media (min-width:1120px){
  .wd-col,.wt-col,.wi-col,.sv-col,.co-col{max-width:calc(100% - var(--rail-w) - var(--space-rail));}
}
/* The service pages carry the one title that is a single long word:
   Accessibility, at thirteen characters. At 320px the hero size floors at
   2.6rem, and the word renders 255px inside a box of 239 on WebKit and 241 on
   Gecko. Blink measures the same word narrower at the same size and does not
   overflow, so the fault shows in two engines out of three: the margin was
   never there, and one engine happened to fit.
   Below 420px the size of these two titles alone drops to 2.2rem, which brings
   the word to about 216px and leaves 23px of margin, enough to absorb the
   difference between engines. Hyphenation would also fix it, and it would put
   a hyphen inside a display title: the word is frozen content, its size is not. */
.wd-h1,.wt-h1,.wi-h1,.sv-h1,.co-h1{font-family:var(--display);font-weight:var(--w-bold);
  font-size:var(--fs-hero);line-height:1.03;letter-spacing:-.028em;color:var(--ink);
  margin:0 0 var(--s5);text-wrap:balance;}
@media (max-width:420px){
  .sv-h1{font-size:2.2rem;}
}
.wd-list{list-style:none;margin:0;padding:0;container-type:inline-size;}
.c-title a{color:inherit;text-decoration:none;}
.c-title a::after{content:"";position:absolute;inset:0;}
.c-card:has(.c-title a:hover) .c-title,.c-card:has(.c-title a:focus-visible) .c-title{color:var(--accent);}
.c-card:has(.c-title a:focus-visible){outline:2px solid var(--rust);outline-offset:3px;}
@media (prefers-reduced-motion: no-preference){
  .c-card:has(.c-title a:hover) .c-sign,.c-card:has(.c-title a:focus-visible) .c-sign{transform:translateY(-4px);}
}

.wt-cap,.wi-cap{font-family:var(--display);font-weight:var(--w-mid);font-size:var(--fs-quiet);
  line-height:1.28;color:var(--ink);max-width:32ch;margin:0 0 var(--space-block);letter-spacing:-.015em;text-wrap:pretty;}
.wt-list{list-style:none;margin:0;padding:0;}
.wt-item{position:relative;padding:var(--s5) 0;border-top:1px solid var(--rule);}
.wt-item:first-child{border-top:1px solid var(--ink);}
.wt-item:last-child{border-bottom:1px solid var(--rule);}
.wt-txt{max-width:var(--measure);min-width:0;}
.wt-title{font-family:var(--display);font-weight:var(--w-bold);font-size:var(--fs-h2);line-height:1.1;
  color:var(--ink);margin:0;letter-spacing:-.018em;text-wrap:balance;}
.wt-title a{color:inherit;text-decoration:none;}
.wt-title a::after{content:"";position:absolute;inset:0;}
.wt-meta{font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.13em;text-transform:uppercase;
  color:var(--stone);margin:var(--s2) 0 0;max-width:none;line-height:2.1;}
.wt-meta .wt-src + .wt-src::before{content:"";display:inline-block;width:.42em;height:.42em;
  border-radius:50%;border:1px solid var(--clay);margin:0 .8em;vertical-align:.1em;}
/* The file type sat at the end of a row of entries separated by dots, so «PDF»
   read as the venue and the year did: one datum among data. It is now a mark,
   boxed and in the accent colour, and it carries the direction of what it does:
   the downward arrow for a file that downloads, the diagonal one for an address
   that leads off the site. The direction comes from `href`, so there is nothing to
   keep in step by hand. */
.wt-meta .wt-src:last-child{display:inline-flex;align-items:center;gap:.42em;
  color:var(--accent);border:1px solid var(--accent);padding:.22em .5em;line-height:1;
  margin-left:.85em;vertical-align:.1em;}
.wt-meta .wt-src:last-child::before{content:none;}
.wt-item:has(.wt-title a[href$=".pdf"]) .wt-meta .wt-src:last-child::after{content:"\2193";font-size:1.1em;}
.wt-item:has(.wt-title a[href^="http"]) .wt-meta .wt-src:last-child::after{content:"\2197";font-size:1.1em;}
.wt-gloss{font-size:var(--fs-detail);line-height:1.5;color:var(--ink);margin:var(--s3) 0 0;max-width:none;text-wrap:pretty;}
/* A clickable title announces itself in two ways at once, because colour alone is
   not enough for anyone who cannot tell it apart: it goes to the accent and it
   underlines. The underline is on text-decoration rather than on a bar in ::after,
   so it follows every line of a title that wraps instead of running beneath the
   whole block. */
.wt-title a,.c-title a{color:inherit;text-decoration:underline;text-decoration-thickness:2px;
  text-underline-offset:.18em;text-decoration-color:transparent;
  transition:color var(--dur-fast) var(--ease),text-decoration-color var(--dur-fast) var(--ease);}
.wt-title a:hover,.wt-title a:focus-visible,.c-title a:hover,.c-title a:focus-visible{
  color:var(--accent);text-decoration-color:currentColor;}
.wt-item:hover .wt-title,.wt-item:focus-within .wt-title{color:var(--accent);}
.c-card.seen .c-title a{text-decoration-color:currentColor;}
.wt-item:has(.wt-title a:focus-visible){outline:2px solid var(--rust);outline-offset:3px;}
.wt-title a:focus-visible{outline:none;}
@media (prefers-reduced-motion: no-preference){
  .wt-title{transition:color var(--dur-fast) var(--ease);}
}

.wi-photo{display:block;width:100%;height:auto;max-width:100%;border-radius:0;border:none;}
.wi-fig{width:min(100%, 23rem);margin:0 0 var(--space-block);border-top:3px solid var(--plate);padding-top:var(--s2);}
.wi-txt{font-size:var(--fs-body);max-width:var(--measure);}
.wi-txt p{max-width:none;}
.wi-mv{margin-top:var(--s5);}
.wi-statement,.wi-closer{font-size:var(--fs-quiet);line-height:1.22;margin:var(--s7) 0;max-width:30ch;}
.wi-closer{margin:var(--s7) 0 var(--s4);}

/* service pages */
.sv-txt,.co-txt{font-size:var(--fs-body);max-width:var(--measure);}
.sv-txt p,.co-txt p{max-width:none;}
.sv-reg,.co-reg{margin:var(--s6) 0 0;max-width:var(--measure);
  border-top:1px solid var(--ink);border-bottom:1px solid var(--rule);}
.sv-reg .row,.co-reg .row{display:grid;grid-template-columns:10rem 1fr;gap:var(--s4);
  padding:var(--s3);border-top:none;}
.sv-reg .row:nth-child(odd),.co-reg .row:nth-child(odd){background:var(--paper-2);}
.sv-reg .k,.co-reg .k{font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.11em;
  text-transform:uppercase;color:var(--plate);padding-top:.3em;}
.sv-reg.numbered .k{color:var(--stone);}
.sv-reg .v,.co-reg .v{max-width:none;margin:0;}
.sv-reg .v p,.co-reg .v p{margin:0;max-width:none;font-size:var(--fs-detail);}
.sv-reg .v p + p{margin-top:var(--s2);}
.sv-reg a,.co-reg a{color:inherit;text-decoration:underline;text-decoration-thickness:1px;
  text-underline-offset:.18em;text-decoration-color:var(--stone);}
.sv-reg a:hover,.sv-reg a:focus-visible,.co-reg a:hover,.co-reg a:focus-visible{color:var(--rust);text-decoration-color:currentColor;}
.co-reg .v .q{display:block;font-family:var(--display);font-weight:var(--w-mid);font-size:var(--fs-h3);
  line-height:1.3;color:var(--ink);margin-bottom:.4rem;}
.co-reg .v .d{display:block;color:var(--stone);}
.sv-sign-plate{width:min(100%, 15rem);display:grid;margin:0 0 var(--space-block);}
@media (prefers-reduced-motion: no-preference){
  .sv-reg a,.co-reg a{transition:color var(--dur-fast) var(--ease),text-decoration-color var(--dur-fast) var(--ease);}
}

/* OPENING PLATE. The four non-case pages all open on a full width field with the
   title and a single sentence: that is the figure they share. What they do not
   share is the field and what sits on the right, because repeating the dark field
   and the Contact sign on all four did not make them a series, it made them the
   same page four times.
   The field comes from the paper family, where there is a tone for each, and the
   plate black stays with the two personal pages. On the right sits whatever the
   page has of its own and nothing else: the portrait on Who I am, the house sign
   on Contact, and nothing on the two pages that carry only words, where the band
   becomes a single column and the sentence breathes on a wider measure.
   The opening sentence carries the hero bridge size rather than the Contact recall
   size: at 27 pixels on a wide band it became a wall. */
.page-plate{margin-bottom:calc(var(--space-section) * 0.8);}
.page-plate .page{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:var(--s6);
  row-gap:var(--s4);align-items:center;padding-block:var(--space-section);}
.page-plate h1{margin:0;}
/* One rule for the opening sentence of all four pages: same face, same weight,
   same size and same reading column. The three sisters and Contact used to have
   separate rules, so the sentence changed on every page: the cacophony was between
   pages rather than inside one. The breathing comes from leading at 1.5 and from a
   column of 46 characters, and the longest of the four sentences sits in four
   lines, which do not make a wall. */
.page-plate .ph-say > p,.co-plate .co-lead{font-family:var(--display);font-weight:var(--w-mid);
  font-size:var(--fs-plate-lead);line-height:1.5;margin:var(--s4) 0 0;max-width:46ch;
  letter-spacing:-.01em;color:var(--paper);text-wrap:pretty;}
/* THE TWO PAGES WITH NO OBJECT. They have neither a photograph nor a mark to
   place on the right, and coining a new sign to fill the space would be noise: a
   sign that means nothing is worse than emptiness. The emptiness was not one of
   content though, it was a proportion: the band occupies the full width and the ink
   sat in the first third. Words cannot be added, because the rendered text of the
   eleven indexable pages does not move by a single character.
   So the band is always two columns. Where there is an object the second column
   carries it; where there is not, it carries the sentence. Same figure, no new
   sign, no extra words, and the width fills. Title and sentence share the baseline
   of the first line, as the dossier registers do. */
/* On the right, where there is neither a photograph nor a mark, goes a watermark.
   It is not one of the five signs: it is built with their grammar, viewBox 0 0 120
   120, a ring, a solid stroke and a hidden stroke, a node where two lines meet. It
   sits in the background, in paper at eighteen per cent and clipped by the right
   edge, so it does not compete with the title and it adds no mark to the
   vocabulary.
   The two figures differ, and each says, in the abstract, the title it accompanies.
   What I do: three concentric rings of radius 38, 26 and 14, the middle one hidden.
   They are the scales, and that is the sentence of the page itself, three projects
   at different scales.
   What I think: two rings of equal radius offset by 24, the hidden one in front of
   the solid one, with nodes at the two points where they cross. It is the question
   that comes before the project, and it is the sentence of the page.
   The dashing is not `border-style:dashed`, which distributes the step around a
   circle as it pleases: it is the `.hd` class from the vocabulary of the signs, so
   the thread is at 0.64 of the solid and the step is one to two, as on every other
   sign on the site. */
.page-plate.pp-solo{position:relative;overflow:hidden;}
.page-plate.pp-solo .page{display:block;position:relative;z-index:1;}
.ph-mark{position:absolute;right:-7%;top:50%;transform:translateY(-50%);
  width:clamp(260px, 32vw, 440px);height:auto;opacity:.18;pointer-events:none;z-index:0;}

/* the three fields */
/* The four fields. Bone and Paper two were two warm greys almost identical to
   each other: flat, and on two neighbouring pages they gave the same impression of
   nothing. The two pages carrying only words now take the two solid colours of the
   system, and the two personal pages take the plate black. Paper on Rust measures
   5.45 and on Indigo 8.51, so the text moves to full weight and size on both. */
.pp-rust{background:var(--rust);}
.pp-indigo{background:var(--indigo);}
.pp-ink{background:var(--plate-ink);}
.pp-rust,.pp-indigo,.pp-ink{color:var(--paper);}
.pp-rust h1,.pp-indigo h1,.pp-ink h1{color:var(--paper);}
.page-plate .ph-portrait{width:clamp(148px, 8rem + 8vw, 248px);justify-self:end;}
.page-plate .ph-portrait img{display:block;width:100%;height:auto;}
@media (max-width:820px){
  .page-plate .page{grid-template-columns:1fr;}
  .page-plate .ph-portrait{justify-self:start;width:clamp(132px, 7rem + 8vw, 190px);}
}
/* Contact keeps its own plate and its own sign */
/* Contact keeps the dark plate and its own sign: it is the page that asks for an
   action, and the darkest field in the system is its own. */
.co-plate{background:var(--plate-ink);color:var(--paper);margin-bottom:calc(var(--space-section) * 0.8);}
.co-plate .page{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:var(--s6);
  row-gap:var(--s4);align-items:center;padding-block:var(--space-section);}
.co-plate .co-h1{color:var(--paper);margin:0;}
/* The Contact sign is the mark of the page, so it carries the largest size among
   the signs on stage. The clamp is rem plus vw: it scales in proportion at every
   window width instead of jumping at a threshold. */
.co-sign{width:clamp(150px, 9rem + 7vw, 248px);justify-self:end;}
.co-sign .sgn{width:100%;}
@media (max-width:820px){
  .co-plate .page{grid-template-columns:1fr;}
  .co-sign{justify-self:start;order:-1;width:clamp(128px, 8rem + 7vw, 196px);}
}

/* ------------------------------------------------------------- responsive */
/* The register has a threshold of its own, the one at which the dominant and the
   square of satellites no longer sit side by side: the rule separating them turns
   from vertical to horizontal and the composition stays the same. */
/* Here sat the 820 px adaptation of the old metric register. It put back 2rem of
   breathing on all four sides, the 64 px that below 400 left the satellites 104 px
   of text, plus the channels and margins of the two by two grid. The rewritten
   component carries its own three sizes beside it, at the frame's 860 and 620
   thresholds, so this block had nothing left to adapt and stayed only to
   contradict, 570 lines below what it contradicted. */

@media (max-width:1080px){
  .meta-block{grid-template-columns:repeat(3,1fr);}
}
@media (max-width:860px){
  .dossier{width:100%;}
  .contents-grid{columns:1;column-rule:none;}
  .evstrip{grid-template-columns:repeat(2,1fr);}
}
@media (max-width:620px){
  .meta-block{grid-template-columns:1fr;}
  .beforeafter{grid-template-columns:1fr;}
  .evstrip{grid-template-columns:1fr;}
  .ag-register .row,.chan-reg .row,.sv-reg .row,.co-reg .row{grid-template-columns:1fr;gap:.5rem;}
  .chan-reg.numbered .row{grid-template-columns:1fr;gap:.5rem;}
  .nextcase{grid-template-columns:1fr;}
  .nextcase .plate{grid-row:auto;}
  .nextcase .line,.nextcase .cta{grid-column:1;grid-row:auto;}
  .ct-row{padding:var(--s4);}
}

/* ------------------------------------------------------------------- print */
@media print{
  .site-header{position:static;}
  .skip{display:none !important;}
  .reveal{opacity:1 !important;transform:none !important;}
  a{color:var(--ink);}
  .readline{display:none !important;}
  .plate,.c-sign,.ct-row,.co-plate,.evstrip .item .k{
    -webkit-print-color-adjust:exact;print-color-adjust:exact;}
  .breakout{position:static !important;transform:none !important;width:auto !important;}
  figure.imgslot{break-inside:avoid;}
  figure.imgslot img{max-height:60vh;object-fit:contain;}
  .sign-card .pl:not(.is-cur){display:none;}

  /* ---- 3.9: what the stylesheet added, and what paper does not want ----
     a. The bands of pale paper. They are pseudo-elements 100vw wide, and in print
        `vw` measures against the page: a rectangle of colour across a full page
        that either overruns the sheet, or forces a blank sheet, or prints a fill
        nobody asked for. On screen the band is the boundary; on paper the boundary
        is made by the rule, which is what the stylesheet did before 3.9. So the
        band disappears and the three rules return, each with the gap it had:
        contents list and scan band separated from each other, as they were before
        their fields touched.
     b. The dossier measure. `.breakout` already zeroed the width, but nobody
        touched the negative margin that centres it: with an automatic width that
        margin would pull the block off axis.
     c. `overflow-x:clip` on the body. It exists to stop the band's 100vw from
        scrolling the window; with no bands it is no longer needed, and on paper it
        would simply clip whatever runs off the page. */
  .contents::before,.scanband::before,.nextcase::before{display:none !important;}
  .contents{border-top:1px solid var(--rule) !important;
    margin-top:var(--s6) !important;padding:var(--s4) 0 0 !important;}
  .scanband{margin-top:var(--s6) !important;padding:0 !important;}
  .nextcase{border-top:1px solid var(--ink) !important;
    margin-top:0 !important;padding:var(--s7) 0 var(--s6) !important;}
  .dossier{width:auto !important;margin-inline:0 !important;}
  body{overflow-x:visible !important;}

  /* The metric register no longer has a field delimiting it: its rule at the head
     carries the colour of the case, and without this line some engines print it
     grey like all the others. */
  .metric-register{-webkit-print-color-adjust:exact;print-color-adjust:exact;
    break-inside:avoid;}
  /* The geometry of the band in print is handled by `.dossier`, which returns it
     to the column as it does with the other four blocks of the upper zone. A rule
     used to sit here zeroing the breathing of the cells: it served the full window
     version, where the two outer cells carried breathing computed on `100vw`. That
     version is gone, and the rule stayed on to take the twenty-four pixels of
     channel away from all five cells: on paper the dividers ended up a pixel from
     the figure beside them. */
}

/* ------------------------------------------------------ reduced motion */
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto;}
  .reveal{opacity:1;transform:none;transition:none;}
  .nav a:not(.cta)::after,.cta::before{transition:none;}
  .sign-card .pl{display:none;}
  .sign-card .pl.is-cur{display:grid;}
  .readline{display:none;}
}

/* The specimen: the size of the cell heading lives in the stylesheet rather than
   in the tag, so the heading level stays free to serve the sequence. */
.signs .cell h3,.signs .cell h4,.signs .cell h5{font-family:var(--body);font-weight:var(--w-bold);
  font-size:var(--fs-detail);line-height:1.3;margin:var(--s3) 0 var(--s1);}

/* The CTA inside a recall card carries the colour of the card. Outside the cards
   it stays Rust, the colour of the site's links: here the card already has a colour
   of its own declared, and a red button on an indigo tint would be a third colour
   belonging to neither. */
.cl-grid > .cl-card .cta{color:var(--plate);border-color:var(--plate);}
.cl-grid > .cl-card .cta::before{background:var(--plate);}
.cl-grid > .cl-card .cta:hover,.cl-grid > .cl-card .cta:focus-visible,
.cl-grid > .cl-card .cta:active{color:var(--paper);}
.cl-grid > .cl-card .cta:focus-visible{outline-color:var(--plate);}

/* The line at the head has gone: a thick band forces the top corner to run
   square, and curvature on two corners alone is not curvature, it is a defect. The
   colour of the card is still carried by the sign, by the button and by the tint,
   which are three places and enough.
   And the sign takes a size of its own instead of the column width: at full width
   it was the sign dictating the height of the card. */
.cl-obj{width:clamp(64px, 4rem + 2vw, 88px);}

/* The portrait in the card: a radius of fifty per cent on a box that is not
   square gives an ellipse rather than a circle. The image declares the ratio, and
   the crop keeps the face centred high instead of cutting off the forehead. */
.cl-obj img{width:100%;height:auto;aspect-ratio:1;object-fit:cover;
  object-position:50% 12%;border-radius:50%;display:block;}

/* The line at the head returns, and with it the square top corners: a thick band
   wants a sharp edge, and the curvature stays at the foot, where it has nothing to
   cut. */
.cl-grid > .cl-card{border-top:10px solid var(--plate);
  border-radius:0 0 var(--r-card) var(--r-card);}

/* ============================================================ HERO CODA
   The title set by value rather than by token. Twice a new token failed to reach
   the declarations block, and a `font-size:var(--x)` with --x undeclared does not
   fall back to the previous value: it is invalid at computed-value time, so the
   title inherits the body size. Written by value it cannot fail in silence.
   The three lines are decided by the ratio between size and column: 55 characters
   in 487 pixels sit on three lines at 54, not at 61. The clamp stays rem plus vw. */
.hh-title{font-size:clamp(2.4rem, 1.5rem + 3.2vw, 3.9rem);line-height:1.06;
  letter-spacing:-.028em;max-width:20ch;text-wrap:balance;}

/* The contact hook carries its own sign, to the left of the text: the card said
   let us talk without showing who with. The plate is the site's own, so it sits at
   7.7 per cent of radius, and the line becomes sign, sentence, command. */
.ct-row{display:flex;align-items:center;justify-content:flex-start;gap:var(--s3);}
.ct-row .cl-gloss{margin-right:auto;}
.ct-sign{flex:none;width:clamp(104px, 5.5rem + 3.8vw, 148px);height:clamp(104px, 5.5rem + 3.8vw, 148px);aspect-ratio:1;}
.ct-sign .sgn{width:84%;}
@media (max-width:620px){
  .ct-row{flex-direction:column;align-items:flex-start;gap:var(--s4);}
}

/* ======================================================================
   FRAME 3.8 · CODA TO THE REDESIGN
   Everything that follows is added on top of frame 3.7, which stays unchanged
   line by line. Five entries, each with its own reason:
     1. the reveal on scroll, which 3.7 triggered without dressing;
     2. the reading line, which 3.7 declared and never drew;
     3. the CV component, with all its states;
     4. opening a figure at full size;
     5. the detail corrections that came out of the checks.
   ====================================================================== */

/* --------------------------------------------------------------- 0. hidden
   The `hidden` attribute amounts to `display:none` in the user agent stylesheet,
   which has zero specificity: any rule of ours carrying a class beats it, and a
   register row declared `display:grid` would stay visible even when hidden. That
   is the case of the CV row, which sits in the page and stays unseen until it is
   configured: here the attribute has to win. */
[hidden]{display:none !important;}

/* ------------------------------------------------------- 1. REVEAL ON ENTRY
   3.7 added the `reveal` and `in` classes from script and never dressed them: the
   observer ran, the stylesheet did not answer, and the two rules for print and for
   reduced motion cancelled an effect that did not exist. The movement was there in
   intention and not on the page.
   It is there now, and it stays inside the limits the project set itself: two
   composited properties, `opacity` and `transform`, ten pixels of offset and the
   reveal duration already in a token. There is no layout shift, because the offset
   is a transform rather than a margin. No information depends on the movement: the
   base class lives only inside `no-preference`, so with reduced motion the text was
   never transparent even for a frame. And `site.js` carries a net: two seconds
   after load any block still covered is uncovered, so an observer that fails to
   fire cannot leave the page blank. */
@media (prefers-reduced-motion: no-preference){
  .reveal{opacity:0;transform:translateY(10px);
    transition:opacity var(--dur-reveal) var(--ease),transform var(--dur-reveal) var(--ease);}
  .reveal.in{opacity:1;transform:none;}
}

/* --------------------------------------------------- 2. READING LINE
   `.readline` sat in the header of all twelve pages as an empty container: no
   height, no field, and two rules hiding it in print and under reduced motion. It
   was a place laid at table.
   It is now occupied by the one thing that place can do well, which is to say how
   much is left. The three case pages are long, twelve figures, ten chapters, forty
   thousand characters, and the contents list at the head says where you can go,
   not where you are.
   It appears only where it is needed: short pages have nothing to measure, and on
   those the line is not drawn. Progress arrives as a custom property and renders
   through `transform:scaleX`, so every frame stays in compositing and never
   touches layout. The colour is that of the page plate, so the line carries the
   rust of CS1, the indigo of CS2 and the plate black of CS3 like everything else
   in the case. */
.site-header .readline{display:none;height:2px;background:var(--rule);}
html:is(.k-cs1,.k-cs2,.k-cs3) .site-header .readline{display:block;}
.site-header .readline::before{content:"";display:block;height:100%;background:var(--plate);
  transform:scaleX(var(--read-progress,0));transform-origin:left center;}

/* -------------------------------------------------------- 3. CV COMPONENT
   The CV is the one piece of material foreseen and not yet present. The place is
   decided and built; the document will arrive inside `docs/` and is switched on
   with a single value in `assets/site-config.js`.
   Where it sits. In two places rather than three: the navigation entry, which
   makes it reachable from each of the twelve pages, and the row of the Contact
   register, which is its natural seat because the address and the profile already
   live there. Not a third button on the Home: the contact hook already carries a
   single action, and two actions in one band are two weakened actions.
   What rank it has. In the bar it is a text link rather than a command: the header
   holds one button, and that button is Contact. It does carry a direction though,
   the downward arrow, with the same grammar as the document mark on What I think,
   so anyone reading it knows they are downloading a file before they press.
   Why it is invisible today. A disabled command declares an absence: it tells the
   visitor something is missing, and to a recruiter that is the signature of a
   neglected site. The place is prepared, not performed: while the value is null
   the entry does not exist in the page and no measurement changes, because the bar
   is a flex with gap and the register row is held by `hidden`, so it leaves
   neither leading nor a zebra row out of step. The disabled state exists all the
   same, dressed and documented on the system sheet: it is there for the day the
   document is under revision and the entry has to stay in place without leading
   anywhere. */
.nav .cv-link,.mobile-panel .cv-link{display:inline-flex;align-items:center;gap:.45em;}
.mobile-panel .cv-link{display:flex;}
.cv-link .vs{font-family:var(--mono);font-size:.86em;line-height:1;opacity:.85;}
/* The non-interactive state. It is not `disabled`, which does not exist on a
   link: it is `aria-disabled`, so assistive technology announces it and the
   pointer promises nothing. Clay on Paper measures 3.34, below the text floor,
   and that is intended, because a non-interactive element should not compete with
   the ones that are interactive, and the text stays readable beside its label. */
.cv-link[aria-disabled="true"]{color:var(--clay);cursor:default;}
.nav a.cv-link[aria-disabled="true"]:hover,.nav a.cv-link[aria-disabled="true"]:focus-visible{color:var(--clay);}
.nav a.cv-link[aria-disabled="true"]:hover::after,
.nav a.cv-link[aria-disabled="true"]:focus-visible::after{transform:scaleX(0);}
.co-reg .cv-link[aria-disabled="true"]{text-decoration-color:var(--clay);}
/* The four entry bar. With the CV entry the group goes from three to four, and
   between 820 and 1000 pixels the 2.1rem channel sent the last entry into the
   button. The channel narrows where the window is narrow and returns to full as
   soon as there is room: the threshold is the one at which four entries and the
   command sit in a row with the intended breathing. */
@media (max-width:1040px){
  .nav .group{gap:1.5rem;margin-right:1.8rem;}
}

/* ------------------------------------------ 4. FIGURE AT FULL SIZE
   The case figures are working documents: service maps, blueprints, matrices.
   Three of them reach 4200 pixels on a side and render in column at 940: the
   composition reads, the labels inside it do not. The original is already in the
   package, so the shortest way is also the most honest, which is that the figure
   opens its own file at the size it was delivered in.
   No lens, no script, no modal window to govern from the keyboard: it is a link,
   and it behaves like a link. The caption declares it with an interface label in
   mono, which is the site's register for labels, and the diagonal direction says
   that it opens elsewhere. `cursor:zoom-in` on the image is the only added cue. */
figure.imgslot a.f-open{display:block;cursor:zoom-in;}
figure.imgslot a.f-open img{transition:border-color var(--dur-fast) var(--ease);}
figure.imgslot a.f-open:hover img,figure.imgslot a.f-open:focus-visible img{border-color:var(--plate);}
figure.imgslot a.f-open:focus-visible{outline:2px solid var(--rust);outline-offset:3px;}
figure.imgslot figcaption .f-note{display:inline-flex;align-items:center;gap:.4em;
  margin-left:.7em;font-family:var(--mono);font-size:var(--fs-tag);letter-spacing:.1em;
  text-transform:uppercase;color:var(--stone);text-decoration:none;white-space:nowrap;}
figure.imgslot figcaption .f-note:hover,figure.imgslot figcaption .f-note:focus-visible{color:var(--rust);}

/* ------------------------------------------------- 5. DETAIL CORRECTIONS
   a. The mobile panel closes when an entry is chosen: it used to stay open over
      the freshly loaded page. That lives in `site.js`, and needs no stylesheet.
   b. The placeholder for downloadable content: `picture` is not a container with
      layout of its own, but declaring it a block avoids the phantom baseline an
      inline element leaves beneath the image.
   c. The focus ring on the article container, which carries `tabindex=-1` for the
      skip link: without this rule the skip moves focus and does not show it. */
figure.imgslot picture{display:block;}
.ph-portrait picture{display:block;}
/* `picture` is inline by default: inside a container that gives the child its
   height, the image would measure a hundred per cent of nothing. This applies to
   the portrait on the plate and to the one in the Home recall. */
.cl-obj picture{display:block;width:100%;height:100%;}
.article-main:focus{outline:none;}
.article-main:focus-visible{outline:2px solid var(--rust);outline-offset:6px;}

@media print{
  .site-header .readline{display:none !important;}
  figure.imgslot figcaption .f-note{display:none !important;}
}

/* ======================================================================
   FRAME 3.9 · THE EVIDENCE ON THE FRONT PAGE
   ----------------------------------------------------------------------
   The site held thirty-one images of real work and showed none of them before the
   third screen of a case page. The work index carried an abstract sign 104 px
   wide: beautiful, and silent about the project it announced.
   The card now carries the evidence. The sign does not leave: it becomes the plate
   resting on the corner of the proof, which is precisely the hero plate component
   at the size of a marker. The system and the work in the same object.
   The crop is 4:3 and takes the head of the document, the part by which a public
   service is recognised: the masthead, the title, the action.
   ====================================================================== */
.c-card{grid-template-columns:clamp(220px,44%,400px) minmax(0,1fr);
  column-gap:var(--s5);padding-top:var(--s5);}
.c-shot{position:relative;display:block;align-self:start;}
/* The curvature of the proof is eight pixels, and it is chosen this way: it is
   the radius the plate resting on its corner actually has. The plate curves at 7.7
   per cent of its own width, and at its typical size of ninety-one pixels that
   makes seven pixels of radius. Eight on the proof means the two overlapping
   objects have the same corner as an absolute value rather than in the same
   proportion, and that is the only consistency you can see, because the two
   corners touch.
   A radius in per cent was tried and taken out: the same proportion that softens a
   ninety pixel token becomes twenty-five pixels on a card of three hundred and
   thirty, and at that point it softens a register that has to stay dry. Eight is
   half of `--r-card`, the radius of the Home recall cards: the family is the same,
   the degree is lower because the object is smaller.
   The rule stays at one pixel: at one pixel it delimits, at one and two tenths it
   begins to draw. */
.c-shot img{display:block;width:100%;height:auto;aspect-ratio:4 / 3;object-fit:cover;object-position:top center;
  border-radius:8px;border:1px solid var(--clay);background:var(--paper-2);
  transition:border-color var(--dur) var(--ease);}
/* The alternative text of the proof depends on what the link is, and the two
   pages using this card do not share a structure.
   On the Home the whole card is an <a>: everything inside it enters the accessible
   name, in document order. A descriptive alternative text there would put ninety
   characters describing the image BEFORE the chip and the title, and anyone
   tabbing the index would hear three times over where to look before learning
   where they are going. The image is redundant against the title and the outcome
   sitting beside it inside the same link, so alt="" and a clean accessible name.
   The same rule is already applied to the sign, which is aria-hidden, and to the
   portrait in the recall, which is alt="".
   On What I do the card is a <div> and the link is the title alone: the image sits
   outside the link, does not touch its name, and the alternative text goes back to
   being descriptive, because there it is the only way to know what it shows. The
   opposite holds for the figure on a case page, where the link IS the image and
   the alternative text is its name. */
/* The plate rides the corner: a fifth out to the left and a quarter down, so it
   bites the rule of the card instead of floating beside it. */
.c-card .c-sign{position:absolute;left:0;bottom:0;z-index:1;
/* The plate rises from 24 to 27 hundredths of the proof, with the ceiling from
   84 to 96 px and the floor from 60 to 68. It is the point where the sign reads as
   an object rather than as a postage stamp, and where it still occupies a little
   over a quarter of the proof: above thirty hundredths it would begin to compete
   with the image instead of marking it. The floor is there for narrow windows,
   where 27 per cent of a 256 px card would give 69 px and the sign would lose its
   own nodes. */
  width:clamp(68px,27%,96px);color:var(--paper);transform:translate(-22%,26%);}
.c-card .c-sign .sgn{width:74%;}
.c-card:hover .c-shot img,.c-card:focus-visible .c-shot img,
.c-card:has(.c-title a:hover) .c-shot img,
.c-card:has(.c-title a:focus-visible) .c-shot img{border-color:var(--plate);}

@media (prefers-reduced-motion: no-preference){
  /* The lift on the sign already existed: here it adds to the translation that
     holds it on the corner, otherwise the second would cancel the first. */
  .c-card:hover .c-sign,.c-card:focus-visible .c-sign,.c-card.seen .c-sign,
  .c-card:has(.c-title a:hover) .c-sign,
  .c-card:has(.c-title a:focus-visible) .c-sign{transform:translate(-20%,24%) translateY(-5px);}
}
@container (max-width: 560px){
  .c-card{grid-template-columns:1fr;row-gap:var(--s4);}
  .c-shot{order:1;}
  .c-txt{order:2;}
  .c-card .c-sign{width:84px;transform:translate(-13%,26%);}
}
@container (max-width: 560px){
  @media (prefers-reduced-motion: no-preference){
    .c-card:hover .c-sign,.c-card:focus-visible .c-sign,.c-card.seen .c-sign,
    .c-card:has(.c-title a:hover) .c-sign{transform:translate(-13%,26%) translateY(-5px);}
  }
}
@media print{
  .c-shot img{border-color:var(--clay) !important;}
}

/* ----------------------------------------------------------------------
   The watermark on the opening plate takes the space it occupies. At 18 per cent
   and 440 px it was a ghost inside an empty third of plate: visible enough to look
   like a printing error and not visible enough to be a sign. It grows, runs off
   the right edge and rises to 28 per cent, which on Rust and on Indigo stays below
   the title and above the threshold of the visible. Where the window is narrow the
   text passes over it, and there it draws back, because legibility comes before
   the sign.
   -------------------------------------------------------------------- */
.ph-mark{right:-9%;width:clamp(300px, 38vw, 560px);opacity:.28;}
@media (max-width:900px){
  .ph-mark{right:-14%;width:clamp(210px, 32vw, 330px);opacity:.14;}
}

/* ======================================================================
   FRAME 3.9 · THE DOSSIER MEASURE, PUT BACK IN PLACE
   ----------------------------------------------------------------------
   Five components of every case page carry the `dossier` class: the case header,
   the project metadata, the metric register, the contents list and the scan band.
   In the stylesheet that class appeared once, and only to cancel itself:

       @media (max-width:860px){ .dossier{width:100%;} }

   A cancellation with nothing to cancel. The width was never there, and the five
   components rendered to the 704 px reading column rather than to the 940 px span.
   The cost showed most on the metric register, which is the first element you read
   of a case: 704 less the 96 of breathing, less the 48 of channel, divided by two,
   less the 48 of the panel, left the satellites 79 px of text. Ten characters a
   line: «services / mapped / across / the City». That is not a typographic choice,
   it is a missing rule.
   The formula is not invented: it is the one from the surviving twin,
   `figure.f-feature`, which has always done the same thing. The dossier is worth
   at most 92vw, so it cannot overflow at any width.
   Below 860 px the rule already written in 3.7 returns, plus the restoration of
   the margin, which without the width served nobody and with the width does:
   cancelling the width alone would leave the negative margins to push the block
   off axis.
   ====================================================================== */
.dossier{width:var(--dossier);margin-inline:calc((100% - var(--dossier)) / 2);}
@media (max-width:860px){
  .dossier{width:100%;margin-inline:0;}
}

/* `100vw` counts the scrollbar as well, which `clientWidth` does not: on a long
   page the contents band would overrun by the width of the scrollbar and the
   window would scroll horizontally. `clip` prevents that. Not `hidden`, which
   would make the body a scroll container and unstick the header from the top of
   the window: `clip` simply clips, and the sticky position stays as it is.
   It is declared on `html` as well as on `body`, and that is the part that took a
   measurement to find. When the root element's overflow is `visible`, the used
   value is taken from the body and the body's own becomes `visible` in turn, so
   declaring it on the body alone left the three case pages scrolling by exactly
   the width of the scrollbar, seven pixels, at every window width. Declaring it
   on both ends the propagation and the clip applies where the bands are. */
html,body{overflow-x:clip;}

/* ======================================================================
   3.9 · THREE BREAKS AT THE SMALL SIZES
   ====================================================================== */

/* 1. A command never wraps.
   «Read the pieces» broke onto two lines at 320 px, and a button on two lines is
   not a button, it is a paragraph with a border round it. Forbidding the wrap on
   its own only moves the problem, because the command would then leave the card
   instead of breaking. The real cause sat in the card: 48 px of breathing a side on
   a card 256 wide left 160 to the content, and 116 to the text of the command.
   Where the window is narrow the lateral breathing drops to the previous step of
   the scale, and the text goes from 116 to 166 px against the roughly 110 it
   needs. */
.cta{white-space:nowrap;}
@media (max-width:480px){
  .cl-grid > .cl-card{padding:var(--s4) var(--s3) var(--s4);}
}

/* 2. A web address is a single word.
   `linkedin.com/in/federicorita` has no spaces, so its minimum width is the whole
   string: 255 px inside a column of 208. The column could not narrow and the text
   ended at 311 px on a page that closes at 288, inside the window by a hair and
   outside the margin everything else respects.
   `anywhere` rather than `break-word`: only `anywhere` enters the min-content
   calculation as well, which is exactly what needs unblocking here. `break-word`
   would have wrapped the text while leaving the column as wide as before. The
   break point stays a last resort: while the line fits, the address does not
   break. */
.co-reg .v,.sv-reg .v,.co-reg .v .q,.sv-reg .v .q{overflow-wrap:anywhere;}

/* 3. A table does not compress below its own content.
   The matrix on the system sheet measures 327 px, and at a 320 window it scrolled
   the whole page horizontally: reading a table cost you the axis of everything
   else. It becomes a block that scrolls on its own, so the axis of the page stays
   still and the table is leafed through where it sits.
   `-webkit-overflow-scrolling` is there for the versions of Safari that otherwise
   give the finger no momentum. */
@media (max-width:620px){
  .ss-block table.matrix{display:block;max-width:100%;overflow-x:auto;
    -webkit-overflow-scrolling:touch;}
}

/* The contents list now sits on a field tinted with the colour of the case, and
   the field is what carries that colour. The signs sitting on top of it can
   therefore stop carrying it, and that is a clear gain: the chapter number in Rust
   measured 5.23 on that field and the label in Stone 6.35, both below the AAA
   threshold of 7. In Ink they measure 15.10.
   Rust cannot reach AAA against any background, its theoretical maximum on pure
   white being 6.15, so while the number carried the colour of the case that
   threshold was unreachable by construction.
   The node beside the number keeps the colour of the case: it is a sign rather
   than text, so the threshold does not apply to it, and on its own it is enough to
   say which case this is. */
.contents .contents-label{color:var(--ink);}
.contents .contents-grid .c-n{color:var(--ink);}
