/* v7 pages: home (landing and project as two states of one stage) and the Willis eCOA case study,
   Figma A2KyiZUWE17TfXjvDe1X6Y "FINAL 1". Desktop from 988px (frames at 1728 x 1117), tablet 768-987
   (frames at 987), mobile to 767 (the Oct 27 proposal). Values come from v7-tokens.css. */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }

/* Page background: content/background with the frame's grain image multiplied over it, tiled from
   the top left. Fixed to the viewport so the fixed header, painted the same way, lines up with it. */
body {
  margin: 0;
  background-color: var(--content-background);
  color: var(--content-text-primary);
  font-family: var(--font-primary);
  font-weight: var(--font-weight);
}
body.is-home { --grain-size: var(--pending-landing-grain-size); }

p, h1, h2, h3, dl, dt, dd, ol, ul, figure, figcaption { margin: 0; padding: 0; }
h1, h2, h3 { font-size: inherit; font-weight: inherit; }  /* one weight of Söhne only: never bold */
a { color: inherit; text-decoration: none; }
img { display: block; }

/* Type (fibonacci/*) */
.t-small { font-size: var(--font-size-small); line-height: var(--line-height-small); letter-spacing: var(--tracking); }
.t-body { font-size: var(--font-size-body); line-height: var(--line-height-body); letter-spacing: var(--tracking); }
.t-heading { font-size: var(--font-size-heading); line-height: var(--line-height-heading); letter-spacing: var(--tracking); }
.t-display { font-size: var(--font-size-display); line-height: var(--line-height-display); letter-spacing: var(--tracking); }
.t-muted { color: var(--content-text-muted); }
.t-nums { font-feature-settings: "lnum" 1, "tnum" 1; }
.t-paras > p + p { margin-top: var(--paragraph-gap); }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* The frame grid: 13 columns on desktop */
.frame-grid {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  column-gap: var(--frame-grid-gutter);
  padding: var(--frame-margin);
}

/* Header (2689:41408): fixed, clear. Content passing under it blurs (main::before, a backdrop blur); the case
   study's images pass over it instead (Alex, Oct 30), so the grain never covers them. The blur smooths the page
   grain beneath it, so html::before lays the grain back over the header, masked as the blur is; the blur is
   brightened (dark mode: dimmed) by the tone that re-laid grain takes back, so neither leaves a band.
   Layers: page grain -1, case study text 2, blur 9, its grain 10, header 13, case study images 14, toggle 15. */
main::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 9;
  height: var(--header-h);
  background-color: color-mix(in srgb, var(--content-background) var(--head-ground-opacity), transparent);
  -webkit-backdrop-filter: blur(var(--head-ground-blur)) var(--head-blur-comp);
  backdrop-filter: blur(var(--head-ground-blur)) var(--head-blur-comp);
  pointer-events: none;
}
/* The page grain: a fixed layer under the content, so it never covers the images (Alex, Oct 30), jumping
   between eight offsets as faint living film static (the old site's, Oct 22; returned Oct 30). Near the cursor
   a second layer, masked to a circle around it, runs the static faster and stronger while the cursor moves
   (v7.js sets --mx, --my and --disturb). Still under reduced motion. */
body::after, body::before, html::after, html::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  opacity: var(--grain-opacity);
  background-image: var(--grain-page);
  background-size: var(--grain-page-size) var(--grain-page-size);
  mix-blend-mode: var(--grain-page-blend);
  pointer-events: none;
  animation: var(--static-animation);
}
/* The cursor repels the static (Alex, Oct 30): around a moving cursor the page grain clears (a hole in body::after's
   mask, as deep as --disturb), and html::after lays the same grain, enlarged about the cursor, in a ring just
   beyond, so it reads as pushed outward. Once the cursor stops the grain is drawn back in past where it was:
   body::before lays it shrunk about the cursor, inside --static-disturb-r, and the page grain thins just beyond
   (as deep as --gather). --disturb follows the cursor's speed and eases back to 0; --gather rises once it is
   still (v7.js). */
@property --disturb { syntax: "<number>"; inherits: true; initial-value: 0; }
@property --gather { syntax: "<number>"; inherits: true; initial-value: 0; }
:root { transition: --disturb var(--static-repel-settle) ease-out, --gather var(--static-gather-in) ease-in-out; }
:root.is-repelling { transition: --disturb 0.12s ease-out, --gather 0.12s ease-out; }  /* quick to clear, slow to settle back */
/* Under the header the page grain stops where the blur ends, and html::before lays the same grain over the blur
   above that line: the blur never sees the moving grain, even faintly (blurred, it drifted as blotches across
   the header; Alex, Oct 30). Below the blur's foot the two hand over across --grain-handoff, so no edge shows
   between them (a hard switch read as a line); html::before's fade is weighted so the two together keep the
   grain's strength at --grain-opacity 0.6 (m2 = (1 - m1) / (1 - 0.6 m1)). The repel ring stops there too.
   --gr-edge follows the blur as the header hides. */
:root {
  --gr-edge: calc(var(--header-h) + var(--head-soft-h));
  --gr-hole: linear-gradient(to bottom, transparent var(--gr-edge), rgb(0 0 0 / 0.25) calc(var(--gr-edge) + var(--grain-handoff) * 0.25), rgb(0 0 0 / 0.5) calc(var(--gr-edge) + var(--grain-handoff) * 0.5), rgb(0 0 0 / 0.75) calc(var(--gr-edge) + var(--grain-handoff) * 0.75), #000 calc(var(--gr-edge) + var(--grain-handoff)));
}
:root.is-head-hidden { --gr-edge: calc(-1 * var(--grain-handoff)); }
/* The landing, pinned, never passes anything under its header: no blur there and no grain of the header's own,
   just the page grain, unbroken (on some screens the blurred ground and its grain read as a band; Alex, Oct 30) */
:root:has(.home[data-mode="pinned"]) { --gr-edge: calc(-1 * var(--grain-handoff)); }
:root:has(.home[data-mode="pinned"])::before, .home[data-mode="pinned"]::before { display: none; }
:root[data-layout="split"].is-head-hidden { --gr-edge: calc(var(--modes-band) + var(--head-blur-ramp)); }
body::after {
  -webkit-mask-image: radial-gradient(circle var(--static-disturb-r) at var(--mx, -999px) var(--my, -999px), rgb(0 0 0 / calc(1 - var(--disturb))) 50%, rgb(0 0 0 / calc(1 - 0.6 * var(--gather))) 80%, #000 100%), var(--gr-hole);
  mask-image: radial-gradient(circle var(--static-disturb-r) at var(--mx, -999px) var(--my, -999px), rgb(0 0 0 / calc(1 - var(--disturb))) 50%, rgb(0 0 0 / calc(1 - 0.6 * var(--gather))) 80%, #000 100%), var(--gr-hole);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
html::after {
  opacity: calc(var(--disturb) * var(--grain-opacity));
  background-size: calc(var(--grain-page-size) * var(--static-repel-scale)) calc(var(--grain-page-size) * var(--static-repel-scale));
  background-position: calc(var(--mx, 0px) * (1 - var(--static-repel-scale))) calc(var(--my, 0px) * (1 - var(--static-repel-scale)));
  -webkit-mask-image: radial-gradient(circle var(--static-disturb-r) at var(--mx, -999px) var(--my, -999px), transparent 45%, #000 80%, transparent 100%), var(--gr-hole);
  mask-image: radial-gradient(circle var(--static-disturb-r) at var(--mx, -999px) var(--my, -999px), transparent 45%, #000 80%, transparent 100%), var(--gr-hole);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
  animation: none;
}
body::before {
  opacity: calc(var(--gather) * var(--grain-opacity));
  background-size: calc(var(--grain-page-size) * var(--static-gather-scale)) calc(var(--grain-page-size) * var(--static-gather-scale));
  background-position: calc(var(--mx, 0px) * (1 - var(--static-gather-scale))) calc(var(--my, 0px) * (1 - var(--static-gather-scale)));
  -webkit-mask-image: radial-gradient(circle var(--static-disturb-r) at var(--mx, -999px) var(--my, -999px), #000 40%, transparent 100%), var(--gr-hole);
  mask-image: radial-gradient(circle var(--static-disturb-r) at var(--mx, -999px) var(--my, -999px), #000 40%, transparent 100%), var(--gr-hole);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
  animation: none;
}
html::before {
  z-index: 10;
  bottom: auto;
  height: calc(var(--header-h) + var(--head-soft-h) + var(--grain-handoff));  /* past the blur's foot, handing over to the page grain */
  --foot: calc(var(--header-h) + var(--head-soft-h));
  -webkit-mask-image: linear-gradient(to bottom, #000 var(--foot), rgb(0 0 0 / 0.882) calc(var(--foot) + var(--grain-handoff) * 0.25), rgb(0 0 0 / 0.714) calc(var(--foot) + var(--grain-handoff) * 0.5), rgb(0 0 0 / 0.455) calc(var(--foot) + var(--grain-handoff) * 0.75), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 var(--foot), rgb(0 0 0 / 0.882) calc(var(--foot) + var(--grain-handoff) * 0.25), rgb(0 0 0 / 0.714) calc(var(--foot) + var(--grain-handoff) * 0.5), rgb(0 0 0 / 0.455) calc(var(--foot) + var(--grain-handoff) * 0.75), transparent 100%);
  transition: transform var(--head-slide-duration) var(--head-slide-ease), visibility 0s;
}
:root.is-head-hidden::before { transform: translateY(-100%); visibility: hidden; transition: transform var(--head-slide-duration) var(--head-slide-ease), visibility 0s var(--head-slide-duration); }
:root[data-layout="split"].is-head-hidden::before { transform: translateY(calc(var(--modes-band) - (var(--header-h) + var(--head-soft-h) - var(--head-blur-ramp)))); visibility: visible; transition: transform var(--head-slide-duration) var(--head-slide-ease); }
/* while the page scrolls, the static holds still (v7.js) */
:root.is-scrolling body::after, :root.is-scrolling::before, :root.is-scrolling::after { animation-play-state: paused; }
@keyframes static {  /* eight offsets, held 0.3s each (Alex, Oct 30: back from the drift, which read as snowfall) */
  0% { background-position: 0 0; }
  12.5% { background-position: -97px 61px; }
  25% { background-position: 43px -128px; }
  37.5% { background-position: -151px -37px; }
  50% { background-position: 118px 89px; }
  62.5% { background-position: -29px 167px; }
  75% { background-position: 76px -71px; }
  87.5% { background-position: -188px 113px; }
}
/* Under the header, a soft edge, at every size (Alex, Oct 30): the blur carries on past the header's foot and
   tapers to nothing over --head-soft-h, so content passing beneath softens into focus with no line at its
   edge. */
main::before {
  /* it runs --head-blur-bleed past the screen's top and sides, so the blur's own edges are off screen (at an
     edge a blur pulls in nothing, which tints a band along it) */
  top: calc(-1 * var(--head-blur-bleed));
  left: calc(-1 * var(--head-blur-bleed));
  right: calc(-1 * var(--head-blur-bleed));
  height: calc(var(--head-blur-bleed) + var(--header-h) + var(--head-soft-h));
  /* the blur eases out over --head-blur-ramp, ending where the content starts */
  --ramp-0: calc(var(--head-blur-bleed) + var(--header-h) + var(--head-soft-h) - var(--head-blur-ramp));
  -webkit-mask-image: linear-gradient(to bottom, #000 var(--ramp-0), rgb(0 0 0 / 0.82) calc(var(--ramp-0) + var(--head-blur-ramp) * 0.25), rgb(0 0 0 / 0.5) calc(var(--ramp-0) + var(--head-blur-ramp) * 0.5), rgb(0 0 0 / 0.18) calc(var(--ramp-0) + var(--head-blur-ramp) * 0.75), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 var(--ramp-0), rgb(0 0 0 / 0.82) calc(var(--ramp-0) + var(--head-blur-ramp) * 0.25), rgb(0 0 0 / 0.5) calc(var(--ramp-0) + var(--head-blur-ramp) * 0.5), rgb(0 0 0 / 0.18) calc(var(--ramp-0) + var(--head-blur-ramp) * 0.75), transparent 100%);
}
.site-head {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 13;
  height: var(--header-h);
  align-items: start;
  pointer-events: none;  /* only its links take clicks: the text fading below it stays selectable */
  view-transition-name: site-head;
}
.site-head a { pointer-events: auto; }
/* The header's text blends with what's beneath it: ink and muted over the page, light over a dark image */
.site-head { --content-text-primary: var(--head-blend-text); --content-text-muted: var(--head-blend-muted); color: var(--content-text-primary); mix-blend-mode: var(--head-blend-mode); }
/* Case study: the header and its ground slide away on the way down and back on any scroll up (v7.js;
   Alex, Oct 30; specs §3b). Hidden, they're also out of the tab order once the slide ends. */
.site-head, main::before { transition: transform var(--head-slide-duration) var(--head-slide-ease), visibility 0s; }
:root.is-head-hidden .site-head,
:root.is-head-hidden main::before {
  transform: translateY(calc(-100% - var(--head-blur-bleed)));
  visibility: hidden;
  transition: transform var(--head-slide-duration) var(--head-slide-ease), visibility 0s var(--head-slide-duration);
}
.site-logo { grid-column: 1; white-space: nowrap; }
.site-nav { grid-column: 3; display: flex; flex-direction: column; align-items: flex-start; white-space: nowrap; }
.site-nav-link { color: var(--content-text-muted); }
.site-nav-link.is-current { color: var(--content-text-primary); }
.site-nav-arrow { display: inline-block; width: var(--nav-arrow-w); margin-right: var(--frame-column-gap); white-space: nowrap; }
.site-where { grid-column: 6; display: flex; flex-direction: column; align-items: flex-start; white-space: nowrap; }
.site-contact { grid-column: 12 / span 2; display: flex; flex-direction: column; align-items: flex-end; white-space: nowrap; }
.site-contact-link.is-muted { color: var(--content-text-muted); }
.site-foot { display: none; }
.page-main { padding-top: var(--header-h); }

/* Mockup panel and device (the "mockup" component) */
.panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--panel-pad);
  background-color: var(--content-surface);
  background-image: var(--grain-panel);
  background-size: var(--grain-size) var(--grain-size);
  background-position: 0 0;
  background-blend-mode: var(--grain-blend);
}
.device {
  display: block;
  position: relative;
  flex-shrink: 0;
  width: 100%;
  aspect-ratio: var(--device-ratio);
  border: 1px solid var(--device-border);
  border-radius: var(--device-radius);
  box-shadow: var(--device-shadow);
}
.device-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;  /* two screens are 1438 wide: contained, they left a dark sliver inside the stroke (cover trims a pixel) */
  border-radius: var(--device-radius);
}
.device.is-tablet { --device-ratio: var(--device-ratio-tablet); border-radius: var(--device-radius-tablet); }
.device.is-tablet .device-img { border-radius: var(--device-radius-tablet); }
.device.is-recording::before {  /* the screen's recording ring */
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  box-shadow: inset 0 0 0 max(2px, 0.22%) var(--device-recording);
  pointer-events: none;
}
.device::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  box-shadow: var(--device-inset);
  pointer-events: none;
}

/* Home stage: About (the landing) and Projects (the project) are two states of one frame. Pinned
   (v7.js sets data-mode), the frame sticks and each state takes a screen of scroll, snapping to it;
   one more screen goes into the case study. Stacked, the states follow each other on the page. */
.home-frame { padding-top: var(--header-h); }
.home[data-mode="pinned"] { position: relative; height: calc((var(--stops) + var(--state-lead)) * 100vh); }
.home[data-mode="pinned"] .home-frame { position: sticky; top: 0; display: grid; height: 100vh; }
.home[data-mode="pinned"] .home-state { grid-area: 1 / 1; height: calc(100vh - var(--header-h)); }
.home-state { scroll-margin-top: var(--header-h); }  /* stacked, #about and #projects land below the header, not under it (Alex, Oct 30) */
.home[data-mode="pinned"] .home-state:not(.is-shown) { visibility: hidden; }
:root:has(.home[data-mode="pinned"]) { scrollbar-width: none; }  /* no scroll snapping: v7.js eases to the nearest state when the scroll stops */
:root:has(.home[data-mode="pinned"])::-webkit-scrollbar { display: none; }
.home-mark { position: absolute; left: 0; top: calc(var(--i) * 100vh); width: 1px; height: 100vh; pointer-events: none; }
.home-next { display: block; height: var(--home-next-run); }

/* Landing state (2689:40699): the hero and the lists, no gap between them. Pinned, the hero takes the
   screen above the lists (690px at the design size), so its 13 rows follow the screen like the project's. */
.home-state.is-about { display: flex; flex-direction: column; }
.l-hero {
  height: var(--landing-hero-h);
  flex: none;
  grid-template-rows: repeat(13, minmax(0, 1fr));
  row-gap: var(--frame-grid-gutter);
  overflow: clip;
}
.home[data-mode="pinned"] .l-hero { height: auto; flex: 1 1 0; min-height: 0; }
.l-headline { grid-column: 1 / span 3; grid-row: 1 / span 3; align-self: start; }
.l-portrait { position: relative; grid-column: 9 / span 4; grid-row: 1 / span 13; }
.l-portrait-img { width: 100%; height: 100%; object-fit: cover; mix-blend-mode: var(--portrait-blend); }
/* The page's static runs over the portrait too, in register with the page's, and the cursor disturbs it the same
   way (Alex, Oct 30): ::after is the page grain with its repel hole, .l-portrait-static's ::before the repelled
   ring and its ::after the gathered grain, all centred on the cursor's place within the portrait (--px, --py
   are the portrait's place on screen; v7.js). */
.l-portrait::after, .l-portrait-static::before, .l-portrait-static::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--grain-page);
  background-size: var(--grain-page-size) var(--grain-page-size);
  mix-blend-mode: var(--grain-page-blend);
  opacity: var(--grain-opacity);
  pointer-events: none;
  --cx: calc(var(--mx, -999px) - var(--px, 0px));
  --cy: calc(var(--my, -999px) - var(--py, 0px));
}
.l-portrait::after {
  animation: var(--static-animation);
  -webkit-mask-image: radial-gradient(circle var(--static-disturb-r) at var(--cx) var(--cy), rgb(0 0 0 / calc(1 - var(--disturb))) 50%, rgb(0 0 0 / calc(1 - 0.6 * var(--gather))) 80%, #000 100%);
  mask-image: radial-gradient(circle var(--static-disturb-r) at var(--cx) var(--cy), rgb(0 0 0 / calc(1 - var(--disturb))) 50%, rgb(0 0 0 / calc(1 - 0.6 * var(--gather))) 80%, #000 100%);
}
:root.is-scrolling .l-portrait::after { animation-play-state: paused; }
.l-portrait-static { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.l-portrait-static::before {
  opacity: calc(var(--disturb) * var(--grain-opacity));
  background-size: calc(var(--grain-page-size) * var(--static-repel-scale)) calc(var(--grain-page-size) * var(--static-repel-scale));
  background-position: calc(var(--cx) * (1 - var(--static-repel-scale))) calc(var(--cy) * (1 - var(--static-repel-scale)));
  -webkit-mask-image: radial-gradient(circle var(--static-disturb-r) at var(--cx) var(--cy), transparent 45%, #000 80%, transparent 100%);
  mask-image: radial-gradient(circle var(--static-disturb-r) at var(--cx) var(--cy), transparent 45%, #000 80%, transparent 100%);
}
.l-portrait-static::after {
  opacity: calc(var(--gather) * var(--grain-opacity));
  background-size: calc(var(--grain-page-size) * var(--static-gather-scale)) calc(var(--grain-page-size) * var(--static-gather-scale));
  background-position: calc(var(--cx) * (1 - var(--static-gather-scale))) calc(var(--cy) * (1 - var(--static-gather-scale)));
  -webkit-mask-image: radial-gradient(circle var(--static-disturb-r) at var(--cx) var(--cy), #000 40%, transparent 100%);
  mask-image: radial-gradient(circle var(--static-disturb-r) at var(--cx) var(--cy), #000 40%, transparent 100%);
}
.l-intro { grid-column: 3 / span 3; grid-row: 9 / span 3; align-self: start; }
.l-lists {
  height: var(--landing-lists-h);
  flex: none;
  grid-template-rows: minmax(0, 1fr);
  row-gap: var(--landing-lists-row-gap);
  overflow: clip;
}
.l-list {
  display: flex;
  flex-direction: column;
  gap: var(--pending-landing-list-gap);
  width: var(--landing-list-w);
  align-self: start;
  justify-self: start;
}
.l-list.is-disciplines { grid-column: 1 / span 2; }
.l-list.is-industries { grid-column: 3 / span 2; }
.l-list.is-other { grid-column: 5 / span 2; }
.l-list-label { color: var(--content-text-muted); }
.l-list-label.is-tall { height: var(--pending-landing-label-h); }
.l-list-items { display: flex; flex-direction: column; list-style: none; }
.l-list-item { height: var(--pending-landing-list-row-h); }
.l-list-item.is-line { height: auto; }  /* "Design systems": the file leaves its height at the line */

/* Project state (2689:41465): one 13 x 13 section the height of the screen below the header */
.p-section {
  height: calc(100vh - var(--header-h));
  grid-template-rows: repeat(13, minmax(0, 1fr));
  row-gap: var(--frame-grid-gutter);
  overflow: clip;
}
.kicker { display: flex; flex-direction: column; align-items: flex-start; gap: var(--frame-column-gap); white-space: normal; min-width: 0; }  /* wraps in its column (Alex, Oct 28) */
.p-kicker { grid-column: 1; grid-row: 3; align-self: start; }
.p-willis { grid-column: 2; grid-row: 3; align-self: start; justify-self: start; white-space: nowrap; }
.p-ecoa { grid-column: 3 / span 2; grid-row: 4; align-self: start; justify-self: start; white-space: nowrap; }
.p-content, .p-about-group, .p-facts-group { display: contents; }  /* groups only on tablet */
.p-about-label { grid-column: 1; grid-row: 6; }
.p-about { grid-column: 2 / span 3; grid-row: 6 / span 3; align-self: start; }
.facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--frame-column-gap) var(--frame-grid-gutter);
  align-self: start;
}
.facts-label { color: var(--content-text-muted); }
.facts-list { display: flex; flex-direction: column; }
.facts-extra { display: none; }  /* Disciplines and Regulations: on the project only on tablet */
.p-facts { grid-row: 9; }
.p-facts.is-a { grid-column: 1 / span 2; }
.p-facts.is-b { grid-column: 3 / span 2; }
.p-view { grid-column: 2; grid-row: 11; width: 131px; }
.p-image {
  grid-column: 6 / span 8;
  grid-row: 1 / span 13;
  display: flex;
  align-items: center;
  overflow: clip;
}
.panel.is-project { flex: 1 0 0; min-width: 1px; height: var(--project-panel-h); padding: var(--pending-project-panel-pad); }

/* Case study (2690:41610): chapters on the 13-column grid */
.cs-chapter { align-items: start; row-gap: 10px; scroll-margin-top: var(--header-h); }
.cs-content { grid-column: 1 / span var(--cs-text-cols); display: flex; flex-direction: column; gap: var(--frame-grid-gutter); }
/* Split (desktop): a regular scrolling page (Alex, Oct 29). Each chapter's text, cols 1-4 (1-5 narrower than
   1440), sticks below the header while its images scroll past in the columns after, over the header; then it
   scrolls away with its chapter. The sticky column is the screen's height, its notes at the foot. Text too
   tall for the screen (data-flow, v7.js) scrolls until its foot reaches the screen's, then sticks there. A staged figure's panel (Jun's growth map) sticks
   while the scroll runs through its stages. */
:root[data-layout="split"] .cs-content {
  position: sticky;
  top: var(--content-top);
  z-index: 2;  /* under the header's blurred ground, as on phones (Alex, Oct 30) */
  min-height: calc(100vh - var(--content-top) - var(--frame-margin));
}
:root[data-layout="split"] .cs-content[data-flow] { min-height: 0; }  /* sticks once its foot reaches the screen's (v7.js sets its top) */
:root[data-layout="split"] .cs-group.is-notes { margin-top: auto; }
:root[data-layout="split"] .cs-images {
  position: relative;
  z-index: 14;  /* panels scroll over the header (Alex, Oct 28; again Oct 30), so the grain never covers them */
  padding-bottom: 0;
}
:root[data-layout="split"] .cs-chapter + .cs-chapter { margin-top: var(--frame-grid-gutter); }
/* Stacked (tablet, phone): text and images fading out over the header are lifted over its ground, under its
   name and links (v7.js adds the class) */
.cs-fade { position: relative; z-index: 12; }
:root[data-layout="split"] .panel[data-stages] { position: sticky; top: var(--content-top); }
:root[data-layout="split"] .panel.is-room { height: var(--cs-room); min-height: 0; overflow: clip; }
.cs-group {
  display: grid;
  grid-template-columns: repeat(var(--cs-text-cols), minmax(0, 1fr));
  gap: var(--frame-grid-gutter);
}
/* The label and heading block is 144 tall whatever the heading's lines; the body starts right below it.
   Chapter 01's title block has 144 below it (55 narrower than the 1440 frame), and 42 between About and the facts. */
.cs-group.is-head { height: var(--cs-title-h); align-content: start; margin-bottom: calc(-1 * var(--frame-grid-gutter)); }
.cs-group.is-title { grid-template-rows: repeat(2, fit-content(100%)); white-space: nowrap; height: var(--cs-title-h); margin-bottom: calc(var(--cs-title-after) - var(--frame-grid-gutter)); }
.cs-group.is-facts { margin-top: var(--frame-grid-gutter); }
.cs-kicker { grid-column: 1; grid-row: 1; align-self: start; }
.cs-willis { grid-column: 2; grid-row: 1; align-self: start; justify-self: start; }
.cs-ecoa { grid-column: 3 / span 2; grid-row: 2; align-self: start; justify-self: start; }
.cs-label { grid-column: 1; align-self: start; color: var(--content-text-muted); }
.cs-about, .cs-text { grid-column: 2 / -1; align-self: start; }
.cs-heading { grid-column: 2 / -1; align-self: start; }
.cs-group.is-head > .cs-label, .cs-group.is-head > .cs-heading { align-self: baseline; }  /* the date sits on the title's first baseline (Alex, Oct 29) */
.cs-link { text-decoration-line: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
.cs-sources { display: flex; flex-direction: column; gap: var(--frame-column-gap); list-style: none; }
/* Footnotes: markers at 8px in the text. The notes: a hairline, then each note's number and term in the
   two halves of col 1 (the number at full size, set superscript), its text in cols 2-4. */
.cs-ref { font-size: var(--note-marker-size); line-height: 0; vertical-align: super; color: var(--content-text-muted); }
.cs-ref a:focus-visible { outline: 1px solid var(--content-text-primary); outline-offset: 1px; }
.cs-group.is-notes { color: var(--content-text-muted); }
.cs-notes {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  row-gap: var(--frame-grid-gutter);
  padding-top: var(--cs-note-pad);
  border-top: var(--cs-note-rule);
  list-style: none;
}
.cs-note { display: contents; }
.cs-note-term { grid-column: 1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
.cs-note-term > :last-child { grid-column: 2; }
.cs-note-mark { font-variant-position: super; }
.cs-note-text { grid-column: 2 / -1; }
/* An image in the text column (Dec II's slider): it fades in and out with its chapter, no blur */
.cs-inline { width: 100%; aspect-ratio: var(--cs-slider-ratio); }
.cs-inline .shot, .cs-inline .shot-img { width: 100%; height: 100%; object-fit: contain; }
.cs-facts { grid-column: span 2; grid-template-rows: repeat(3, fit-content(100%)); }
.cs-images {
  grid-column: calc(var(--cs-text-cols) + 2) / -2;  /* a column clear of the text, to column 12 (13 is the minimap's) */
  display: flex;
  flex-direction: column;
  gap: var(--frame-grid-gutter);
  padding-bottom: var(--chapter-end);
}
/* The chapters' panels: 21px in (spacing/6). A chapter's main panel is as tall as the room below the
   header; the picture or diagram fits inside it (is-fit pictures by object-fit, HTML diagrams scaled by
   v7.js). Dec's participant table is cropped. */
.cs-chapter:not(.is-first) .panel { padding: var(--cs-panel-pad); }
.panel.is-room { min-height: var(--cs-room); }
.panel.is-fit { height: var(--cs-room); }
.panel.is-diagram { align-items: stretch; }
.panel.is-bleed { padding-left: 0; }  /* a picture cropped at its left edge (Dec II's table) meets the panel's edge */
.panel.is-crop { height: var(--cs-crop-h); justify-content: flex-start; overflow: clip; }
.shot { display: block; width: 100%; }
.shot-img { width: 100%; height: auto; }
.shot.is-fit { flex: 1 1 0; min-height: 0; }
.shot.is-fit .shot-img { height: 100%; object-fit: contain; }
.cs-progress { display: none; }
/* TL;DR / weeds toggle (Figma 2804:20676, 2690:41610): a pill of two buttons, the chosen one filled.
   Desktop: in the header band under the name. Stacked (tablet, phones): floating at the screen's foot.
   Its rounded pill, glass blur and shadow are from the frames (Alex, Oct 30). The TL;DR hides [data-weeds]. */
.cs-modes {
  position: fixed;
  z-index: 15;
  display: flex;
  padding: var(--modes-pad);
  border-radius: 999px;
  background-color: var(--modes-fill);
  -webkit-backdrop-filter: blur(var(--modes-blur));
  backdrop-filter: blur(var(--modes-blur));
  box-shadow: var(--modes-shadow);
  left: var(--modes-left, 50%);  /* v7.js places it on the grid (and sizes it to whole columns) */
  bottom: var(--modes-bottom);
}
:root[data-layout="split"] .cs-modes { top: var(--modes-top); bottom: auto; transform: none; background-color: var(--modes-fill-desktop); }
/* Desktop (Figma 2811:20926): text, as the header's nav: "Read mode" in column 1, the two choices stacked in
   column 2, the chosen one in ink, the other muted. Stacked (tablet, phones): the pill at the screen's foot. */
.cs-modes-label { display: none; }
:root[data-layout="split"] .cs-modes {
  display: grid;
  grid-template-columns: var(--modes-col, auto) auto;
  column-gap: var(--modes-gap, var(--frame-grid-gutter));
  align-items: start;
  padding: 0;
  border-radius: 0;
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow: none;
}
:root[data-layout="split"] .cs-modes::before { display: none; }
:root[data-layout="split"] .cs-modes-label { display: block; grid-column: 1; grid-row: 1 / span 2; color: var(--content-text-primary); }
:root[data-layout="split"] .cs-mode { grid-column: 2; flex: none; padding: 0; border-radius: 0; text-align: left; color: var(--content-text-muted); }
:root[data-layout="split"] .cs-mode[aria-pressed="true"] { color: var(--content-text-primary); }
:root[data-layout="split"] .cs-mode:hover { color: var(--content-text-primary); }
/* with the header slid away, the toggle moves up to the top of the screen, clear of the text (Alex, Oct 30) */
:root[data-layout="split"] .cs-modes { transition: transform var(--head-slide-duration) var(--head-slide-ease); }
:root[data-layout="split"].is-head-hidden .cs-modes { transform: translateY(calc(var(--frame-margin) - var(--modes-top))); }
/* ... and the header's blurred ground slides only partway, staying behind Read mode so it reads clear over the
   content (Alex, Oct 30) */
:root[data-layout="split"].is-head-hidden main::before {
  transform: translateY(calc(var(--modes-band) - (var(--header-h) + var(--head-soft-h) - var(--head-blur-ramp))));  /* solid to Read mode's foot, then the ramp */
  visibility: visible;
  transition: transform var(--head-slide-duration) var(--head-slide-ease);
}
.cs-modes { animation: modes-in var(--motion-duration) var(--motion-ease) var(--modes-in-delay) both; }
@keyframes modes-in { from { opacity: 0; scale: var(--modes-in-scale); filter: blur(var(--motion-exit-blur)); } }
/* the dark selection is one shape that slides between the two (v7.js sets its place and width) */
.cs-modes::before {
  content: "";
  position: absolute;
  top: 1px;
  bottom: 1px;
  left: var(--mode-x, 2px);
  width: var(--mode-w, 0);
  border-radius: 999px;
  background-color: var(--mode-on-fill);
  transition: left var(--mode-slide) var(--motion-ease), width var(--mode-slide) var(--motion-ease);
}
.cs-modes:not(.is-measured)::before { transition: none; }
.cs-mode { position: relative; flex: 1 1 0; text-align: center; padding: var(--mode-pad); border: 0; border-radius: 999px; background: none; color: var(--content-text-primary); font-family: inherit; cursor: pointer; white-space: nowrap; transition: color var(--mode-slide) var(--motion-ease); }
.cs-mode[aria-pressed="true"] { color: var(--mode-on-text); }
.cs-mode:focus-visible { outline: 1px solid var(--content-text-primary); outline-offset: 2px; }
:root[data-mode="tldr"] [data-weeds] { display: none !important; }

/* ---------- Diagrams ----------
   perm and paper: the FINAL 1 styling (work/brooklyn-health/reference/final1/). Söhne 13/18, ink and muted,
   hairlines; a dot for full access, a dash for none, words for partial; paper's At site, arrow and In Willis
   sit on the matrix's columns. */
.dg { width: 100%; min-width: 0; }
.dg-grid { display: grid; grid-template-columns: var(--diagram-columns); column-gap: var(--frame-grid-gutter); align-items: start; }
.dg-head { color: var(--content-text-muted); padding-bottom: var(--diagram-row-pad); border-bottom: 1px solid var(--diagram-rule); }
.dg-head .dg-to, .dg-prow .dg-to { grid-column: 3 / -1; }
.dg-group { margin-top: var(--group-gap); }
.dg-ghead { margin-bottom: var(--frame-grid-gutter); }
.dg-gnote { grid-column: 2 / -1; color: var(--content-text-muted); }
.dg-row { padding: var(--diagram-row-pad) 0; }
.dg-row + .dg-row, .dg-prow + .dg-prow { border-top: 1px solid var(--diagram-rule-faint); }
/* The matrix on phones (below --diagram-min-w, 640px; v7-matrix-phones-brief.md): one block per role, in
   words, instead of the grid scrolling sideways. Hidden from 640px, where the grid shows. */
.pm { display: none; }
.pm-group + .pm-group { margin-top: var(--pm-group-gap); }
.pm-gnote { color: var(--content-text-muted); padding-bottom: var(--diagram-row-pad); border-bottom: 1px solid var(--diagram-rule); }
.pm-role { padding: var(--diagram-row-pad) 0; }
.pm-role + .pm-role { border-top: 1px solid var(--diagram-rule-faint); }
.pm-pri { color: var(--content-text-muted); }
.pm-access { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); column-gap: var(--diagram-row-pad); row-gap: var(--pm-row-gap); margin: var(--frame-column-gap) 0 0; }
.pm-access dt { color: var(--content-text-muted); }
.pm-access dd { margin: 0; }
.pm-access dd.is-none { color: var(--content-text-muted); }
@media (max-width: 639px) {
  .dg.perm > .dg-table, .dg.perm > .dg-key { display: none; }
  .pm { display: block; }
}
.dg-who { display: flex; flex-direction: column; padding-right: var(--diagram-key-gap); }
.dg-pri { color: var(--content-text-muted); }
.dg-none { color: var(--diagram-none); }
.dg-dot {
  display: inline-block;
  width: var(--diagram-dot);
  height: var(--diagram-dot);
  border-radius: 50%;
  background-color: var(--content-text-primary);
  vertical-align: var(--diagram-dot-lift);
}
.dg-key { display: flex; flex-wrap: wrap; gap: var(--diagram-key-gap); margin-top: var(--group-gap); color: var(--content-text-muted); }
.dg-key > span { display: inline-flex; gap: var(--frame-column-gap); align-items: baseline; }
.dg-prows { list-style: none; }
.dg-prow { padding: var(--diagram-row-pad-paper) 0; }
.dg-from { padding-right: var(--diagram-key-gap); }
.dg-via { grid-column: 2; }
.dg-arrow { display: inline-block; color: var(--content-text-muted); }
/* each row's At site and In Willis: read aloud, shown only when the rows stack (the column heads say it wide) */
.dg-where { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; color: var(--content-text-muted); }

/* tree, flows and growth: the repo's diagrams (scripts/build_diagrams.py), laid out for 16px Söhne and
   fitted to their panel (the flows by v7.js, the maps by their viewBox). TODO(designer): their FINAL 1 styling. */
.dg.tree, .dg.flow, .dg.growth { font-size: var(--diagram-text-size); line-height: var(--diagram-line-height); letter-spacing: var(--tracking); }
.panel.is-fit .dg { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; justify-content: center; }
.dg-fit { flex: 1 1 0; min-height: 0; width: 100%; }
.dg-fit > svg { display: block; width: 100%; height: 100%; overflow: visible; }
.tree-tall, .flow-compact, .growth-tall { display: none; }
/* The maps' vertical form, when the page stacks (v7-vertical-maps-brief.md, Oct 30): the whole tree top to
   bottom, nothing collapsed. Chips with the wide map's box styling; children indent on a spine with an elbow
   into each, styled as the wide map's edge into that child; a run of sibling leaves shares a wrapping row.
   Rows draw in as they're read (v7.js). */
.vt { font-size: var(--vt-text-size); line-height: var(--vt-line-height); letter-spacing: var(--tracking); }
.vt ul { margin: 0; padding: 0; list-style: none; }
.vt .vt-key { display: flex; flex-direction: column; gap: var(--vt-gap); margin-bottom: var(--diagram-key-gap); color: var(--content-text-muted); }
.vt-key-item { display: flex; align-items: center; gap: var(--vt-gap); }
.vt-key-item .vt-chip { width: var(--vt-key-chip-w); padding: 0; }
.vt-chip { display: inline-flex; align-items: center; flex: none; max-width: 100%; min-height: var(--vt-chip-h); padding: var(--vt-chip-pad); background-color: var(--diagram-cell); border: 1px solid var(--diagram-rule); color: var(--content-text-primary); }
.vt-chip.st-m { border-color: var(--content-text-primary); border-style: dashed; }
.vt-chip.st-p { border-color: var(--diagram-ink-soft); border-style: dotted; color: var(--content-text-muted); }
.vt-chip.st-d { border-color: var(--diagram-cut); border-style: dashed; color: var(--diagram-cut); text-decoration-line: line-through; }
.vt-key-item .vt-chip.st-d { text-decoration-line: none; }
.vt-chip.is-root { background-color: var(--content-text-primary); border-color: var(--content-text-primary); color: var(--content-background); }
.vt-chip.is-new { background-color: var(--diagram-new-fill); border: var(--diagram-new-stroke-w) solid var(--diagram-new-stroke); }
.vt-row { display: flex; flex-wrap: wrap; align-items: center; column-gap: var(--vt-gap); row-gap: 2px; }
.vt-tag, .vt-also { color: var(--content-text-muted); }
.vt-tag.is-cut { color: var(--diagram-cut); }
.vt-when { color: var(--diagram-new-stroke); }
.vt-also { flex-basis: 100%; }  /* a cross-link takes the full width under its chip */
.vt-entries { display: flex; flex-wrap: wrap; gap: var(--vt-gap); padding-bottom: var(--vt-gap); }
.vt-entries + .vt-list > .vt-item.is-root { position: relative; }
.vt-entries + .vt-list > .vt-item.is-root::before {  /* the entries join the root */
  content: ""; position: absolute; left: var(--vt-spine); top: calc(var(--vt-gap) * -1); height: var(--vt-gap); border-left: 1px solid var(--diagram-ink-soft);
}
.vt-list .vt-list { padding-left: var(--vt-indent); }
.vt-item { position: relative; padding-top: var(--vt-gap); }
.vt-list.is-top > .vt-item { padding-top: 0; }
/* the elbow into each child, and the spine on down to the next sibling. Edge styles set
   border-left-style and border-bottom-style only: a bare border-style would turn on the top and right (brief §1) */
.vt-list .vt-list > .vt-item::before {
  content: ""; position: absolute; left: calc(var(--vt-spine) - var(--vt-indent)); top: 0;
  width: calc(var(--vt-indent) - var(--vt-spine)); height: calc(var(--vt-gap) + var(--vt-chip-h) / 2);
  border-left: 1px solid var(--diagram-ink-soft); border-bottom: 1px solid var(--diagram-ink-soft);
}
.vt-list .vt-list > .vt-item:not(:last-child)::after {
  content: ""; position: absolute; left: calc(var(--vt-spine) - var(--vt-indent)); top: 0; bottom: 0; border-left: 1px solid var(--diagram-ink-soft);
}
.vt-list > .vt-item.st-p::before { border-left-style: dotted; border-bottom-style: dotted; }
.vt-list > .vt-item.st-d::before { border-left-style: dashed; border-bottom-style: dashed; border-left-color: var(--diagram-cut); border-bottom-color: var(--diagram-cut); }
.vt-list > .vt-item:has(+ .st-p)::after { border-left-style: dotted; }
.vt-list > .vt-item:has(+ .st-d)::after { border-left-style: dashed; border-left-color: var(--diagram-cut); }
.vt-list > .vt-item.is-new::before { border-left-color: var(--diagram-new-stroke); border-bottom-color: var(--diagram-new-stroke); }
.vt-list > .vt-item:has(+ .is-new)::after { border-left-color: var(--diagram-new-stroke); }
.vt-leaves { display: flex; flex-wrap: wrap; gap: var(--vt-gap); }
.vt-leaf .vt-row { column-gap: 6px; }
.vt-leaves > li:has(.vt-also) { flex-basis: 100%; }  /* a leaf with a cross-link takes its own row, the link under its chip */
/* Drawing in (v7.js adds vt-anim, then is-in row by row): the elbow draws from the spine, then the chips
   rise out of a slight blur */
.vt-anim .vt-key, .vt-anim .vt-entries, .vt-anim .vt-item > .vt-row, .vt-anim .vt-item > .vt-leaves {
  opacity: 0; filter: blur(var(--motion-exit-blur)); transform: translateY(var(--motion-exit-distance));
  transition: opacity var(--motion-duration) var(--motion-ease), filter var(--motion-duration) var(--motion-ease), transform var(--motion-duration) var(--motion-ease);
  transition-delay: var(--motion-panel-delay);
}
.vt-anim .vt-item::before, .vt-anim .vt-item::after { clip-path: inset(0 100% 100% 0); transition: clip-path var(--motion-duration-exit) var(--motion-ease); }
.vt-anim .vt-key.is-in, .vt-anim .vt-entries.is-in, .vt-anim .vt-item.is-in > .vt-row, .vt-anim .vt-item.is-in > .vt-leaves { opacity: 1; filter: none; transform: none; }
.vt-anim .vt-item.is-in::before, .vt-anim .vt-item.is-in::after { clip-path: inset(0); }
.node-box { fill: var(--diagram-cell); stroke: var(--diagram-rule); stroke-width: 1px; }
.node-text { fill: var(--content-text-primary); font-family: inherit; font-size: var(--diagram-text-size); text-anchor: middle; dominant-baseline: central; }
.node.is-root .node-box, .g-node.is-root .node-box { fill: var(--content-text-primary); stroke: var(--content-text-primary); }
.node.is-root .node-text, .g-node.is-root .node-text { fill: var(--content-background); }
.edge, .g-edge { fill: none; stroke: var(--diagram-ink-soft); stroke-width: 1px; }
/* The growth map grows release by release through Jun's scroll (v7.js); what each release adds is
   highlighted, and its date and name sit at the panel's foot. Stacked, the map shows the latest release. */
.g-node, .g-edge { transition: opacity var(--motion-duration) var(--motion-ease), stroke var(--motion-duration) var(--motion-ease); }
.g-node .node-box { transition: fill var(--motion-duration) var(--motion-ease), stroke var(--motion-duration) var(--motion-ease); }
.g-node.is-off, .g-edge.is-off { opacity: 0; }
.g-node.is-new .node-box { fill: var(--diagram-new-fill); stroke: var(--diagram-new-stroke); stroke-width: var(--diagram-new-stroke-w); }
.g-edge.is-new { stroke: var(--diagram-new-stroke); stroke-width: var(--diagram-new-stroke-w); }
.panel.is-growth { position: relative; }
.g-release { display: none; }
:root[data-layout="split"] .g-release { display: block; position: absolute; left: var(--cs-panel-pad); bottom: var(--cs-panel-pad); }
.g-release-item { display: flex; gap: var(--frame-grid-gutter); }
.g-release-item[hidden] { display: none; }
.g-release-when { color: var(--content-text-muted); }
.node.st-m .node-box { stroke: var(--content-text-primary); stroke-dasharray: var(--dash-mid-fi); }
.node.st-p .node-box { stroke: var(--diagram-ink-soft); stroke-dasharray: var(--dash-slated); }
.node.st-p .node-text { fill: var(--content-text-muted); }
.edge.st-p { stroke-dasharray: var(--dash-slated); }
.node.st-d .node-box { stroke: var(--diagram-cut); stroke-dasharray: var(--dash-mid-fi); }
.node.st-d .node-text { fill: var(--diagram-cut); }
.node-strike { stroke: var(--diagram-cut); stroke-width: 1px; }
.edge.st-d { stroke: var(--diagram-cut); stroke-dasharray: var(--dash-mid-fi); }
.node-tag { fill: var(--content-text-muted); font-family: inherit; font-size: var(--diagram-text-size); dominant-baseline: central; }
.node-tag.is-cut { fill: var(--diagram-cut); }
.out-list { margin: 0; padding: 0 0 0 var(--diagram-pad); list-style: none; border-left: 1px solid var(--diagram-rule); }
.out-list.is-top { padding-left: 0; border-left-style: none; }
.out-item { margin: var(--frame-column-gap) 0 0; }
.out-summary { cursor: pointer; }
.out-item.st-p > .out-label, .out-item.st-p > .out-branch > .out-summary > .out-label { color: var(--content-text-muted); }
.out-item.st-d > .out-label, .out-item.st-d > .out-branch > .out-summary > .out-label { color: var(--diagram-cut); text-decoration-line: line-through; }
.out-tag { color: var(--content-text-muted); }
.out-tag.is-cut { color: var(--diagram-cut); }
.flow-fit { width: var(--flow-fit-w, auto); height: var(--flow-fit-h, auto); margin: 0 auto; }
.flow-fit .flow-wide { transform: scale(var(--flow-scale, 1)); transform-origin: 0 0; }
.flow-wide { position: relative; }
.flow-lines { position: absolute; top: 0; left: 0; overflow: visible; }
.flow-line { fill: none; stroke: var(--diagram-ink-soft); stroke-width: 1px; }
.flow-line.is-tossed { stroke: var(--diagram-cut); stroke-dasharray: var(--dash-tossed); }
.flow-head { fill: var(--diagram-ink-soft); }
.flow-head.is-tossed { fill: var(--diagram-cut); }
.flow-step { position: absolute; display: flex; flex-direction: column; gap: var(--diagram-stack); padding: var(--diagram-pad); border: 1px solid var(--diagram-rule); background-color: var(--diagram-cell); }
.flow-who, .flow-note { color: var(--content-text-muted); }
.flow-step.is-key { border-color: var(--content-text-primary); background-color: var(--content-text-primary); }
.flow-step.is-key .flow-who, .flow-step.is-key .flow-title, .flow-step.is-key .flow-note { color: var(--content-background); }
.flow-step.is-done { border-color: var(--content-text-primary); }
.flow-step.is-tossed { border: 1px dashed var(--diagram-cut); background-color: transparent; }
.flow-step.is-tossed .flow-who, .flow-step.is-tossed .flow-title, .flow-step.is-tossed .flow-note { color: var(--diagram-cut); }
.flow-step.is-tossed .flow-title { text-decoration-line: line-through; }
.flow-step.is-tabled { border: 1px dashed var(--diagram-ink-soft); background-color: transparent; }
.flow-step.is-tabled .flow-title { color: var(--content-text-muted); }
.flow-lane { position: absolute; color: var(--diagram-cut); }
.flow-tall, .flow-branch, .flow-strip-list { margin: 0; padding: 0; list-style: none; }
.flow-tall .flow-step, .flow-tossed-strip .flow-step, .flow-pin-tall .flow-step { position: static; }
.flow-split, .flow-strip-list { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--diagram-stack); }
.flow-down { display: block; padding: var(--diagram-stack) 0; color: var(--content-text-muted); text-align: center; }
.flow-tossed-strip, .flow-pin-tall { margin-top: var(--cs-panel-pad); }
.flow-lane-tall { margin: 0 0 var(--diagram-stack); color: var(--diagram-cut); }
.flow-item { margin: 0; }

/* Minimap (col 13): fixed beside the chapters, vertically centered in the space below the header */
.mm-layer {
  position: fixed;
  top: var(--header-h);
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  pointer-events: none;
}
.mm {
  grid-column: 13;
  height: calc(100vh - var(--header-h) - 2 * var(--frame-margin));
  padding: 0 var(--frame-margin);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.mm-map { position: relative; pointer-events: auto; touch-action: none; cursor: pointer; }
/* A chapter in miniature: copies of its text and image columns at full size, scaled down (v7.js). The
   columns' fixed placing, offstage fades, steps and pinned notes don't apply to the copies. */
.mm-mini { position: absolute; left: 0; transform-origin: 0 0; overflow: clip; pointer-events: none; }
.mm-mini .cs-content, .mm-mini .cs-images { position: absolute !important; top: 0 !important; opacity: 1 !important; transform: none !important; }
.mm-mini .cs-content { left: 0 !important; width: var(--cs-col-width); }
.mm-mini .cs-images { left: var(--mm-img-left) !important; width: var(--cs-img-width); }
.mm-mini .cs-group.is-notes { position: static !important; padding: 0 !important; }
.mm-mini, .mm-mini * { view-transition-name: none !important; animation: none !important; transition: none !important; }
.mm-frame { position: absolute; left: -3px; right: -3px; border: 1px solid var(--content-text-primary); cursor: grab; }
.mm-frame.is-dragging { cursor: grabbing; }
.mm-chapter { position: absolute; left: 0; right: 0; }
.mm-chapter:focus-visible { outline: 1px solid var(--content-text-primary); outline-offset: 2px; }
.mm-tip {
  position: absolute;
  right: 0;
  bottom: calc(100% + var(--frame-column-gap));
  white-space: nowrap;
  color: var(--content-text-muted);
  pointer-events: none;
  visibility: hidden;
}
.mm-tip.is-shown { visibility: visible; }

/* Screens open full size (Figma 2705:43019). Every device with data-viewer-open is a button; the viewer
   is a modal dialog over the whole screen: the scrim with the page grain at 20%, the screen across
   columns 2-12 from row 2, Previous and Next in row 7. The screen grows out of the one tapped
   (a same-page view transition) and shrinks back into it. */
[data-viewer-open] { cursor: zoom-in; }
[data-viewer-open]:focus-visible { outline: 1px solid var(--content-text-primary); outline-offset: 4px; }
:root.is-viewing { overflow: hidden; }
.viewer {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  border: 0;
  padding: var(--frame-margin);
  background-color: var(--viewer-scrim);
  color: var(--viewer-text);
  grid-template-rows: repeat(13, minmax(0, 1fr));
  row-gap: var(--frame-grid-gutter);
  overflow: clip;
}
.viewer[open] { display: grid; }
.viewer { -webkit-backdrop-filter: blur(var(--viewer-glass-blur)); backdrop-filter: blur(var(--viewer-glass-blur)); }
.viewer:not([open]) { display: none; }  /* .frame-grid would otherwise show the closed dialog */
.viewer::backdrop { background-color: transparent; }
.viewer::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--grain-page);
  background-size: var(--grain-page-size) var(--grain-page-size);
  background-position: 0 0;
  mix-blend-mode: var(--grain-page-blend);
  opacity: var(--viewer-grain-opacity);
  pointer-events: none;
}
.viewer-nav {
  position: relative;
  grid-row: 7;
  align-self: stretch;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: var(--tracking);
  text-align: left;
  cursor: pointer;
}
.viewer-nav.is-prev { grid-column: 1; }
.viewer-nav.is-next { grid-column: 13; text-align: right; }
.viewer-nav[hidden] { display: none; }
.viewer-nav:focus-visible, .viewer-close:focus-visible { outline: 1px solid var(--viewer-text); outline-offset: 4px; }
.viewer-image {
  position: relative;
  grid-column: 2 / span 11;
  grid-row: 2 / span 12;
  align-self: start;
  display: flex;
  justify-content: center;
  overflow: clip;
}
/* the screen across the columns, or as wide as the rows allow on a shorter screen */
.viewer-mockup {
  position: relative;
  width: min(100%, calc(((100vh - 2 * var(--frame-margin) - 12 * var(--frame-grid-gutter)) * 12 / 13 + 11 * var(--frame-grid-gutter)) * var(--viewer-ratio, 1440 / 900)));
}
.viewer-mockup .device { cursor: default; aspect-ratio: var(--viewer-ratio, var(--device-ratio)); }
.viewer-mockup .device.is-shot { border-color: transparent; border-radius: 0; box-shadow: none; background-color: var(--content-surface); }  /* shots are transparent: they keep their panel's ground */
.viewer-mockup .device.is-shot::after, .viewer-mockup .device.is-shot .device-img { border-radius: 0; box-shadow: none; }
/* A diagram opens as a copy of its panel, laid out at its size on the page and zoomed to fill the viewer
   (v7.js sets the zoom); its grain is drawn at the page's size, not zoomed with it */
.viewer-diagram { position: absolute; inset: 0; overflow: clip; }
.viewer-diagram[hidden], .viewer-mockup .device-img[hidden] { display: none; }
.viewer-diagram > .panel { background-size: calc(var(--grain-size) / var(--viewer-zoom, 1)) calc(var(--grain-size) / var(--viewer-zoom, 1)); }
/* a diagram is no single picture: its panel opens it, and a button the keyboard reaches (visually hidden) */
.panel:has(> [data-viewer-key]:focus-visible) { outline: 1px solid var(--content-text-primary); outline-offset: 4px; }
/* stacked (tablet, phone), a diagram is already as wide as the screen: it doesn't open */
:root:not([data-layout="split"]) .panel.is-diagram[data-viewer-open] { cursor: auto; }
:root:not([data-layout="split"]) [data-viewer-key] { display: none; }
.viewer-close {
  position: absolute;
  top: var(--frame-margin);
  right: var(--frame-margin);
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: var(--tracking);
  cursor: pointer;
  opacity: 0;  /* not in the design: there for the keyboard, shown on focus */
}
.viewer-close:focus-visible { opacity: 1; }
::view-transition-group(v7-zoom) { animation-duration: var(--motion-duration); animation-timing-function: var(--motion-ease); }
/* Opening and closing (v7.js sets data-zoom for the transition): the scrim and glass fade in or out from
   the first frame, and only the larger picture of the screen is drawn while it moves (the viewer's, which
   is sharp at every size), never the small one scaled up. */
/* the names that carry the project into the case study stay out of it: only the screen moves (its
   inline name outranks this), so nothing else is lifted above the scrim mid-transition */
html[data-zoom] * { view-transition-name: none; }
html[data-zoom]::view-transition-old(root) { animation: none; }
html[data-zoom]::view-transition-new(root) { animation: v7-fade-in var(--motion-duration-exit) var(--motion-ease) both; mix-blend-mode: normal; }
html[data-zoom="open"]::view-transition-old(v7-zoom) { display: none; }
html[data-zoom="open"]::view-transition-new(v7-zoom) { animation: none; }
html[data-zoom="close"]::view-transition-new(v7-zoom) { display: none; }
html[data-zoom="close"]::view-transition-old(v7-zoom) { animation: none; }

/* Project details become the case study: the same pieces carry the same names on both pages, so the
   browser moves each from its place on the project to its place in the case study (cross-document
   view transitions); what's new fades in. Without support the page simply opens (v7.js fades first). */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) { @view-transition { navigation: none; } }
/* Until v7.js starts the page's reveal (the head script sets this; at most 3s) */
.is-revealing [data-blur] { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .is-revealing [data-blur] { opacity: 1; } }
::view-transition-group(*) { animation-duration: var(--motion-duration); animation-timing-function: var(--motion-ease); }
/* The page around the moving pieces: the old one holds, and the new one (the case study's own text and
   images) fades in once the pieces are halfway, so nothing new lands on text still on its way */
::view-transition-old(root) { animation: none; }
::view-transition-new(root) {
  animation-name: v7-fade-in;  /* a plain fade: the default adds the pages (plus-lighter), which washes the new one out over the held old one */
  animation-delay: calc(var(--motion-duration) / 2);
  animation-duration: var(--motion-duration-exit);
  animation-fill-mode: both;
  mix-blend-mode: normal;
}
@keyframes v7-fade-in { from { opacity: 0; } }
::view-transition-old(v7-view) { animation-duration: var(--motion-duration-exit); }
.p-view { view-transition-name: v7-view; }
.p-kicker, .cs-kicker { view-transition-name: v7-kicker; }
.p-willis, .cs-willis { view-transition-name: v7-willis; }
.p-ecoa, .cs-ecoa { view-transition-name: v7-ecoa; }
.p-about-label, .cs-about-label { view-transition-name: v7-about-label; }
.p-about, .cs-about { view-transition-name: v7-about; }
.vt-f1 { view-transition-name: v7-f1; }
.vt-f2 { view-transition-name: v7-f2; }
.vt-f3 { view-transition-name: v7-f3; }
.vt-f4 { view-transition-name: v7-f4; }
.vt-f5 { view-transition-name: v7-f5; }
.vt-f6 { view-transition-name: v7-f6; }
.vt-f7 { view-transition-name: v7-f7; }
.vt-f8 { view-transition-name: v7-f8; }
.p-image, .cs-figure.is-first .panel { view-transition-name: v7-panel; }
.p-image .device, .cs-figure.is-first .device { view-transition-name: v7-device; }
/* What the project thumbnail doesn't show arrives with the case study (Alex, Oct 28): the minimap slides in
   as the image shrinks to make way for it, and the facts the thumbnail hid (Disciplines, Regulations) ease
   in as text does. Back out to the project, the same pieces leave. */
.vt-mm { view-transition-name: v7-minimap; }
.vt-x1 { view-transition-name: v7-x1; }
.vt-x2 { view-transition-name: v7-x2; }
.vt-x3 { view-transition-name: v7-x3; }
.vt-x4 { view-transition-name: v7-x4; }
::view-transition-new(v7-minimap) { animation: v7-slide-in var(--motion-duration) var(--motion-ease) both; }
::view-transition-old(v7-minimap) { animation: v7-slide-out var(--motion-duration-exit) var(--motion-ease) both; }
::view-transition-new(v7-x1), ::view-transition-new(v7-x2), ::view-transition-new(v7-x3), ::view-transition-new(v7-x4) {
  animation: v7-blur-in var(--motion-duration) var(--motion-ease) calc(var(--motion-duration) * 0.4) both;
}
::view-transition-old(v7-x1), ::view-transition-old(v7-x2), ::view-transition-old(v7-x3), ::view-transition-old(v7-x4) {
  animation: v7-blur-out var(--motion-duration-exit) var(--motion-ease) both;
}
@keyframes v7-slide-in { from { opacity: 0; transform: translateX(var(--mm-slide)); } }
@keyframes v7-slide-out { to { opacity: 0; transform: translateX(var(--mm-slide)); } }
@keyframes v7-blur-in { from { opacity: 0; filter: blur(var(--motion-blur)); transform: translateY(var(--motion-distance)); } }
@keyframes v7-blur-out { to { opacity: 0; filter: blur(var(--motion-exit-blur)); transform: translateY(calc(-1 * var(--motion-exit-distance))); } }
::view-transition-group(v7-panel) { overflow: clip; }
::view-transition-old(v7-panel), ::view-transition-new(v7-panel) { height: 100%; object-fit: cover; }

/* ---------- Tablet, 768-987 (Figma 2698:42075, 2699:42146): 8 columns ---------- */
@media (max-width: 987px) {
  .frame-grid { grid-template-columns: repeat(var(--tablet-columns), minmax(0, 1fr)); }
  .site-contact { grid-column: 7 / span 2; }

  .l-hero, .l-lists { padding: var(--tablet-landing-margin); column-gap: var(--tablet-landing-gutter); }
  .l-hero { grid-template-rows: repeat(8, minmax(0, 1fr)); row-gap: var(--tablet-landing-gutter); }
  .l-headline { grid-column: 1 / span 3; grid-row: 1 / span 3; }
  .l-intro { grid-column: 1 / span 3; grid-row: 6 / span 3; }
  .l-portrait { grid-column: 5 / span 4; grid-row: 1 / span 8; aspect-ratio: 504 / 648; justify-self: end; max-width: 100%; max-height: 100%; }  /* its own proportions, as tall as the stage allows: a short screen shrinks it, never crops it to a strip (Alex, Oct 30) */
  .l-list { width: auto; justify-self: stretch; gap: var(--tablet-landing-margin); }
  .l-list.is-disciplines { grid-column: 1; }
  .l-list.is-industries { grid-column: 2; }
  .l-list.is-other { grid-column: 3 / span 2; }

  .p-section { grid-template-rows: repeat(var(--tablet-project-rows), minmax(0, 1fr)); }
  .p-kicker { grid-column: 1; grid-row: 1; }
  .p-willis { grid-column: 1; grid-row: 3; }
  .p-ecoa { grid-column: 2 / span 2; grid-row: 5; }
  .p-content { display: flex; flex-direction: column; gap: var(--tablet-group-gap); grid-column: 4 / span 5; grid-row: 1 / span 6; }
  .p-about-group, .p-facts-group { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--frame-grid-gutter); }
  .p-about-label { grid-column: 1; grid-row: auto; align-self: start; }
  .p-about { grid-column: 2 / span 3; grid-row: auto; }
  .p-facts { grid-row: auto; grid-template-rows: repeat(3, fit-content(100%)); }
  .p-facts.is-a, .p-facts.is-b { grid-column: span 2; }
  dt.facts-extra { display: block; }
  dd.facts-extra { display: flex; flex-direction: column; }
  .p-view { display: none; }  /* not in the tablet frame */
  .p-image { grid-column: 1 / span 8; grid-row: 8 / span 12; align-items: stretch; }
  .panel.is-project { height: auto; padding: var(--frame-margin) var(--pending-project-panel-pad); }

  /* Case study on tablet: not in the file yet. Built from the tablet project: the title in columns 1-3,
     the text in 4-8, then the images full width. No pinning, no minimap. Each chapter's date and heading
     sit in columns 1-3 beside its text, as on the previous site (Alex, Oct 28).
     TODO(designer): the tablet case study. */
  .cs-content { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(var(--tablet-columns), minmax(0, 1fr)); column-gap: var(--frame-grid-gutter); row-gap: 0; }
  .cs-group { grid-column: 4 / span 5; }
  .cs-group + .cs-group { margin-top: var(--tablet-group-gap); }  /* gaps as margins: the rows the left block spans add none */
  .cs-group.is-title, .cs-group.is-head { grid-row: 1 / span 12; align-self: start; height: auto; margin: 0; }
  .cs-group.is-title + .cs-group, .cs-group.is-head + .cs-group { margin-top: 0; }
  .cs-group.is-title { grid-column: 1 / span 3; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: none; row-gap: var(--tablet-group-gap); }
  .cs-group.is-head { grid-column: 1 / span 3; display: flex; flex-direction: column; gap: var(--frame-column-gap); }
  .cs-kicker { grid-column: 1; grid-row: 1; }
  .cs-willis { grid-column: 1; grid-row: 2; }
  .cs-ecoa { grid-column: 2 / span 2; grid-row: 3; }
  .cs-images, .cs-chapter.is-first .cs-images { grid-column: 1 / -1; margin-top: var(--tablet-group-gap); gap: var(--stacked-image-gap); }
  .cs-inline { grid-column: 4 / span 5; }
  .cs-chapter + .cs-chapter { margin-top: var(--tablet-group-gap); }
  .panel.is-room, .panel.is-fit { min-height: 0; height: auto; }
  .panel.is-crop { height: auto; }  /* the table scaled down fits whole: no crop, no empty space under it (Alex, Oct 30) */
  .shot.is-fit, .dg-fit, .panel.is-fit .dg { flex: none; }
  .shot.is-fit .shot-img, .dg-fit > svg { height: auto; }
  .tree-wide, .flow-scroll { display: none; }
  .tree-tall, .flow-compact, .growth-tall { display: block; }
  .g-map { display: none; }  /* the vertical form instead of the SVG scaled to the width */
  .cs-images .panel { padding: var(--frame-margin) var(--pending-project-panel-pad); }
  .mm-layer { display: none; }
  /* Viewer on tablet and phones (not in the file yet): the screen across the width, Previous and Next below */
  .viewer-image { grid-column: 1 / -1; grid-row: 2 / span 11; align-self: center; }
  .viewer-nav { grid-row: 13; align-self: end; }
  .viewer-nav.is-next { grid-column: -2 / -1; }
  /* In place of the minimap: a reading-progress line down the right edge, filling as the page is read */
  .cs-progress { display: block; position: fixed; top: 0; bottom: 0; right: 0; z-index: 13; width: var(--progress-w); background-color: var(--content-border-secondary); pointer-events: none; }
  .cs-progress::after { content: ""; position: absolute; inset: 0; background-color: var(--content-text-muted); transform-origin: 0 0; transform: scaleY(var(--progress, 0)); }
}

/* ---------- Mobile, to 767 (proposal approved Oct 27): 5 columns, 13px margin and gutter ---------- */
@media (max-width: 767px) {
  :root { --header-h: var(--mobile-head-h); --frame-margin: var(--mobile-margin); --frame-grid-gutter: var(--mobile-gutter); }
  .frame-grid { grid-template-columns: repeat(var(--mobile-columns), minmax(0, 1fr)); padding: 0 var(--mobile-margin); }
  .site-head { align-items: center; }
  .site-logo { grid-column: 1 / span 3; }
  .site-nav { grid-column: 4 / span 2; justify-self: end; flex-direction: row; gap: var(--mobile-gap-s); }
  .site-head .site-where, .site-head .site-contact { display: none; }
  .site-foot { display: grid; margin-top: var(--mobile-gap-l); padding-top: var(--mobile-gap-s); padding-bottom: max(var(--mobile-foot-clear), env(safe-area-inset-bottom)); }
  .site-foot .site-where { grid-column: 1 / span 2; }
  .site-foot .site-contact { grid-column: 3 / span 3; justify-self: end; }

  .home-state.is-about { display: block; }
  .l-hero, .l-lists, .p-section { height: auto; padding: 0 var(--mobile-margin); column-gap: var(--mobile-gutter); grid-template-rows: none; overflow: visible; }
  .l-headline { grid-column: 1 / -1; grid-row: auto; margin-top: var(--mobile-gap-m); }
  .l-portrait { grid-column: 3 / -1; grid-row: auto; margin-top: var(--mobile-gap-m); aspect-ratio: 504 / 648; }  /* about half the screen, on the grid (Alex, Oct 30; was 2 / -1) */
  .l-intro { grid-column: 1 / span 4; grid-row: auto; margin-top: var(--mobile-gap-m); }
  .l-lists { margin-top: var(--mobile-gap-l); row-gap: var(--mobile-gap-m); }
  .l-list { gap: var(--mobile-gap-s); }
  .l-list.is-disciplines { grid-column: 1 / span 2; }
  .l-list.is-industries { grid-column: 3 / span 3; }
  .l-list.is-other { grid-column: 1 / -1; }
  .l-list-label.is-tall { height: auto; }

  .p-section { margin-top: var(--mobile-gap-l); }
  .p-kicker { grid-column: 1 / span 3; grid-row: auto; margin-top: var(--mobile-gap-m); }
  .p-willis { grid-column: 2 / -1; grid-row: auto; margin-top: var(--mobile-gap-s); }  /* with the body text (Alex, Oct 30): fits from 320px */
  .p-ecoa { grid-column: 3 / -1; grid-row: auto; margin-top: var(--mobile-gap-s); }
  .p-content, .p-about-group, .p-facts-group { display: contents; }
  .p-about-label { grid-column: 1; margin-top: var(--mobile-gap-l); }
  .p-about { grid-column: 2 / -1; margin-top: var(--mobile-gap-l); }
  dt.p-extra, dd.p-extra { display: none; }
  .p-facts.is-a, .p-facts.is-b, .cs-facts { grid-column: 1 / -1; grid-template-columns: subgrid; column-gap: var(--mobile-gutter); grid-template-rows: none; margin-top: var(--mobile-gap-s); }
  .p-facts.is-a, .cs-facts.is-a { margin-top: var(--mobile-gap-m); }
  .facts > dt { grid-column: 1; }
  .facts > dd { grid-column: 2 / -1; }  /* values line up with the About text above (Alex, Oct 30) */
  .p-view { display: block; grid-column: 1 / -1; grid-row: auto; width: auto; margin-top: var(--mobile-gap-m); }
  .p-image { grid-column: 1 / -1; grid-row: auto; margin: var(--mobile-gap-m) calc(var(--mobile-margin) * -1) 0; }
  .panel.is-project, .cs-images .panel { padding: var(--mobile-margin); }

  .cs-chapter { padding: 0 var(--mobile-margin); }
  .viewer.frame-grid { padding: var(--mobile-margin); }
  .viewer-nav.is-prev { grid-column: 1 / span 2; }
  .viewer-nav.is-next { grid-column: 4 / span 2; }
  .cs-content, .cs-group, .cs-group.is-title, .cs-group.is-head { display: contents; }
  .cs-kicker { grid-column: 1 / span 3; grid-row: auto; margin-top: var(--mobile-gap-m); }
  .cs-willis { grid-column: 2 / -1; grid-row: auto; margin-top: var(--mobile-gap-s); }  /* with the body text (Alex, Oct 30): fits from 320px */
  .cs-ecoa { grid-column: 3 / -1; grid-row: auto; margin-top: var(--mobile-gap-s); }
  .cs-label { margin-top: var(--mobile-gap-l); }
  .cs-about, .cs-text, .cs-heading { grid-column: 2 / -1; margin-top: var(--mobile-gap-l); }
  .cs-inline { grid-column: 1 / -1; margin-top: var(--mobile-gap-m); }
  .cs-notes { grid-column: 1 / -1; margin-top: var(--mobile-gap-l); }
  .cs-group.is-coda > * { order: 1; }  /* Looking back (and the notes) after Jun's growth map, not before it (Alex, Oct 30) */  /* subgrid of the chapter's 5 columns */
  .cs-chapter:not(.is-first) .panel { padding: var(--mobile-margin); }
  .dg.perm { position: relative; overflow-x: auto; }  /* relative: keeps its visually hidden labels inside it */
  .dg.perm > .dg-table, .dg.perm > .dg-key { min-width: var(--diagram-min-w); }  /* 640-767: the grid at its width; below 640 the blocks (.pm) instead */
  .dg-prow, .dg-head { grid-template-columns: minmax(0, 1fr); row-gap: var(--frame-column-gap); }
  .dg-head .dg-to, .dg-prow .dg-to { grid-column: 1; }
  .dg-head { display: none; }
  .dg-from { padding-right: 0; }
  /* stacked rows: At site over the from-title, then the arrow turned down beside In Willis, then the to */
  .dg-where { position: static; width: auto; height: auto; overflow: visible; clip-path: none; white-space: normal; }
  .dg-from > .dg-where { display: block; }
  .dg-via { grid-column: 1; display: flex; align-items: center; gap: var(--frame-column-gap); }
  .dg-arrow { transform: rotate(90deg); }
  .cs-images, .cs-chapter.is-first .cs-images { grid-column: 1 / -1; margin: var(--mobile-gap-m) calc(var(--mobile-margin) * -1) 0; gap: var(--stacked-image-gap); }
}

/* Phones wide enough (from 460px, measured: the second list's longest label and value each need a column
   of about 75px): the facts' second list sits beside the first, its values still under the About text
   (Alex, Oct 30) */
@media (min-width: 460px) and (max-width: 767px) {
  .p-facts.is-a, .cs-facts.is-a { grid-column: 1 / span 3; }
  .p-facts.is-b, .cs-facts.is-b { grid-column: 4 / -1; margin-top: var(--mobile-gap-m); }
}

/* Hovering an image, its contents expand a little inside their panel and lean toward the cursor; the portrait,
   which doesn't open full size, does the same within the page (Alex, Oct 30) */
@media (hover: hover) and (pointer: fine) {
  .cs-images .panel, .p-image { overflow: clip; }
  .cs-images .panel > *, .p-image > *, .l-portrait {
    translate: calc(var(--nx, 0) * var(--image-follow)) calc(var(--ny, 0) * var(--image-follow));  /* toward the cursor (v7.js) */
    transition: scale var(--image-hover-duration) var(--motion-ease), translate var(--image-hover-duration) var(--motion-ease);
  }
  .cs-images .panel:hover > *, .p-image:hover > *, .l-portrait:hover { scale: var(--image-hover-scale); }
}
