/* EZO Labs Research: the article (its contents rail from 901px, a chapter bar under it), the
 * index and the topic pages. The index and topic pages open the same way: the nav on paper as
 * /enterprise's sits, over a full-bleed ink band holding one row, the lockup and the topics as
 * one segmented control. Under the band the index is a magazine grid on paper from 641px up and
 * a list of posts on the ground below it; a topic page is that list at every width. The nav and
 * the band are the site's section head (styles.css `.paper-nav`, `.section-head`), shared with
 * /security and its archive; the topics are this file's.
 *
 * Loaded after styles.css on research pages only, and built from its tokens: every colour,
 * length and radius is a var() from styles.css or one declared here. The new surface is
 * --paper, the index's magazine grid (below); it lives here and nowhere else.
 *
 * Look plan, inherited from the site and /enterprise and nothing added to them: seven hex values
 * (the five styles.css palette colours these pages use, plus --paper and /enterprise's dark nav
 * paper, #1d1e23, which styles.css holds as --nav-paper), one accent hue (the field blue), Inter 500 display with ss01 + cv11 and
 * negative tracking, JetBrains Mono for the tracked uppercase labels (the recorded brand
 * exception) and the topic counts, two radii: 6px for frames and the verdict chip, 999px for
 * the segmented control, pills and meters. The bold element per page: the list pages' full-bleed
 * ink band over the ink-ruled paper grid; the article's numbers strip, the lead number in field
 * blue.
 *
 * Both schemes (styles.css): the ground and the text swap, everything here reads them through
 * the tokens. The field blue as text or an underline on the ground is --field-on-ground (the
 * deeper tint in light, where the raw blue is 4.1:1; the raw blue in dark). The ink band is the
 * same in both, the off-white on ink, as the footer is. The list pages' nav is /enterprise's
 * (styles.css `.paper-nav`). The paper grid follows the scheme: the warm paper ruled in ink in light; in
 * dark a raised ink panel (--surface, the contact dialog's) ruled in the muted grey, with the
 * off-white on it. Its tints derive from the text colour either way: print.css re-declares
 * --surface as white paper, so a dark pick still prints on white.
 *
 * Breakpoints are in page pixels (styles.css's page zoom is 1): 640/641 is the phone edge,
 * 900/901 the tablet edge, where the article gains its contents rail. */

:root {
  --paper: #f4f3ee;
  --paper-rule: var(--ink);   /* the grid's 1px rules: ink on the warm paper, 17:1 */
  --measure: 37.5rem;  /* the reading column, about 75 characters of Inter at 16px */
  --wide: 52.5rem;     /* figures, tables and the article's first screen: 1.4x the measure */
  --rail: 10rem;       /* the contents rail */
  --bar: 48px;         /* the phone chapter bar */
  --post-title: clamp(32px, 5 * var(--vw), 56px);   /* the article's h1 */
  /* the follow band: its heading a step under the home page's display size, the bars mark
     rising from its bottom edge at half its size */
  --follow-head: clamp(40px, 5.6 * var(--vw), 80px);
  --follow-head-phone: clamp(32px, 10 * var(--vw), 44px);
  --follow-mark: clamp(180px, 24 * var(--vw), 340px);
  --follow-mark-phone: 168px;
  --follow-measure: 44rem;
  --follow-form: 32rem;     /* the email field and its button on one row */
  --follow-input: 14rem;    /* the field's least width before the button wraps under it */
}
/* Dark: the paper goes dark with the page. The raised ink panel on the black ground, ruled in
   the muted grey (3.4:1 on it, where the ink rule would vanish); the off-white reads on it at
   18:1. Both are tokens styles.css already holds. */
html[data-theme="dark"] {
  --paper: var(--surface);
  --paper-rule: var(--muted);
}
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.research [id] { scroll-margin-top: var(--s5); }
/* Any string a post sets (a title, a name, an address, a word with no break point) breaks inside
   its column before it runs past it or into a neighbour, and counts as narrow when a grid or
   flex track sizes to it. A table and a code block keep their words whole and scroll (below). */
.research { overflow-wrap: anywhere; }

/* ---------- the verdict chip: ink on the field, 4.55:1 ----------
   One box: it moves to the next line whole and breaks inside itself only when it is wider than
   its whole column, as a 320px phone at 200% text makes it (an inline-block shrinks to its
   words up to the column's width; a chip that never wrapped would run past the screen there).
   When it does break, its lines are balanced and held to the row. */
.verdict {
  display: inline-block;
  max-width: 100%;
  padding: 0 var(--s2);
  border-radius: var(--r-frame);
  background: var(--field);
  color: var(--ink);
  font-weight: 500;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

/* ================================================================ the article */
/* inline padding as longhands, as styles.css writes its edges: a shorthand holding var()
   leaves its longhands empty in the CSSOM, where the mobile gate looks for the notch inset */
.post {
  padding-top: var(--s8);
  padding-bottom: var(--s9);
  padding-left: var(--edge);
  padding-right: var(--edge-r);
}
.post__main { min-width: 0; max-width: var(--wide); }
.post__rail { display: none; }

.post__kicker { margin: 0 0 var(--s5); color: var(--text-2); }
.post__hero h1 {
  margin: 0;
  max-width: 22ch;
  font-size: var(--post-title);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.post__dek {
  margin: var(--s5) 0 0;
  max-width: 34em;
  font-size: var(--t-lead);
  line-height: 1.6;
  letter-spacing: -0.01em;
  color: var(--text-2);
  text-wrap: pretty;
}
.post__dek .verdict { margin-right: var(--s1); }

/* by, published, section, report: one ruled row */
.post__meta {
  display: flex;
  flex-wrap: wrap;
  margin: var(--s6) 0 0;
  border-block: 1px solid var(--hairline);
}
.post__meta > div { padding: var(--s3) var(--s5); border-left: 1px solid var(--hairline); }
.post__meta > div:first-child { padding-left: 0; border-left: 0; }
.post__meta dd { margin: 0; font-size: var(--t-small); line-height: 1.5; color: var(--text); }
.post__meta > div + div dd { font-family: var(--mono); font-size: var(--t-label); line-height: 1.75; letter-spacing: 0.04em; color: var(--text-2); }
.post__meta a { color: var(--text); text-decoration: underline; text-decoration-color: var(--field-on-ground); text-underline-offset: 3px; }
.post__meta a:hover { text-decoration-color: currentColor; }

/* ---------- the numbers strip ---------- */
.numbers { margin-top: 0; }
.numbers__list {
  --numbers-cols: 3;
  --numbers-fit: 0.21;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--numbers-cols), minmax(0, 1fr));
  border-bottom: 1px solid var(--hairline);
  container-type: inline-size;
}
.numbers__item {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  min-width: 0;
  padding: var(--s6) var(--s5);
  border-left: 1px solid var(--hairline);
}
.numbers__item:first-child { padding-left: 0; border-left: 0; }
/* Every value in a strip shares one size, fitted to the narrowest cell (a third of the strip less
   two paddings): the viewport size holds until --numbers-fit of that cell is smaller. 0.21 fits
   4.76em on one line, past the widest value of up to 8 characters the posts carry ("40-218/h",
   4.4em of Inter 500); a strip with a longer value (render.mjs marks it is-long) takes 0.16, 6.25em,
   past the widest at the schema's 12-character cap ("-16.5 -> +1.8", 6.1em). A wider value wraps
   between its tokens, and a token wider than its cell breaks inside itself: it wraps, it never runs
   into the next cell. The 20px floor keeps a figure above body size; below it the value wraps. */
.numbers__list.is-long { --numbers-fit: 0.16; }
.numbers__value {
  font-size: max(var(--t-h3), min(clamp(32px, 3.6 * var(--vw), 48px), (100cqi / var(--numbers-cols) - 2 * var(--s5)) * var(--numbers-fit)));
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
  text-wrap: balance;
}
/* the lead number in the field's blue: 6.4:1 on the light ground, 4.75:1 on black, past 4.5:1 at any size */
.numbers__item.is-lead .numbers__value { color: var(--field-on-ground); }
.numbers__label { font-size: var(--t-small); line-height: 1.45; color: var(--text-2); text-wrap: pretty; }
/* decorative: the writer's fraction of the bar, never a printed value */
.meter { display: block; width: 100%; height: 4px; margin-top: auto; border-radius: var(--r-pill); overflow: hidden; }
.meter__track { fill: var(--text-3); }
.meter__fill { fill: var(--field); }

/* ---------- assumptions ---------- */
.assumptions {
  margin-top: var(--s6);
  padding: var(--s5);
  border: 1px solid var(--text-3);
  border-radius: var(--r-frame);
}
.assumptions__label { margin: 0 0 var(--s4); color: var(--text-2); }
.assumptions__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s4) var(--s6);
}
.assumptions__list li {
  position: relative;
  padding-left: var(--s4);
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--text-2);
  text-wrap: pretty;
}
.assumptions__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--field);
}

/* ---------- abstract ---------- */
.post__abstract { margin-top: var(--s7); max-width: var(--measure); }
.abstract__label { margin: 0 0 var(--s3); color: var(--text-2); }
.post__abstract p { margin: 0; font-size: var(--t-body); line-height: 1.6; letter-spacing: -0.01em; text-wrap: pretty; }

/* ---------- the chapter bar (under 901px): contents, sticky once past the hero ----------
   It sits after the hero in the flow, so it pins only when the hero has scrolled away.
   A <details>: it opens and closes with no script; research.js names the chapter. */
.chapter {
  position: sticky;
  top: 0;
  z-index: 3;
  margin: var(--s6) calc(-1 * var(--edge-r)) 0 calc(-1 * var(--edge));
  background: var(--ground);
  border-block: 1px solid var(--hairline);
}
/* The bar is the <summary>, a tap target end to end: it stands off the notch by margin (0 but
   on a phone on its side), as the nav's outer cells do, and its padding makes up the rest of
   the content edge, so its label, chapter and chevron sit inside the safe area while the
   <details> behind it still paints the ground full bleed. */
.chapter__bar {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: var(--bar);
  margin-left: var(--inset-l);
  margin-right: var(--inset-r);
  padding-left: max(0px, var(--edge) - var(--inset-l));
  padding-right: max(0px, var(--edge-r) - var(--inset-r));
  list-style: none;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.chapter__bar::-webkit-details-marker { display: none; }
.chapter__label { flex: none; color: var(--text-2); }
.chapter__now {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--t-small);
  color: var(--text);
}
.chapter__chev,
.revisions__chev {
  flex: none;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  transition: transform var(--quick) ease-out;
}
.chapter[open] .chapter__chev,
.revisions[open] .revisions__chev { transform: rotate(180deg); }
.revisions__chev { margin-left: auto; color: var(--text-2); }
.chapter__list {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  max-height: calc(100 * var(--dvh) - var(--bar) - var(--s6));
  overflow-y: auto;
  margin: 0;
  padding-bottom: var(--s3);
  padding-left: var(--edge);
  padding-right: var(--edge-r);
  list-style: none;
  background: var(--ground);
  border-bottom: 1px solid var(--hairline);
}
.chapter__a {
  display: flex;
  align-items: center;
  min-height: var(--target);
  padding: var(--s2) 0 var(--s2) var(--s3);
  border-top: 1px solid var(--hairline);
  font-size: var(--t-small);
  line-height: 1.4;
  color: var(--text-2);
}
.chapter__a:hover { color: var(--text); }
.chapter__a[aria-current="true"] { color: var(--text); box-shadow: inset 2px 0 0 var(--field-on-ground); }
/* Once pinned, the bar (and its two hairlines) covers the top of the screen: the page's
   scroller keeps clear of it, so a link's jump and a Tab or Shift+Tab focus scroll both land
   below it with the focus ring (2px outline + 3px offset) showing whole. */
@media (max-width: 900px) {
  html:has(> body.research-post) { scroll-padding-top: calc(var(--bar) + var(--s2)); }
  .research-post [id] { scroll-margin-top: var(--s2); }
}

/* ---------- the body ---------- */
.post__body { margin-top: var(--s7); }
.post__body > * { max-width: var(--measure); }
.post__body > .figure,
.post__body > .table-wrap,
.post__body > .footnotes { max-width: none; }
.post__body p,
.post__body li {
  font-size: var(--t-body);
  line-height: 1.6;
  letter-spacing: -0.01em;
  color: var(--text-2);
  text-wrap: pretty;
}
.post__body p { margin: 0 0 var(--s4); }
.post__body strong { color: var(--text); font-weight: 500; }
.post__body ul,
.post__body ol { margin: 0 0 var(--s4); padding-left: var(--s5); }
.post__body li { margin-bottom: var(--s2); }
.post__body li > ul,
.post__body li > ol { margin: var(--s2) 0 0; }
.post__body li::marker { color: var(--text-2); }
.post__body h2 {
  margin: var(--s8) 0 var(--s4);
  font-size: clamp(24px, 2.6 * var(--vw), 32px);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.025em;
  text-wrap: balance;
}
.post__body h3 {
  margin: var(--s6) 0 var(--s3);
  font-size: var(--t-h3);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.post__body a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--field-on-ground);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.post__body a:hover { text-decoration-color: currentColor; }
.post__body code {
  padding: 0 var(--s1);
  border-radius: var(--r-frame);
  background: var(--tint);
  font-family: var(--mono);
  font-size: 0.875em;
  letter-spacing: 0;
  color: var(--text);
  overflow-wrap: anywhere;
}

/* a code block: its lines as written, in a hairline frame that scrolls sideways (render.mjs
   makes it focusable, so a keyboard scrolls it too) */
.post__body pre {
  margin: var(--s5) 0;
  padding: var(--s3) var(--s4);
  overflow-x: auto;
  overflow-wrap: normal;
  border: 1px solid var(--hairline);
  border-radius: var(--r-frame);
  font-size: var(--t-small);
  line-height: 1.6;
}
.post__body pre:focus-visible { outline-offset: var(--s1); }
.post__body pre code { padding: 0; border-radius: 0; background: none; font-size: inherit; overflow-wrap: normal; }

/* math: KaTeX's own fonts and metrics; never inherit the tracking or a label's case */
.post .katex { font-size: 1.1em; letter-spacing: 0; text-transform: none; color: var(--text); }
/* A wide equation scrolls sideways, and the scroller clips: its block padding is in em so it
   grows with the math and holds a fraction's ascenders and subscripts at any text size. Inside a
   list item or a quote too; render.mjs makes it focusable, so a keyboard scrolls it. */
.post__body .katex-display {
  margin: var(--s5) 0;
  padding: 0.5em 0;
  overflow-x: auto;
  overflow-y: hidden;
}

/* ---------- tables: a hairline table, its caption above (the paper's convention) ---------- */
/* the scroller is the caption's query container: a caption no wider than what shows, pinned
   left, so a table wider than the screen scrolls under its caption instead of clipping it */
.table-wrap { margin: var(--s6) 0; overflow-x: auto; container-type: inline-size; overflow-wrap: normal; }
/* the table's provenance and its data, tucked under it */
.post__body .table__src { max-width: var(--measure); margin: calc(var(--s3) - var(--s6)) 0 var(--s6); }
.table-wrap:focus-visible { outline-offset: var(--s1); }
.post__body table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-small);
  line-height: 1.5;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}
.post__body caption {
  caption-side: top;
  position: sticky;
  left: 0;
  max-width: min(var(--measure), 100cqi);
  padding-bottom: var(--s4);
  text-align: left;
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--text-2);
  text-wrap: pretty;
}
.table__n { display: block; margin-bottom: var(--s1); color: var(--text); }
.post__body thead th {
  padding: 0 var(--s4) var(--s3) 0;
  border-bottom: 1px solid var(--text-3);
  text-align: left;
  vertical-align: bottom;
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
}
/* render.mjs wraps a header's lowercase Greek: λ upper-cased is Λ, a different symbol */
.post__body th .keep-case { text-transform: none; }
.post__body td {
  min-width: 7rem;
  padding: var(--s3) var(--s4) var(--s3) 0;
  border-bottom: 1px solid var(--hairline);
  vertical-align: top;
  color: var(--text-2);
}
.post__body td:first-child { color: var(--text); }
/* eight columns at the 7rem floor overrun the wide column: off the phone such a table drops the
   floor and fits by its content, so it never scrolls on a screen that has the room */
@media (min-width: 641px) {
  .post__body table:has(th:nth-child(8)) td { min-width: 0; }
}
.post__body th:last-child,
.post__body td:last-child { padding-right: 0; }

/* ---------- figures: inline SVG in currentColor, wider than the measure ---------- */
/* A drawing fills its column, never narrower than the width its `width` attribute names:
   the research build sets it where the drawing's smallest text draws at 9px, so on a column
   narrower than that (a phone) the drawing keeps its legible size and scrolls in its labelled
   region. The hint under it shows only while the region has more to scroll to (a scroll timeline
   is active only when there is overflow); "full size" opens the drawing on its own. */
.figure { margin: var(--s7) 0; timeline-scope: --figure-scroll; }
.figure__art { color: var(--text); overflow-x: auto; scroll-timeline: --figure-scroll inline; }
.figure__art:focus-visible { outline-offset: var(--s1); }
.figure__svg { display: block; height: auto; }
.figure__art .figure__svg { min-width: 100%; max-width: none; }
.figure__hint {
  display: block;
  height: 0;
  visibility: hidden;
  text-align: right;
  animation: figure-scrolls linear both;
  animation-timeline: --figure-scroll;
}
@keyframes figure-scrolls {
  from, to { height: auto; margin-top: var(--s2); visibility: visible; }
}
/* Dark: an interval band tinted from the field blue at 35% sinks into the black ground (1.4:1,
   skill-descriptions' after-the-rewrite bands); there it draws at 70%, 2.7:1, as plain to read
   as the grey band beside it. The light ground keeps the file's own tint. */
html[data-theme="dark"] .figure__svg [stroke-width="6"][stroke-opacity="0.35"] { stroke-opacity: 0.7; }
.figure figcaption {
  display: grid;
  grid-template-columns: var(--s8) minmax(0, 1fr);
  gap: var(--s2) var(--s5);
  max-width: var(--measure);
  margin-top: var(--s4);
  font-size: var(--t-small);
  line-height: 1.5;
  color: var(--text-2);
  text-wrap: pretty;
}
.figure__n { color: var(--text); }
.figure__t,
.figure__src { grid-column: 2; }
/* "Source: …" and the data link: a figure's and a table's provenance, a step under the caption */
.post__body .figure__src,
.post__body .table__src { font-size: var(--t-label); line-height: 1.6; letter-spacing: 0; color: var(--text-2); }
.post__body .figure__src { margin: 0; }
.figure__src a,
.table__src a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--text-3);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--quick) ease-out;
}
.figure__src a:hover,
.table__src a:hover { text-decoration-color: currentColor; }
/* the converter's links, set apart by a gap rather than a glyph */
.figure__src .figure__link,
.table__src .figure__link { margin-left: var(--s2); }
/* the drawing at its own size: offered where the page shrinks it (phones) */
.figure__full { display: none; }

/* ---------- notes: the apparatus at the end ---------- */
.post__body sup.fn { font-size: 0.75em; line-height: 0; vertical-align: super; }
.post__body sup.fn a {
  padding: 0 var(--s1);
  border-radius: var(--r-frame);
  background: var(--field-tint);
  font-family: var(--mono);
  color: var(--text);
  text-decoration: none;
}
.post__body sup.fn a:hover { background: var(--field); color: var(--ink); }
.post__body .footnotes {
  margin-top: var(--s9);
  padding-top: var(--s7);
  border-top: 1px solid var(--text-3);
}
.post__body .footnotes h2 { margin-top: 0; }
.post__body .footnotes ol { margin: 0; padding: 0; list-style: none; counter-reset: note; }
.post__body .footnotes li {
  position: relative;
  margin: 0 0 var(--s4);
  padding-left: var(--s6);
  counter-increment: note;
  font-size: var(--t-small);
  line-height: 1.5;
  break-inside: avoid;
}
.post__body .footnotes li::before {
  content: counter(note);
  position: absolute;
  left: 0;
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 500;
  line-height: 1.75;
  color: var(--text-2);
}
.post__body .footnotes li p { margin: 0; font-size: inherit; line-height: inherit; }
.post__body .footnotes li:target { border-radius: var(--r-frame); background: var(--field-tint); box-shadow: 0 0 0 var(--s2) var(--field-tint); }
.post__body a[data-footnote-backref] { margin-left: var(--s1); font-family: var(--mono); color: var(--text-2); text-decoration: none; }
.post__body a[data-footnote-backref]:hover { color: var(--text); }

/* ---------- the end: revisions, cite, more ---------- */
.post__end { margin-top: var(--s9); max-width: var(--wide); }
.revisions { border-block: 1px solid var(--hairline); }
.revisions summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s1) var(--s4);
  min-height: var(--target);
  padding: var(--s2) 0;
  list-style: none;
  cursor: pointer;
  font-size: var(--t-small);
  color: var(--text-2);
}
.revisions summary::-webkit-details-marker { display: none; }
.revisions summary .label { color: var(--text); }
.revisions__table { width: 100%; max-width: var(--measure); margin: 0 0 var(--s4); border-collapse: collapse; font-size: var(--t-small); }
.revisions__table th,
.revisions__table td { padding: var(--s2) var(--s4) var(--s2) 0; border-bottom: 1px solid var(--hairline); text-align: left; font-weight: 400; color: var(--text-2); }
.revisions__table th { font-family: var(--mono); font-size: var(--t-label); letter-spacing: 0.14em; text-transform: uppercase; border-bottom-color: var(--text-3); }
.revisions__table time { font-family: var(--mono); font-size: var(--t-label); white-space: nowrap; }

.cite {
  display: grid;
  gap: var(--s4);
  margin-top: var(--s7);
  padding: var(--s5);
  border: 1px solid var(--text-3);
  border-radius: var(--r-frame);
}
.cite__label { margin: 0; color: var(--text-2); }
.cite__ref { margin: 0; max-width: var(--measure); font-size: var(--t-small); line-height: 1.5; color: var(--text); overflow-wrap: anywhere; }
.cite__bib {
  margin: 0;
  padding: var(--s3);
  overflow-x: auto;
  border-radius: var(--r-frame);
  background: var(--tint);
  font-family: var(--mono);
  font-size: var(--t-label);
  line-height: 1.6;
  letter-spacing: 0;
  color: var(--text);
}
.cite__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s4); margin: 0; }
.cite__actions:has(button[hidden]):has(.cite__status:empty) { display: none; }
.cite__status { font-size: var(--t-small); color: var(--text-2); }
.cite__license { margin: 0; font-size: var(--t-small); color: var(--text-2); }
.cite__license a,
.rail-cite__links a,
.post__all a,
.authors__list a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--text-3);
  text-underline-offset: 4px;
  transition: text-decoration-color var(--quick) ease-out;
}
.cite__license a:hover,
.rail-cite__links a:hover,
.post__all a:hover,
.authors__list a:hover { text-decoration-color: currentColor; }

/* the copy buttons: a pill; the rail's is the field (ink on blue, never white), and turns the
   text colour on hover, with the ground for its label (it reads in both schemes) */
.cite__copy,
.rail-cite__copy {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding: 0 var(--s4);
  border: 1px solid currentColor;
  border-radius: var(--r-pill);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: var(--t-nav);
  font-weight: 500;
  letter-spacing: -0.01em;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--quick) ease-out, color var(--quick) ease-out;
}
.cite__copy:hover { background: var(--text); color: var(--ground); }
.rail-cite__copy { border-color: var(--field); background: var(--field); color: var(--ink); }
.rail-cite__copy:hover { border-color: var(--text); background: var(--text); color: var(--ground); }
.cite__copy[hidden],
.rail-cite__copy[hidden] { display: none; }

.authors { margin-top: var(--s7); }
.authors__label,
.post__next-label { margin: 0 0 var(--s3); color: var(--text-2); }
.authors__list { list-style: none; margin: 0; padding: 0; font-size: var(--t-small); }
.authors__list li { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--s3); min-height: var(--target); }
.authors__list .authors__x { font-family: var(--mono); font-size: var(--t-label); color: var(--text-2); }

/* next: the topic pages' rows, then the way back to every post */
.post__next { margin-top: var(--s8); }
.post__next .entries__list { border-top: 1px solid var(--hairline); }
.post__all { margin: var(--s4) 0 0; font-size: var(--t-small); }
.post__all a { display: inline-flex; align-items: center; min-height: var(--target); }

/* ---------- follow: the field closes the page ----------
   Full bleed, the field blue with ink on it in both schemes (the home page's hero), the
   bars mark rising from the band's bottom edge. Two ways to follow, no form. */
.follow {
  position: relative;
  overflow: hidden;
  padding: var(--s9) var(--edge-r) var(--s9) var(--edge);
  background: var(--field);
  color: var(--ink);
}
.follow ::selection { background: var(--ink); color: var(--field-on-ink, var(--field)); }
.follow :focus-visible { outline-color: var(--ink); }
.follow__in { position: relative; z-index: 1; max-width: var(--follow-measure); }
.follow__h {
  margin: 0;
  font-size: var(--follow-head);
  font-weight: 500;
  line-height: var(--head-display-lh);
  letter-spacing: var(--head-display-ls);
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.follow__line { margin: var(--s5) 0 0; font-size: var(--t-lead); line-height: 1.4; text-wrap: pretty; }
.follow__actions { display: flex; flex-wrap: wrap; gap: var(--s3); margin: var(--s5) 0 0; padding: 0; list-style: none; }
/* the newsletter: a plain form to Buttondown, the field and its button the pills' shape */
.follow__form { margin: var(--s6) 0 0; }
.follow__label { display: block; margin: 0 0 var(--s2); color: var(--ink); }
.follow__field { display: flex; flex-wrap: wrap; gap: var(--s3); max-width: var(--follow-form); }
.follow__input,
.follow__submit {
  min-height: calc(var(--target) + var(--s2));
  border: 1px solid var(--ink);
  border-radius: var(--r-pill);
  font: inherit;
}
.follow__input {
  flex: 1 1 var(--follow-input);
  min-width: 0;
  padding: 0 var(--s5);
  background: transparent;
  color: var(--ink);
  font-size: var(--t-body);
}
.follow__submit {
  padding: 0 var(--s5);
  background: var(--ink);
  color: var(--field-on-ink, var(--field));
  font-size: var(--t-nav);
  font-weight: 500;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: background-color var(--quick) ease-out, color var(--quick) ease-out;
}
.follow__submit:hover { background: transparent; color: var(--ink); }
.follow__pill {
  display: inline-flex;
  align-items: center;
  min-height: calc(var(--target) + var(--s2));
  padding: var(--s2) var(--s5);
  border: 1px solid var(--ink);
  border-radius: var(--r-pill);
  color: var(--ink);
  font-size: var(--t-nav);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
  transition: background-color var(--quick) ease-out, color var(--quick) ease-out;
}
.follow__pill:hover { background: var(--ink); color: var(--field-on-ink, var(--field)); }
.follow__mark {
  position: absolute;
  right: var(--edge-r);
  bottom: calc(var(--follow-mark) / -2);
  width: var(--follow-mark);
  height: var(--follow-mark);
  fill: var(--ink);
}

/* ---------- the contents rail: 901px and up ---------- */
.toc__label,
.rail-cite__label { margin: 0 0 var(--s3); color: var(--text-2); }
.toc__list { list-style: none; margin: 0; padding: 0; }
.toc__a {
  display: flex;
  align-items: center;
  min-height: var(--target);
  padding: var(--s1) 0 var(--s1) var(--s3);
  font-size: var(--t-small);
  line-height: 1.4;
  color: var(--text-2);
  text-wrap: pretty;
  transition: color var(--quick) ease-out;
}
.toc__a:hover { color: var(--text); }
.toc__a[aria-current="true"] { color: var(--text); box-shadow: inset 2px 0 0 var(--field-on-ground); }
.rail-cite { margin-top: var(--s5); padding-top: var(--s5); border-top: 1px solid var(--hairline); }
.rail-cite__links { display: flex; gap: var(--s4); margin: 0; font-size: var(--t-small); }
/* a link here is one short word ("bibtex", "data"), narrower than a finger: the target's width
   too, the word still on the rail's left edge */
.rail-cite__links a { display: inline-flex; align-items: center; min-width: var(--target); min-height: var(--target); }
.rail-cite__copy { margin-top: var(--s4); }

@media (min-width: 901px) {
  .post {
    display: grid;
    grid-template-columns: var(--rail) minmax(0, var(--wide));
    column-gap: var(--s7);
    justify-content: center;
    align-items: start;
    padding-top: var(--s9);
  }
  .post__rail {
    display: block;
    position: sticky;
    top: var(--s4);
    max-height: calc(100 * var(--dvh) - var(--s6));
    overflow-y: auto;
    /* the focus ring of the first link must not clip against the rail's edge */
    padding: var(--s1);
    margin: calc(-1 * var(--s1));
  }
  /* a long contents list overruns a laptop's height (twelve sections need about 750px at
     1440x900): the cite block then pins to the rail's foot, whole, and the list scrolls under
     it, so the copy buttons are never cut in half at the rail's edge */
  .post__rail .rail-cite { position: sticky; bottom: calc(-1 * var(--s1)); padding-bottom: var(--s1); background: var(--ground); }
  .chapter { display: none; }
  .post__body .footnotes ol { columns: 2; column-gap: var(--s6); }
}

/* ================================================================ the list pages' first screen */
/* The nav on paper and the ink band are the site's section head (styles.css `.paper-nav`,
   `.section-head`, shared with /security and its archive, its sizes the --head-* tokens shared
   with /enterprise's hero). What stays here is research's own: the topics in the head's slot. */

/* ---------- the topics: one segmented control ----------
   /enterprise's segmented track (enterprise.css `.pv-modes`) at the hero's size: a 1px off-white
   pill holding the segments, the current one filled off-white with ink on it (18.9:1), a rule
   between two unfilled neighbours, each count in mono at its label's 62% (7.3:1 on ink, 6.6:1
   on the fill). A hovered segment draws its own pill outline, where the fill would sit. */
.segments {
  display: flex;
  max-width: 100%;
  padding: var(--s1);
  border: 1px solid var(--on-ink);
  border-radius: var(--r-pill);
}
.segment {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  min-height: var(--s7);
  padding: 0 var(--s5);
  border-radius: var(--r-pill);
  font-size: var(--t-body);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--on-ink);
  white-space: nowrap;
  transition: background-color var(--quick) ease-out, color var(--quick) ease-out, box-shadow var(--quick) ease-out;
}
.segment + .segment::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(-1 * var(--s1));
  bottom: calc(-1 * var(--s1));
  border-left: 1px solid var(--on-ink);
}
.segment[aria-current="page"]::before,
.segment[aria-current="page"] + .segment::before { display: none; }
@media (hover: hover) {
  .segment:hover { box-shadow: inset 0 0 0 1px var(--on-ink); }
}
.segment[aria-current="page"] { background: var(--on-ink); color: var(--ink); }
/* the ring hugs the segment, inside the track's 4px inset, so it never runs over the outline */
.segment:focus-visible { border-radius: var(--r-pill); outline-offset: 0; }
.segment__n {
  font-family: var(--mono);
  font-size: var(--t-small);
  font-weight: 400;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  color: color-mix(in srgb, currentColor 62%, transparent);
}

/* ---------- shared row parts (phone index, topic pages) ---------- */
.lead__meta,
.side__meta,
.entry__meta { margin: 0; color: var(--text-2); }
.lead__title a,
.side__title a,
.entry__title a { text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: 1px; text-underline-offset: 0.12em; transition: text-decoration-color var(--quick) ease-out; }
.lead__title a:hover,
.side__title a:hover,
.entry__title a:hover { text-decoration-color: var(--field-on-ground); }
.lead__dek,
.entry__dek { margin: 0; font-size: var(--t-body); line-height: 1.5; color: var(--text-2); text-wrap: pretty; }
.lead__dek .verdict,
.entry__dek .verdict { margin-right: var(--s2); }
.lead__figure { display: none; }

.empty {
  margin: 0;
  font-family: var(--mono);
  font-size: var(--t-label);
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
}
.empty__action { margin: var(--s3) 0 0; font-size: var(--t-small); }
.empty__action a,
.counts__feed a,
.earlier__list a { text-decoration: underline; text-decoration-color: currentColor; text-decoration-thickness: 1px; text-underline-offset: 4px; }
.empty__action a { display: inline-flex; align-items: center; min-height: var(--target); color: var(--text); }
.index-empty { padding-top: var(--s8); padding-bottom: var(--s9); padding-left: var(--edge); padding-right: var(--edge-r); }

/* topic pages: the list on the ground at every width */
.entries { padding-top: var(--s6); padding-bottom: var(--s9); padding-left: var(--edge); padding-right: var(--edge-r); }
.entries__list { list-style: none; margin: 0; padding: 0; max-width: var(--wide); }
.entries > .empty { padding-top: var(--s6); }
.entry { padding: var(--s6) 0; border-bottom: 1px solid var(--hairline); }
.entry__title {
  margin: var(--s3) 0;
  max-width: 28ch;
  font-size: clamp(22px, 2.6 * var(--vw), 32px);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.025em;
  text-wrap: balance;
}

/* ---------- phone: the posts as a list on the ground ---------- */
@media (max-width: 640px) {
  .segment { padding: 0 var(--s3); font-size: var(--t-small); }
  .segment__n { font-size: var(--t-label); }
  .index-grid { padding-bottom: var(--s8); padding-left: var(--edge); padding-right: var(--edge-r); }
  .lead-cell,
  .side { padding: var(--s6) 0; border-bottom: 1px solid var(--hairline); }
  .lead__title,
  .side__title {
    margin: var(--s3) 0;
    font-size: clamp(22px, 7 * var(--vw), 28px);
    font-weight: 500;
    line-height: 1.15;
    letter-spacing: -0.025em;
    text-wrap: balance;
  }
  .counts { display: none; }
  .earlier { padding: var(--s6) 0; }
  .earlier__label { margin: 0 0 var(--s3); color: var(--text-2); }
  .earlier__list { list-style: none; margin: 0; padding: 0; }
  .earlier__list li { display: grid; gap: var(--s1); padding: var(--s3) 0; border-bottom: 1px solid var(--hairline); }
  .earlier__list time,
  .earlier__list .label { font-family: var(--mono); font-size: var(--t-label); color: var(--text-2); }
  .post { padding-top: var(--s7); }
  /* by, published / section, report: two by two */
  .post__meta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .post__meta > div { padding: var(--s3) 0; border-left: 0; }
  .post__meta > div:nth-child(even) { padding-left: var(--s3); border-left: 1px solid var(--hairline); }
  .post__meta > div:nth-child(n + 3) { border-top: 1px solid var(--hairline); }
  .numbers__list { --numbers-cols: 1; }
  .numbers__item { padding: var(--s5) 0; border-left: 0; border-top: 1px solid var(--hairline); }
  .numbers__item:first-child { border-top: 0; }
  .assumptions { padding: var(--s4); }
  .assumptions__list { grid-template-columns: minmax(0, 1fr); }
  /* a chart fits the screen whole, and its caption offers it at its own size to read the labels */
  .figure figcaption { grid-template-columns: minmax(0, 1fr); gap: var(--s1); }
  .figure__t,
  .figure__src { grid-column: 1; }
  .figure__full { display: inline; }
  .follow { --follow-mark: var(--follow-mark-phone); padding-top: var(--s8); padding-bottom: calc(var(--follow-mark) / 2 + var(--s6)); }
  .follow__h { font-size: var(--follow-head-phone); }
  .cite { padding: var(--s4); }
}

/* Under 481px the four segments do not fit one row (367px with the phone sizes, 350 to spare at
   390): the control breaks into two pairs, stacked, each pair one outlined track split by its
   rule, the current segment's fill still an inset pill inside it. Wrapping, never a sideways
   scroller: a topic page's segment could start out of view and its focus ring cut at the edge. */
@media (max-width: 480px) {
  .segments {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: var(--s2);
    width: 100%;
    padding: 0;
    border: 0;
  }
  .segment { border: 1px solid var(--on-ink); }
  .segment:nth-child(odd) { border-right: 0; border-radius: var(--r-pill) 0 0 var(--r-pill); }
  .segment:nth-child(even) { border-left: 0; border-radius: 0 var(--r-pill) var(--r-pill) 0; }
  .segment:nth-child(odd)::before { display: none; }
  .segment + .segment::before { top: 0; bottom: 0; }
  .segment[aria-current="page"] { isolation: isolate; background: none; }
  .segment[aria-current="page"]::after {
    content: "";
    position: absolute;
    inset: var(--s1);
    z-index: -1;
    border-radius: var(--r-pill);
    background: var(--on-ink);
  }
}

/* ---------- a phone on its side ----------
   Safari leaves 280 to 402px of height, and the article's title lands in it as the section
   heads' lockup does (styles.css, the (max-height: 500px) tier, whose tokens these are): the
   page's top pad is the heads' landscape pad, and the title is sized by the small viewport
   height, never past its own size. After the phone block, so a narrow phone is reached too.
   Measured 2026-10-29 at 874x280: agent-fleet-occupancy's three lines ended at 297px, under
   the 280px first screen; they end at 221 on these. */
@media (max-height: 500px) and (orientation: landscape) {
  .post { padding-top: var(--head-pad-top); }
  .post__hero h1 { font-size: min(var(--post-title), var(--head-display)); }
}

/* ---------- 641px and up: the paper magazine grid with 1px rules ---------- */
@media (min-width: 641px) {
  .paper {
    /* the paper's own tints of its text colour (ink on the warm paper, the off-white on the
       dark one): a lighter frame and a rule that reads on the paper, where the ground's would
       not (the dark ground's hairline is 1.1:1 on the ink panel) */
    --text-2: color-mix(in srgb, var(--text) 62%, transparent);
    --text-3: color-mix(in srgb, var(--text) 32%, transparent);
    --hairline: color-mix(in srgb, var(--text) 12%, transparent);
    color: var(--text);
  }
  .index-grid {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    gap: 1px;
    background: var(--paper-rule);
    border-bottom: 1px solid var(--paper-rule);
  }
  .index-grid > * { background: var(--paper); }
  .paper ::selection { background: var(--text); color: var(--paper); }
  .paper :focus-visible { outline-color: var(--text); }
  .lead-cell { padding-top: var(--s7); padding-bottom: var(--s8); padding-left: var(--edge); padding-right: var(--s6); }
  .lead__title {
    margin: var(--s5) 0 var(--s4);
    max-width: 20ch;
    font-size: clamp(32px, 4.4 * var(--vw), 64px);
    font-weight: 500;
    line-height: 1.04;
    letter-spacing: -0.03em;
    text-wrap: balance;
  }
  .lead__dek { max-width: 30em; font-size: var(--t-lead); }
  .index-side { display: flex; flex-direction: column; gap: 1px; background: var(--paper-rule); }
  .index-side > * { background: var(--paper); }
  /* the column's last cell runs to the lead's foot: past it the rule colour would show as a void */
  .index-side > :last-child { flex: 1; }
  .side { padding-block: var(--s7); padding-left: var(--s6); padding-right: var(--edge-r); }
  .side__title { margin: var(--s4) 0 0; font-size: var(--t-h3); font-weight: 500; line-height: 1.2; letter-spacing: -0.02em; text-wrap: balance; }
  .counts {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: var(--s4);
    padding-block: var(--s7);
    padding-left: var(--s6);
    padding-right: var(--edge-r);
  }
  .counts__label { margin: 0; color: var(--text-2); }
  .counts__list { margin: 0; }
  .counts__list > div {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: var(--target);
    border-top: 1px solid var(--hairline);
  }
  .counts__list dt,
  .counts__list dd {
    margin: 0;
    font-family: var(--mono);
    font-size: var(--t-label);
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-variant-numeric: tabular-nums;
  }
  .counts__list a { display: inline-flex; align-items: center; min-height: var(--target); text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 4px; }
  .counts__list a:hover { text-decoration-color: currentColor; }
  .counts__feed { margin: auto 0 0; font-size: var(--t-small); }
  .counts__feed a { display: inline-flex; align-items: center; min-height: var(--target); }
  .earlier { padding-top: var(--s6); padding-bottom: var(--s7); padding-left: var(--edge); padding-right: var(--s6); }
  .earlier__label { margin: 0 0 var(--s3); color: var(--text-2); }
  .earlier__list { list-style: none; margin: 0; padding: 0; }
  .earlier__list li {
    display: grid;
    grid-template-columns: var(--s10) minmax(0, 1fr) auto;
    align-items: baseline;
    gap: var(--s4);
    padding: var(--s3) 0;
    border-top: 1px solid var(--hairline);
  }
  .earlier__list time { font-family: var(--mono); font-size: var(--t-label); color: var(--text-2); }
  .earlier__list a { font-size: var(--t-body); text-decoration-color: transparent; }
  .earlier__list a:hover { text-decoration-color: currentColor; }
  .earlier__list .label { color: var(--text-2); }
}
@media (min-width: 901px) {
  .lead__figure { display: block; max-width: 47.5rem; margin-top: var(--s6); color: var(--text); }
  .lead__figure .figure__svg { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .chapter__chev, .revisions__chev, .toc__a, .segment, .cite__copy, .rail-cite__copy,
  .cite__license a, .rail-cite__links a, .post__all a, .authors__list a, .follow__submit,
  .figure__src a, .table__src a, .follow__pill,
  .lead__title a, .side__title a, .entry__title a { transition: none; }
  /* .figure__hint keeps its scroll-driven animation: it moves nothing (one held state, start to
     end) and only shows the hint while the drawing scrolls, which a reader who scrolls needs */
}
