/* type.css -- Prose type and the things attached to a number: unfilled slots, the provenance popover, and a caveat bound to the figure it qualifies.
 *
 * Part 3 of 9. These files were one style.css and are still one
 * stylesheet: equal-specificity rules resolve by document order, so the
 * <link> tags in every page must stay in this order and nothing may move
 * between files without checking what it lands after.
 *   tokens.css -> layout.css -> type.css -> prose.css -> charts.css -> sources.css -> paper.css -> interactive.css -> home.css
 *
 * See site/README.md for the rules that govern all of them. */

/* --- Type ---------------------------------------------------------------- */

.hero { padding: var(--space-7) 0 var(--space-5); }

/* There was an `.eyebrow` here: the uppercase, wide-tracked, accent-colored
 * kicker that sat above every page title -- "THE FINDINGS", "A CLOSER LOOK",
 * "METHODS". It went through two versions, first as a tinted pill and then as
 * bare tracked caps, and the second was better than the first without being
 * right, because the object itself is the problem. Caps at 0.14em tracking in
 * the accent color above a headline is the most imitated mark in machine-made
 * page design, and it was on all nine pages.
 *
 * Nothing replaces it. Every one of those kickers restated either the page's own
 * <title>, the tab the reader had just pressed, or the h1 immediately below it. */

/* Headings wear the display face; everything that argues wears the body face.
 *
 * All three are set at 700 and tracked in rather than out. Work Sans opens up
 * at display sizes, and the negative tracking is what makes a headline read as
 * one object instead of a row of words -- it is the difference between this
 * and the default, more than the family change is. */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: var(--track-display);
  /* `balance` was here, and it split every long heading into two lines of
   * equal length -- a heading that would fit on a line and a bit came out as
   * two half-lines, which read as a stack rather than a title. Headings now
   * wrap the way body text does: fill the line, carry only the overflow.
   * `pretty` rather than plain `wrap` so a lone word is not left stranded. */
  text-wrap: pretty;
}

/* The two display steps, taken from the scale rather than written here.
 *
 * Both of these used to carry their own clamp() -- a heading that decided for
 * itself how it grew with the window, on top of a root font size that was
 * already growing. Two independent fluid curves in one rule is unpredictable
 * at every width between the ends, and every rule inventing its own curve is
 * how a page ends up with twelve sizes. The fluidity now lives in --size-5 and
 * --size-6, stated once, and these two rules only say which step a title is. */
h1 {
  font-size: var(--size-6);
  line-height: var(--lh-tight);
  margin: 0 0 var(--space-4);
}

h2 {
  font-size: var(--size-5);
  line-height: var(--lh-tight);
  margin: 0 0 var(--space-3);
}

h3 {
  font-size: var(--size-3);
  line-height: var(--lh-snug);
  letter-spacing: -0.008em;
  margin: 0 0 var(--space-2);
}

/* One short rule per page, under the page title, and nowhere else.
 *
 * It used to be under every section heading too, which on the research page
 * meant eleven of them: the same 3px accent dash, at the same length, at eleven
 * points down one column. A mark that appears once is a flourish and a mark that
 * appears eleven times is a template -- and it was doing no work the heading was
 * not already doing, since an h2 in the display face at nearly twice the size of
 * the prose is not in danger of being mistaken for a paragraph.
 *
 * What separates sections now is what always separated them: the hairline across
 * the top of each one, and the space. */
.hero h1::after {
  content: "";
  display: block;
  width: 3.25rem;
  height: 3px;
  margin-top: var(--space-3);
  background: var(--accent);
}

/* The standfirst under a page title: one step above the prose, in full ink.
 *
 * It has been both wrong ways round. It was once set near heading size, where
 * it read as a second smaller title and the reader met two headlines before
 * meeting a sentence; the fix was to drop it to body size, which removed the
 * step altogether and left it distinguished from the paragraph below it by
 * nothing but a lighter gray.
 *
 * Graying it was the real mistake, and it was the site's habit everywhere: a
 * census of one page found a quarter of all its text set in one of the two gray
 * tokens, with ledes, captions, card copy and caveats all stepped down that
 * ramp. Fading text out is the cheapest possible way to signal hierarchy and it
 * is the one every generated page reaches for. This is a sentence meant to be
 * read before any other on the page, so it is the size that says so and the
 * same ink as everything else. It stays in the body face, which is what keeps
 * it a standfirst rather than a title -- headings here are the display face,
 * and that is the difference the reader is actually reading. */
.lede { font-size: var(--size-4); color: var(--text-primary); }

/* Fine print inside a lede: a parenthetical disclaimer that belongs to the
 * paragraph but should not carry its weight. One step down in size and a
 * shade lighter, so it reads as a footnote at the foot of the thought. */
.fine {
  font-size: var(--size-3);
  color: var(--text-secondary);
  line-height: var(--lh-body);
}

/* The accent bar is the section marker -- a colored tab above the heading
 * rather than a rule across the page, so the color reads as belonging to this
 * section rather than dividing it from the last. */
section {
  padding: var(--space-6) 0;
  border-top: 1px solid var(--border);
  scroll-margin-top: 4.75rem;
}
/* The research page is a dozen sections long, and at full padding a reader
 * spends more of the scroll on blank paper than on prose. Halved there, at the
 * author's request (2026-08-18); the other pages keep the wider setting. */
.page-research section { padding: calc(var(--space-6) / 2) 0; }
/* The going-further pages are continuous prose rather than a sequence of
 * distinct exhibits, so the gaps between their sections are tightened further
 * still (2026-08-19, at the author's request). */
.page-further section { padding: var(--space-4) 0; }
/* The accent tab that used to sit above each section heading is gone: the rule
 * under the heading is now doing that job, and two accent bars a heading apart
 * read as a rendering fault rather than as a marker. Deleted rather than
 * hidden, so nothing has to work out later which of the two is live. */
section:first-of-type { border-top: none; }

p { margin: 0 0 var(--space-4); }

/* Links in running prose. There was no rule for these at all until now, which
 * means every one of them -- the Methods link in the lede, the cross-references
 * between sections, every outbound citation -- was rendering in the browser's
 * default #0000ee, a color that appears nowhere else on this site and that no
 * palette here was ever checked against.
 *
 * Ink, not the accent. A paragraph with four links in it should read as a
 * paragraph, and coloring each one turns the text into a field of markers;
 * the underline already says "link" and has since 1993. The accent arrives on
 * hover instead, where it confirms the one link the reader is actually
 * reaching for.
 *
 * The underline sits below the baseline with the descenders skipped, so it is
 * a rule under the words rather than a line through the tails of the g's, and
 * it is drawn in a diluted accent so that a link is visible in a block of text
 * without being loud in it.
 *
 * Deliberately unscoped. Every component that owns its anchors -- the tabs,
 * the section map, the citation superscripts, the home page's doors -- sets
 * its own color and decoration, and each of those files loads after this one
 * or outranks it on specificity. Anything left over is prose, and prose is
 * what this describes. */
a {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  text-decoration-skip-ink: auto;
  text-decoration-color: color-mix(in oklab, var(--accent) 55%, transparent);
  transition: color 0.12s ease, text-decoration-color 0.12s ease;
}
a:hover,
a:focus-visible {
  color: var(--accent);
  text-decoration-color: currentColor;
}
/* There is deliberately no second rule here giving standalone links the accent
 * from the start. The obvious way to write it -- `p > a:only-child` -- does not
 * mean what it reads as: `:only-child` counts elements and ignores text, so it
 * matched the Methods link in the middle of the lede and turned an inline
 * cross-reference green. A selector that cannot tell a destination from a
 * mention should not be the thing deciding which links shout. */

em { font-style: italic; }
.nowrap { white-space: nowrap; }

/* A number that came from the analysis, marked with a wash of the section's
 * accent. Tinting the background rather than the glyphs keeps every figure at
 * full text contrast while still making the quantities visible at a glance --
 * which is the point, since the numbers are the substance of the page. */
b[data-stat] {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  /* A highlighter stroke drawn inside the glyph box rather than a padded chip.
   * Padding would push a trailing unit away from its number and render "8.97 %"
   * with a space in it. This adds no metrics at all.
   *
   * Painted as a background rather than an inset shadow so its width can be
   * animated -- the stroke is drawn left to right as the sentence is reached,
   * the way you would mark up a printed page. A shadow can only fade. */
  background-image: linear-gradient(color-mix(in oklab, var(--accent) calc(24% * var(--tint-strength)), var(--tint-base)) 0 100%);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 0.42em;
}

/* Statistical asides ride in a smaller sans face so a reader who does not want
 * them can skip the whole visual band rather than parsing each one. */
.stat {
  font: 500 var(--size-2)/var(--lh-body) var(--font-display);
  color: var(--text-muted);
  white-space: nowrap;
}
/* The wash belongs to running prose. In a heading it reads as a highlighter
 * mark on a title, and in the statistical asides it fights the muted band those
 * are set in. */
.stat b[data-stat],
h1 b[data-stat],
h2 b[data-stat],
.chart-sub b[data-stat],
.ratio b[data-stat] { background-image: none; }

/* --- Slots that have not been filled yet ---------------------------------- */

/* Every figure on these pages is an empty <b data-stat> until data.json lands,
 * which on a slow connection means the first thing a reader sees is prose full
 * of holes -- sentences that read as broken rather than as loading. A block the
 * size of the missing number says "not yet" instead.
 *
 * Two things keep this from becoming a lie. It is gated on `.is-loading`, which
 * charts.js sets as it starts and clears when the payload has been applied *or
 * has failed* -- so a slot that ends up empty because its value is genuinely
 * missing goes back to being empty, and a reader with JavaScript off never sees
 * a shimmer that will never resolve. And it is `::before` on an empty element,
 * so it cannot cover a number: the moment a slot has content, `:empty` stops
 * matching and the placeholder is gone.
 *
 * The width is one size for every slot rather than a guess per slot. A
 * placeholder that matched each number's real width would have to know the
 * number, which is the thing it exists to stand in for. */
.is-loading b[data-stat]:empty::before {
  content: "";
  display: inline-block;
  width: 2.5ch;
  height: 0.72em;
  vertical-align: -0.04em;
  border-radius: var(--radius);
  background: var(--surface-raised);
  background-image: linear-gradient(
    90deg,
    var(--surface-raised) 0%,
    color-mix(in oklab, var(--text-muted) 18%, var(--surface-raised)) 50%,
    var(--surface-raised) 100%);
  background-size: 220% 100%;
}
@media (prefers-reduced-motion: no-preference) {
  .is-loading b[data-stat]:empty::before {
    animation: slot-waiting 1.25s ease-in-out infinite;
  }
}
@keyframes slot-waiting {
  from { background-position: 120% 0; }
  to   { background-position: -120% 0; }
}

/* --- Where a number came from --------------------------------------------- */

/* The claim this whole arrangement rests on is that no number on these pages
 * was typed here: each one is a slot addressed by a dotted path into data.json,
 * filled at load. That claim currently lives in an HTML comment, where no
 * reader will ever meet it. Hovering a figure states it about that figure --
 * the path it came from, and the date the payload was built.
 *
 * Pointer and touch only, and hidden from assistive technology. Making every
 * slot focusable would put several hundred stops into the tab order of the
 * methods page, between which a keyboard reader would have to hold down a key
 * to cross a paragraph -- a serious cost, to reach a note that says the same
 * thing about every number and is stated in prose on the about page besides.
 *
 * One node per page rather than one per slot, moved to whichever slot is under
 * the pointer. The methods page carries a few hundred of these. */
.stat-note {
  position: fixed;
  z-index: 60;
  max-width: 20rem;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-soft);
  font: 400 var(--size-1)/var(--lh-snug) var(--font-display);
  color: var(--text-secondary);
  pointer-events: none;
  opacity: 0;
  transform: translateY(3px);
  transition: opacity 0.14s ease, transform 0.14s ease;
}
.stat-note[data-visible="true"] { opacity: 1; transform: none; }
.stat-note__path {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--size-1);
  color: var(--text-primary);
  word-break: break-all;
}
.stat-note__from { display: block; margin-top: var(--space-1); color: var(--text-muted); }

/* The slot itself answers the pointer, so the note is confirmation rather than
 * the only feedback -- the wash deepens under the number being asked about.
 * `help` rather than `pointer`: there is nothing here to click. */
.is-sourced b[data-stat] { cursor: help; }
.is-sourced b[data-stat]:hover {
  background-image: linear-gradient(color-mix(in oklab, var(--accent) calc(46% * var(--tint-strength)), var(--tint-base)) 0 100%);
}
/* Except where the wash is deliberately absent; deepening a stroke that was
 * never drawn would put a highlighter mark into a heading on hover. */
.is-sourced .stat b[data-stat]:hover,
.is-sourced h1 b[data-stat]:hover,
.is-sourced h2 b[data-stat]:hover,
.is-sourced .chart-sub b[data-stat]:hover,
.is-sourced .ratio b[data-stat]:hover { background-image: none; }

.conclusion {
  font-size: var(--size-4);
  font-weight: 600;
  padding: var(--space-3) 0 var(--space-3) var(--space-4);
  border-left: 4px solid var(--accent);
}

.callout {
  background: color-mix(in oklab, var(--accent) calc(7% * var(--tint-strength)), var(--tint-base));
  border: 1px solid color-mix(in oklab, var(--accent) calc(22% * var(--tint-strength)), var(--tint-base));
  /* Rounded explicitly: a callout is content on the paper, not chrome, so it
   * does not follow the square --radius the controls use. */
  border-radius: 0.5rem;
  padding: var(--space-4);
  margin: 0 0 var(--space-4);
}
.callout h3 { color: var(--accent); }
.callout p:last-child { margin-bottom: 0; }

/* Caveats keep their own color rather than the section's: a warning that
 * changes hue by section stops reading as a warning. */
.caveat {
  font-size: var(--size-2);
  color: var(--text-primary);
  border-left: 4px solid var(--accent-red);
  padding-left: var(--space-4);
}
.caveat strong { color: var(--text-primary); }

/* --- A number and the caveat that qualifies it ---------------------------- */

/* Several numbers on this site mean materially less than they look like they
 * mean, and the paragraph saying so is the only thing standing between a reader
 * and an overclaim. On a page this long that paragraph is easy to skim past. So
 * a qualified number is marked as qualified at rest, and the two light each
 * other up on hover.
 *
 * The mark is a dotted red rule under the number, in the caveat's own color
 * rather than the section's accent -- the same reasoning as `.caveat` itself: a
 * warning that changes hue by section stops reading as a warning. Dotted rather
 * than solid, and an underline rather than a second background layer, so it
 * cannot be mistaken for the wash that means "this came from the analysis" and
 * adds no metrics to the line.
 *
 * `is-contested` is applied by script, so a page whose JavaScript never ran does
 * not advertise a hover response nothing is listening for. */
.is-contested {
  text-decoration: underline dotted color-mix(in oklab, var(--accent-red) 62%, transparent);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 0.28em;
  cursor: help;
}
/* The number, while its caveat is hovered. */
.is-qualified {
  text-decoration-color: var(--accent-red);
  background-image: linear-gradient(
    color-mix(in oklab, var(--accent-red) calc(30% * var(--tint-strength)), var(--tint-base)) 0 100%) !important;
}
/* The caveat, while one of its numbers is hovered. A wash and a thicker rule --
 * no movement, because a paragraph that shifts on hover pushes the rest of the
 * page down and costs the reader the line they were on. */
.is-qualifying {
  background: color-mix(in oklab, var(--accent-red) calc(8% * var(--tint-strength)), var(--tint-base));
  border-left-width: 6px;
  /* The 2px the border gained, given back, so the text does not step sideways. */
  padding-left: calc(var(--space-4) - 2px);
}
.is-contested,
.is-qualified,
.is-qualifying { transition: background 0.18s ease, text-decoration-color 0.18s ease; }

@media (prefers-reduced-motion: reduce) {
  .is-contested,
  .is-qualified,
  .is-qualifying { transition: none; }
}

/* On paper there is no hover, and a dotted rule under a dozen numbers is noise
 * a printed page cannot explain. The caveats are all still there, in order. */
@media print {
  .is-contested { text-decoration: none; }
}

