/* Foundation — public site styles.
   Tokens first, then layout, then components. Colours are only ever referenced
   through var(--token) so the dark scheme below is the single override point. */

:root {
  --ink: #0d1b2a;
  --ink-soft: #35475c;
  --ink-faint: #5c6f85;

  --bg: #ffffff;
  --bg-alt: #f5f7fa;
  --bg-sunk: #eef2f7;
  --surface: #ffffff;

  /* Blues taken from the staff GUI's default_dark theme
     (gui/fdn-gui/css/themes/default_dark.scss):
       --accent        = its --accent-primary       #2e52c9
       --accent-strong = its --wb-connection-blue   #2245b1
     The wash has no counterpart there, so it is an 8% tint of --accent on
     white. Contrast on white: accent 6.6:1, accent-strong 8.2:1. */
  --accent: #2e52c9;
  --accent-strong: #2245b1;
  --accent-wash: #e7ecfb;
  /* Text set on --accent-strong. 8.2:1. */
  --on-accent: #ffffff;

  /* One hue per component, for the home page orbit. Kept apart from the
     accent blue, which belongs to "Your System" at its centre, and from each
     other. Named by slug, so a component keeps its colour if the catalogue is
     reordered; a new component needs a token here. */
  --comp-ai-harness: #6d4fd8;
  --comp-case-workspace: #0f8f82;
  --comp-pre-action-protocol: #b7791f;
  --comp-claim-builder: #c8505a;
  --comp-security: #4b8f2f;
  --comp-integration: #a8428f;
  /* Sky: between Pre-Action Protocol's amber and the Claim Builder's rose on
     the ring, so it is set against warm colours on both sides. */
  /* What the data layer's heartbeat flushes toward. White on both grounds,
     because a pulse brightens, so there is no dark value below. */
  --flush: #ffffff;

  --line: #d7dee7;
  --line-soft: #e6ebf1;

  --focus: #b8541f;

  /* Amber, for the development-stage banner. Warm enough to read as "in
     progress" without the alarm of a red. */
  --status-ink: #7a5300;
  --status-wash: #fdf4e0;
  --status-line: #e8d5a8;

  --rad: 8px;
  --rad-lg: 14px;
  --shadow: 0 1px 2px rgba(13, 27, 42, 0.06), 0 4px 16px rgba(13, 27, 42, 0.06);

  --measure: 68ch;
  --page: 1120px;
  --gutter: 24px;

  --font: "Inter", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "JetBrains Mono", "Cascadia Mono", Consolas, "SF Mono", ui-monospace, monospace;

  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #e8eef5;
    --ink-soft: #b3c1d1;
    --ink-faint: #8497aa;

    --bg: #0a1622;
    --bg-alt: #0f2031;
    --bg-sunk: #132840;
    --surface: #10202f;

    /* On the dark ground the roles invert — the brighter blue carries links and
       buttons. --accent is default_dark's --link-blue (#527aff, 4.9:1 on our
       ground); --accent-strong lightens it so it still clears 4.5:1 against the
       --accent-wash pill; the wash is default_dark's --wb-card-bg-blue. */
    --accent: #527aff;
    --accent-strong: #8aa6ff;
    --accent-wash: #1e3a5f;
    /* The strong accent is light here, so what sits on it goes dark. */
    --on-accent: #0a1424;

    --comp-ai-harness: #a08bff;
    --comp-case-workspace: #3cc9b7;
    --comp-pre-action-protocol: #f0b44c;
    --comp-claim-builder: #f07f86;
    --comp-security: #8fd16b;
    --comp-integration: #e57cc0;

    --line: #24394f;
    --line-soft: #1b2c3e;

    --focus: #ffb454;

    --status-ink: #ffc247;
    --status-wash: #33280d;
    --status-line: #5c4a1a;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3);

    color-scheme: dark;
  }
}

/* ---------- base ---------- */

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

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3,
h4 {
  color: var(--ink);
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 0 0 0.5em;
  text-wrap: balance;
}

h1 {
  font-size: clamp(2.1rem, 1.5rem + 2.6vw, 3.3rem);
  font-weight: 700;
}
h2 {
  font-size: clamp(1.5rem, 1.2rem + 1.3vw, 2.1rem);
  font-weight: 650;
}
h3 {
  font-size: 1.18rem;
  font-weight: 650;
}
h4 {
  font-size: 1rem;
  font-weight: 650;
}

p,
li {
  max-width: var(--measure);
  text-wrap: pretty;
}

p {
  margin: 0 0 1.1em;
}

a {
  color: var(--accent-strong);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

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

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

code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: var(--bg-sunk);
  border-radius: 4px;
  padding: 0.12em 0.4em;
}

hr {
  border: 0;
  border-top: 1px solid var(--line-soft);
  margin: 2.5rem 0;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- phase banner ---------- */

.phase {
  background: var(--bg-alt);
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.87rem;
}

.phase__inner {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  padding-block: 0.6rem;
}

.phase__inner p {
  margin: 0;
  color: var(--ink-soft);
  max-width: none;
}

.phase__tag {
  flex: none;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--status-ink);
  background: var(--status-wash);
  border: 1px solid var(--status-line);
  border-radius: 999px;
  padding: 0.12rem 0.55rem;
}

@media (max-width: 620px) {
  .phase__inner {
    align-items: flex-start;
    flex-direction: column;
    gap: 0.4rem;
  }
}

/* ---------- scroll reveal ---------- */

/* Sections are visible by default. The hidden state exists only under
   `.js-reveal`, which src/reveal.rs sets on <html> once it has confirmed the
   browser has an IntersectionObserver to drive it. No script, an old browser,
   or a panic before that point all leave the page readable. */

.js-reveal .reveal .section__head,
.js-reveal .reveal .grid > *,
.js-reveal .reveal .btn-row,
.js-reveal .reveal .facts,
.js-reveal .reveal .prose,
.js-reveal .reveal .arch {
  opacity: 0;
  transform: translateY(12px);
  /* Ease-out: quick to start, settling slowly, which reads as arriving rather
     than sliding. */
  transition: opacity 0.5s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.js-reveal .reveal.is-visible .section__head,
.js-reveal .reveal.is-visible .grid > *,
.js-reveal .reveal.is-visible .btn-row,
.js-reveal .reveal.is-visible .facts,
.js-reveal .reveal.is-visible .prose,
.js-reveal .reveal.is-visible .arch {
  opacity: 1;
  transform: none;
}

/* The heading leads, then the cards follow it in. Capped at four: beyond that
   the last card waits long enough to feel broken rather than choreographed. */
.js-reveal .reveal.is-visible .grid > :nth-child(1) { transition-delay: 80ms; }
.js-reveal .reveal.is-visible .grid > :nth-child(2) { transition-delay: 150ms; }
.js-reveal .reveal.is-visible .grid > :nth-child(3) { transition-delay: 220ms; }
.js-reveal .reveal.is-visible .grid > :nth-child(n + 4) { transition-delay: 290ms; }

@media (prefers-reduced-motion: reduce) {
  /* The observer still runs and still marks sections visible; only the
     movement is dropped. */
  .js-reveal .reveal .section__head,
  .js-reveal .reveal .grid > *,
  .js-reveal .reveal .btn-row,
  .js-reveal .reveal .facts,
  .js-reveal .reveal .prose,
  .js-reveal .reveal .arch {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ---------- page changes ---------- */

/* Moving between pages is a view transition (`transition` in src/app.rs):
   the old page settles back and fades as the new one rises into its place.
   Quick on the way out and a little slower in, so the new page is what the
   eye lands on. The masthead is a layer of its own and holds still. A
   browser without view transitions changes page as it always did. */
::view-transition-old(root) {
  animation: page-out 0.18s cubic-bezier(0.4, 0, 1, 1) both;
}

::view-transition-new(root) {
  animation: page-in 0.32s cubic-bezier(0.22, 0.61, 0.36, 1) 0.06s both;
}

@keyframes page-out {
  to {
    opacity: 0;
    transform: translateY(-6px);
  }
}

@keyframes page-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }

  .nav {
    transition: none !important;
  }
}

/* ---------- layout primitives ---------- */

.page {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.site {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.site > main {
  flex: 1 0 auto;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--accent-strong);
  color: #fff;
  padding: 0.7rem 1.1rem;
  border-radius: 0 0 var(--rad) 0;
  font-weight: 600;
}

.skip-link:focus {
  left: 0;
  color: #fff;
}

.section {
  padding-block: clamp(3rem, 6vw, 5.5rem);
}

.section--alt {
  background: var(--bg-alt);
  border-block: 1px solid var(--line-soft);
}

.section__head {
  margin-bottom: 2.5rem;
}

/* The section straight after the hero is pulled up close to it. The hero and a
   full section band each carry their own generous padding, and stacked they put
   a screen's worth of nothing between the headline and the first real thing on
   the page. Only the first one: further down the page that spacing is what
   separates one subject from the next, and is worth keeping. */
.hero + .section {
  padding-top: clamp(1rem, 2vw, 1.5rem);
}

/* The same on an interior page: the lede and the first section's heading
   belong together, and a full band's padding between them reads as the end
   of the page rather than the start of it. */
.page-head + .section {
  padding-top: clamp(1.25rem, 2.5vw, 2rem);
}

/* The board is exactly this band's bottom padding taller than it was, and takes
   that padding's place. The next section therefore begins where it already did
   — the empty strip under the cards becomes part of the area you can drag in
   rather than the gap between two sections. */
.section--flush {
  padding-bottom: 0;
}

.hero + .section .section__head {
  margin-bottom: 1.25rem;
}

.section__head p {
  color: var(--ink-soft);
  font-size: 1.05rem;
  margin-bottom: 0;
}

.eyebrow {
  display: block;
  font-size: 0.78rem;
  font-weight: 650;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.7rem;
}

.noscript {
  max-width: 40rem;
  margin: 4rem auto;
  padding: 0 1.5rem;
  font-family: system-ui, sans-serif;
}

/* ---------- header / nav ---------- */

.masthead {
  position: sticky;
  top: 0;
  z-index: 40;
  /* Its own layer in a page change, so it holds still while the page under
     it changes (see "page changes"). */
  view-transition-name: masthead;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line-soft);
}

.masthead__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 68px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 700;
  font-size: 1.12rem;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
  flex: none;
}

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

/* The mark is the shared <svg> from components/marks.rs; it carries its own
   width and height, and its own corner radius. */
.brand .mk {
  flex: none;
}

.nav {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-left: auto;
}

.nav__link {
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.95rem;
  font-weight: 550;
  padding: 0.45rem 0.7rem;
  border-radius: var(--rad);
  white-space: nowrap;
}

.nav__link:hover {
  color: var(--ink);
  background: var(--bg-sunk);
}

.nav__link[aria-current="page"] {
  color: var(--accent-strong);
  background: var(--accent-wash);
}

.nav__toggle {
  display: none;
  margin-left: auto;
  align-items: center;
  gap: 0.5rem;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 550;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--rad);
  padding: 0.45rem 0.8rem;
  cursor: pointer;
}

@media (max-width: 860px) {
  .nav__toggle {
    display: inline-flex;
  }

  .nav {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0.15rem;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
    padding: 0.75rem var(--gutter) 1.1rem;
    box-shadow: var(--shadow);
    /* The menu drops into place and lifts away again, rather than snapping.
       `allow-discrete` holds `display` until the fade out has finished, and
       @starting-style gives the fade in somewhere to start from, so this is
       all the stylesheet's: the toggle in masthead.rs only sets the class.
       A browser without either simply snaps, as before. */
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity 0.2s ease, transform 0.25s cubic-bezier(0.22, 0.61, 0.36, 1),
      display 0.25s allow-discrete;
  }

  .nav--open {
    display: flex;
    opacity: 1;
    transform: none;
  }

  @starting-style {
    .nav--open {
      opacity: 0;
      transform: translateY(-8px);
    }
  }

  .nav__link {
    padding: 0.65rem 0.75rem;
    font-size: 1rem;
  }
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font: inherit;
  font-size: 0.97rem;
  font-weight: 600;
  line-height: 1.2;
  padding: 0.78rem 1.35rem;
  border-radius: var(--rad);
  border: 1px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

.btn--primary {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: #fff;
}

.btn--primary:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  transform: translateY(-1px);
}

.btn--secondary {
  background: var(--surface);
  border-color: var(--line);
  color: var(--ink);
}

.btn--secondary:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
  transform: translateY(-1px);
}

@media (prefers-color-scheme: dark) {
  /* Ink on the bright blue button, rather than white, which would sit at
     about 2:1 against it. This is 8:1. */
  .btn--primary,
  .btn--primary:hover {
    color: #0a1424;
  }
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-top: 1.8rem;
}

/* ---------- hero ---------- */

.hero {
  /* Kept tight so the library section below, and the orbit in it, is on the
     first screen at common laptop heights. Every rule in this block is set
     with that in mind: loosen one and check 1440x900 again. */
  padding-top: clamp(1.25rem, 2vw, 1.75rem);
  padding-bottom: clamp(1.1rem, 1.8vw, 1.5rem);
  /* No background: the dot field sits behind this band, and an opaque hero
     would paint straight over it. The wash it used to carry now lives on
     `.topfield`. */
  border-bottom: 1px solid var(--line-soft);
}

/* The name, on its own line above the headline. Sized in em so it tracks the
   h1's own clamp rather than needing a second one, and still inside the h1, so
   the heading a screen reader reads is one sentence beginning with the name. */
.hero__brand {
  display: block;
  font-size: 0.42em;
  font-weight: 650;
  letter-spacing: 0.01em;
  color: var(--accent);
  margin-bottom: 0.25em;
}

.hero h1 {
  margin-bottom: 0.35em;
}

/* Wider and a size down from what it was, so it sets in two lines rather
   than three on a laptop screen. */
.hero__lede {
  font-size: clamp(1.02rem, 0.97rem + 0.3vw, 1.14rem);
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 70ch;
  margin-bottom: 0;
}

.hero .btn-row {
  margin-top: 1.25rem;
}

.hero__note {
  margin-top: 0.9rem;
  margin-bottom: 0;
  font-size: 0.9rem;
  color: var(--ink-faint);
  /* One line on a wide screen: at this size the measure breaks it short. */
  max-width: none;
}

/* ---------- cards / grids ---------- */

.grid {
  display: grid;
  gap: 1.3rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
}

/* For sets of exactly four, so they settle as 2x2 rather than 3 + 1. */
.grid--duo {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--rad-lg);
  padding: 1.5rem;
  box-shadow: var(--shadow);
}

.card h3 {
  margin-bottom: 0.45rem;
}

.card p:last-child {
  margin-bottom: 0;
  color: var(--ink-soft);
  font-size: 0.97rem;
}

/* Icon and category label on one line. The row owns the spacing beneath, so a
   card without an icon sits identically to one with. */
.card__meta {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.75rem;
  /* The glyph takes currentColor, so the colour is set once, here. */
  color: var(--accent);
}

.card__meta .icon {
  width: 17px;
  height: 17px;
  flex: none;
}

/* A card that is itself a link. The anchor has to be told to behave like the
   <article> it replaces, because `a` is inline and carries link colour and
   underline from the base rules. */
.card--link {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: border-color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
}

.card--link h3 {
  color: var(--accent);
}

.card--link:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(13, 27, 42, 0.07), 0 10px 26px rgba(13, 27, 42, 0.09);
}

.card--link:hover h3 {
  text-decoration: underline;
  text-underline-offset: 2px;
}

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

  .card--link:hover {
    transform: none;
  }
}

.card__index {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: inherit;
  /* Mono digits and caps sit high against a 17px glyph; nudge to the optical
     centre so the pair share a baseline. */
  line-height: 1;
  padding-top: 1px;
}

/* ---------- definition-style fact list ---------- */

.facts {
  margin: 0;
  display: grid;
  gap: 0;
  border: 1px solid var(--line);
  border-radius: var(--rad-lg);
  overflow: hidden;
  background: var(--surface);
  max-width: var(--measure);
}

.facts__row {
  display: grid;
  grid-template-columns: minmax(12rem, 32%) 1fr;
  gap: 1rem;
  padding: 0.95rem 1.25rem;
  border-top: 1px solid var(--line-soft);
}

.facts__row:first-child {
  border-top: 0;
}

.facts dt {
  font-weight: 600;
  color: var(--ink-soft);
  font-size: 0.93rem;
}

.facts dd {
  margin: 0;
}

@media (max-width: 620px) {
  .facts__row {
    grid-template-columns: 1fr;
    gap: 0.2rem;
  }
}

/* ---------- prose (legal + long-form pages) ---------- */

/* `.prose` is applied alongside `.page`, so it must not constrain the container
   itself — that would re-centre the body away from the page heading. Constrain
   the children instead, and the measure is kept without breaking alignment. */
.prose > * {
  max-width: var(--measure);
}

.prose h2 {
  margin-top: 2.6rem;
  padding-top: 0.3rem;
  scroll-margin-top: 90px;
}

.prose h3 {
  margin-top: 1.8rem;
  scroll-margin-top: 90px;
}

.prose ul,
.prose ol {
  padding-left: 1.3rem;
  margin: 0 0 1.1em;
}

.prose li {
  margin-bottom: 0.45em;
}

.prose li::marker {
  color: var(--ink-faint);
}

/* A component screenshot or recording, below the prose that introduces it. */
.shot {
  margin: 2.5rem 0 0;
}

.shot img,
.shot video {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: var(--shadow);
}

.shot__title {
  margin-bottom: 1rem;
}

/* What is going on in a recording, kept to the prose measure beneath it. */
.shot__caption {
  margin-top: 1.2rem;
  max-width: var(--measure);
  color: var(--ink-soft);
}

.shot__caption p:last-child {
  margin-bottom: 0;
}

.page-head {
  padding-block: clamp(2.5rem, 5vw, 4rem) 0;
}

.page-head p {
  color: var(--ink-soft);
  font-size: 1.05rem;
}

.meta-line {
  font-size: 0.88rem;
  color: var(--ink-faint);
  margin-bottom: 0;
}

/* Editorial placeholder marker — every unresolved legal fact is wrapped in this
   so an unreviewed value is impossible to miss in review or in production. */
.todo {
  background: #fff3cd;
  color: #5c4708;
  border-bottom: 2px dotted #b8860b;
  padding: 0 0.25em;
  font-weight: 600;
}

@media (prefers-color-scheme: dark) {
  .todo {
    background: #4a3a08;
    color: #ffe9a8;
    border-bottom-color: #ffc107;
  }
}

.callout {
  border-left: 3px solid var(--accent);
  background: var(--bg-alt);
  border-radius: 0 var(--rad) var(--rad) 0;
  padding: 1.1rem 1.3rem;
  margin: 1.8rem 0;
}

.callout > :last-child {
  margin-bottom: 0;
}

/* A cited passage from a published report. Shaped like a callout so it reads
   as set apart from our own words; the citation is always visible. */
.quote {
  border-left: 3px solid var(--accent);
  background: var(--bg-alt);
  border-radius: 0 var(--rad) var(--rad) 0;
  padding: 1.1rem 1.3rem;
  margin: 1.8rem 0;
  max-width: var(--measure);
}

.quote blockquote {
  margin: 0;
}

.quote blockquote p {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.6;
  color: var(--ink);
}

.quote__cite {
  margin-top: 0.7rem;
  font-size: 0.85rem;
  color: var(--ink-faint);
}

/* The two sides of a layer on the Security page: what it gives the person
   inside it, and what it keeps out. Side by side, so each reads against the
   other; stacked where there is no room. */
.aims {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.8rem;
  margin: 0.6rem 0 0.4rem;
  padding: 0;
}

.aims > div {
  border-top: 2px solid var(--line);
  padding-top: 0.5rem;
}

.aims > div:first-child {
  border-top-color: var(--accent);
}

.aims dt {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.aims dd {
  margin: 0.2rem 0 0;
  color: var(--ink-soft);
}

@media (max-width: 620px) {
  .aims {
    grid-template-columns: 1fr;
  }
}

/* A component drawn as layers, each inside the one before it (the figure on
   the Security page). Each layer is tinted a little more with the
   component's colour than the one round it, through --tint, which the page
   sets per layer. Padding narrows at small widths so the record at the
   centre still has room for its name. */
.diagram.layers {
  margin: 2rem 0 2.2rem;
}

.layers .diagram__body {
  padding: 1rem;
}

.layers__door {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 0.3rem 0.9rem;
}

.layers__layer {
  border: 1.5px solid color-mix(in srgb, var(--comp-security) 55%, var(--line));
  border-radius: var(--rad-lg);
  background: color-mix(in srgb, var(--comp-security) var(--tint, 4%), var(--bg));
  padding: 0.55rem 0.8rem 0.8rem;
}

.layers__layer .layers__layer {
  margin-top: 0.55rem;
}

/* The innermost layer is the record itself: drawn solid, as the thing
   everything else is round. */
.layers__layer:not(:has(.layers__layer)) {
  border-width: 2px;
  border-color: var(--comp-security);
  padding-bottom: 0.6rem;
}

.layers__layer--planned {
  border-style: dashed;
}

.layers__head {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.55rem;
  align-items: baseline;
}

.layers__num {
  grid-row: span 2;
  display: inline-grid;
  place-items: center;
  width: 1.45rem;
  height: 1.45rem;
  border-radius: 50%;
  background: var(--comp-security);
  color: var(--bg);
  font-size: 0.75rem;
  font-weight: 700;
  align-self: start;
}

.layers__name {
  font-weight: 600;
  color: var(--ink);
  line-height: 1.35;
}

.layers__checks {
  font-size: 0.86rem;
  color: var(--ink-soft);
  line-height: 1.35;
}

.layers__badge {
  margin-left: 0.5em;
  padding: 0.05em 0.5em;
  border: 1px solid var(--status-line);
  border-radius: 999px;
  background: var(--status-wash);
  color: var(--status-ink);
  font-size: 0.72rem;
  font-weight: 600;
  vertical-align: 0.1em;
}

@media (max-width: 620px) {
  .layers__layer {
    padding: 0.45rem 0.4rem 0.5rem;
  }

  .layers__layer .layers__layer {
    margin-top: 0.45rem;
  }
}

/* ---------- footer ---------- */

.footer {
  margin-top: auto;
  background: var(--bg-alt);
  border-top: 1px solid var(--line);
  padding-block: 3rem 2rem;
  font-size: 0.92rem;
  color: var(--ink-soft);
}

.footer__cols {
  display: grid;
  gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--line);
}

.footer h2 {
  font-size: 0.78rem;
  font-weight: 650;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 0.9rem;
}

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

.footer li {
  margin-bottom: 0.5rem;
}

.footer a {
  color: var(--ink-soft);
  text-decoration: none;
}

.footer a:hover {
  color: var(--accent-strong);
  text-decoration: underline;
}

.footer__legal {
  padding-top: 1.8rem;
  font-size: 0.86rem;
  color: var(--ink-faint);
}

.footer__legal p {
  max-width: 85ch;
  margin-bottom: 0.7rem;
}

.footer__legal p:last-child {
  margin-bottom: 0;
}

/* ---------- the brand mark ---------- */

/* The shield on its navy plate. #527aff rather than the light-ground --accent
   (#2e52c9), because the plate is a fixed navy in both themes and the darker
   blue sits at about 1.6:1 on it. This is the one mark that is not part of the
   temporary review below — keep it when that block goes. */
.mk--ink {
  --mk-plate: #0d1b2a;
  /* The lit corner of the plate's gradient. A lift of the same navy rather than
     a different hue, so the plate still reads as one colour. */
  --mk-plate-lit: #1d3450;
  --mk-ink: #527aff;
}

/* ---------- logo review (TEMPORARY, with src/pages/logos.rs) ---------- */

.lg-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.9rem;
  margin-bottom: 2rem;
}

.lg-controls__label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.lg-seg {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--rad);
}

.lg-seg button {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 550;
  color: var(--ink-soft);
  background: none;
  border: 0;
  border-radius: 6px;
  padding: 0.45rem 0.9rem;
  cursor: pointer;
}

.lg-seg button:hover { color: var(--ink); }

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

.lg-grid {
  display: grid;
  gap: 1.3rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
}

.lg-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--rad-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.lg-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.8rem;
  padding: 1.1rem 1.25rem 0.85rem;
}

.lg-card__head h3 { margin: 0; }

.lg-chip {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.18rem 0.6rem;
  white-space: nowrap;
}

/* The stage paints the site's real header colours, independent of page theme. */
.lg-stage {
  border-block: 1px solid var(--line-soft);
  padding: 1.5rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 1.3rem;
}

.lg-stage.lg-light { background: #ffffff; color: #0d1b2a; --lg-fg: 13, 27, 42; }
.lg-stage.lg-dark { background: #0a1622; color: #e8eef5; --lg-fg: 232, 238, 245; }

/* Variants that follow the surrounding ground rather than fixing a colour. */
.lg-light .mk--bare,
.lg-light .mk--original { --mk-ink: #1e834d; --mk-course: #1e834d; }
.lg-dark .mk--bare,
.lg-dark .mk--original { --mk-ink: #3fc183; --mk-course: #3fc183; }

/* Fixed-colour variants. These read the same on either ground, by design. */
.mk--inverse { --mk-plate: #0d1b2a; --mk-ink: #e8eef5; }
.mk--field { --mk-plate: #1e834d; --mk-ink: #f4f7f4; }
.mk--course { --mk-plate: #0d1b2a; --mk-ink: #3fc183; --mk-course: #e8eef5; }

.mk { display: block; }

.lg-stage__top {
  display: flex;
  align-items: flex-end;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.lg-ramp {
  display: flex;
  align-items: flex-end;
  gap: 0.9rem;
  flex-wrap: wrap;
}

.lg-ramp__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
}

.lg-px {
  font-family: var(--font-mono);
  font-size: 0.56rem;
  opacity: 0.55;
}

.lg-mocks { display: flex; flex-direction: column; gap: 0.8rem; }

.lg-cap {
  font-family: var(--font-mono);
  font-size: 0.56rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.5;
  margin: 0 0 0.35rem;
}

.lg-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 260px;
  background: rgba(var(--lg-fg), 0.1);
  border-radius: 9px 9px 0 0;
  padding: 0.5rem 0.85rem;
  font-size: 0.78rem;
}

.lg-tab span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lg-bar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  border: 1px solid rgba(var(--lg-fg), 0.16);
  border-radius: 9px;
  padding: 0.65rem 0.9rem;
}

.lg-word {
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: -0.02em;
}

.lg-nav {
  margin-left: auto;
  display: flex;
  gap: 0.85rem;
  font-size: 0.78rem;
  opacity: 0.62;
}

.lg-card__foot { padding: 1rem 1.25rem 1.25rem; }

.lg-note {
  margin: 0 0 0.7rem;
  font-size: 0.9rem;
  color: var(--ink-soft);
}

.lg-spec {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.8rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  color: var(--ink-faint);
}

.lg-swatch { display: inline-flex; align-items: center; gap: 0.35rem; }

.lg-swatch i {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  border: 1px solid rgba(128, 128, 128, 0.4);
}

.lg-subhead { margin: 3rem 0 0.3rem; }

.lg-subnote {
  color: var(--ink-soft);
  font-size: 0.95rem;
  margin-bottom: 1.5rem;
}

@media (max-width: 520px) {
  .lg-stage__top { gap: 1rem; }
}

/* ---------- home page architecture diagram ---------- */

.arch {
  margin: 0;
}

/* A drawing, not a layout: it keeps its proportions and scrolls sideways on a
   narrow screen rather than shrinking its labels into illegibility. */
.arch__scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding-bottom: 0.4rem;
}

.arch__svg {
  display: block;
  width: 100%;
  min-width: 660px;
  height: auto;
}

/* Boxes that link to their component page. The whole box is the target, so
   the cursor and the hover have to be on the anchor rather than the rect —
   an SVG <a> has no box of its own to style. */
.arch__link {
  cursor: pointer;
}

.arch__link .arch__box--link {
  transition: stroke-width 140ms ease;
}

/* Under the pointer a box firms up: its outline goes solid and heavier, and
   its name takes its colour. */
.arch__link:hover .arch__box--link {
  stroke-width: 2.4;
  stroke-dasharray: none;
}

.arch__link:hover .arch__title {
  fill: var(--hue);
}

/* SVG ignores the document's focus ring, so the focused box states it in the
   only property available to it. */
.arch__link:focus-visible {
  outline: none;
}

.arch__link:focus-visible .arch__box--link {
  stroke: var(--focus);
  stroke-width: 3;
  stroke-dasharray: none;
}

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

.arch__title {
  font-family: var(--font);
  font-size: 15px;
  font-weight: 600;
  fill: var(--ink);
}

.arch__sub {
  font-family: var(--font);
  font-size: 12px;
  fill: var(--ink-faint);
}


/* ---------- connecting systems ---------- */

/* See src/pages/connecting.rs. A still drawing on the platform page's `.arch`
   frame; what is its own is the hub's outline and the solid/dashed rule, which
   here means "runs today" against "designed, not yet built". */
.hub__svg {
  min-width: 760px;
}


/* ---------- the AI harness ---------- */

/* See src/components/harness.rs. A still diagram, set above the prose on the
   AI harness page; its boxes are the shared .dg- ones. What is its own is the
   sandbox's wall, with a gap in it for reads and a door for changes. */
.diagram.harness {
  margin-bottom: 2.5rem;
}

.harness__svg--a {
  min-width: 780px;
}

/* The sandbox: dashed, because it is a boundary rather than a thing. */
.harness__sandbox {
  fill: color-mix(in srgb, var(--tint) 30%, var(--bg));
  stroke: var(--hue);
  stroke-width: 1.8;
  stroke-dasharray: 7 5;
}

/* An opening in the sandbox wall: painted over the dashes in the colour of
   what lies behind it. */
.harness__gap {
  fill: color-mix(in srgb, var(--tint) 30%, var(--bg));
}

.harness__door {
  fill: var(--pastel-blue-ink);
}

/* Dashed: a set of conditions, not a thing. */
.harness__needs {
  fill: none;
  stroke: var(--hue);
  stroke-width: 1.2;
  stroke-dasharray: 4 4;
}

.harness__chip-title {
  font-size: 14px;
}

.harness__note {
  font-family: var(--font);
  font-size: 12.5px;
  fill: var(--ink-soft);
}

.harness__note--strong {
  font-weight: 600;
}

.harness__or {
  font-family: var(--font);
  font-size: 12px;
  font-style: italic;
  fill: var(--ink-faint);
}

.harness__link {
  font-family: var(--font);
  font-size: 12.5px;
  font-weight: 600;
  fill: var(--accent);
  text-decoration: underline;
}

a:hover > .harness__link {
  fill: var(--accent-strong);
}

a:focus-visible > .harness__link {
  outline: 2px solid var(--focus);
}


/* ---------- the Integration drawing's discs ---------- */

/* See src/components/combined.rs. All the movement is written there, frame by
   frame, as attributes; nothing here animates. What the stylesheet owns is how
   each piece looks. The class names are the orbit's, the drawing it grew
   from. */

/* Each component's line carries its own `--hue`, like its disc. Thinner than
   the shared piece lines: there are seven of them. */
.orbit__line {
  stroke: var(--hue);
  stroke-opacity: 0.7;
  stroke-width: 1.6;
  stroke-linecap: round;
}

.orbit__halo {
  fill: var(--accent-wash);
}

.orbit__core {
  fill: var(--accent-strong);
}

/* Size is set on the element by combined.rs, which positions the two lines
   from it. */
.orbit__core-label {
  font-family: var(--font);
  font-weight: 700;
  letter-spacing: -0.01em;
  fill: var(--on-accent);
}

/* ---------- the pieces the drawings share ---------- */

/* The Integration drawing is drawn in one language, set out in
   src/components/drawing.rs: a glow behind each piece, the solid
   shape, the name beneath in the same type, thin lines between pieces, a
   flow of dots along them, and a heartbeat of colour on the data layer.
   Each piece carries `--hue`, set by the drawing — a component's own token
   on the components' discs, the accent blues on everything that is the API's
   or the reader's — so the colours stay in the token block at the top of this
   file and one set of rules serves every colour. Nothing here animates;
   every frame is written as attributes by the drawing's loop. */

.piece__glow {
  fill: var(--hue);
  fill-opacity: 0.16;
  transition: fill-opacity 160ms ease;
}

.piece__disc,
.piece__pill,
.piece__cyl {
  fill: var(--hue);
}

/* Not built yet, and drawn so: hollow, with the dashed outline the site
   already uses for "this part is not solid". */
.piece--design {
  fill: var(--bg);
  stroke: var(--hue);
  stroke-width: 2;
  stroke-dasharray: 5 4;
}

/* A cylinder's end, a shade off the body so it reads as a lid: toward the
   page background, which is lighter on the light ground and darker on the
   dark one. */
.piece__lid {
  fill: var(--bg);
  fill-opacity: 0.28;
  stroke: var(--bg);
  stroke-opacity: 0.35;
  stroke-width: 1;
}

/* The heartbeat: two layers whose opacity the loop takes from nothing to
   full and back, twice a beat — a second glow over the first, and a flush
   over the body. Colour only; nothing here changes size. Kept faint: it is
   meant to be felt, not watched. */
.piece__beat-glow {
  fill: var(--hue);
  fill-opacity: 0.18;
}

.piece__beat {
  fill: var(--flush);
  fill-opacity: 0.16;
}

/* The lines between pieces, a little heavier than the orbit's component
   lines, in the API's blue; and the flow: dots running along them, under
   the pieces at either end, each in a component's own colour — set as
   --hue by the drawing, in turn — so what runs along the lines reads as
   the components' data. */
.piece__line {
  stroke: var(--accent);
  stroke-opacity: 0.8;
  stroke-width: 2.2;
  stroke-linecap: round;
}

.piece__flow {
  fill: var(--hue);
}

/* Names hang below their pieces, and some sit right across a line. The
   stroke, painted under the fill in the page background colour, cuts the
   line away behind the letters so the text stays clean. */
.piece__label,
.piece__status {
  paint-order: stroke;
  stroke: var(--bg);
  stroke-width: 5px;
  stroke-linejoin: round;
}

.piece__label {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 600;
  fill: var(--ink);
  transition: fill 160ms ease;
}

.piece__status {
  font-family: var(--font-mono);
  font-size: 10.5px;
  fill: var(--ink-faint);
}

.piece__link {
  cursor: pointer;
}

.piece__link:hover .piece__glow {
  fill-opacity: 0.4;
}

.piece__link:hover .piece__label {
  fill: var(--accent-strong);
}

/* SVG ignores the document's focus ring, so a focused piece states it in
   the only property available to it. */
.piece__link:focus-visible {
  outline: none;
}

.piece__link:focus-visible .piece__disc,
.piece__link:focus-visible .piece__pill,
.piece__link:focus-visible .piece__cyl {
  stroke: var(--focus);
  stroke-width: 3;
  stroke-dasharray: none;
}

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

/* ---------- diagrams ---------- */

/* The diagrams' one palette, set on every diagram (Diagram in
   src/components/ui.rs): a pastel set taken from the cards in "A case, laid
   out": the first four pairs are their header chips (Claim, Case, Document,
   Hearing) and the pale fill with the deeper label; teal is the judge's, and
   rose and pink extend the set in the same lightness. Each pair is a
   tint for a body and an ink for its outline, lines and flow. A thing wears
   the same pair in every diagram: the record steel, the API's parts slate,
   a database sand, a Connector or translator mint, the reader's systems
   blue, sage and ochre, and each component its own. */
.diagram {
  --pastel-blue: #e2e6f6;
  --pastel-blue-ink: #3355c4;
  --pastel-green: #d0f7d6;
  --pastel-green-ink: #17761a;
  --pastel-lilac: #e0d7ec;
  --pastel-lilac-ink: #7338bd;
  --pastel-peach: #eecfb2;
  --pastel-peach-ink: #c96a17;
  --pastel-teal: #cdece7;
  --pastel-teal-ink: #1f6e63;
  --pastel-rose: #f5d5d9;
  --pastel-rose-ink: #b8404c;
  --pastel-pink: #efd4e7;
  --pastel-pink-ink: #a23c86;
  /* And four for the pieces of the ways, so they are not all blue. */
  --pastel-sky: #d5e9f5;
  --pastel-sky-ink: #1d6fa3;
  --pastel-sand: #ebe2d3;
  --pastel-sand-ink: #7a5d36;
  --pastel-mint: #d3f1e3;
  --pastel-mint-ink: #1f7a55;
  --pastel-slate: #dfe4eb;
  --pastel-slate-ink: #4b5d73;
  /* The data layer: a bluer slate, a step apart from the API. */
  --pastel-steel: #d6e2f0;
  --pastel-steel-ink: #3a6490;
  /* The existing and legacy systems, beside the modern one's blue: a muted
     sage, and a warm, aged ochre. */
  --pastel-sage: #dde9d8;
  --pastel-sage-ink: #4a7340;
  --pastel-ochre: #f2e0c2;
  --pastel-ochre-ink: #9a5f14;

  /* Blue is the reader's system, and the lines of the ways. */
  --accent: var(--pastel-blue-ink);
  --accent-strong: var(--pastel-blue-ink);
  --accent-wash: var(--pastel-blue);

  /* The components take the other seven, set so that warm and cool take
     turns along the row under the bar (see ROW in combined.rs). */
  --comp-security: var(--pastel-green-ink);
  --tint-security: var(--pastel-green);
  --comp-integration: var(--pastel-pink-ink);
  --tint-integration: var(--pastel-pink);
  --comp-case-workspace: var(--pastel-teal-ink);
  --tint-case-workspace: var(--pastel-teal);
  --comp-ai-harness: var(--pastel-peach-ink);
  --tint-ai-harness: var(--pastel-peach);
  --comp-pre-action-protocol: var(--pastel-lilac-ink);
  --tint-pre-action-protocol: var(--pastel-lilac);
  --comp-claim-builder: var(--pastel-rose-ink);
  --tint-claim-builder: var(--pastel-rose);

  /* The two panels: the reader's estate, a breath of their blue, and
     Foundation, a breath of the API's slate. Solid colours, not
     transparencies, as each panel's children take one as their --bg. */
  --zone-yours: color-mix(in srgb, var(--pastel-blue) 40%, var(--bg));
  --zone-ours: color-mix(in srgb, var(--pastel-slate) 55%, var(--bg));
}

@media (prefers-color-scheme: dark) {
  /* The cards' dark theme colours only the label, so here the inks are
     their dark values and each tint is its ink sunk most of the way into
     the page. */
  .diagram {
    --pastel-blue-ink: #7b97ff;
    --pastel-green-ink: #87f197;
    --pastel-lilac-ink: #b985f0;
    --pastel-peach-ink: #ffa552;
    --pastel-teal-ink: #3fb8a8;
    --pastel-rose-ink: #f07f86;
    --pastel-pink-ink: #e57cc0;
    --pastel-sky-ink: #6cc3f5;
    --pastel-sand-ink: #d9b98a;
    --pastel-mint-ink: #6fdcaa;
    --pastel-slate-ink: #a3b3c8;
    --pastel-steel-ink: #8fb6e0;
    --pastel-sage-ink: #9cc98f;
    --pastel-ochre-ink: #e3aa5c;
    --pastel-blue: color-mix(in srgb, var(--pastel-blue-ink) 22%, var(--bg));
    --pastel-green: color-mix(in srgb, var(--pastel-green-ink) 22%, var(--bg));
    --pastel-lilac: color-mix(in srgb, var(--pastel-lilac-ink) 22%, var(--bg));
    --pastel-peach: color-mix(in srgb, var(--pastel-peach-ink) 22%, var(--bg));
    --pastel-teal: color-mix(in srgb, var(--pastel-teal-ink) 22%, var(--bg));
    --pastel-rose: color-mix(in srgb, var(--pastel-rose-ink) 22%, var(--bg));
    --pastel-pink: color-mix(in srgb, var(--pastel-pink-ink) 22%, var(--bg));
    --pastel-sky: color-mix(in srgb, var(--pastel-sky-ink) 22%, var(--bg));
    --pastel-sand: color-mix(in srgb, var(--pastel-sand-ink) 22%, var(--bg));
    --pastel-mint: color-mix(in srgb, var(--pastel-mint-ink) 22%, var(--bg));
    --pastel-slate: color-mix(in srgb, var(--pastel-slate-ink) 22%, var(--bg));
    --pastel-steel: color-mix(in srgb, var(--pastel-steel-ink) 22%, var(--bg));
    --pastel-sage: color-mix(in srgb, var(--pastel-sage-ink) 22%, var(--bg));
    --pastel-ochre: color-mix(in srgb, var(--pastel-ochre-ink) 22%, var(--bg));
  }
}


/* Every diagram in one frame: a light border round the drawing, and joined
   to its foot a panel holding its title and what it says. No shadow and no
   blur: the edges are drawn, crisp, as the drawing's own are. */
.diagram {
  /* A step darker than the site's own hairlines, so the frame reads as a
     frame, but still one pixel. */
  --diagram-edge: color-mix(in srgb, var(--ink-faint) 45%, var(--line));
  margin: 0;
  border: 1px solid var(--diagram-edge);
  border-radius: var(--rad-lg);
  background: var(--bg);
  overflow: hidden;
}

.diagram__body {
  padding: 1.25rem 1.25rem 0.9rem;
}

/* The panel is set apart from the drawing: ruled off in the frame's own
   colour, on a ground a clear step darker than the drawing's. */
.diagram__panel {
  display: block;
  padding: 0.9rem 1.25rem 1.05rem;
  border-top: 1px solid var(--diagram-edge);
  background: color-mix(in srgb, var(--pastel-slate) 90%, var(--bg));
}

.diagram__title {
  display: block;
  margin-bottom: 0.3rem;
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--ink);
}

/* Across the panel's full width, and a shade darker than the site's soft
   grey: it sits on a tinted ground. */
.diagram__desc {
  display: block;
  font-size: 0.9rem;
  line-height: 1.55;
  color: color-mix(in srgb, var(--ink-soft) 65%, var(--ink));
}

/* The Integration drawing runs its panels out to the frame, and sits above
   the prose as the harness drawings do. */
.combined-figure .diagram__body {
  padding: 0;
}

.diagram.combined-figure {
  margin-bottom: 2.5rem;
}

/* The still diagrams' pieces (src/components/still.rs). Each carries --hue
   and --tint from the palette. Rounded 10 for a box, 14 for a panel round
   boxes, and fully for a pill, as in every diagram. */
.dg-box {
  fill: var(--tint);
  stroke: var(--hue);
  stroke-width: 1.5;
  transition: stroke-width 140ms ease;
}

/* Replaceable: the outline dashed, the body still there. */
.dg-box--dashed {
  stroke-dasharray: 5 4;
}

/* Designed and not built: hollow and dashed, as on the home page. */
.dg-box--planned {
  fill: var(--bg);
  stroke-dasharray: 5 4;
}

/* What everything else is round: solid and heavier. */
.dg-box--core {
  stroke-width: 2.2;
}

.dg-in:hover > .dg-box {
  stroke-width: 2.4;
}

.dg-frame {
  fill: color-mix(in srgb, var(--tint) 40%, var(--bg));
  stroke: color-mix(in srgb, var(--hue) 45%, var(--bg));
  stroke-width: 1.2;
}

.dg-line {
  fill: none;
  stroke: var(--pastel-slate-ink);
  stroke-opacity: 0.7;
  stroke-width: 1.6;
  stroke-linecap: round;
}

.dg-line--planned {
  stroke-dasharray: 5 4;
}

.dg-line--strong {
  stroke-width: 2.2;
}

/* A change on its way through the person who admits it, in their blue. */
.dg-line--gate {
  stroke: var(--pastel-blue-ink);
  stroke-opacity: 1;
  stroke-width: 2.2;
}

.dg-arrow {
  fill: var(--pastel-slate-ink);
}

.dg-arrow--gate {
  fill: var(--pastel-blue-ink);
}

.dg-dot {
  fill: var(--hue);
  pointer-events: none;
}

.dg-heading {
  font-family: var(--font);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  fill: var(--ink-soft);
}

.dg-heading--frame {
  fill: var(--hue);
}

.dg-pill-label {
  font-family: var(--font);
  font-size: 12px;
  font-weight: 600;
  fill: var(--hue);
}

/* The still diagrams' motion. Hidden only under .js-reveal, which reveal.rs
   sets once it can drive the reveal, so nothing is ever left hidden: each
   piece rises into place in its turn (--i) once the diagram is on screen,
   with a little spring; lines draw themselves in; and then the dots start
   to run. */
.js-reveal .diagram--animate .dg-in {
  opacity: 0;
  transform: translateY(10px) scale(0.97);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 0.5s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.75s cubic-bezier(0.34, 1.45, 0.64, 1);
  transition-delay: calc(120ms + var(--i, 0) * 110ms);
}

.js-reveal .diagram--animate.is-visible .dg-in {
  opacity: 1;
  transform: none;
}

.js-reveal .diagram--animate .dg-draw {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1.6s cubic-bezier(0.65, 0, 0.35, 1) 0.25s;
}

.js-reveal .diagram--animate.is-visible .dg-draw {
  stroke-dashoffset: 0;
}

.js-reveal .diagram--animate .dg-flow {
  opacity: 0;
  transition: opacity 0.8s ease 1.8s;
}

.js-reveal .diagram--animate.is-visible .dg-flow {
  opacity: 1;
}

/* The Security layers arrive from the outside in, and then, over and over,
   each in turn rings once, sharply, from the outermost in: every request is
   checked by every layer on its way to the record. */
.js-reveal .diagram--animate.layers .layers__layer {
  opacity: 0;
  transform: scale(0.985);
  transition: opacity 0.5s cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 0.6s cubic-bezier(0.34, 1.45, 0.64, 1);
  transition-delay: calc(150ms + var(--i, 0) * 140ms);
}

.js-reveal .diagram--animate.layers.is-visible .layers__layer {
  opacity: 1;
  transform: none;
  animation: layer-check 4.8s ease-in-out infinite;
  animation-delay: calc(1.8s + var(--i, 0) * 0.32s);
}

@keyframes layer-check {
  0%,
  12%,
  100% {
    box-shadow: 0 0 0 0 transparent;
  }
  5% {
    box-shadow: 0 0 0 2px var(--comp-security);
  }
}

@media (prefers-reduced-motion: reduce) {
  .js-reveal .diagram--animate .dg-in,
  .js-reveal .diagram--animate .dg-draw,
  .js-reveal .diagram--animate.layers .layers__layer {
    opacity: 1;
    transform: none;
    stroke-dashoffset: 0;
    transition: none;
    animation: none;
  }

  .dg-flow {
    display: none;
  }

  .dg-box {
    transition: none;
  }
}

/* combined: the Integration drawing, see src/components/combined.rs */
/* Pale bodies with an outline in the ink, like the cards. */
.combined .piece__disc:not(.piece--design),
.combined .piece__pill:not(.piece--design),
.combined .piece__cyl {
  fill: var(--tint);
  stroke: var(--hue);
  stroke-width: 1.5;
}

/* Kept faint, so each piece's edge is its outline and not a blur. */
.combined .piece__glow {
  fill-opacity: 0.05;
}

.combined .piece__lid {
  fill: var(--hue);
  fill-opacity: 0.12;
  stroke: var(--hue);
  stroke-opacity: 0.7;
  stroke-width: 1.2;
}

/* The heartbeat fills the body with its own colour and leaves the outline
   and the glow around it alone: the inside pulses, gently, not the edge. */
.combined .piece__beat-glow {
  display: none;
}

.combined .piece__beat {
  fill: var(--hue);
  fill-opacity: 0.28;
}

.combined .orbit__halo {
  fill-opacity: 0.3;
}

.combined .orbit__core {
  fill: var(--accent-wash);
  stroke: var(--accent);
  stroke-width: 2;
}

.combined .orbit__core-label {
  fill: var(--accent);
}

/* The API bar's name, inside the bar in its ink, like a card's label on
   its chip. */
.combined__bar-name {
  font-family: var(--font);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.01em;
  fill: var(--hue);
  pointer-events: none;
}

/* What the bar does, under its name: smaller, lighter, in the same ink. */
.combined__bar-note {
  font-family: var(--font);
  font-size: 11.5px;
  font-weight: 500;
  fill: var(--hue);
  fill-opacity: 0.85;
  pointer-events: none;
}

/* The two panels, filled with their own --bg (see zone_bg in combined.rs),
   run out to the diagram's frame, with the line between them, and each
   one's name up its left edge. */
.combined__zone {
  fill: var(--bg);
}

.combined__seam {
  stroke: var(--pastel-slate-ink);
  stroke-opacity: 0.3;
  stroke-width: 1;
}

.combined__zone-name {
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  fill: var(--ink-faint);
}

/* "Planned" sits across the Connectors' pair of lines, and a monospaced
   word has wide gaps between its letters: a thicker cut closes them. */
.combined .piece__status {
  stroke-width: 7px;
}

/* A few words beside a place in the drawing, saying what happens there:
   quieter than the names, and cut out of the panel behind them as the
   names are. */
.combined__aside-text {
  font-family: var(--font);
  font-size: 12px;
  font-weight: 500;
  fill: var(--ink-faint);
  paint-order: stroke;
  stroke: var(--bg);
  stroke-width: 4px;
  stroke-linejoin: round;
  pointer-events: none;
}

/* A dot sinking into the data layer, drawn over it, the dots that have
   settled there, filling it, and those running on each component's line. */
.combined__drop,
.combined__settled,
.combined__comp-flow {
  fill: var(--hue);
  pointer-events: none;
}

/* A dot on its way up, back from the API: a shade brighter than one on its
   way down, so the two directions can be told apart at a glance. */
.combined__up {
  filter: brightness(1.25) saturate(1.15);
}

/* A word or two under a component's name: lighter than the name. */
.combined__note {
  font-size: 12px;
  font-weight: 500;
  fill: var(--ink-faint);
}

/* Lighter lines, so the blue of the ways does not outweigh the colours,
   but not so light that they go soft. */
.combined .piece__line {
  stroke-opacity: 0.6;
  stroke-width: 2;
}

.combined .lanes__own {
  stroke-opacity: 0.6;
}

.combined .orbit__line {
  stroke-opacity: 0.6;
}

/* One drawing at every width. Below its min-width it keeps its proportions
   and scrolls sideways, as the Connecting systems drawing does: scaled to a
   phone, its labels would be about five pixels. */
.combined__scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.combined__svg {
  display: block;
  width: 100%;
  min-width: 620px;
  height: auto;
}


/* The reader's link between their system and their database, thinner and in
   their own blue, and the headings above each way in. */
.lanes__own {
  stroke: var(--accent-strong);
  stroke-opacity: 0.6;
  stroke-width: 1.6;
  stroke-linecap: round;
}

.lanes__heading {
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* ---------- the dot field behind each page's header ---------- */

/* `main` becomes the stacking context so the field can sit at z-index -1:
   behind the page's own content, but in front of the body background. */
.site > main {
  position: relative;
  z-index: 0;
}

.topfield {
  position: absolute;
  inset: 0 0 auto 0;
  height: clamp(300px, 44vh, 520px);
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
  /* The wash the hero used to carry, now under the dots rather than over them. */
  background: radial-gradient(
    ellipse 80% 70% at 15% -10%,
    var(--accent-wash),
    transparent 70%
  );
}

/* The canvas cannot resolve var(), so dot_field.rs reads these two back through
   getComputedStyle: `color` for the dots, `border-top-color` for the crest.
   Hence a border declared with no width — it exists only to carry a colour. */
.topfield__canvas {
  display: block;
  width: 100%;
  height: 100%;
  color: var(--ink);
  border: 0 solid var(--accent);
}

/* The chosen mark, shown large at the top of the review page (TEMPORARY,
   with src/pages/logos.rs). */

.lg-chosen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2rem;
  margin-bottom: 1rem;
}

.lg-chosen__stage {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.25rem;
  border-radius: var(--rad-lg);
  border: 1px solid var(--line);
}

.lg-chosen__notes {
  flex: 1 1 320px;
  min-width: 0;
}

.lg-chosen__notes h2 {
  margin-bottom: 0.5rem;
}

.lg-chosen__notes .lg-ramp {
  margin-top: 1.4rem;
}

/* ---------- desktop-only sections ---------- */

/* The architecture diagram and the board are both fixed-width drawings meant to
   be taken in at a glance, and neither reflows: on a phone they become a
   sideways scroll through something too small to read. They are dropped rather
   than shrunk. `display: none` also takes them out of the accessibility tree,
   so nothing is announced that cannot be seen or used. Everything they say is
   said in words elsewhere on the page. */
@media (max-width: 900px) {
  .wide-only {
    display: none;
  }
}

/* ---------- the draggable board ---------- */

/* Shapes taken from the staff GUI's proto editor
   (gui/fdn-gui/css/components/proto_editor.scss): a 180px body on --off-white
   with a --special-blue ring, a 28px header chip inset by 3px, 22px slot rows,
   9px slot dots sitting inside the card, and the type and bracketed name
   floating above. Read top to bottom, case first. */

:root {
  /* The editor's own surfaces, which are not the site's. Its card body is a
     shade off white so the slot dots read against it. */
  --pc-body: #f2f2f2;
  --pc-ring: #cccccc;
  --pc-dot: #ffffff;

  /* Tighter than the site's own --rad: these cards are small, and at 8px the
     corner starts eating into the header chip behind it. */
  --pc-rad: 4px;
  --pc-panel-w: 176px;

  /* Entity and relationship colours, from the staff themes. Claimant links are
     blue and defendant links green, as the editor draws them. */
  --pc-case-fg: #17761a;
  --pc-claim-fg: #3355c4;
  --pc-doc-fg: #7338bd;
  --pc-claimant: #4a7fe8;
  --pc-defendant: #3fae7c;
  --pc-live: #4a7fe8;

  /* The editor's --hearing-icon-col and --judge-text-col. It draws the case to
     hearing connector in the first and the hearing to judge one in the second,
     so a link is coloured after the card it arrives at. */
  --pc-hearing-fg: #d97822;
  --pc-judge-fg: #1f6e63;
}

@media (prefers-color-scheme: dark) {
  :root {
    --pc-body: #2e2e2e;
    --pc-ring: #393939;
    --pc-dot: #0f1115;

    --pc-case-fg: #87f197;
    --pc-claim-fg: #7b97ff;
    --pc-doc-fg: #b985f0;
    --pc-claimant: #5b87ff;
    --pc-defendant: #5cc99a;
    --pc-live: #5b87ff;

    /* The editor keeps --hearing-icon-col at #d97822 in its dark themes, which
       is too dim to read on this ground; its own dark themes define
       --hearing-text-col for exactly that reason, and that is what is used
       here. The judge colour is the editor's dark --judge-text-col. */
    --pc-hearing-fg: #ffa552;
    --pc-judge-fg: #3fb8a8;
  }
}

/* No ground: the nodes float on the page. A positioning context, and the box
   every node is clamped inside, so nothing can be dragged out over the rest of
   the page. The frame marks that box. */
.pc-board {
  position: relative;
  height: 456px;
  touch-action: none;
}

/* The frame is drawn on a pseudo-element, not as a border on the board. A real
   border would sit inside the rectangle the component measures and clamps
   against, and a card pushed to the edge would end up on top of it.

   All four lines run on past the corners by --reach and fade out over the last
   --fade of it, so this layer stands --reach proud of the board on every side
   and the lines are drawn as backgrounds, --reach in. Each corner carries a
   filled square centred on the point where the lines cross. A 1px line only
   has a true centre in an odd-sized square, hence 9px and not 8. */
.pc-board::before {
  --fade: 5px;
  --corner: 9px;
  --half: calc((var(--corner) - 1px) / 2);
  --edge: calc(var(--reach) - var(--half));
  --across: linear-gradient(to right, transparent, var(--line) var(--fade),
      var(--line) calc(100% - var(--fade)), transparent);
  --down: linear-gradient(to bottom, transparent, var(--line) var(--fade),
      var(--line) calc(100% - var(--fade)), transparent);
  --dot: linear-gradient(var(--line) 0 0);

  content: "";
  position: absolute;
  inset: calc(var(--reach) * -1);
  pointer-events: none;
  background:
    var(--dot) var(--edge) var(--edge) / var(--corner) var(--corner) no-repeat,
    var(--dot) calc(100% - var(--edge)) var(--edge) / var(--corner) var(--corner) no-repeat,
    var(--dot) var(--edge) calc(100% - var(--edge)) / var(--corner) var(--corner) no-repeat,
    var(--dot) calc(100% - var(--edge)) calc(100% - var(--edge)) / var(--corner) var(--corner) no-repeat,
    var(--across) 0 var(--reach) / 100% 1px no-repeat,
    var(--across) 0 calc(100% - var(--reach)) / 100% 1px no-repeat,
    var(--down) var(--reach) 0 / 1px 100% no-repeat,
    var(--down) calc(100% - var(--reach)) 0 / 1px 100% no-repeat;
}

/* The sides run up past the board by the frame's --reach, which is more than
   the gap under the heading, and would cross the last line of the lede.
   Written `.section.section--bleed` rather than `.section--bleed` so it
   outranks `.hero + .section .section__head` on specificity: this band used to
   sit directly under the hero and may again, and the frame has to be cleared
   wherever it lands. */
.section.section--bleed .section__head {
  margin-bottom: calc(var(--reach) + 1rem);
}

/* Between about 900px and 1170px wide the page gutter is narrower than the
   frame's --reach, and the top and bottom would run off the window into a
   sideways scroll. `clip`, not `hidden`: it trims sideways without making the
   section a scroll container, so hover panels still spill out top and bottom. */
.section--bleed {
  /* How far the board's frame runs past its corners. Set here rather than on
     the frame so the heading above can make room for it too. */
  --reach: 50px;
  overflow-x: clip;
}

.pc-links {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 1;
}

/* The editor draws these saturated, because on its canvas they are the point.
   Here they run behind a block of prose, so they are held back: same colours,
   carried at part strength so the cards stay the thing you look at. */
.pc-link {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-opacity: 0.45;
}

/* A link the editor shows as not yet settled. The dash is scaled to the stroke
   so it stays legible at this size. */
.pc-link--dashed {
  stroke-dasharray: 6 5;
}

.pc-link--process {
  stroke: var(--pc-claim-fg);
}
.pc-link--claimant {
  stroke: var(--pc-claimant);
}
.pc-link--defendant {
  stroke: var(--pc-defendant);
}
.pc-link--doc {
  stroke: var(--pc-doc-fg);
}
.pc-link--hearing {
  stroke: var(--pc-hearing-fg);
}
.pc-link--judge {
  stroke: var(--pc-judge-fg);
}


.pc-node {
  position: absolute;
  top: 0;
  left: 0;
  box-sizing: border-box;
  border-radius: var(--pc-rad);
  background: var(--pc-body);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08), 0 6px 20px rgba(0, 0, 0, 0.06);
  cursor: grab;
  /* Position is driven straight from the pointer; a transition would lag it. */
  transition: box-shadow 0.15s ease;
  user-select: none;
}

.pc-node.is-held {
  cursor: grabbing;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12), 0 14px 34px rgba(0, 0, 0, 0.14);
}

/* The ring, as a pseudo-element so it never affects layout. */
.pc-node::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: 0 0 0 1px var(--pc-ring);
}

.pc-node:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}

/* Parties are circles with a glyph, not cards. */
.pc-node--party {
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The type above, the bracketed name below. */
.pc-node__label {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.25;
  white-space: nowrap;
  pointer-events: none;
  /* Labels sit over the links, so they carry the page colour behind them. */
  text-shadow: 0 0 3px var(--bg), 0 0 3px var(--bg), 0 0 6px var(--bg);
}

.pc-node__type {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.pc-node__name {
  font-size: 11px;
  font-weight: 500;
  color: var(--ink);
}

.pc-node__bracket {
  color: var(--ink-faint);
  padding: 0 0.15em;
}

.pc-node__header {
  position: absolute;
  top: 2px;
  left: 2px;
  right: 2px;
  height: 24px;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 7px;
  border-radius: 3px;
  background: var(--pc-head-bg);
  color: var(--pc-head-fg);
}

/* The editor's own icons, used the way it uses them: as a mask tinted by the
   header colour, rather than redrawn by hand. */
.pc-node__icon,
.pc-node__glyph {
  flex: none;
  background: currentColor;
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
}

.pc-node__icon {
  width: 13px;
  height: 13px;
}

/* The file each card takes its glyph from, as named by Stafford — the mapping
   is not what the filenames suggest. */
.pc--case .pc-node__icon {
  mask-image: url("/icons/claim.svg");
  -webkit-mask-image: url("/icons/claim.svg");
}

.pc--claim .pc-node__icon {
  mask-image: url("/icons/proceeding.svg");
  -webkit-mask-image: url("/icons/proceeding.svg");
}

.pc--doc .pc-node__icon {
  mask-image: url("/icons/file.svg");
  -webkit-mask-image: url("/icons/file.svg");
}

.pc--hearing .pc-node__icon {
  mask-image: url("/icons/hearing.svg?v=2");
  -webkit-mask-image: url("/icons/hearing.svg?v=2");
}

/* The ?v=2 on the two person glyphs is a one-off cache bust, not part of the
   scheme. An earlier serve.py sent `immutable, max-age=1 year` on every asset
   suffix, including unhashed ones like these, so a browser that loaded the old
   placeholder icons will never ask for them again. The header is fixed, but
   only a different URL reaches a cache already poisoned by it. Droppable once
   everyone looking at the site has loaded it once. */
.pc-node__glyph {
  width: 24px;
  height: 24px;
  color: var(--ink-soft);
  mask-image: url("/icons/person.svg?v=2");
  -webkit-mask-image: url("/icons/person.svg?v=2");
}

.pc-node__kind {
  font-size: 11px;
  font-weight: 600;
}

.pc-node__rows {
  position: absolute;
  top: 28px;
  left: 0;
  right: 0;
}

.pc-node__row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 18px;
  padding: 0 18px;
}

.pc-node__slot {
  font-size: 11px;
  line-height: normal;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The dots a connector docks to: inside the card, not overflowing it, with the
   ring pair the editor draws around them. */
.pc-node__dot {
  position: absolute;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: var(--pc-dot);
  box-shadow: 0 0 0 1px var(--pc-dot), 0 0 0 2px var(--pc-ring);
}

.pc-node__dot--l {
  left: 4.5px;
}
.pc-node__dot--r {
  right: 4.5px;
}

/* Stacking is done here rather than in the inline style the component writes,
   because an inline z-index would outrank the hover rule below. */
.pc-node {
  z-index: 3;
}
.pc-node.is-held {
  z-index: 4;
}
.pc-node:hover,
.pc-node:focus-within {
  z-index: 6;
}

/* A dot with a link docked to it is filled. One colour for every slot on every
   card type, not the card's own accent. */
.pc-node__dot.is-live {
  background: var(--pc-live);
}

.pc--case {
  --pc-head-bg: #d0f7d6;
  --pc-head-fg: var(--pc-case-fg);
}
.pc--claim {
  --pc-head-bg: #e2e6f6;
  --pc-head-fg: var(--pc-claim-fg);
}
.pc--doc {
  --pc-head-bg: #e0d7ec;
  --pc-head-fg: var(--pc-doc-fg);
}
.pc--hearing {
  /* The editor's --hearing-col, without its 73% alpha: every other chip here
     is flat, and the board has no canvas behind it to show through. */
  --pc-head-bg: #eecfb2;
  --pc-head-fg: var(--pc-hearing-fg);
}

/* The judge is a circle like a party, but the editor recolours its ring and
   glyph — that, and the glyph itself, are the whole difference between them. */
.pc--judge .pc-node__glyph {
  /* Larger than the person glyph: wig, face and gown is three shapes to the
     person's two, in the same 24 unit square. */
  width: 32px;
  height: 32px;
  color: var(--pc-judge-fg);
  mask-image: url("/icons/judge.svg?v=2");
  -webkit-mask-image: url("/icons/judge.svg?v=2");
}

.pc--judge::after {
  box-shadow: 0 0 0 1px var(--pc-judge-fg);
}

@media (prefers-color-scheme: dark) {
  /* The dark theme leaves the chip clear and colours only the label. */
  .pc--case,
  .pc--claim,
  .pc--doc,
  .pc--hearing {
    --pc-head-bg: transparent;
  }
}

/* The card's own details, opened on whichever side of it has room. Present in
   the document at all times — a screen reader reads them with the card — and
   only faded in and out, so nothing about the page's layout moves. */
.pc-panel {
  position: absolute;
  top: -2px;
  left: calc(100% + 10px);
  width: var(--pc-panel-w);
  margin: 0;
  padding: 9px 11px;
  border-radius: var(--pc-rad);
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--line), 0 10px 28px rgba(13, 27, 42, 0.14);
  /* Never takes the pointer: the card underneath owns the drag, and a panel
     that could be hovered would flicker as it opened under the cursor. */
  pointer-events: none;
  opacity: 0;
  transform: translateX(-6px) scale(0.97);
  transform-origin: left center;
  transition: opacity 0.16s ease, transform 0.16s ease;
}

/* Near the right edge there is no room to the right, so it opens leftwards. */
.pc-node--flip .pc-panel {
  left: auto;
  right: calc(100% + 10px);
  transform: translateX(6px) scale(0.97);
  transform-origin: right center;
}

/* Opens only once you have stayed on a card. Without the wait, crossing the
   board on the way somewhere else sets off a run of panels. The delay is on the
   way in only — the base rule above has none, so leaving closes it at once. */
.pc-node:hover .pc-panel,
.pc-node:focus-visible .pc-panel {
  opacity: 1;
  transform: none;
  transition-delay: 600ms;
}

/* Not while the card is being dragged: the panel would ride along under the
   cursor and cover whatever you were dragging towards. Same specificity as the
   hover rule above, so it has to come after it — including to cancel the wait
   that rule sets, which would otherwise hold the panel open for 600ms into the
   drag. */
.pc-node.is-held .pc-panel {
  opacity: 0;
  transform: translateX(-6px) scale(0.97);
  transition-delay: 0s;
}

.pc-panel dt {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.pc-panel dd {
  margin: 0 0 7px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--ink);
}

.pc-panel dd:last-child {
  margin-bottom: 0;
}

@media (prefers-color-scheme: dark) {
  .pc-panel {
    box-shadow: 0 0 0 1px var(--line), 0 10px 28px rgba(0, 0, 0, 0.5);
  }
}
