/*
 * Site rules on top of @mctlhq/css: the CSS-driven bilingual/theme toggle
 * (.l.en/.l.ru, .t.dark/.t.light) and basic page layout. This file is the
 * source of truth; `npm run vendor` copies it to public/styles/site.css,
 * which Base.astro links to so it is served from public/, never bundled or
 * inlined by Astro.
 */

/* Metric-matched local fallback for Onest (issue #50, Q6): a preload plus
 * this fallback is what stops the swap from moving anything, rather than
 * font-display: optional, which would risk never showing Onest at all on a
 * slow connection. The percentages are starting values derived from
 * Onest's own vertical metrics against a generic sans; a Lighthouse run is
 * the named reviewer step that confirms them (this cannot be measured in a
 * headless clone). Declared here, not in public/assets/mctl/mctl.css: that
 * file is SHA-256-pinned by scripts/vendor-assets.mjs and any edit to it
 * fails the next vendor run. Arial/Helvetica Neue are macOS and Windows
 * only, and Liberation Sans/DejaVu Sans are not guaranteed on every Linux
 * install either -- on Android and most Linux, none of the four resolves,
 * so `local()` falls through the whole list and the override silently does
 * nothing there. Roboto (Android's system sans, also shipped on ChromeOS
 * and many Linux desktops) and Noto Sans (the broadest cross-platform sans
 * covering the rest of Linux) are added so the override actually applies
 * outside macOS/Windows too. */
@font-face {
  font-family: 'Onest Fallback';
  src:
    local('Arial'),
    local('Helvetica Neue'),
    local('Liberation Sans'),
    local('DejaVu Sans'),
    local('Roboto'),
    local('Noto Sans');
  size-adjust: 96%;
  ascent-override: 96%;
  descent-override: 24%;
  line-gap-override: 0%;
}
:root {
  --font-display: 'Onest', 'Onest Fallback', system-ui, -apple-system, sans-serif;
}

/* Language toggle. */
:root[data-lang='en'] .l.ru {
  display: none;
}
:root[data-lang='ru'] .l.en {
  display: none;
}

/* Theme toggle. */
:root[data-theme='dark'] .t.light {
  display: none;
}
:root[data-theme='light'] .t.dark {
  display: none;
}

/* Fallback for a future document without data-theme; Base.astro always
 * authors data-theme="dark" so this is inert here but keeps the scale live. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --surface-bg: var(--mctl-surface-light-bg);
    --surface-fg: var(--mctl-surface-light-fg);
    --surface-fg-muted: var(--mctl-surface-light-fg-muted);
    --surface-line: var(--mctl-surface-light-line);
  }
}

/* Layout. */
:root {
  --content-max: 768px;
  /* 768px / 9.6 = 80px -- the largest size at which the longer hero string
   * ("Дмитрий Машков") stays on one line inside --content-max; see the
   * 2026-09-12 journal entry. */
  --hero-name-cap: calc(var(--content-max) / 9.6);
}
body {
  padding-inline: var(--mctl-space-4);
}
.site-header,
.site-footer,
main {
  max-width: var(--content-max);
  margin-inline: auto;
}
code,
pre,
.font-mono {
  font-family: var(--font-mono);
  overflow-wrap: anywhere;
}
:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
}

/* Navigation. */
.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--mctl-space-4);
  padding-block: var(--mctl-space-2);
  border-bottom: 1px solid var(--surface-line);
}
.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--mctl-space-4);
  padding-block: 0;
}
.site-nav a {
  color: var(--surface-fg);
  text-decoration: none;
}
.site-nav a:hover {
  color: var(--accent);
}
/* Current-page marking (Nav.astro derives aria-current from
 * Astro.url.pathname at build time; matched on attribute presence so both
 * "page" and "true" hit). Colour and underline together, so colour is never
 * the sole indicator. */
.site-nav a[aria-current] {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 0.25em;
  text-decoration-thickness: 2px;
}

/* Skip link: the first focusable element in <body>, clipped out of layout
 * until it receives focus. No animation or transition (test/a11y.test.ts). */
.skip-link {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.skip-link:focus {
  position: fixed;
  inset-block-start: var(--mctl-space-2);
  inset-inline-start: var(--mctl-space-2);
  inline-size: auto;
  block-size: auto;
  margin: 0;
  overflow: visible;
  clip-path: none;
  white-space: normal;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-inline: var(--mctl-space-4);
  background: var(--surface-elevated);
  color: var(--surface-fg);
  border: 1px solid var(--surface-line);
  border-radius: var(--mctl-radius-md);
}

/* Breadcrumb (journal and ADR pages). Separators come from CSS only, so no
 * screen reader announces them. */
.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--mctl-space-2);
  list-style: none;
  margin: 0 0 var(--mctl-space-3);
  padding: 0;
  font-size: var(--mctl-typography-font-size-sm);
}
.breadcrumb li + li::before {
  content: '/';
  margin-inline-end: var(--mctl-space-2);
  color: var(--surface-fg-muted);
}

/* Icon toggles (issue #108, Q18): one button per CSS stance -- .t.dark/
 * .t.light, .l.en/.l.ru -- the same mutually-exclusive display:none
 * mechanism as every other bilingual/theme element on the site, just one
 * glyph or label each instead of a two-button segmented pair. No inner
 * divider and no overflow: the lesson from the Q16 segmented control (an
 * overflow:hidden container clips the :focus-visible ring) doesn't even
 * arise here, but is worth restating: this class must never gain one. */
.icon-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 32px;
  block-size: 32px;
  min-inline-size: 32px;
  min-block-size: 32px;
  padding: 0;
  border: 1px solid var(--surface-line);
  border-radius: var(--mctl-radius-lg);
  background: var(--surface-card);
  color: var(--surface-fg-muted);
  cursor: pointer;
}
.icon-toggle:hover {
  background: var(--surface-elevated);
}
.icon-toggle svg {
  inline-size: 20px;
  block-size: 20px;
}
.lang-toggle {
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: var(--mctl-typography-font-weight-semibold);
  letter-spacing: 0.02em;
}
.toggle-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--mctl-space-4);
  padding-block: 0;
  margin-inline-start: auto;
  justify-content: flex-end;
}
.toggle-bar noscript {
  flex-basis: 100%;
  text-align: end;
}

/* Footer. */
.site-footer {
  display: flex;
  flex-wrap: wrap;
  gap: var(--mctl-space-4);
  align-items: center;
  padding-block: var(--mctl-space-6);
  color: var(--surface-fg-muted);
  border-top: 1px solid var(--surface-line);
}
.site-footer a {
  color: inherit;
}

/* Hero (home page). */
.eyebrow {
  display: block;
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-sm);
  color: var(--surface-fg-muted);
  margin-block-end: var(--mctl-space-2);
}
.hero-name {
  font-family: var(--font-display);
  font-weight: var(--mctl-typography-font-weight-bold);
  font-size: min(var(--mctl-typography-font-size-hero), var(--hero-name-cap));
  line-height: var(--mctl-typography-line-height-hero);
  letter-spacing: var(--mctl-typography-letter-spacing-hero);
  margin-block: var(--mctl-space-6) var(--mctl-space-4);
}
.thesis {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-lede);
  line-height: var(--mctl-typography-line-height-lede);
  margin-block-end: var(--mctl-space-3);
}
.subline {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-body);
  line-height: var(--mctl-typography-line-height-body);
  color: var(--surface-fg-muted);
  margin-block-end: var(--mctl-space-6);
}

/* Stat tiles. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--mctl-space-5);
  padding-block: var(--mctl-space-5);
  border-block: 1px solid var(--surface-line);
}
.stat {
  display: flex;
  flex-direction: column;
  gap: var(--mctl-space-1);
}
.stat-value {
  font-family: var(--font-display);
  font-size: clamp(28px, 8vw, 40px);
  font-variant-numeric: tabular-nums;
  line-height: var(--mctl-typography-line-height-tight);
}
.stat-label {
  font-size: var(--mctl-typography-font-size-sm);
  color: var(--surface-fg-muted);
}
.stat-caption {
  grid-column: 1 / -1;
  font-size: var(--mctl-typography-font-size-xs);
  color: var(--surface-fg-muted);
  margin: 0;
}

/* CTAs. */
.ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--mctl-space-4);
  padding-block: var(--mctl-space-6);
}
.cta {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-inline: var(--mctl-space-4);
  border-radius: var(--mctl-radius-md);
  border: 1px solid var(--surface-line);
  color: var(--surface-fg);
  text-decoration: none;
}
.cta:hover {
  color: var(--accent);
  border-color: var(--accent);
}

/* Primary CTA (issue #98, Q15): a filled variant of .cta so the primary
 * action (#contact) is visually distinguishable from the secondary one
 * (/work/) without a second colour pair -- accent-fg on accent is already
 * proven in scripts/check-contrast.mjs's PAIRS list. The :hover/:visited
 * pins live in the "Pins" section below, after .cta:visited:not(:hover),
 * so the equal-specificity tie between the two resolves in their favour. */
.cta-primary {
  background-color: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}

/* Collapsible blocks. */
.block {
  border-top: 1px solid var(--surface-line);
  padding-block: var(--mctl-space-3);
}
.block > summary {
  cursor: pointer;
  min-block-size: 44px;
  padding-block: var(--mctl-space-3);
  display: list-item;
}
.block > summary h2 {
  display: inline;
  font: inherit;
  margin: 0;
}
.block ul {
  margin: 0;
  padding-inline-start: var(--mctl-space-5);
}
.block li {
  margin-block-end: var(--mctl-space-2);
}
.block p {
  margin-block-end: var(--mctl-space-2);
}

/* Identity, capability and contact sections (home page, issue #98, Q15):
 * the same top-border-plus-block-padding rhythm .block already uses, so the
 * new always-visible sections read as siblings of the two remaining
 * disclosures rather than a different kind of content. */
#about,
#capabilities,
#contact {
  border-top: 1px solid var(--surface-line);
  padding-block: var(--mctl-space-5);
}
#about h2,
#capabilities h2,
#contact h2 {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-lg);
  line-height: var(--mctl-typography-line-height-tight);
  margin-block-end: var(--mctl-space-3);
}
#about p,
#contact p {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-body);
  line-height: var(--mctl-typography-line-height-body);
  margin-block-end: var(--mctl-space-3);
}
.capability-list h3 {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-lede);
  line-height: var(--mctl-typography-line-height-tight);
  margin-block: var(--mctl-space-4) var(--mctl-space-1);
}
.capability-list h3:first-child {
  margin-block-start: 0;
}
.capability-list p {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-body);
  line-height: var(--mctl-typography-line-height-body);
  color: var(--surface-fg-muted);
  margin: 0;
}
.contact-list {
  list-style: none;
  margin: var(--mctl-space-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--mctl-space-2);
}
.contact-list a {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
}

/* Text for assistive technology only: present in the accessibility tree
 * (so a <summary> can carry a distinct accessible name) but not painted.
 * display:none or visibility:hidden would remove it from the tree, which
 * is the whole point of the class. */
.visually-hidden {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Work page. */
.project {
  padding-block: var(--mctl-space-5);
  border-top: 1px solid var(--surface-line);
}
.project-name {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-lg);
  line-height: var(--mctl-typography-line-height-tight);
  margin-block-end: var(--mctl-space-2);
}
.project-summary {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-body);
  line-height: var(--mctl-typography-line-height-body);
  color: var(--surface-fg-muted);
  margin-block-end: var(--mctl-space-3);
}
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--mctl-space-2);
  list-style: none;
  margin: 0 0 var(--mctl-space-3);
  padding: 0;
}
.chip {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-xs);
  color: var(--surface-fg-muted);
  background: var(--surface-elevated);
  border: 1px solid var(--surface-line);
  border-radius: var(--mctl-radius-pill);
  padding: var(--mctl-space-1) var(--mctl-space-3);
}
.project-links {
  list-style: none;
  margin: 0 0 var(--mctl-space-2);
  padding: 0;
}
.project-links a {
  color: var(--surface-fg);
}

/* Content links: any <a> inside <main> that carries no component class of its
 * own. The UA default (#0000EE / visited #551A8B) is 2.10:1 / 1.79:1 on the
 * dark surface; --accent measures 5.40:1 (surface-bg) and 5.19:1
 * (surface-elevated) dark, 4.81:1 and 5.11:1 light. :visited is pinned to the
 * same colour so #551A8B never renders. --accent-highlight on :hover measures
 * 8.53:1 and 8.19:1 dark, 6.30:1 and 6.70:1 light. */
main a {
  color: var(--accent);
}
main a:visited:not(:hover) {
  color: var(--accent);
}
main a:hover {
  color: var(--accent-highlight);
}

/* Pins. main a:hover (0,1,2) outranks .cta (0,1,0) only on the element count,
 * and main a:visited:not(:hover) (0,2,2) outranks both .cta:visited (0,2,0)
 * and .project-links a:visited (0,2,1). :visited:not(:hover) keeps each pin
 * above the content rules AND out of the way of its own :hover rule, so the
 * result does not depend on source order. */
.cta:visited:not(:hover) {
  color: var(--surface-fg);
}
/* .cta-primary keeps accent-fg on its filled accent background in every
 * state, unlike the outline .cta above: hover is distinguished by an
 * underline (a non-colour affordance), not a colour change. */
.cta-primary:hover {
  color: var(--accent-fg);
  text-decoration: underline;
}
.cta-primary:visited:not(:hover) {
  color: var(--accent-fg);
}
.project-links a:hover,
.project-links a:visited:not(:hover) {
  color: var(--surface-fg);
}

.project-metrics {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-sm);
  color: var(--surface-fg-muted);
  margin: 0;
}

/* Approach page: the DevLoop cycle diagram. Narrow-first so a context
 * without media query evaluation (print) gets the readable vertical
 * variant. Colours are all currentColor / design tokens (no literal),
 * so the diagram follows the page's theme toggle. */
.cycle {
  margin: 0 0 var(--mctl-space-6);
}
.cycle-svg {
  display: block;
  width: 100%;
  height: auto;
  color: var(--surface-fg);
}
.cycle-wide {
  display: none;
}
.cycle-node rect {
  fill: var(--surface-elevated);
  stroke: var(--surface-line-strong);
  stroke-width: 1;
}
.cycle-node.is-gate rect {
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: 5 4;
}
.cycle-node text {
  fill: currentColor;
  font-family: var(--font-display);
  font-size: 14px;
}
.cycle-edges path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}
@media (min-width: 800px) {
  .cycle-narrow {
    display: none;
  }
  .cycle-wide {
    display: block;
  }
  .cycle-node text {
    font-size: 13px;
  }
  /* The wide variant's boxes are 130 units wide; a Russian label one step
   * smaller keeps the longest label (Мерж шефердом) inside its box with
   * padding to spare (test/cycle-diagram.test.ts encodes the arithmetic). */
  :root[data-lang='ru'] .cycle-wide .cycle-node text {
    font-size: 12px;
  }
}

/* Approach page: the dashed-outline legend, visible below the diagram
 * without opening a disclosure. The swatch is a CSS-drawn box, not a third
 * inline <svg> -- it costs nothing against the 12288-byte SVG budget and
 * keeps the component's single-<svg>-per-variant shape (test/approach.test.ts).
 * No animation or transition (test/a11y.test.ts). */
.cycle-legend {
  display: flex;
  align-items: center;
  gap: var(--mctl-space-2);
  margin-block-start: var(--mctl-space-3);
  color: var(--surface-fg-muted);
  font-size: var(--mctl-typography-font-size-sm);
}
.cycle-legend-swatch {
  display: inline-block;
  flex: none;
  inline-size: var(--mctl-space-4);
  block-size: var(--mctl-space-4);
  border: 2px dashed var(--accent);
  border-radius: var(--mctl-radius-sm);
}

/* Tap targets: the navigation and footer links are at least 44px tall at any
 * viewport width, per the 360px acceptance criterion. This is not a
 * page-wide floor -- the standalone-link rule below is 24px, and the
 * header's .icon-toggle controls are a fixed 32px box -- and 24px is the
 * floor test/a11y.test.ts enforces for every selector in TARGET_SELECTORS. */
.site-nav a,
.site-footer a {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
}
/* Standalone links (issue #88, Q13): a link that stands on its own -- a
 * repository or docs link on /work/, a breadcrumb step, the issue and PR
 * links in a journal entry's meta list, a link inside one of the colophon
 * tables -- is a tap target in its own right and measured 17-20px. Prose
 * links inside a paragraph (main a) are deliberately not here: turning an
 * inline sentence link into a 24px flex box would break the line box it
 * sits in. No min-width, no fixed height, no animation, no transition. */
.project-links a,
.breadcrumb a,
.journal-meta a,
.table-scroll a {
  display: inline-flex;
  align-items: center;
  min-block-size: 24px;
}

/* Colophon page: section spacing, the cycle/ADR tables, the keyboard-
 * reachable horizontal scroll region and the intervention records.
 * Narrow-first; the scroll region is what keeps the eight-column cycle
 * table usable at 360px instead of a stacked layout, which cannot carry a
 * bilingual ::before label (see design.md, alternative 5). */
.colophon-section {
  padding-block: var(--mctl-space-5);
  border-top: 1px solid var(--surface-line);
}
.table-hint {
  color: var(--surface-fg-muted);
  font-size: var(--mctl-typography-font-size-xs);
  margin-block-end: var(--mctl-space-2);
}
.table-scroll {
  position: relative;
  overflow-x: auto;
  margin-block-end: var(--mctl-space-3);
}
.table-scroll:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
}
/* A static, CSS-only edge affordance for readers on a narrow screen where the
 * table still overflows after the wrapping fix below: no animation, no
 * transition (test/a11y.test.ts), pointer-events: none so it never blocks the
 * focusable .table-scroll region. The .table-hint text is the accessible
 * carrier of the same message at every width. */
@media (max-width: 599px) {
  .table-scroll::after {
    content: '';
    position: absolute;
    display: block;
    inset-block: 0;
    inset-inline-end: 0;
    inline-size: var(--mctl-space-5);
    background-image: linear-gradient(to left, var(--surface-bg), transparent);
    pointer-events: none;
  }
}
table.cycles,
table.adr-index {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-sm);
}
table.cycles caption,
table.adr-index caption {
  text-align: left;
  color: var(--surface-fg-muted);
  font-size: var(--mctl-typography-font-size-xs);
  margin-block-end: var(--mctl-space-2);
}
table.cycles th,
table.cycles td,
table.adr-index th,
table.adr-index td {
  padding: var(--mctl-space-2) var(--mctl-space-3);
  border-bottom: 1px solid var(--surface-line);
  text-align: left;
}
table.cycles th,
table.adr-index th {
  color: var(--surface-fg-muted);
  font-weight: var(--mctl-typography-font-weight-semibold);
  /* A heading may wrap at a space but never break mid-word, at any width. */
  white-space: normal;
  overflow-wrap: normal;
  word-break: normal;
  hyphens: manual;
}
/* Every column except the two title-link columns (table.cycles column 3,
 * table.adr-index column 2) keeps its content on one line: dates, release
 * tags, GitHub references, the service name and numeric values never break
 * across lines. The title columns are left to wrap so all columns fit inside
 * --content-max without horizontal scrolling at a 1440px viewport. */
table.cycles td:nth-child(1),
table.cycles td:nth-child(2),
table.cycles td:nth-child(4),
table.cycles td:nth-child(5),
table.cycles td:nth-child(6),
table.cycles td:nth-child(7),
table.cycles td:nth-child(8),
table.cycles td:nth-child(9) {
  white-space: nowrap;
}
table.adr-index td:nth-child(1),
table.adr-index td:nth-child(3),
table.adr-index td:nth-child(4) {
  white-space: nowrap;
}
table.cycles td:nth-child(1),
table.cycles td:nth-child(8),
table.cycles td:nth-child(9) {
  font-variant-numeric: tabular-nums;
}
.lead-time-missing {
  color: var(--surface-fg-muted);
}
.step-interval {
  color: var(--surface-fg-muted);
  margin-inline-start: var(--mctl-space-2);
}
/* Below 600px, drop Service and Pull request from table.cycles (heading and
 * cells alike) so the remaining seven columns fit a phone; both values
 * remain one click away on the cycle's own journal page. Column 6 (Pull
 * request), not 5, since Status is now inserted at column 4. */
@media (max-width: 599px) {
  table.cycles th:nth-child(2),
  table.cycles td:nth-child(2),
  table.cycles th:nth-child(6),
  table.cycles td:nth-child(6) {
    display: none;
  }
}
.cycle-totals {
  font-family: var(--font-display);
  color: var(--surface-fg-muted);
  font-variant-numeric: tabular-nums;
}

/* Journal entry page. */
.journal-meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--mctl-space-1) var(--mctl-space-4);
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-sm);
  padding-block: var(--mctl-space-4);
  border-block: 1px solid var(--surface-line);
  margin-block-end: var(--mctl-space-4);
}
.journal-meta dt {
  color: var(--surface-fg-muted);
}
.journal-meta dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
}
/* The abandonment reason, rendered under .journal-meta only for an
 * abandoned entry -- a muted, quoted-looking paragraph, distinct from the
 * decided-heading prose but with no animation or transition (test/a11y.test.ts). */
.journal-abandoned {
  color: var(--surface-fg-muted);
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-body);
  line-height: var(--mctl-typography-line-height-body);
  margin-block-end: var(--mctl-space-2);
}
.journal-decided {
  font-family: var(--font-display);
  font-size: var(--mctl-typography-font-size-body);
  line-height: var(--mctl-typography-line-height-body);
  margin-block-end: var(--mctl-space-4);
}
.journal-timeline {
  margin: 0;
  padding-inline-start: var(--mctl-space-5);
  font-variant-numeric: tabular-nums;
}
.journal-timeline li {
  margin-block-end: var(--mctl-space-2);
}
.interventions {
  margin: 0;
  padding-inline-start: var(--mctl-space-5);
}
.interventions li {
  margin-block-end: var(--mctl-space-4);
}
.interventions p {
  margin: 0 0 var(--mctl-space-1);
}
.intervention-at {
  font-variant-numeric: tabular-nums;
  color: var(--surface-fg-muted);
  font-size: var(--mctl-typography-font-size-xs);
}

/* ADR page. */
.adr-meta {
  font-family: var(--font-display);
  color: var(--surface-fg-muted);
  font-size: var(--mctl-typography-font-size-sm);
  margin-block-end: var(--mctl-space-2);
}

/* Print. Base.astro hardcodes data-theme="dark", which is unreadable on
 * paper, so print always uses a light palette regardless of the attribute.
 * Closed <details> bodies are forced visible so the printed page carries
 * the same content as the screen. */
@media print {
  :root {
    --surface-bg: #fff;
    --surface-fg: #111;
    --surface-fg-muted: #444;
    --surface-line: #bbb;
    /* --accent resolves to the dark-theme #e25a3c here, 3.64:1 on the forced
     * white background. The light-theme value measures 5.62:1. */
    --accent: #b83d28;
  }
  .site-header,
  .toggle-group,
  .ctas {
    display: none;
  }
  .block > *:not(summary) {
    display: block !important;
    content-visibility: visible !important;
  }
  /* The rule above forces every non-summary child of a collapsed .block to
   * display:block so print carries the full content, but .l.en/.l.ru pairs
   * (see the language toggle at the top of this file) can be direct children
   * of a .block (e.g. the two <ul> lists in each home-page <details>). Without
   * this override both languages would print at once. Higher specificity than
   * the block-forcing rule above lets it win even though both use !important. */
  :root[data-lang='en'] .block > .l.ru,
  :root[data-lang='ru'] .block > .l.en {
    display: none !important;
  }
  a[href^='http']::after {
    content: ' (' attr(href) ')';
    font-size: var(--mctl-typography-font-size-xs);
  }
}
