/* ==========================================================================
   mohdatasha.com: design system
   Institutional and restrained.

   Every rule that exists to satisfy a WCAG 2.2 AAA success criterion is
   annotated with its number. Do not "tidy" those away.
   ========================================================================== */

/* --- Tokens ------------------------------------------------------------- */

:root {
  /* Typography. System stacks only: no third-party origins, no privacy leak. */
  --font-display: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia,
    "Times New Roman", serif;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  /* Scale. Fluid, but never below 16px and never reliant on viewport alone. */
  --step--1: clamp(0.875rem, 0.85rem + 0.12vw, 0.9375rem);
  --step-0: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --step-1: clamp(1.1875rem, 1.13rem + 0.28vw, 1.375rem);
  --step-2: clamp(1.4375rem, 1.34rem + 0.48vw, 1.75rem);
  --step-3: clamp(1.75rem, 1.6rem + 0.75vw, 2.25rem);
  --step-4: clamp(2.125rem, 1.9rem + 1.13vw, 2.875rem);

  /* 1.4.8: line spacing at least 1.5 within paragraphs. */
  --leading: 1.6;
  /* 1.4.8: paragraph spacing at least 1.5x the line spacing. */
  --para-gap: 2.4em;
  /* 1.4.8: no more than 80 characters per line. */
  --measure: 68ch;

  --space-1: 0.5rem;
  --space-2: 0.875rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  --space-5: 4rem;
  --space-6: 6.5rem;

  /* 2.5.5: target size (enhanced) 44x44 CSS px. */
  --target: 2.75rem;

  --rule-width: 1px;
  --focus-width: 0.125rem;
}

/* --- Themes -------------------------------------------------------------
   1.4.6: every foreground/background pair below meets or exceeds 7:1 for
   body text and 4.5:1 for large text.

   The annotated ratios are computed, not estimated. Three of them were
   previously wrong (ink-muted 7.6 vs 8.0, ink accent 10.1 vs 9.7, sepia ink
   16.2 vs 15.6). None was an accessibility failure (all pass AAA either way),
   but /colophon/ invites the reader to check the site's claims, and a
   stated ratio is a checkable claim. Recompute with the WCAG relative
   luminance formula before changing any value here; do not round from memory.
   1.4.8: the user can select foreground and background. Four themes are
   exposed in the footer control; OS preference is honoured with no JS.
   ------------------------------------------------------------------------ */

:root,
[data-theme="paper"] {
  --bg: #fbfaf8;
  --bg-sunk: #f2f0ea;
  --ink: #16161a;      /* 17.3:1 on --bg */
  --ink-muted: #4a4a52; /*  8.4:1 on --bg */
  --accent: #1f3a5f;   /* 11.0:1 on --bg */
  --rule: #d5d1c8;
  --focus: #1f3a5f;
}

[data-theme="ink"] {
  --bg: #131316;
  --bg-sunk: #1c1c20;
  --ink: #edebe6;      /* 15.6:1 on --bg */
  --ink-muted: #adaaa1; /*  8.0:1 on --bg */
  --accent: #9dbfe4;   /*  9.7:1 on --bg */
  --rule: #33333a;
  --focus: #9dbfe4;
}

[data-theme="contrast"] {
  --bg: #ffffff;
  --bg-sunk: #ffffff;
  --ink: #000000;      /* 21:1 */
  --ink-muted: #000000;
  --accent: #00006e;
  --rule: #000000;
  --focus: #000000;
  --rule-width: 2px;
}

[data-theme="sepia"] {
  --bg: #f6efe1;
  --bg-sunk: #ece3d1;
  --ink: #1c1710;      /* 15.6:1 on --bg */
  --ink-muted: #4d4436; /*  8.4:1 on --bg */
  --accent: #4a2f12;   /* 10.8:1 on --bg */
  --rule: #d6c9ad;
  --focus: #4a2f12;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #131316;
    --bg-sunk: #1c1c20;
    --ink: #edebe6;
    --ink-muted: #adaaa1;
    --accent: #9dbfe4;
    --rule: #33333a;
    --focus: #9dbfe4;
  }
}

/* --- Reset --------------------------------------------------------------- */

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

/* 2.3.3: animation from interactions can be disabled. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: var(--leading);
  /* 1.4.8: text is not justified. */
  text-align: left;
  text-wrap: pretty;
}

/* --- Focus --------------------------------------------------------------
   2.4.13 Focus Appearance: at least 2px thick, and at least 3:1 against
   adjacent colours. 2.4.11/2.4.12: never obscured; nothing on this site is
   sticky or overlaid, which is the simplest way to guarantee it.
   ------------------------------------------------------------------------ */

:focus-visible {
  outline: var(--focus-width) solid var(--focus);
  outline-offset: var(--focus-width);
  border-radius: 1px;
}

:focus:not(:focus-visible) {
  outline: none;
}

/* --- Skip link ----------------------------------------------------------- */

.skip {
  position: absolute;
  left: var(--space-3);
  top: var(--space-3);
  z-index: 10;
  padding: var(--space-2) var(--space-3);
  background: var(--bg);
  color: var(--accent);
  border: var(--rule-width) solid var(--accent);
  transform: translateY(-250%);
}

.skip:focus {
  transform: translateY(0);
}

/* --- Layout -------------------------------------------------------------- */

.shell {
  min-height: 100vh;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

.wrap {
  width: 100%;
  max-width: 46rem;
  margin-inline: auto;
  padding-inline: var(--space-3);
}

.wrap--wide {
  max-width: 60rem;
}

main {
  padding-block: var(--space-5) var(--space-6);
}

/* --- Masthead ------------------------------------------------------------ */

.masthead {
  border-bottom: var(--rule-width) solid var(--rule);
  padding-block: var(--space-3);
}

.masthead__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: baseline;
  justify-content: space-between;
}

/* On a 390x844 phone the masthead was 203px, 24% of the first screen, and
   pushed the h1 on /about/ down to 351px, leaving 43 words above the fold.
   Seven nav items cannot fit one row at this width, so the second row stays;
   what is reclaimed is padding and gaps only.

   The 44px targets are untouched: 2.5.5 Target Size (Enhanced) is AAA and is
   the reason they exist. 2.5.8 sets a 24px floor and neither criterion
   requires spacing between targets, so collapsing the row gap to zero is
   safe: the targets still measure 44px and merely sit flush.

   203px -> ~159px, about 19% of the screen. Verified by measurement, not by
   eye; re-measure if these numbers change. */
@media (max-width: 40rem) {
  .masthead {
    padding-block: var(--space-1);
  }

  .masthead__inner {
    gap: 0.125rem var(--space-3);
  }

  .masthead nav ul {
    gap: 0 var(--space-3);
  }
}

.wordmark {
  font-family: var(--font-display);
  font-size: var(--step-1);
  color: var(--ink);
  text-decoration: none;
  letter-spacing: 0.01em;
  min-height: var(--target);
  display: inline-flex;
  align-items: center;
}

.wordmark:hover {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

nav ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-3);
  margin: 0;
  padding: 0;
}

/* 2.5.5: every interactive target is at least 44x44. */
nav a {
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding-inline: 0.125rem;
  font-size: var(--step--1);
  color: var(--ink-muted);
  text-decoration: none;
  letter-spacing: 0.02em;
}

nav a:hover,
nav a[aria-current="page"] {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

nav a[aria-current="page"] {
  text-decoration-thickness: 2px;
}

/* --- Prose --------------------------------------------------------------- */

.prose {
  max-width: var(--measure);
}

.prose > * + * {
  margin-block-start: var(--para-gap);
}

.prose p,
.prose li {
  /* 1.4.8: paragraph spacing and line spacing. */
  line-height: var(--leading);
}

.prose h2,
.prose h3,
.prose h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.25;
  margin-block-start: calc(var(--para-gap) * 1.4);
  margin-block-end: calc(var(--para-gap) * -0.55);
  text-wrap: balance;
}

.prose h2 { font-size: var(--step-2); }
.prose h3 { font-size: var(--step-1); }
.prose h4 { font-size: var(--step-0); letter-spacing: 0.02em; }

.prose ul,
.prose ol {
  padding-inline-start: 1.4em;
}

.prose li + li {
  margin-block-start: calc(var(--para-gap) * 0.45);
}

.prose a {
  color: var(--accent);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

.prose a:hover {
  text-decoration-thickness: 2px;
}

.prose strong { font-weight: 600; }

.prose blockquote {
  margin-inline: 0;
  padding-inline-start: var(--space-3);
  border-inline-start: 2px solid var(--rule);
  color: var(--ink-muted);
  font-family: var(--font-display);
  font-size: var(--step-1);
}

.prose code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--bg-sunk);
  padding: 0.1em 0.3em;
}

/* --- Page head ----------------------------------------------------------- */

.page-head {
  margin-block-end: var(--space-5);
}

.page-head h1 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--step-4);
  line-height: 1.12;
  letter-spacing: -0.01em;
  margin: 0;
  max-width: 22ch;
  text-wrap: balance;
}

.page-head .standfirst {
  margin-block-start: var(--space-3);
  font-size: var(--step-1);
  color: var(--ink-muted);
  max-width: 48ch;
  line-height: 1.5;
}

/* --- Eyebrow / meta ------------------------------------------------------ */

.eyebrow {
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--space-2);
}

.meta {
  font-size: var(--step--1);
  color: var(--ink-muted);
}

/* --- Plain summary ------------------------------------------------------
   3.1.5 Reading Level: supplementary plain-language version of every
   substantive page. This block is not decoration. Do not remove it.
   ------------------------------------------------------------------------ */

.plain {
  margin-block: var(--space-4);
  padding: var(--space-3);
  background: var(--bg-sunk);
  border-inline-start: 3px solid var(--accent);
  max-width: var(--measure);
}

.plain h2 {
  font-family: var(--font-body);
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--space-2);
  font-weight: 600;
}

.plain p {
  margin: 0;
  line-height: var(--leading);
}

.plain p + p {
  margin-block-start: calc(var(--para-gap) * 0.7);
}

/* --- Definitions --------------------------------------------------------
   3.1.3 Unusual Words: every term of art links to its glossary entry.
   ------------------------------------------------------------------------ */

.dfn {
  color: inherit;
  text-decoration-line: underline;
  text-decoration-style: dotted;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  font-style: normal;
}

.dfn:hover {
  text-decoration-style: solid;
}

/* --- Index lists --------------------------------------------------------- */

.index {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: var(--rule-width) solid var(--rule);
}

.index > li {
  border-bottom: var(--rule-width) solid var(--rule);
}

.index a.index__link {
  display: block;
  padding-block: var(--space-3);
  min-height: var(--target);
  text-decoration: none;
  color: inherit;
}

.index a.index__link:hover .index__title {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.index__title {
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.3;
  display: block;
  color: var(--accent);
}

.index__desc {
  display: block;
  margin: var(--space-1) 0 0;
  color: var(--ink-muted);
  max-width: var(--measure);
}

.index__meta {
  display: block;
  margin: var(--space-1) 0 0;
  font-size: var(--step--1);
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

/* --- Definition list (frameworks, credentials) --------------------------- */

.deflist {
  margin: 0;
  border-top: var(--rule-width) solid var(--rule);
}

.deflist > div {
  border-bottom: var(--rule-width) solid var(--rule);
  padding-block: var(--space-3);
}

.deflist dt {
  font-family: var(--font-display);
  font-size: var(--step-1);
  margin: 0 0 var(--space-1);
}

.deflist dd {
  margin: 0;
  color: var(--ink-muted);
  max-width: var(--measure);
}

.deflist dd + dd {
  margin-block-start: var(--space-1);
}

/* --- Standing block ------------------------------------------------------ */

.standing {
  border-top: var(--rule-width) solid var(--rule);
  padding-block-start: var(--space-3);
  margin-block-start: var(--space-4);
}

.standing__role {
  font-family: var(--font-display);
  font-size: var(--step-1);
  margin: 0 0 var(--space-1);
  line-height: 1.3;
}

.standing__body {
  margin: 0;
  color: var(--ink-muted);
  max-width: var(--measure);
}

/* --- Statement (homepage thesis) ----------------------------------------- */

.statement {
  font-family: var(--font-display);
  font-size: var(--step-3);
  line-height: 1.25;
  max-width: 26ch;
  margin: 0;
  text-wrap: balance;
}

.statement--sub {
  font-size: var(--step-1);
  color: var(--ink-muted);
  max-width: 44ch;
  margin-block-start: var(--space-3);
  line-height: 1.45;
}

/* --- Section ------------------------------------------------------------- */

.section {
  margin-block-start: var(--space-6);
}

.section > h2 {
  font-family: var(--font-body);
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-muted);
  font-weight: 600;
  margin: 0 0 var(--space-3);
  padding-block-end: var(--space-2);
  border-bottom: var(--rule-width) solid var(--rule);
}

/* --- Quote --------------------------------------------------------------- */

.quote {
  margin: 0;
  max-width: var(--measure);
}

.quote blockquote {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-2);
  line-height: 1.4;
  color: var(--ink);
}

.quote--stacked {
  padding-block-end: var(--space-4);
  border-bottom: var(--rule-width) solid var(--rule);
  margin-block-end: var(--space-4);
}

.quote--stacked blockquote {
  font-size: var(--step-1);
}

.field__optional {
  font-weight: 400;
  color: var(--ink-muted);
  letter-spacing: 0;
}

.quote figcaption {
  margin-block-start: var(--space-3);
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.5;
}

/* --- Poem ---------------------------------------------------------------- */

.poem {
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.75;
  white-space: pre-line;
  max-width: 44ch;
  margin: 0;
}

/* --- Forms --------------------------------------------------------------
   3.3.6 Error Prevention (All): the contact form uses an explicit review
   step before submission. See routes/contact.ts.
   3.3.2 Labels or Instructions: every field is labelled and described.
   ------------------------------------------------------------------------ */

.field {
  margin-block-end: var(--space-3);
  max-width: 34rem;
}

.field label {
  display: block;
  font-size: var(--step--1);
  letter-spacing: 0.04em;
  margin-block-end: var(--space-1);
  font-weight: 600;
}

.field .hint {
  display: block;
  font-size: var(--step--1);
  color: var(--ink-muted);
  margin-block-end: var(--space-1);
}

.field input,
.field textarea {
  width: 100%;
  min-height: var(--target);
  padding: var(--space-2);
  font: inherit;
  font-size: var(--step-0);
  color: var(--ink);
  background: var(--bg);
  border: var(--rule-width) solid var(--ink-muted);
  border-radius: 0;
}

.field textarea {
  min-height: 9rem;
  resize: vertical;
}

.field input:focus-visible,
.field textarea:focus-visible {
  border-color: var(--accent);
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--target);
  min-width: var(--target);
  padding: var(--space-2) var(--space-4);
  font: inherit;
  font-size: var(--step-0);
  letter-spacing: 0.02em;
  color: var(--bg);
  background: var(--accent);
  border: var(--rule-width) solid var(--accent);
  border-radius: 0;
  cursor: pointer;
  text-decoration: none;
}

.button:hover {
  background: var(--ink);
  border-color: var(--ink);
}

.button--quiet {
  color: var(--accent);
  background: transparent;
}

.button--quiet:hover {
  color: var(--bg);
}

/* honeypot: removed from the accessibility tree and from view */
.trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- Next step ----------------------------------------------------------
   The onward route at the end of a page. A rule and space, not a panel: the
   evidence above it (assessments, record figures, doctrine) should stay the
   loudest thing on the page. Sized at --step-1 so it is unmissable at a
   glance without becoming a marketing button.
   ------------------------------------------------------------------------ */

.next-step {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-3);
  border-top: var(--rule-width) solid var(--rule);
  max-width: var(--measure);
}

.next-step__link {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.35;
}

.next-step__link a {
  color: var(--accent);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  /* 2.5.5: this was written as `padding-block: 0.4rem` on the assumption that
     it would clear 44px. Measured in the browser it came to 40px: the line box
     at --step-1 / 1.35 is ~27px, and 2 x 6.4px of padding leaves it 4px short.
     Padding arithmetic against a clamp()ed font size is guesswork, so assert
     the floor directly with the --target token instead. inline-flex is what
     lets min-height apply while the label still wraps on narrow screens. */
  display: inline-flex;
  align-items: center;
  min-height: var(--target);
  padding-block: 0.4rem;
}

.next-step__link a:hover {
  text-decoration-thickness: 2px;
}

.next-step__note {
  margin: var(--space-1) 0 0;
  font-size: var(--step--1);
  color: var(--ink-muted);
}

/* --- Notice -------------------------------------------------------------- */

.notice {
  padding: var(--space-3);
  border: var(--rule-width) solid var(--rule);
  background: var(--bg-sunk);
  max-width: var(--measure);
}

.notice p:first-child { margin-block-start: 0; }
.notice p:last-child { margin-block-end: 0; }

/* --- Breadcrumb ---------------------------------------------------------
   2.4.8 Location: a breadcrumb trail on every page below the root.
   ------------------------------------------------------------------------ */

.crumbs {
  margin-block-end: var(--space-4);
  font-size: var(--step--1);
}

.crumbs ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  color: var(--ink-muted);
}

.crumbs li + li::before {
  content: "/";
  margin-inline-end: var(--space-1);
  color: var(--rule);
}

.crumbs a {
  color: var(--ink-muted);
  min-height: var(--target);
  display: inline-flex;
  align-items: center;
}

/* --- Footer -------------------------------------------------------------- */

.footer {
  border-top: var(--rule-width) solid var(--rule);
  padding-block: var(--space-4) var(--space-5);
  font-size: var(--step--1);
  color: var(--ink-muted);
}

.footer__grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
  .footer__grid {
    grid-template-columns: 1fr auto;
    align-items: start;
  }
}

.footer h2 {
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 600;
  margin: 0 0 var(--space-2);
  color: var(--ink-muted);
}

.footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer a {
  color: var(--ink-muted);
  min-height: var(--target);
  display: inline-flex;
  align-items: center;
  text-decoration-line: underline;
  text-underline-offset: 0.18em;
}

.footer a:hover { color: var(--ink); }

/* --- Theme control ------------------------------------------------------
   1.4.8: user-selectable foreground and background. Works without
   JavaScript via the OS preference; the control persists an explicit choice.
   ------------------------------------------------------------------------ */

.themes {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0;
  padding: 0;
  border: 0;
}

.themes legend {
  font-size: var(--step--1);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 0;
  margin-block-end: var(--space-2);
}

/* 1.4.11 Non-text Contrast: a control's visual boundary needs 3:1. These
   were bounded by --rule, which is 1.46:1 on paper and 1.48:1 on ink: it is
   intended for hairline dividers between blocks of text, where no contrast
   minimum applies, and it made four buttons read as plain labels. --ink-muted
   gives 8.4:1 on paper, 8.0:1 on ink and 8.4:1 on sepia.

   axe-core passes this page, because it does not evaluate a boundary drawn
   only in CSS against its background, which is why the ratio was computed by
   hand. Do not swap this back to --rule for visual quietness. */
.themes button {
  min-height: var(--target);
  min-width: var(--target);
  padding-inline: var(--space-2);
  font: inherit;
  font-size: var(--step--1);
  color: var(--ink-muted);
  background: transparent;
  border: var(--rule-width) solid var(--ink-muted);
  cursor: pointer;
}

.themes button[aria-pressed="true"] {
  color: var(--bg);
  background: var(--ink);
  border-color: var(--ink);
}

/* --- Impact figures -----------------------------------------------------
   The strongest quantified proof on the site. Rendered as text in the DOM:
   never animated from zero, because a number that only exists in JavaScript
   cannot be read by a language model, a screen reader, or anyone with
   scripting disabled.
   ------------------------------------------------------------------------ */

.figures {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: 1fr;
  margin: 0;
  border-top: var(--rule-width) solid var(--rule);
  padding-block-start: var(--space-3);
}

@media (min-width: 34rem) {
  .figures {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-4);
  }
}

.figures > div {
  margin: 0;
}

.figures dt {
  font-family: var(--font-display);
  font-size: var(--step-3);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.figures dd {
  margin: var(--space-1) 0 0;
  font-size: var(--step--1);
  color: var(--ink-muted);
  line-height: 1.4;
}

.figures__note {
  margin: var(--space-3) 0 0;
  font-size: var(--step--1);
  color: var(--ink-muted);
  max-width: var(--measure);
}

/* --- Diagrams -----------------------------------------------------------
   Inline SVG, themed with the same tokens as everything else so a diagram
   follows the reader's chosen theme including high contrast. No third-party
   request, no extra round trip, and readable to a screen reader and a
   language model via title and desc.
   ------------------------------------------------------------------------ */

.figure {
  margin: var(--space-5) 0;
  max-width: 100%;
}

.figure figcaption {
  margin-block-start: var(--space-3);
  font-size: var(--step--1);
  color: var(--ink-muted);
  max-width: var(--measure);
  line-height: 1.5;
}

.dgm {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}

/* Groups one unit of a diagram. Kept as a hook so panels can be targeted
   together, and so the SVG source reads as structure rather than a bag of
   shapes. */
.dgm-panel {
  vector-effect: non-scaling-stroke;
}

.dgm-box {
  fill: none;
  stroke: var(--rule);
  stroke-width: 1;
}

[data-theme='contrast'] .dgm-box {
  stroke: var(--ink);
  stroke-width: 2;
}

.dgm-box--key {
  fill: var(--bg-sunk);
  stroke: var(--accent);
}

.dgm-h {
  fill: var(--ink-muted);
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.dgm-l {
  fill: var(--ink);
  font-family: var(--font-display);
  font-size: 15px;
}

.dgm-n {
  fill: var(--ink-muted);
  font-family: var(--font-body);
  font-size: 12px;
}

/* Inbound: the thing that cost you. Drawn heavier, and dashed so the
   distinction survives for a reader who cannot rely on colour. */
.dgm-in {
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
  fill: none;
}

.dgm-out {
  stroke: var(--ink-muted);
  stroke-width: 1.5;
  fill: none;
}

.dgm-cut {
  stroke: var(--rule);
  stroke-width: 1;
  stroke-dasharray: 2 4;
}

/* --- Portrait ------------------------------------------------------------ */

.portrait {
  margin: var(--space-4) 0 0;
  max-width: 20rem;
}

.portrait img {
  display: block;
  width: 100%;
  height: auto;
}

.portrait figcaption {
  margin-block-start: var(--space-2);
  font-size: var(--step--1);
  color: var(--ink-muted);
}

/* --- Photographs ---------------------------------------------------------
   Wider than the portrait and always captioned, because these carry an
   evidential claim rather than a face. `aspect-ratio` is not set here: the
   width and height attributes are on the img itself, which reserves the right
   box before the bytes arrive and so costs no layout shift.
   ------------------------------------------------------------------------ */

.photo {
  margin: var(--space-5) 0;
  max-width: 42rem;
}

.photo img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--rule);
}

.photo figcaption {
  margin-block-start: var(--space-3);
  font-size: var(--step--1);
  color: var(--ink-muted);
  max-width: var(--measure);
  line-height: 1.5;
}

/* Small, beside text. Confirms there is a person here without making the
   page about the photograph. */
.portrait--inline {
  float: right;
  width: 120px;
  margin: 0 0 var(--space-3) var(--space-3);
  shape-outside: margin-box;
}

@media (max-width: 30rem) {
  .portrait--inline {
    float: none;
    margin-inline: 0;
  }
}

/* --- Utilities ----------------------------------------------------------
   Spacing helpers exist because the content security policy forbids inline
   `style` attributes. A `style="…"` on an element here is silently dropped by
   the browser: it does not warn, it simply does not apply. Use these.
   ------------------------------------------------------------------------ */

.mt-1 { margin-block-start: var(--space-1); }
.mt-3 { margin-block-start: var(--space-3); }
.mt-4 { margin-block-start: var(--space-4); }
.mt-5 { margin-block-start: var(--space-5); }
.mb-4 { margin-block-end: var(--space-4); }
.preserve-lines { white-space: pre-line; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.stack-3 > * + * { margin-block-start: var(--space-3); }
.stack-4 > * + * { margin-block-start: var(--space-4); }

/* --- Print --------------------------------------------------------------
   The biography and the three doctrine documents are the pages people
   actually print: a doctrine argument gets taken into a meeting, and the
   biography gets attached to an introduction. Everything below serves those
   two cases. It is not a "make it greyscale" afterthought.

   Five things were wrong with the previous fifteen-line version, and each
   fix below is annotated with which one it addresses.

   (1) THEME LEAKAGE, the serious one. The old block set `body { background:
       #fff; color: #000 }` but left the custom properties alone. Every
       descendant on this site draws its colour from var(--ink),
       var(--ink-muted), var(--rule), var(--bg-sunk) or var(--accent), so a
       reader printing in the ink theme, or merely on an OS set to dark mode
       (which triggers the prefers-color-scheme override on
       :root:not([data-theme])), sent pale grey text to the printer inside
       panels filled dark. The body was white and the words were not. The
       properties are therefore re-declared below, at a specificity that
       beats both [data-theme="…"] and the dark-mode override.

   (2) FLUID TYPE. Every --step-* token is a clamp() with a vw term, so the
       printed size depended on the paper viewport. Paper has a fixed width,
       so the scale is restated in pt: the one place on this site where a
       physical unit is the correct unit.

   (3) WASTED PAPER. --para-gap: 2.4em and --space-6: 6.5rem are right for a
       screen you scroll and wrong for a sheet you pay for. --measure: 68ch
       also left a wide unused right margin on A4. Both are retuned.

   (4) CHROME. Only the nav, the theme control and the skip link were
       hidden. The wordmark and its rule, the breadcrumb trail and the whole
       footer link list still printed.

   (5) PAGE BREAKS. There were no break rules at all, so headings stranded
       at the foot of a sheet and deflist rows split across sides.

   And one thing that was missing rather than wrong: provenance. /colophon/
   invites the reader to check this site's claims, which a photocopy cannot
   support if it does not say where it came from. The canonical URL is
   printed once at the top of the sheet from a data- attribute on <main>,
   which is the only added markup this change needs.
   ------------------------------------------------------------------------ */

@page {
  size: A4;
  /* Generous inner margin: these are documents that get stapled or punched. */
  margin: 18mm 16mm 20mm 20mm;
}

@media print {
  /* --- (1) Neutralise the theme -----------------------------------------
     Declared on all three selectors that can carry a theme so this wins
     regardless of what the reader chose or what their OS reports. Pure
     black on pure white: on paper there is no 7:1 contrast question to
     answer, and grey text is simply harder to read under bad lighting.
     --bg-sunk becomes white because panel fills are dropped below anyway,
     and --rule becomes a mid grey that still resolves after photocopying.
     -------------------------------------------------------------------- */
  :root,
  :root:not([data-theme]),
  [data-theme="paper"],
  [data-theme="ink"],
  [data-theme="sepia"],
  [data-theme="contrast"] {
    --bg: #fff;
    --bg-sunk: #fff;
    --ink: #000;
    --ink-muted: #000;
    --accent: #000;
    --rule: #999;
    --focus: #000;
    --rule-width: 1px;

    /* (2) Fixed physical type. 11pt body is the smallest that stays
       comfortable in a serif at arm's length; the display sizes step down
       hard from screen, where they were doing work that a printed page
       does not need them to do. */
    --step--1: 8.5pt;
    --step-0: 10.5pt;
    --step-1: 12pt;
    --step-2: 13.5pt;
    --step-3: 16pt;
    --step-4: 20pt;

    /* (3) Retuned rhythm. --para-gap at 2.4em was set to satisfy 1.4.8
       paragraph spacing on screen; 1.05em still clears the 1.5x line
       spacing that criterion asks for, while fitting roughly twice the
       text on a sheet. --measure widens because the A4 text column is
       already constrained by @page, not by this token. */
    --leading: 1.45;
    --para-gap: 1.05em;
    --measure: none;

    --space-1: 0.2rem;
    --space-2: 0.35rem;
    --space-3: 0.6rem;
    --space-4: 0.9rem;
    --space-5: 1.2rem;
    --space-6: 1.5rem;

    /* 2.5.5 target size is a pointer criterion. Nothing on paper is a
       target, and a 2.75rem min-height on every link is what was pushing
       the breadcrumb and footer lists to absurd heights. */
    --target: 0;
  }

  html {
    /* A printed page is not scrolled. */
    scroll-behavior: auto;
  }

  body {
    background: #fff;
    color: #000;
    font-family: var(--font-display);
    font-size: var(--step-0);
    line-height: var(--leading);
  }

  /* --- (4) Chrome that must not reach the paper --------------------------
     The nav, wordmark and footer link list are navigation: they are useless
     in ink and they cost a third of the first sheet. The theme control is a
     form. The skip link is an accessibility affordance for keyboard focus.
     The onward "next step" prompt is a call to action for a reader who can
     click.
     -------------------------------------------------------------------- */
  .skip,
  .masthead,
  .crumbs,
  .themes,
  .footer,
  .next-step,
  .trap {
    display: none !important;
  }

  /* The shell is a min-height:100vh grid on screen. On paper 100vh is one
     sheet, which forces a spurious page break on any short document. */
  .shell {
    display: block;
    min-height: 0;
  }

  .wrap,
  .wrap--wide {
    max-width: none;
    padding-inline: 0;
  }

  main {
    padding-block: 0;
  }

  /* --- Provenance -------------------------------------------------------
     Printed once, before the title, from the canonical URL that layout.tsx
     puts on <main data-print-source>. A doctrine sheet circulating in a
     meeting is a claim; this is how a sceptical reader gets back to the
     source and to the version and revision date already rendered in the
     page body. Uses ::before on main rather than a position:fixed running
     header, because a fixed header repeats over body text in every
     engine and clips unpredictably.
     -------------------------------------------------------------------- */
  main[data-print-source]::before {
    content: "Printed from " attr(data-print-source);
    display: block;
    font-family: var(--font-mono);
    font-size: 7.5pt;
    color: #000;
    padding-block-end: 2mm;
    margin-block-end: 5mm;
    border-block-end: 0.5pt solid #999;
    /* Long URLs must not push the column wider than the sheet. */
    word-break: break-all;
  }

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

  .page-head {
    margin-block-end: var(--space-4);
  }

  .page-head h1 {
    font-size: var(--step-4);
    max-width: none;
  }

  .page-head .standfirst {
    font-size: var(--step-1);
    max-width: none;
  }

  .prose,
  .prose h2,
  .prose h3,
  .prose h4 {
    max-width: none;
  }

  .prose h2 { font-size: var(--step-2); }
  .prose h3 { font-size: var(--step-1); }
  .prose h4 { font-size: var(--step-0); }

  /* On screen these headings pull their following paragraph up with a
     negative bottom margin. In print the tighter --para-gap makes that
     collapse the gap entirely, so state both margins explicitly. */
  .prose h2,
  .prose h3,
  .prose h4 {
    margin-block-start: 1.6em;
    margin-block-end: 0.4em;
  }

  .statement {
    font-size: var(--step-3);
    max-width: none;
  }

  .statement--sub {
    font-size: var(--step-1);
    max-width: none;
  }

  /* --- Panels become rules ---------------------------------------------
     printBackground is off by default in every browser's print dialogue,
     so a filled panel arrives as an outline with no fill: a border round
     nothing. These blocks carry meaning (the plain-language summary is
     there for 3.1.5, the notice carries a caveat), so they keep a single
     hairline rule to stay distinguishable, and lose the fill and the
     heavy accent bar.
     -------------------------------------------------------------------- */
  .plain {
    background: none;
    border-inline-start: 0;
    border-block: 0.5pt solid #999;
    padding: 2mm 0;
    margin-block: var(--space-4);
    max-width: none;
  }

  .notice {
    background: none;
    border: 0.5pt solid #999;
    padding: 2.5mm 3mm;
    max-width: none;
  }

  .prose code {
    background: none;
    border: 0.5pt solid #999;
  }

  .prose blockquote {
    border-inline-start: 1pt solid #999;
  }

  /* --- Form controls ----------------------------------------------------
     The enquiry form is worth printing: someone drafts answers on paper
     before typing them. But .button sets `color: var(--bg)` against
     `background: var(--accent)`, which was the right way round on screen
     and inverts to white-on-white here, because printBackground drops the
     fill and leaves the label invisible. Restate it as ink on paper.
     -------------------------------------------------------------------- */
  .button,
  .button--quiet {
    color: #000;
    background: none;
    border: 0.75pt solid #000;
    padding: 1mm 3mm;
    min-height: 0;
  }

  /* Input outlines are the point of a printed form: they are where a reader
     writes. Kept, but at a hairline so a sheet of them does not read as a
     grid, and shortened, since --target no longer inflates them. */
  .field input,
  .field textarea {
    border: 0.5pt solid #000;
    background: none;
    min-height: 0;
    padding: 1.5mm;
  }

  .field textarea {
    min-height: 22mm;
  }

  /* --- Images -----------------------------------------------------------
     The portrait is decoration on a printed biography and floats awkwardly
     into a narrower column. The evidential photographs stay, because the
     caption makes a claim about them, but they are capped so one does not
     take a whole sheet.
     -------------------------------------------------------------------- */
  .portrait,
  .portrait--inline {
    display: none;
  }

  .photo {
    max-width: 100%;
    margin-block: var(--space-4);
  }

  .photo img {
    max-height: 90mm;
    width: auto;
    border: 0.5pt solid #999;
  }

  .figure {
    margin-block: var(--space-4);
  }

  /* Diagram strokes are theme variables; the overrides above already
     resolve them to black on white. Only the fill needs stating, since a
     white fill on white paper is invisible either way and printBackground
     would otherwise be needed to see the key box. */
  .dgm-box--key {
    fill: none;
    stroke: #000;
  }

  /* --- (5) Page breaks --------------------------------------------------
     `break-*` is the current property; `page-break-*` is the legacy alias
     and is still what some print engines honour. Both are emitted
     deliberately: this is not duplication to be tidied away.
     -------------------------------------------------------------------- */
  h1, h2, h3, h4 {
    break-after: avoid;
    page-break-after: avoid;
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .section > h2 {
    /* The uppercase section rules read as dividers, so let one start a
       fresh sheet rather than sit alone at the foot of the previous one. */
    break-after: avoid;
    page-break-after: avoid;
  }

  .plain,
  .notice,
  .quote,
  .figure,
  .photo,
  .standing,
  .deflist > div,
  .index > li,
  .figures > div,
  blockquote,
  figcaption,
  tr {
    break-inside: avoid;
    page-break-inside: avoid;
  }

  /* 1.4.8 asks for no more than 80 characters per line and no forced
     hyphenation; orphans/widows are a separate typographic concern and
     two lines is the conventional floor. */
  p, li, dd, dt {
    orphans: 2;
    widows: 2;
  }

  /* --- Link destinations ------------------------------------------------
     A printed link is dead unless its destination is on the page, and this
     is the site where that matters most: every doctrine argument is backed
     by a list of sources, and /colophon/ invites the reader to check them.

     The rule is therefore in two halves, because the naive versions are
     both wrong.

     Expanding NOTHING but .prose (what the previous block did) missed the
     single most important case. The doctrine source citations are not in
     prose at all: they are .index__link items, so a printed doctrine sheet
     listed its sources by title with no way to reach any of them. That is
     precisely the claim /colophon/ says a reader may check, rendered
     uncheckable by a stylesheet.

     Expanding EVERYTHING is also wrong. These pages are dense with .dfn
     glossary links (3.1.3 Unusual Words), and every one would inject
     "(/glossary/#term)" into the middle of a sentence.

     So: every absolute external URL is expanded wherever it appears, since
     those are the citations. Internal links are expanded only in running
     text, where they are cross-references a reader might want to follow,
     and are left bare in index and definition lists, where the title
     already names the destination page. Glossary terms and same-page
     fragments are never expanded: a fragment points into the sheet the
     reader is already holding.
     -------------------------------------------------------------------- */
  a {
    color: #000;
    text-decoration: underline;
  }

  /* The citations. These carry the evidential weight. */
  a[href^="http"]::after,
  /* Internal cross-references in running text. */
  .prose a[href^="/"]::after,
  .plain a[href^="/"]::after,
  figcaption a[href^="/"]::after {
    content: " <" attr(href) ">";
    font-family: var(--font-mono);
    font-size: 7.5pt;
    font-weight: 400;
    word-break: break-all;
    /* The underline belongs to the link text, which is what a reader would
       have clicked. Carrying it under the appended URL as well reads as one
       long underlined run and makes the URL harder to transcribe by eye,
       which is the only thing it is there for. */
    text-decoration: none;
  }

  /* Withdrawn, in every container: see the note above. */
  a.dfn::after,
  a[href^="#"]::after {
    content: "" !important;
  }

  /* .index__link is a display:block wrapper around a title, a description
     and a meta line, so its expanded URL lands under the meta line rather
     than beside the title. Give it its own line and keep it out of the
     text colour flow of the title above. */
  .index a[href^="http"]::after {
    display: block;
    margin-block-start: 0.15em;
  }

  .dfn {
    /* The dotted underline signals "there is a definition behind this",
       which is not true of a sheet of paper. */
    text-decoration: none;
  }

  /* Nothing is focused on paper. */
  :focus-visible {
    outline: none;
  }
}
