@layer reset, tokens, typography, layout, components, animations, utilities;

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

  html {
    text-size-adjust: 100%;
    -webkit-text-size-adjust: 100%;
    hanging-punctuation: first last;
  }

  body,
  h1,
  h2,
  h3,
  h4,
  h5,
  h6,
  p,
  figure,
  blockquote,
  dl,
  dd {
    margin: 0;
  }

  ul,
  ol {
    list-style: none;
    margin: 0;
    padding: 0;
  }

  img,
  picture,
  video,
  canvas,
  svg {
    display: block;
    max-inline-size: 100%;
  }

  input,
  button,
  textarea,
  select {
    font: inherit;
  }

  p,
  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    overflow-wrap: break-word;
  }

  :focus-visible {
    outline: 0.1875rem solid var(--color-accent);
    outline-offset: 0.25rem;
    border-radius: var(--radius-sm);
  }

  @media (prefers-reduced-motion: no-preference) {
    html {
      scroll-behavior: smooth;
    }
  }
}

@layer tokens {
  /*
    Palette: "Case File" — the Missing Scientists dossier skin
    —————————————————————————————————————————————————————————
    Dark mode is the default (set on <html data-theme="dark">): a
    near-black terminal field with phosphor-green text and a brighter
    terminal-green accent. The redaction bars, tier badges, and
    confidence ratings already defined in missing-scientists.css read
    naturally against it.

    Light mode is a "manila folder" case-file look: warm tan paper,
    near-black typewriter ink, deep-green accent.

    Only this file (tokens) and nav.css carry the skin — every other
    style is inherited intact from the upstream engine and themes off
    these variables.

    Contrast (WCAG 2.1), spot-checked:
      Dark:  accent on bg ≈ 9:1   (AAA ✓)
      Light: ink on manila ≈ 11:1 (AAA ✓)
    —————————————————————————————————————————————————————————
  */

  :root {
    /* ── Colors — light mode (manila case file) ── */
    --color-bg:           oklch(90% 0.038 85);    /* manila tan */
    --color-surface:      oklch(94% 0.032 85);    /* lighter folder stock */
    --color-text:         oklch(22% 0.020 60);    /* typewriter ink */
    --color-text-muted:   oklch(45% 0.028 70);    /* faded ink */
    --color-accent:       oklch(46% 0.13 150);    /* deep field green */
    --color-accent-hover: oklch(38% 0.13 150);
    --color-border:       oklch(74% 0.040 85);    /* folder edge */
    --color-code-bg:      oklch(86% 0.040 85);

    /*
      On-accent: text/icon sitting ON an accent-colored fill (buttons,
      badges). Pale on the dark light-mode green.
    */
    --color-on-accent:    oklch(96% 0.02 85);

    /*
      ── Connection-diagram node colors ──
      One node type, one token, read by BOTH the diagram's circles and the
      key's swatches. They used to be declared twice — literal oklch() in
      ms-diagram.ts and again in the key's CSS — and drifted: the key showed
      a person as accent-green while the circles painted the upstream site's
      blue, so the key told the reader the wrong thing.

      Defined once here, not per theme: `person` indirects through
      --color-accent, so it re-themes for free. The other three are fixed
      hues that read on both the tan and the near-black field, which is the
      behaviour the key already had.
    */
    --ms-node-person:             var(--color-accent);
    --ms-node-institution:        oklch(55% 0.12 145);
    --ms-node-location:           oklch(60% 0.10 180);
    --ms-node-program:            oklch(55% 0.12 60);

    /* Hover/focus states. `person` rides --color-accent-hover for the same reason. */
    --ms-node-person-bright:      var(--color-accent-hover);
    --ms-node-institution-bright: oklch(65% 0.16 145);
    --ms-node-location-bright:    oklch(70% 0.14 180);
    --ms-node-program-bright:     oklch(65% 0.16 60);

    /*
      ── Timeline event colors ──
      Same contract as the node colors above: declared once, read by both
      ms-timeline.ts and the timeline key's dots. These were duplicated too,
      and `other` had already drifted — the key's dot showed muted text
      colour while the events painted a blue that matched nothing else.

      Unlike the node colours these are semantic rather than skin: red-ish
      reads as death, green as an arrest. They stay fixed across themes.
    */
    --ms-event-disappearance:           oklch(55% 0.15 30);
    --ms-event-death:                   oklch(40% 0.12 0);
    --ms-event-body-found:              oklch(45% 0.10 300);
    --ms-event-suspect-arrested:        oklch(55% 0.12 145);
    --ms-event-investigation-milestone: oklch(55% 0.10 248);
    --ms-event-institutional-statement: oklch(55% 0.08 200);
    --ms-event-political:               oklch(55% 0.12 60);
    --ms-event-media:                   oklch(60% 0.08 280);
    --ms-event-other:                   var(--color-text-muted);

    /* ── Type scale — fluid via clamp(), ~1.25 modular ratio ── */
    --text-xs:   clamp(0.70rem,  0.68rem + 0.10vw, 0.75rem);
    --text-sm:   clamp(0.875rem, 0.84rem + 0.17vw, 0.9375rem);
    --text-base: clamp(1rem,     0.96rem + 0.20vw, 1.0625rem);
    --text-lg:   clamp(1.125rem, 1.06rem + 0.30vw, 1.25rem);
    --text-xl:   clamp(1.25rem,  1.14rem + 0.55vw, 1.5625rem);
    --text-2xl:  clamp(1.5625rem,1.34rem + 1.12vw, 2.0625rem);
    --text-3xl:  clamp(1.9531rem,1.56rem + 1.96vw, 2.8125rem);

    /* ── Font stacks ──
       Headings go monospace for the redacted-report / terminal feel;
       body stays humanist sans for long-form readability; mono for code
       and the tier/confidence badge accents. */
    --font-heading: ui-monospace, 'Cascadia Code', 'Fira Code', 'SFMono-Regular', Menlo, monospace;
    --font-body:    ui-sans-serif, system-ui, sans-serif;
    --font-mono:    ui-monospace, 'Cascadia Code', 'Fira Code', monospace;

    /* ── Spacing — rem-based, ~1.5 ratio ── */
    --space-2xs: 0.25rem;
    --space-xs:  0.5rem;
    --space-sm:  0.75rem;
    --space-md:  1rem;
    --space-lg:  1.5rem;
    --space-xl:  2.25rem;
    --space-2xl: 3.375rem;
    --space-3xl: 5rem;

    /* ── Border radius — squared off for a documentary/file feel ── */
    --radius-sm:   0.125rem;
    --radius-md:   0.25rem;
    --radius-lg:   0.5rem;
    --radius-full: 9999px;

    /* ── Transitions ── */
    --duration-fast:   150ms;
    --duration-normal: 300ms;
    --duration-slow:   500ms;

    /* ── Container ── */
    --container-max:     75rem;
    --container-padding: clamp(1rem, 5vw, 3rem);
  }

  /* ── Dark mode (default skin) ──
     Near-black terminal field, phosphor text, terminal-green accent. */
  [data-theme="dark"] {
    --color-bg:           oklch(15% 0.012 155);   /* near-black, faint green */
    --color-surface:      oklch(20% 0.016 155);   /* raised panel */
    --color-text:         oklch(92% 0.022 150);   /* phosphor white-green */
    --color-text-muted:   oklch(66% 0.030 150);   /* dim phosphor */
    --color-accent:       oklch(80% 0.165 150);   /* terminal green */
    --color-accent-hover: oklch(88% 0.150 150);   /* brighter green */
    --color-on-accent:    oklch(15% 0.020 155);   /* dark text on green */
    --color-border:       oklch(30% 0.022 155);   /* subtle green divider */
    --color-code-bg:      oklch(18% 0.016 155);   /* code block fill */
  }

  /* ── Light mode (explicit override, mirrors :root) ── */
  [data-theme="light"] {
    --color-bg:           oklch(90% 0.038 85);
    --color-surface:      oklch(94% 0.032 85);
    --color-text:         oklch(22% 0.020 60);
    --color-text-muted:   oklch(45% 0.028 70);
    --color-accent:       oklch(46% 0.13 150);
    --color-accent-hover: oklch(38% 0.13 150);
    --color-on-accent:    oklch(96% 0.02 85);
    --color-border:       oklch(74% 0.040 85);
    --color-code-bg:      oklch(86% 0.040 85);
  }
}

@layer typography {
  /*
    Fraunces: loaded from Google Fonts CDN via @font-face.
    Variable axes: wght 100-900, SOFT 0-100, WONK 0-1.
    We target wght 400 + 700 only; the variable font handles interpolation.
    format("woff2-variations") is the modern descriptor for variable fonts.
  */
  @font-face {
    font-family: 'Fraunces';
    src: url('https://fonts.gstatic.com/s/fraunces/v31/6NUh8FyLNQOQZAnv9bYEvDiIdE9Ea92uemj4B5ary_0mgd0.woff2') format('woff2');
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-036F, U+0370-037F, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  @font-face {
    font-family: 'Fraunces';
    src: url('https://fonts.gstatic.com/s/fraunces/v31/6NUh8FyLNQOQZAnv9bYEvDiIdE9Ea92uemj4B5ary_0mgd0.woff2') format('woff2');
    font-weight: 100 900;
    font-style: italic;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-036F, U+0370-037F, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
  }

  body {
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: 1.6;
    color: var(--color-text);
    background-color: var(--color-bg);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }

  h1,
  h2,
  h3,
  h4 {
    font-family: var(--font-heading);
    line-height: 1.15;
    font-weight: 700;
    color: var(--color-text);
  }

  h1 { font-size: var(--text-3xl); }
  h2 { font-size: var(--text-2xl); }
  h3 { font-size: var(--text-xl); }
  h4 { font-size: var(--text-lg); }

  a {
    color: var(--color-accent);
    text-decoration-thickness: 0.08em;
    text-underline-offset: 0.25em;
    transition: color var(--duration-fast) ease;

    &:hover {
      color: var(--color-accent-hover);
    }
  }

  code,
  kbd,
  samp {
    font-family: var(--font-mono);
    font-size: 0.875em;
  }

  small {
    font-size: var(--text-sm);
  }

  strong {
    font-weight: 600;
  }

  /* Prose: article/long-form content rhythm */
  .prose {
    max-inline-size: 65ch;
    line-height: 1.75;

    & p,
    & li {
      margin-block: var(--space-sm);
    }

    & h2 {
      margin-block-start: var(--space-2xl);
      margin-block-end: var(--space-sm);
    }

    & h3 {
      margin-block-start: var(--space-xl);
      margin-block-end: var(--space-xs);
    }

    & h4 {
      margin-block-start: var(--space-lg);
      margin-block-end: var(--space-xs);
    }

    & a {
      color: var(--color-accent);
      text-decoration-thickness: 0.08em;
      text-underline-offset: 0.25em;
      transition: color var(--duration-fast) ease;

      &:hover {
        color: var(--color-accent-hover);
      }
    }

    & blockquote {
      border-inline-start: 0.25rem solid var(--color-accent);
      padding-inline-start: var(--space-lg);
      padding-block: var(--space-xs);
      margin-inline: 0;
      margin-block: var(--space-lg);
      font-style: italic;
      color: var(--color-text-muted);
    }

    & pre {
      background-color: var(--color-code-bg);
      padding: var(--space-md);
      border-radius: var(--radius-md);
      overflow-x: auto;
      margin-block: var(--space-lg);
      border: 0.0625rem solid var(--color-border);

      /* Custom scrollbar — webkit only, progressive */
      &::-webkit-scrollbar {
        block-size: 0.375rem;
      }

      &::-webkit-scrollbar-track {
        background: transparent;
      }

      &::-webkit-scrollbar-thumb {
        background-color: var(--color-border);
        border-radius: var(--radius-full);
      }

      & code {
        background: none;
        padding: 0;
        font-size: var(--text-sm);
        border-radius: 0;
      }
    }

    & code {
      background-color: var(--color-code-bg);
      padding-inline: 0.3em;
      padding-block: 0.1em;
      border-radius: var(--radius-sm);
      font-size: 0.875em;
    }

    & img {
      border-radius: var(--radius-md);
      margin-block: var(--space-lg);
      inline-size: 100%;
    }

    & ul,
    & ol {
      padding-inline-start: var(--space-lg);
      margin-block: var(--space-sm);
    }

    & ul {
      list-style: disc;
    }

    & ol {
      list-style: decimal;
    }

    & hr {
      border: none;
      border-block-start: 0.0625rem solid color-mix(in oklch, var(--color-border) 80%, transparent);
      margin-block: var(--space-2xl);
    }

    & table {
      /* Markdown pipeline emits bare <table> with no wrapper div.
         display: block turns the table into a scrollable island without
         sacrificing internal table layout (inline-size: max-content preserves it). */
      display: block;
      overflow-x: auto;
      inline-size: max-content;
      max-inline-size: 100%;
      margin-block: var(--space-lg);
      border-collapse: collapse;
      font-size: var(--text-sm);

      &::-webkit-scrollbar {
        block-size: 0.375rem;
      }

      &::-webkit-scrollbar-track {
        background: transparent;
      }

      &::-webkit-scrollbar-thumb {
        background-color: var(--color-border);
        border-radius: var(--radius-full);
      }
    }

    & th,
    & td {
      padding-inline: var(--space-sm);
      padding-block: var(--space-xs);
      border: 0.0625rem solid var(--color-border);
      text-align: start;
      vertical-align: top;
    }

    & th {
      background-color: var(--color-code-bg);
      font-weight: 600;
      color: var(--color-text);
    }

    & tr:nth-child(even) td {
      background-color: color-mix(in oklch, var(--color-surface) 60%, transparent);
    }
  }
}

@layer layout {
  body {
    min-block-size: 100dvh;
    display: grid;
    /* One track per in-flow child of <body> in base.html, in order:
       .site-banner | .site-header | main | .site-footer. Only main takes 1fr, so
       it absorbs the slack on tall viewports and the footer stays put. #skip-link
       is position:absolute and is deliberately not a track.
       Adding or removing a <body> child means adding or removing a track here —
       the tracks are matched by position, so an unpaired child silently shifts
       1fr onto the wrong element. */
    grid-template-rows: auto auto 1fr auto;
    /* Without an explicit column, the implicit track is minmax(auto, auto) which
       expands to fit children — wide <pre>/<table> inside main blow out the page.
       minmax(0, 1fr) caps the track at available viewport width. */
    grid-template-columns: minmax(0, 1fr);
  }

  .container {
    max-inline-size: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--container-padding);
    inline-size: 100%;
  }

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

  /* Page-level section spacing */
  .section {
    padding-block: var(--space-xl);
    display: flex;
    flex-direction: column;
    gap: var(--space-lg);

    /* Consecutive sections would double-stack outer padding — pull the top
       of the following section back in so the gap stays visually even. */
    & + & {
      padding-block-start: var(--space-md);
    }

    /* Kill default paragraph margin — flex gap handles rhythm */
    & > p:last-child {
      margin: 0;
      font-size: var(--text-sm);
      font-weight: 500;

      & a {
        color: var(--color-accent);
        text-decoration: none;
        display: inline-flex;
        align-items: center;
        gap: var(--space-2xs);
        padding-block: var(--space-2xs);
        border-block-end: 0.0625rem solid transparent;
        transition:
          color var(--duration-fast) ease,
          border-color var(--duration-fast) ease;

        &:hover {
          color: var(--color-accent-hover);
          border-block-end-color: var(--color-accent);
        }

        &:focus-visible {
          outline: 0.125rem solid var(--color-accent);
          outline-offset: 0.25rem;
          border-radius: var(--radius-sm);
        }
      }
    }
  }

  /* Two-column grid that collapses to single on narrow viewports */
  .grid-auto {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
    gap: var(--space-lg);
  }

  /* Hero section — all three elements flow as a single wrapping baseline row */
  .hero {
    padding-block: var(--space-md);
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.4ch;

    @media (min-width: 48rem) {
      padding-block: var(--space-lg);
    }

    & .hero__eyebrow {
      margin: 0;
      font-size: var(--text-sm);
      font-weight: 600;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--color-accent);
    }

    & .hero__heading {
      margin: 0;
    }

    & .hero__lead {
      margin: 0;
      font-size: var(--text-lg);
      color: var(--color-text-muted);
    }
  }

  /* Stacked block between .hero and first .section — photo above, bio below. */
  .about {
    padding-block: 0;

    @media (min-width: 48rem) {
      padding-block: var(--space-sm);
    }

    display: flex;
    flex-direction: column;
    gap: var(--space-lg);

    @media (min-width: 48rem) {
      gap: var(--space-md);
    }

    & .about__photo {
      inline-size: 100%;
      block-size: auto;
      border-radius: var(--radius-lg);
      display: block;

      &[hidden] {
        display: none;
      }
    }

    & .about__text {
      display: flex;
      flex-direction: column;
      gap: var(--space-sm);

      & p {
        margin: 0;
      }
    }
  }

  /* Site header */
  .site-header {
    position: sticky;
    inset-block-start: 0;
    z-index: 100;
    background-color: var(--color-bg);
    border-block-end: 0.0625rem solid var(--color-border);
    -webkit-backdrop-filter: blur(0.5rem);
    backdrop-filter: blur(0.5rem);

    /* Tier-1 brand row only — the Tier-2 dossier bar lays itself out (nav.css). */
    & .site-brandbar > .container {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding-block: var(--space-sm);

      @media (min-width: 48rem) {
        display: grid;
        grid-template-columns: 1fr auto 1fr;

        & .nav__logo { justify-self: start; }
        & .nav__controls { justify-self: end; }
      }
    }
  }

  /* Site footer */
  .site-footer {
    border-block-start: 0.0625rem solid var(--color-border);
    padding-block: var(--space-xl);
    color: var(--color-text-muted);
    font-size: var(--text-sm);

    & .container {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: var(--space-md);
      text-align: center;
    }

    & a {
      color: var(--color-text-muted);
      text-decoration: none;

      &:hover {
        color: var(--color-accent);
      }
    }
  }
}

@layer components {
  /* ── Site logo / wordmark ─────────────────────────────────────────── */
  .nav__logo {
    font-family: var(--font-heading);
    font-size: var(--text-xl);
    font-weight: 700;
    color: var(--color-text);
    text-decoration: none;
    letter-spacing: -0.02em;

    & span {
      color: var(--color-accent);
    }

    &:hover {
      color: var(--color-text);
    }
  }

  /* ── Nav shell ────────────────────────────────────────────────────── */
  .nav {
    /* Scroll-hide: JS adds .nav--hidden which translates the header up */
    transition: transform var(--duration-normal) ease;

    &.nav--hidden {
      transform: translateY(-110%);
    }

    /* Hidden checkbox — the pure-CSS toggle mechanism */
    & #nav-toggle {
      display: none;
      position: absolute;
      inset-inline-start: -9999px;
    }
  }

  /* ── Nav links — desktop base ─────────────────────────────────────── */
  .nav__links {
    display: flex;
    align-items: center;
    gap: var(--space-lg);
    list-style: none;
    margin: 0;
    padding: 0;

    & a {
      font-size: var(--text-sm);
      font-weight: 500;
      color: var(--color-text-muted);
      text-decoration: none;
      padding-block: var(--space-2xs);
      border-block-end: 0.125rem solid transparent;
      transition:
        color var(--duration-fast) ease,
        border-color var(--duration-fast) ease;

      &:hover,
      &[aria-current="page"] {
        color: var(--color-text);
        border-block-end-color: var(--color-accent);
      }
    }
  }

  /* ── Hamburger label — hidden on desktop ──────────────────────────── */
  .nav__toggle-label {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 0.3125rem;
    block-size: 2.5rem;
    inline-size: 2.5rem;
    cursor: pointer;
    padding: var(--space-xs);
    border-radius: var(--radius-sm);
    transition: background-color var(--duration-fast) ease;

    &:hover {
      background-color: var(--color-surface);
    }

    & span {
      display: block;
      block-size: 0.125rem;
      inline-size: 100%;
      background-color: var(--color-text);
      border-radius: var(--radius-full);
      transition:
        transform var(--duration-normal) ease,
        opacity var(--duration-fast) ease;
      transform-origin: center;
    }
  }

  /* ── Mobile layout — below 48rem (768px) ─────────────────────────── */
  @media (max-width: 48rem) {
    .nav__toggle-label {
      display: flex;
    }

    .nav .nav__links {
      position: absolute;
      inset-block-start: 100%;
      inset-inline: 0;
      flex-direction: column;
      align-items: stretch;
      gap: 0;
      background-color: var(--color-bg);
      border-block-end: 0.0625rem solid var(--color-border);
      padding-block: var(--space-sm);
      opacity: 0;
      pointer-events: none;
      transform: translateY(-0.5rem);
      transition:
        opacity var(--duration-normal) ease,
        transform var(--duration-normal) ease;

      & a {
        padding-inline: var(--container-padding);
        padding-block: var(--space-sm);
        border-block-end: none;
        font-size: var(--text-base);

        &:hover,
        &[aria-current="page"] {
          border-block-end: none;
          color: var(--color-accent);
        }
      }
    }

    /* Open state — :has() on the nav reads the hidden checkbox */
    .nav:has(#nav-toggle:checked) {
      & .nav__links {
        opacity: 1;
        pointer-events: auto;
        transform: translateY(0);
      }

      /* Animate hamburger → X */
      & .nav__toggle-label span:nth-child(1) {
        transform: translateY(0.4375rem) rotate(45deg);
      }

      & .nav__toggle-label span:nth-child(2) {
        opacity: 0;
      }

      & .nav__toggle-label span:nth-child(3) {
        transform: translateY(-0.4375rem) rotate(-45deg);
      }
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .nav,
    .nav__links,
    .nav__toggle-label span {
      transition: none;
    }
  }

  /* ── Dossier nav logo — squared, monospace wordmark ───────────────── */
  .nav__logo {
    font-family: var(--font-mono);
    letter-spacing: 0.02em;
    text-transform: uppercase;
    font-size: var(--text-base);
  }

  /* ── Project-purpose + AI-disclosure banner ───────────────────────── */
  .site-banner {
    background-color: var(--color-surface);
    border-block-end: 0.0625rem solid var(--color-border);
    color: var(--color-text-muted);
    font-size: var(--text-xs);

    & .container {
      display: flex;
      align-items: baseline;
      gap: var(--space-sm);
      padding-block: var(--space-xs);
    }

    & strong {
      color: var(--color-text);
    }
  }

  .site-banner__tag {
    flex: none;
    font-family: var(--font-mono);
    font-weight: 700;
    letter-spacing: 0.18em;
    color: var(--color-on-accent);
    background-color: var(--color-accent);
    padding-inline: var(--space-xs);
    padding-block: 0.05rem;
    border-radius: var(--radius-sm);
  }

  .site-banner__text {
    line-height: 1.45;
  }

  /* ── Subtle scanline / grain overlay for the terminal feel ────────── */
  body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 9999;
    pointer-events: none;
    background-image: repeating-linear-gradient(
      to bottom,
      color-mix(in oklch, var(--color-text) 4%, transparent) 0,
      color-mix(in oklch, var(--color-text) 4%, transparent) 1px,
      transparent 1px,
      transparent 3px
    );
    opacity: 0.35;
    mix-blend-mode: overlay;
  }

  @media (prefers-reduced-motion: reduce) {
    body::before { opacity: 0.18; }
  }

  /* ── Tier 1: umbrella brand bar ───────────────────────────────────── */
  /* Layout of its inner .container is owned by layout.css (.site-header). */
  .site-brandbar {
    position: relative; /* anchor for the CSS-only mobile menu dropdown */
  }

  /* ── Tier 2: active-dossier context bar ───────────────────────────── */
  .dossier-bar {
    border-block-start: 0.0625rem solid var(--color-border);
    background-color: color-mix(in oklch, var(--color-surface) 55%, transparent);

    & .container {
      display: flex;
      align-items: center;
      gap: var(--space-md);
      padding-block: var(--space-2xs);
    }

    /* Reuse .ms-nav scroll behaviour, but strip its in-article chrome
       (border / margins) now that it lives inside the sticky header. */
    & .ms-nav {
      flex: 1;
      min-inline-size: 0;
      border-block-end: none;
      padding-block-end: 0;
      margin-block-end: 0;
    }
  }

  .dossier-bar__label {
    flex: none;
    font-family: var(--font-mono);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-accent);
    text-decoration: none;
    white-space: nowrap;
    padding-inline-end: var(--space-md);
    border-inline-end: 0.0625rem solid var(--color-border);

    &:hover {
      color: var(--color-accent-hover);
    }

    /* On narrow screens the section nav needs the room — drop the divider. */
    @media (max-width: 37.5rem) {
      border-inline-end: none;
      padding-inline-end: 0;
    }
  }
}

@layer components {
  /* ── Visually hidden ──────────────────────────────────────────────────
     Removes an element from the visual layout while leaving it in the
     accessibility tree, for text that carries structure a sighted reader
     already gets from the design. Not `display: none` / `visibility: hidden`,
     which would take it out of the tree along with the pixels. */
  .visually-hidden {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* ── Skip link ────────────────────────────────────────────────────── */
  #skip-link {
    position: absolute;
    inset-block-start: var(--space-sm);
    inset-inline-start: var(--space-sm);
    padding: var(--space-xs) var(--space-md);
    background-color: var(--color-accent);
    color: var(--color-bg);
    font-weight: 600;
    font-size: var(--text-sm);
    border-radius: var(--radius-md);
    text-decoration: none;
    z-index: 9999;
    transform: translateY(-200%);
    transition: transform var(--duration-fast) ease;

    &:focus-visible {
      transform: translateY(0);
      outline: none;
    }
  }

  /* ── Tag / tech pill ─────────────────────────────────────────────── */
  .tag,
  .tech {
    display: inline-flex;
    align-items: center;
    padding-inline: var(--space-sm);
    padding-block: var(--space-2xs);
    font-size: var(--text-xs);
    font-weight: 500;
    line-height: 1;
    border-radius: var(--radius-full);
    background-color: color-mix(in oklch, var(--color-accent) 15%, transparent);
    color: var(--color-accent);
    border: 0.0625rem solid color-mix(in oklch, var(--color-accent) 30%, transparent);
    white-space: nowrap;
  }

  /* ── Cards (article + project) ────────────────────────────────────── */
  .card {
    /* Anchor for the title-link ::after overlay that makes the whole card clickable */
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
    background-color: var(--color-surface);
    border: 0.0625rem solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--space-lg);
    text-decoration: none;
    color: inherit;
    transition:
      transform var(--duration-normal) ease,
      box-shadow var(--duration-normal) ease,
      border-color var(--duration-normal) ease;

    &:hover {
      transform: translateY(-0.125rem);
      box-shadow: 0 0.5rem 2rem color-mix(in oklch, var(--color-text) 10%, transparent);
      border-color: var(--color-accent);
    }

    & h2,
    & h3 {
      font-family: var(--font-heading);
      font-size: var(--text-xl);
      font-weight: 700;
      line-height: 1.2;
      margin: 0;

      & a {
        color: inherit;
        text-decoration: none;
        transition: color var(--duration-fast) ease;

        /* Stretched overlay: whole card becomes a click target for the title link. */
        &::after {
          content: "";
          position: absolute;
          inset: 0;
          border-radius: inherit;
        }
      }
    }

    &:hover h2 a,
    &:hover h3 a {
      color: var(--color-accent);
    }

    & header {
      display: flex;
      flex-wrap: wrap;
      align-items: baseline;
      gap: var(--space-sm) var(--space-xs);

      & h2,
      & h3 {
        inline-size: 100%;
      }

      & time {
        font-size: var(--text-xs);
        color: var(--color-text-muted);
        font-variant-numeric: tabular-nums;
      }
    }

    & p {
      font-size: var(--text-sm);
      color: var(--color-text-muted);
      line-height: 1.6;
      margin: 0;
      /* pushes tags/links cluster to the bottom of the card */
      flex: 1;
    }

    & .tags {
      display: flex;
      flex-wrap: wrap;
      gap: var(--space-xs);
      margin-block-start: auto;
    }

    & .tech-stack {
      display: flex;
      flex-wrap: wrap;
      gap: var(--space-xs);
      margin-block-start: auto;
    }

    & .links {
      display: flex;
      flex-wrap: wrap;
      gap: var(--space-sm);
      /* Sits above the title-link overlay so Live/GitHub stay independently clickable. */
      position: relative;
      z-index: 1;

      & a {
        display: inline-flex;
        align-items: center;
        gap: var(--space-2xs);
        font-size: var(--text-sm);
        font-weight: 500;
        color: var(--color-accent);
        text-decoration: none;
        padding-block: var(--space-2xs);
        padding-inline: var(--space-sm);
        border: 0.0625rem solid color-mix(in oklch, var(--color-accent) 35%, transparent);
        border-radius: var(--radius-md);
        transition:
          background-color var(--duration-fast) ease,
          border-color var(--duration-fast) ease;

        &:hover {
          background-color: color-mix(in oklch, var(--color-accent) 10%, transparent);
          border-color: var(--color-accent);
        }

        &:focus-visible {
          outline: 0.125rem solid var(--color-accent);
          outline-offset: 0.125rem;
        }
      }
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .card {
      transition: none;
    }
  }

  /* ── Carousel ─────────────────────────────────────────────────────── */
  .carousel-wrapper {
    container-type: inline-size;
    container-name: carousel;
    position: relative;
  }

  .carousel-track {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;

    &::-webkit-scrollbar {
      display: none;
    }
  }

  .carousel-slide {
    flex: 0 0 100%;
    scroll-snap-align: start;
  }

  .carousel-prev,
  .carousel-next {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.5rem;
    block-size: 2.5rem;
    border-radius: var(--radius-full);
    border: 0.0625rem solid var(--color-border);
    background-color: var(--color-surface);
    color: var(--color-text);
    cursor: pointer;
    font-size: var(--text-base);
    line-height: 1;
    padding: 0;
    transition:
      background-color var(--duration-fast) ease,
      border-color var(--duration-fast) ease,
      color var(--duration-fast) ease,
      transform var(--duration-fast) ease;

    &:hover {
      background-color: var(--color-accent);
      border-color: var(--color-accent);
      color: var(--color-on-accent);
      transform: scale(1.08);
    }

    &:focus-visible {
      outline: 0.125rem solid var(--color-accent);
      outline-offset: 0.125rem;
    }

    &:active {
      transform: scale(0.96);
    }
  }

  .carousel-dots {
    display: flex;
    justify-content: center;
    gap: var(--space-xs);
    margin-block-start: var(--space-sm);
  }

  .carousel-dot {
    inline-size: 0.5rem;
    block-size: 0.5rem;
    border-radius: var(--radius-full);
    border: none;
    background-color: var(--color-border);
    cursor: pointer;
    padding: 0;
    transition:
      background-color var(--duration-fast) ease,
      transform var(--duration-fast) ease;

    &[aria-current="true"] {
      background-color: var(--color-accent);
      transform: scale(1.3);
    }

    &:focus-visible {
      outline: 0.125rem solid var(--color-accent);
      outline-offset: 0.125rem;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .carousel-track {
      scroll-behavior: auto;
    }

    .carousel-dot,
    .carousel-prev,
    .carousel-next {
      transition: none;
    }

    .carousel-prev:hover,
    .carousel-next:hover {
      transform: none;
    }

    .carousel-dot[aria-current="true"] {
      transform: none;
    }
  }

  /* ── Article header (article detail page) ────────────────────────── */
  /* Lives in layout — it's the top region of a one-off page, not a reusable widget */
  .article-header {
    padding-block-end: var(--space-xl);
    border-block-end: 0.0625rem solid var(--color-border);
    margin-block-end: var(--space-xl);

    & h1 {
      margin-block-end: var(--space-md);
    }

    & .tags {
      display: flex;
      flex-wrap: wrap;
      gap: var(--space-xs);
      margin-block-start: var(--space-sm);
    }
  }

  /* ── Article meta row (date + reading time) ──────────────────────── */
  .article-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-sm);
    font-size: var(--text-sm);
    color: var(--color-text-muted);

    & time {
      font-variant-numeric: tabular-nums;
    }
  }

  /* ── Reading time atom ───────────────────────────────────────────── */
  .reading-time {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    font-size: var(--text-sm);
    color: var(--color-text-muted);
  }

  /* Dot only when reading-time is preceded by a time element */
  time + .reading-time::before {
    content: "·";
    display: inline-block;
  }

  /* ── Article footer ──────────────────────────────────────────────── */
  .article-footer {
    margin-block-start: var(--space-2xl);
  }

  /* ── Project header ──────────────────────────────────────────────── */
  .project-header {
    padding-block-end: var(--space-xl);
    border-block-end: 0.0625rem solid var(--color-border);
    margin-block-end: var(--space-xl);

    & h1 {
      margin-block-end: var(--space-md);
    }
  }

  /* ── Tech stack — row of tag pills ──────────────────────────────── */
  .tech-stack {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs);
  }

  /* margin only needed on the project detail page, not inside cards */
  .project-header .tech-stack {
    margin-block-end: var(--space-md);
  }

  /* ── Project links — live / github row ──────────────────────────── */
  .project-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-block-start: var(--space-md);

    & a {
      display: inline-flex;
      align-items: center;
      gap: var(--space-2xs);
      font-size: var(--text-sm);
      font-weight: 500;
      color: var(--color-accent);
      text-decoration: none;
      padding-block: var(--space-2xs);
      padding-inline: var(--space-sm);
      border: 0.0625rem solid color-mix(in oklch, var(--color-accent) 35%, transparent);
      border-radius: var(--radius-md);
      transition:
        background-color var(--duration-fast) ease,
        border-color var(--duration-fast) ease;

      &:hover {
        background-color: color-mix(in oklch, var(--color-accent) 10%, transparent);
        border-color: var(--color-accent);
      }

      &:focus-visible {
        outline: 0.125rem solid var(--color-accent);
        outline-offset: 0.125rem;
      }
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .project-links a {
      transition: none;
    }
  }

  /* ── Project footer ──────────────────────────────────────────────── */
  .project-footer {
    margin-block-start: var(--space-2xl);
    padding-block-start: var(--space-xl);
    border-block-start: 0.0625rem solid var(--color-border);
  }

  /* ── Back link ───────────────────────────────────────────────────── */
  .back-link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--color-text-muted);
    text-decoration: none;
    transition: color var(--duration-fast) ease;

    &:hover {
      color: var(--color-accent);
    }

    &:focus-visible {
      outline: 0.125rem solid var(--color-accent);
      outline-offset: 0.125rem;
      border-radius: var(--radius-sm);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .back-link {
      transition: none;
    }
  }

  /* ── Nav controls (theme toggle + hamburger cluster) ─────────────── */
  .nav__controls {
    display: flex;
    align-items: center;
    gap: var(--space-xs);

    & button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      inline-size: 2.5rem;
      block-size: 2.5rem;
      border-radius: var(--radius-sm);
      border: none;
      background-color: transparent;
      color: var(--color-text-muted);
      cursor: pointer;
      transition:
        background-color var(--duration-fast) ease,
        color var(--duration-fast) ease;

      &:hover {
        background-color: var(--color-surface);
        color: var(--color-text);
      }

      &:focus-visible {
        outline: 0.125rem solid var(--color-accent);
        outline-offset: 0.125rem;
      }
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .nav__controls button {
      transition: none;
    }
  }

  /* ── Censor bar ─────────────────────────────────────────────────────── */
  /*
    Bar and revealed-text colors are fixed ink values rather than theme
    tokens: a censor bar is always dark ink regardless of color scheme,
    and the revealed text must contrast that same dark bar in both themes.
    Using theme-adaptive tokens here would invert the bar to light in dark
    mode, breaking the metaphor.
  */
  @keyframes redacted-peek {
    0%   { color: oklch(11% 0.015 260); }
    30%  { color: oklch(97% 0.004 80); }
    70%  { color: oklch(97% 0.004 80); }
    100% { color: oklch(11% 0.015 260); }
  }

  .redacted {
    display: inline-block;
    background-color: oklch(11% 0.015 260);
    color: oklch(11% 0.015 260);
    border-radius: 0.125rem;
    padding-inline: var(--space-2xs);
    cursor: pointer;
    transition: color var(--duration-fast) ease;

    &:hover {
      color: oklch(97% 0.004 80);
    }

    &.redacted--peeking {
      animation: redacted-peek 600ms ease forwards;
      pointer-events: none;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .redacted {
      transition: none;
    }

    .redacted--peeking {
      animation-duration: 1ms;
    }
  }

  /* ── Empty state — shown when a project/article list is empty ────────── */
  .empty-state {
    grid-column: 1 / -1;
    text-align: center;
    color: var(--color-text-muted);
    padding-block: var(--space-xl);
    margin: 0;
  }
}

@layer components {
  /* ═══════════════════════════════════════════════════════════════════
     Missing Scientists — the standalone dossier site
     Academic-register styles for the research dossier.
     All classes prefixed ms- to avoid collisions.
     ═══════════════════════════════════════════════════════════════════ */

  /* ── Section wrapper ─────────────────────────────────────────────── */
  .ms-section {
    padding-block: var(--space-md);
  }

  .ms-article {
    max-inline-size: 100%;
    overflow-x: hidden;
  }

  /* ── Section navigation ──────────────────────────────────────────── */
  .ms-nav {
    border-block-end: 0.0625rem solid var(--color-border);
    padding-block-end: var(--space-xs);
    margin-block-end: var(--space-md);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;

    &::-webkit-scrollbar {
      display: none;
    }
  }

  .ms-nav__links {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--space-xs) var(--space-sm);
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: var(--text-sm);
    white-space: nowrap;
    inline-size: max-content;

    & li {
      flex-shrink: 0;
    }

    & a {
      color: var(--color-text-muted);
      text-decoration: none;
      padding-block: var(--space-2xs);
      border-block-end: 0.125rem solid transparent;
      transition:
        color var(--duration-fast) ease,
        border-color var(--duration-fast) ease;

      &:hover {
        color: var(--color-accent);
      }

      &[aria-current="page"] {
        color: var(--color-accent);
        border-block-end-color: var(--color-accent);
        font-weight: 600;
      }
    }
  }

  /* ── Page header ─────────────────────────────────────────────────── */
  .ms-header {
    margin-block-end: var(--space-sm);

    @media (min-width: 64rem) {
      margin-block-end: var(--space-xl);
    }

    & h1 {
      margin-block-end: var(--space-sm);
    }
  }

  .ms-subtitle {
    color: var(--color-text-muted);
    font-size: var(--text-base);
    max-inline-size: 65ch;
    margin: 0;
  }

  .ms-breadcrumb {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    margin-block-end: var(--space-sm);

    & a {
      color: var(--color-text-muted);
      text-decoration: none;

      &:hover {
        color: var(--color-accent);
      }
    }
  }

  .ms-version {
    font-size: var(--text-xs);
    color: var(--color-text-muted);
    margin: 0;
    margin-block-start: var(--space-md);
  }

  /* ── Content layout (TOC sidebar + prose) ────────────────────────── */
  .ms-layout {
    display: grid;
    gap: var(--space-sm);
    grid-template-columns: minmax(0, 1fr);

    @media (min-width: 64rem) {
      gap: var(--space-xl);
      grid-template-columns: minmax(0, 1fr);

      &:has(.ms-toc) {
        grid-template-columns: 15rem minmax(0, 1fr);
      }
    }
  }

  .ms-prose {
    max-inline-size: 75ch;
    min-inline-size: 0;
    overflow-wrap: anywhere;

    /* Make links clearly visible in research prose */
    & a[href] {
      color: oklch(42% 0.12 248);
      text-decoration: underline;
      text-decoration-thickness: 0.1em;
      text-underline-offset: 0.2em;
      text-decoration-color: color-mix(in oklch, oklch(42% 0.12 248) 40%, transparent);
      transition:
        color var(--duration-fast) ease,
        text-decoration-color var(--duration-fast) ease;

      &:hover {
        color: oklch(35% 0.14 248);
        text-decoration-color: oklch(35% 0.14 248);
      }

      &:visited {
        color: oklch(42% 0.1 300);
        text-decoration-color: color-mix(in oklch, oklch(42% 0.1 300) 40%, transparent);
      }
    }
  }

  [data-theme="dark"] .ms-prose a[href] {
    color: oklch(72% 0.1 248);
    text-decoration-color: color-mix(in oklch, oklch(72% 0.1 248) 40%, transparent);

    &:hover {
      color: oklch(78% 0.12 248);
      text-decoration-color: oklch(78% 0.12 248);
    }

    &:visited {
      color: oklch(72% 0.08 300);
      text-decoration-color: color-mix(in oklch, oklch(72% 0.08 300) 40%, transparent);
    }
  }

  /* ── Table of contents ───────────────────────────────────────────── */
  .ms-toc {
    font-size: var(--text-sm);
    position: relative;

    @media (min-width: 64rem) {
      /* Clear the sticky two-row header (brand bar + dossier bar). Its height
         is published live as --site-header-height by the nav module; the
         fallback covers the pre-hydration / no-JS case. --space-md is the
         breathing gap above and below the pinned TOC. */
      position: sticky;
      inset-block-start: calc(var(--site-header-height, 6rem) + var(--space-md));
      max-block-size: calc(100dvh - var(--site-header-height, 6rem) - 2 * var(--space-md));
      overflow-y: auto;
    }

    & summary {
      font-weight: 600;
      cursor: pointer;
      color: var(--color-text-muted);
      margin-block-end: 0;
      display: list-item;
      list-style: disclosure-closed inside;

      /* Desktop: TOC always visible, no toggle needed */
      @media (min-width: 64rem) {
        display: none;
      }
    }

    & details[open] > summary {
      list-style-type: disclosure-open;
    }

    & ol {
      list-style: none;
      padding: 0;
      margin: 0;
    }

    /* Desktop: always show TOC list regardless of details state */
    @media (min-width: 64rem) {
      & details > ol {
        display: block;
      }
    }

    /* Mobile overlay for the TOC list */
    @media (max-width: 63.999rem) {
      & details[open] > ol {
        position: absolute;
        z-index: 100;
        inset-block-start: 100%;
        inset-inline-start: 0;
        inline-size: max(16rem, 80vw);
        max-inline-size: calc(100vw - 2 * var(--space-md));
        max-block-size: 60vh;
        overflow-y: auto;
        background: var(--color-surface);
        border: 0.0625rem solid var(--color-border);
        border-radius: var(--radius-md);
        padding: var(--space-sm) var(--space-md);
        box-shadow: 0 0.25rem 1rem oklch(0% 0 0 / 20%);
      }
    }
  }

  .ms-toc__item {
    margin-block: var(--space-2xs);

    &[data-level="3"] {
      padding-inline-start: var(--space-md);
    }

    & a {
      color: var(--color-text-muted);
      text-decoration: none;
      line-height: 1.4;
      display: block;
      padding-block: var(--space-2xs);
      border-inline-start: 0.125rem solid transparent;
      padding-inline-start: var(--space-xs);
      transition:
        color var(--duration-fast) ease,
        border-color var(--duration-fast) ease;

      &:hover {
        color: var(--color-accent);
        border-inline-start-color: var(--color-accent);
      }
    }
  }

  /* ── Case index sidebar ──────────────────────────────────────────── */
  .ms-case-nav {
    margin-block-start: var(--space-xl);
    padding-block-start: var(--space-lg);
    border-block-start: 0.0625rem solid var(--color-border);

    & h3 {
      font-size: var(--text-base);
      font-weight: 600;
      margin-block-end: var(--space-sm);
    }

    & ul {
      list-style: none;
      padding: 0;
      margin: 0;
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
      gap: var(--space-2xs) var(--space-lg);
    }

    & a {
      font-size: var(--text-sm);
      color: var(--color-text-muted);
      text-decoration: none;
      padding-block: var(--space-2xs);
      display: block;
      transition: color var(--duration-fast) ease;

      &:hover {
        color: var(--color-accent);
      }

      &[aria-current="page"] {
        color: var(--color-accent);
        font-weight: 600;
      }
    }
  }

  /* ── Analysis sub-navigation ─────────────────────────────────────── */
  .ms-analysis-nav {
    margin-block-end: var(--space-lg);

    & ul {
      display: flex;
      flex-wrap: wrap;
      gap: var(--space-xs) var(--space-md);
      list-style: none;
      padding: 0;
      margin: 0;
    }

    & a {
      font-size: var(--text-sm);
      color: var(--color-text-muted);
      text-decoration: none;
      padding: var(--space-2xs) var(--space-sm);
      border: 0.0625rem solid var(--color-border);
      border-radius: var(--radius-md);
      transition:
        color var(--duration-fast) ease,
        border-color var(--duration-fast) ease,
        background-color var(--duration-fast) ease;

      &:hover {
        color: var(--color-accent);
        border-color: var(--color-accent);
      }

      &[aria-current="page"] {
        color: var(--color-on-accent);
        background-color: var(--color-accent);
        border-color: var(--color-accent);
      }
    }
  }

  /* ── Prev/next navigation ────────────────────────────────────────── */
  .ms-prev-next {
    display: flex;
    justify-content: space-between;
    gap: var(--space-md);
    margin-block-end: var(--space-lg);
  }

  .ms-prev-next__link {
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    text-decoration: none;
    transition: color var(--duration-fast) ease;

    &:hover {
      color: var(--color-accent);
    }
  }

  .ms-prev-next__link--prev {
    text-align: start;
  }

  .ms-prev-next__link--next {
    text-align: end;
    margin-inline-start: auto;
  }

  /* ── Page footer ───────────────────────���─────────────────────────── */
  .ms-page-footer {
    margin-block-start: var(--space-2xl);
    padding-block-start: var(--space-lg);
    border-block-start: 0.0625rem solid var(--color-border);
  }

  /* ── Abbreviation tooltips ────────────────────────────────────────── */
  .ms-prose abbr[data-tooltip] {
    position: relative;
    text-decoration: underline dotted 1.5px;
    text-decoration-color: color-mix(in oklch, var(--color-accent, #6a9fdb) 60%, transparent);
    text-underline-offset: 0.18em;
    cursor: default;
    font-variant: none;
  }

  .ms-prose abbr[data-tooltip]::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 0.4rem);
    left: 50%;
    transform: translateX(-50%);
    padding: 0.35rem 0.6rem;
    background-color: var(--color-surface, #1a1a2e);
    color: var(--color-text, #e0e0e0);
    border: 0.0625rem solid var(--color-border, #333);
    border-radius: var(--radius-md, 0.375rem);
    box-shadow: 0 0.25rem 0.75rem color-mix(in oklch, var(--color-text, #000) 15%, transparent);
    font-size: var(--text-sm, 0.8125rem);
    line-height: 1.4;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s ease;
    z-index: 40;
  }

  .ms-prose abbr[data-tooltip]:hover::after,
  .ms-prose abbr[data-tooltip]:focus::after {
    opacity: 1;
  }

  /* ── Glossary outbound links ────────────────────────────────────── */
  .ms-prose a.glossary-link {
    text-decoration: none;
    border-bottom: none;
    color: inherit;
  }
  .ms-prose a.glossary-link abbr[data-tooltip] {
    text-decoration: underline dotted 1.5px;
    text-decoration-color: color-mix(in oklch, var(--color-accent, #6a9fdb) 60%, transparent);
  }
  .ms-prose a.glossary-link:hover abbr[data-tooltip] {
    text-decoration-style: solid;
    text-decoration-color: var(--color-accent, #6a9fdb);
  }

  /* ── Tier badge links ───────────────────────────────────────────── */
  .ms-tier-link {
    text-decoration: none !important;
    border: none !important;
  }

  /* ── Source tier badges ──────────────────────────────────────────── */
  .ms-tier {
    display: inline-flex;
    align-items: center;
    padding-inline: 0.3em;
    padding-block: 0.05em;
    font-size: 0.8em;
    font-weight: 600;
    font-family: var(--font-mono);
    line-height: 1;
    border-radius: var(--radius-sm);
    vertical-align: baseline;
    cursor: help;

    &[data-tier="1"] {
      background-color: color-mix(in oklch, oklch(55% 0.15 145) 20%, transparent);
      color: oklch(40% 0.12 145);
    }

    &[data-tier="2"] {
      background-color: color-mix(in oklch, oklch(55% 0.1 248) 20%, transparent);
      color: oklch(40% 0.1 248);
    }

    &[data-tier="3"] {
      background-color: color-mix(in oklch, var(--color-text-muted) 15%, transparent);
      color: var(--color-text-muted);
    }

    &[data-tier="4"] {
      background-color: color-mix(in oklch, oklch(60% 0.12 60) 20%, transparent);
      color: oklch(45% 0.1 60);
    }

    &[data-tier="5"] {
      background-color: color-mix(in oklch, oklch(60% 0.15 30) 20%, transparent);
      color: oklch(45% 0.15 30);
    }

    &[data-tier="6"] {
      background-color: color-mix(in oklch, oklch(55% 0.08 300) 15%, transparent);
      color: oklch(45% 0.08 300);
    }

    &[data-tier="7"] {
      background-color: color-mix(in oklch, oklch(50% 0.1 0) 15%, transparent);
      color: oklch(40% 0.1 0);
    }
  }

  [data-theme="dark"] .ms-tier {
    &[data-tier="1"] {
      background-color: color-mix(in oklch, oklch(55% 0.15 145) 25%, transparent);
      color: oklch(70% 0.12 145);
    }

    &[data-tier="2"] {
      background-color: color-mix(in oklch, oklch(55% 0.1 248) 25%, transparent);
      color: oklch(70% 0.1 248);
    }

    &[data-tier="3"] {
      background-color: color-mix(in oklch, var(--color-text-muted) 20%, transparent);
      color: var(--color-text-muted);
    }

    &[data-tier="4"] {
      background-color: color-mix(in oklch, oklch(60% 0.12 60) 25%, transparent);
      color: oklch(70% 0.1 60);
    }

    &[data-tier="5"] {
      background-color: color-mix(in oklch, oklch(60% 0.15 30) 25%, transparent);
      color: oklch(70% 0.15 30);
    }

    &[data-tier="6"] {
      background-color: color-mix(in oklch, oklch(55% 0.08 300) 20%, transparent);
      color: oklch(70% 0.08 300);
    }

    &[data-tier="7"] {
      background-color: color-mix(in oklch, oklch(50% 0.1 0) 20%, transparent);
      color: oklch(70% 0.1 0);
    }
  }

  /* ── Source attribution (visible when source contains links) ─────── */
  .ms-source-attr {
    font-size: 0.8em;
    color: var(--color-text-muted);

    & a[href] {
      color: oklch(42% 0.12 248);
      text-decoration: underline;
      text-decoration-thickness: 0.1em;
      text-underline-offset: 0.15em;
      text-decoration-color: color-mix(in oklch, oklch(42% 0.12 248) 40%, transparent);

      &:hover {
        color: oklch(35% 0.14 248);
        text-decoration-color: oklch(35% 0.14 248);
      }
    }
  }

  [data-theme="dark"] .ms-source-attr {
    & a[href] {
      color: oklch(72% 0.1 248);
      text-decoration-color: color-mix(in oklch, oklch(72% 0.1 248) 40%, transparent);

      &:hover {
        color: oklch(78% 0.12 248);
        text-decoration-color: oklch(78% 0.12 248);
      }
    }
  }

  /* ── Confidence labels ───────────────────────────────────────────── */
  .ms-confidence {
    display: inline-flex;
    align-items: center;
    font-size: 0.8em;
    font-weight: 500;
    line-height: 1;
    vertical-align: baseline;

    &[data-level="confirmed"] {
      color: oklch(45% 0.12 145);
    }

    &[data-level="reported"] {
      color: oklch(45% 0.08 248);
    }

    &[data-level="alleged"] {
      color: oklch(50% 0.12 60);
    }

    &[data-level="speculated"] {
      color: oklch(50% 0.1 0);
    }
  }

  [data-theme="dark"] .ms-confidence {
    &[data-level="confirmed"] {
      color: oklch(70% 0.12 145);
    }

    &[data-level="reported"] {
      color: oklch(70% 0.08 248);
    }

    &[data-level="alleged"] {
      color: oklch(70% 0.12 60);
    }

    &[data-level="speculated"] {
      color: oklch(70% 0.1 0);
    }
  }

  /* ── Source / transparency sections ──────────────────────────────── */
  .ms-source-section {
    padding-block-end: var(--space-lg);
    border-block-end: 0.0625rem solid var(--color-border);
    margin-block-end: var(--space-lg);

    &:last-child {
      border-block-end: none;
    }
  }

  .ms-transparency-section {
    margin-block-end: var(--space-xl);

    & details {
      & summary {
        cursor: pointer;
        font-weight: 600;
        color: var(--color-text-muted);

        &:hover {
          color: var(--color-accent);
        }
      }
    }
  }

  /* ── Interactive pages ───────────────────────────────────────────── */
  .ms-interactive {
    position: relative;
    margin-block: var(--space-lg);
  }

  .ms-interactive__canvas {
    inline-size: 100%;
    min-block-size: 28rem;
    border: 0.0625rem solid var(--color-border);
    border-radius: var(--radius-md);
    background-color: var(--color-surface);
    overflow: hidden;

    &:focus-visible {
      outline: 0.125rem solid var(--color-accent);
      outline-offset: 0.125rem;
    }

    & svg {
      display: block;
      inline-size: 100%;
      block-size: 100%;
    }
  }

  .ms-controls {
    margin-block-end: var(--space-md);
  }

  .ms-layer-toggles {
    border: 0.0625rem solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-sm) var(--space-md);
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-xs) var(--space-lg);
    align-items: center;

    & legend {
      font-weight: 600;
      font-size: var(--text-sm);
      padding-inline: var(--space-xs);
    }

    & label {
      display: inline-flex;
      align-items: center;
      gap: var(--space-xs);
      font-size: var(--text-sm);
      cursor: pointer;
      color: var(--color-text-muted);
    }

    & input[type="checkbox"] {
      accent-color: var(--color-accent);
    }
  }

  /* ── Key / legend ────────────────────────────────────────────────── */
  .ms-key {
    background-color: var(--color-surface);
    border: 0.0625rem solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-md);
    margin-block-end: var(--space-md);

    & h3 {
      font-size: var(--text-base);
      margin-block-end: var(--space-sm);
    }

    & h4 {
      font-size: var(--text-sm);
      font-weight: 600;
      margin-block: var(--space-xs) var(--space-2xs);
    }
  }

  .ms-key__section {
    margin-block-end: var(--space-sm);

    &:last-child {
      margin-block-end: 0;
    }
  }

  .ms-key__list {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: var(--text-sm);
    color: var(--color-text-muted);
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs) var(--space-lg);

    & li {
      display: inline-flex;
      align-items: center;
      gap: var(--space-xs);
    }
  }

  /* Key swatches for diagram node types */
  .ms-key__swatch {
    display: inline-block;
    inline-size: 0.75rem;
    block-size: 0.75rem;
    border-radius: var(--radius-full);
    flex-shrink: 0;
  }

  /* Swatches read the same --ms-node-* tokens the diagram paints its circles
     with (tokens.css). Do not restate colors here — that is exactly how the
     key came to advertise green while the circles rendered blue. */
  .ms-key__swatch--person {
    background-color: var(--ms-node-person);
  }

  .ms-key__swatch--institution {
    background-color: var(--ms-node-institution);
  }

  .ms-key__swatch--location {
    background-color: var(--ms-node-location);
  }

  .ms-key__swatch--program {
    background-color: var(--ms-node-program);
  }

  /* Key lines for edge layers */
  .ms-key__line {
    display: inline-block;
    inline-size: 1.5rem;
    block-size: 0;
    border-block-start: 0.125rem solid var(--color-text-muted);
    flex-shrink: 0;
  }

  .ms-key__line--tight {
    border-block-start-style: solid;
  }

  .ms-key__line--medium {
    border-block-start-style: dashed;
  }

  .ms-key__line--corkboard {
    border-block-start-style: dotted;
    opacity: 0.5;
  }

  /* Key dots for timeline event types */
  .ms-key__dot {
    display: inline-block;
    inline-size: 0.625rem;
    block-size: 0.625rem;
    border-radius: var(--radius-full);
    flex-shrink: 0;
  }

  .ms-key__dot--disappearance {
    background-color: var(--ms-event-disappearance);
  }

  .ms-key__dot--death {
    background-color: var(--ms-event-death);
  }

  .ms-key__dot--body_found {
    background-color: var(--ms-event-body-found);
  }

  .ms-key__dot--suspect_arrested {
    background-color: var(--ms-event-suspect-arrested);
  }

  .ms-key__dot--investigation {
    background-color: var(--ms-event-investigation-milestone);
  }

  .ms-key__dot--institutional {
    background-color: var(--ms-event-institutional-statement);
  }

  .ms-key__dot--political {
    background-color: var(--ms-event-political);
  }

  .ms-key__dot--media {
    background-color: var(--ms-event-media);
  }

  .ms-key__dot--other {
    background-color: var(--ms-event-other);
  }

  /* ── Tooltip ─────────────────────────────────────────────────────── */
  .ms-tooltip {
    position: absolute;
    z-index: 50;
    max-inline-size: 22rem;
    padding: var(--space-sm) var(--space-md);
    background-color: var(--color-surface);
    border: 0.0625rem solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: 0 0.25rem 1rem color-mix(in oklch, var(--color-text) 12%, transparent);
    font-size: var(--text-sm);
    line-height: 1.5;
    pointer-events: none;

    &[hidden] {
      display: none;
    }

    & strong {
      display: block;
      margin-block-end: var(--space-2xs);
    }
  }

  /* ── Noscript fallback ───────────────────────────────────────────── */
  .ms-noscript {
    padding: var(--space-lg);
    background-color: var(--color-surface);
    border: 0.0625rem solid var(--color-border);
    border-radius: var(--radius-md);
    text-align: center;
    color: var(--color-text-muted);
  }

  /* ── Mobile: timeline & key ──────────────────────────────────────── */
  @media (max-width: 37.5rem) {
    .ms-key__list {
      gap: var(--space-2xs) var(--space-md);
      font-size: var(--text-xs, 0.75rem);
    }

    .ms-key {
      padding: var(--space-sm);
    }

    .ms-tooltip {
      max-inline-size: calc(100vw - 2rem);
      font-size: var(--text-xs, 0.75rem);
    }
  }

  /* ── Print styles ────────────────────────────────────────────────── */
  @media print {
    .ms-nav,
    .ms-controls,
    .ms-interactive,
    .ms-prev-next,
    .ms-case-nav {
      display: none;
    }

    .ms-layout {
      display: block;
    }

    .ms-toc {
      position: static;
      page-break-after: always;
    }

    .ms-tier,
    .ms-confidence {
      border: 0.0625rem solid currentColor;
      padding-inline: 0.2em;
    }
  }

  /* ── Diagram node interactivity hints ─────────────────────────────── */
  .ms-interactive__canvas svg g g {
    transition: opacity 0.3s ease;
  }

  /* ── Reduced motion ──────────────────────────────────────────────── */
  @media (prefers-reduced-motion: reduce) {
    .ms-nav__links a,
    .ms-toc__item a,
    .ms-prev-next__link,
    .ms-case-nav a,
    .ms-analysis-nav a {
      transition: none;
    }

    .ms-interactive__canvas svg g g {
      transition: none;
    }
  }

  /* ── Tables (wrapped by renderer in build/missing-scientists.ts) ──── */
  .ms-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    max-inline-size: 100%;
    margin-block: var(--space-md);
    border: 0.0625rem solid var(--color-border);
    border-radius: var(--radius-md);
  }

  .ms-prose .ms-table-wrap > table {
    inline-size: 100%;
    min-inline-size: max-content;
    border-collapse: collapse;

    @media (min-width: 48rem) {
      min-inline-size: 0;
      table-layout: fixed;
    }
    font-size: var(--text-sm);
  }

  .ms-prose .ms-table-wrap :is(th, td) {
    padding: var(--space-xs) var(--space-sm);
    border-block-end: 0.0625rem solid var(--color-border);
    vertical-align: top;
    text-align: start;
    overflow-wrap: anywhere;
  }

  .ms-prose .ms-table-wrap th {
    font-weight: 600;
    background-color: color-mix(in oklch, var(--color-surface) 60%, transparent);
  }

  /* Case Index is the only 7-column table (dossier.md:68-80).
     Hide the "Case File" column under narrow viewports — the Name
     column already links to the case page. */
  @media (max-width: 37.5rem) {
    .ms-prose .ms-table-wrap table:has(th:nth-child(7)) :is(th, td):nth-child(7) {
      display: none;
    }
  }
}

@layer animations {
  @keyframes fade-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

  @keyframes slide-up {
    from {
      opacity: 0;
      transform: translateY(1.5rem);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  @keyframes scale-in {
    from {
      opacity: 0;
      transform: scale(0.94);
    }
    to {
      opacity: 1;
      transform: scale(1);
    }
  }

  /* Page-load entrance animations */
  @media (prefers-reduced-motion: no-preference) {
    [data-animate] {
      animation: slide-up var(--duration-slow) ease both;
    }

    .stagger-1 { animation-delay: 0ms; }
    .stagger-2 { animation-delay: 80ms; }
    .stagger-3 { animation-delay: 160ms; }
    .stagger-4 { animation-delay: 240ms; }
  }

  /* Scroll-driven reveal — progressive enhancement */
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      [data-reveal] {
        animation: fade-in linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 40%;
      }

      /* Explicit declaration — default [data-reveal] already uses fade-in, but
         this selector survives if the default rule's animation-name ever changes. */
      [data-reveal="fade-in"] {
        animation-name: fade-in;
      }

      [data-reveal="fade-up"] {
        animation-name: slide-up;
      }

      [data-reveal="scale-in"] {
        animation-name: scale-in;
      }
    }
  }

  /* JS-driven reveal fallback — only active when scroll-driven animations are unsupported.
     Gated so these rules never compete with the [data-reveal] native path above. */
  @supports not (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      [data-reveal].reveal-pending {
        opacity: 0;
      }

      [data-reveal="fade-up"].reveal-pending {
        transform: translateY(1.5rem);
      }

      [data-reveal="scale-in"].reveal-pending {
        transform: scale(0.94);
      }

      [data-reveal].revealed {
        opacity: 1;
        transform: none;
        transition:
          opacity var(--duration-slow) ease,
          transform var(--duration-slow) ease;
      }

      [data-reveal].no-transition {
        transition: none;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      [data-reveal].reveal-pending {
        opacity: 1;
        transform: none;
      }
    }
  }

  /* Reduced motion: kill everything */
  @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;
    }

    [data-reveal],
    [data-animate] {
      animation: none;
      opacity: 1;
      transform: none;
    }
  }
}
