/* =========================================================================
   manaruler public site stylesheet
   -------------------------------------------------------------------------
   Served from /static/css/site.css and consumed by _base_public.html.

   Design system notes (kept here so the next person does not have to guess):

   * Token naming deliberately mirrors the admin layout's vocabulary
     (--bg, --surface, --border, --text, --accent, --radius, --space-N) so the
     two surfaces read as one product, even though they look different.
   * ONE accent, used everywhere: an evergreen adapted from theme-factory's
     "Botanical Garden" fern green (#4a7c59), darkened to #2c6a46 so it clears
     WCAG AA as body-size text and as a button fill. The preset's marigold and
     terracotta are deliberately dropped: a single accent keeps the page calm,
     which is the point for a first-time visitor.
   * ONE radius scale. Nothing on this page is a pill and nothing is square.
   * Typography carries the point of view: the sans stack is for anything a
     human says, and the mono stack is reserved EXCLUSIVELY for things the
     reader can go and verify (rule numbers, card counts, deck limits). If a
     number is set in mono on this page, it is a checkable fact. Do not spend
     the mono face on decoration.
   * No web fonts on purpose. No build step exists here, and a third-party
     font CDN would add a network dependency plus a layout-shift risk to a
     page that currently has neither.
   * No JavaScript on purpose. Everything below is CSS-only.
   ========================================================================= */

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

:root {
  color-scheme: light dark;

  /* Surfaces and ink (light) */
  --bg: #f4f7f3;
  --surface: #ffffff;
  --surface-sunken: #eaf0ea;
  --border: #d3ddd6;
  --border-strong: #b9c8bf;
  /* Separate from --border-strong on purpose. This is the outline that IS the
     affordance on an outline-only control, so WCAG 1.4.11 wants 3:1 against
     the surface behind it. --border-strong is only 1.7:1 and is for decorative
     dividers, which the same rule does not cover. */
  --control-border: #7b8c83;
  --text: #16211a;
  --text-muted: #4d5c54;

  /* The single accent */
  --accent: #2c6a46;
  --accent-strong: #1f5234;
  --accent-tint: #e2eee7;
  --accent-contrast: #ffffff;

  /* Shape: one radius scale, tinted shadow (never pure black) */
  --radius: 10px;
  --radius-sm: 6px;
  --shadow: 0 1px 2px rgba(22, 33, 26, 0.04), 0 8px 24px -12px rgba(22, 33, 26, 0.16);

  /* Space: same names as the admin layout, plus two larger steps */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 1rem;
  --space-4: 1.5rem;
  --space-5: 2rem;
  --space-6: 3rem;
  --space-7: 4.5rem;
  --space-8: 6rem;

  /* Type */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  --fs-display: clamp(2.25rem, 1.35rem + 3.6vw, 3.75rem);
  --fs-h2: clamp(1.5rem, 1.15rem + 1.45vw, 2.125rem);
  --fs-h3: 1.125rem;
  --fs-lead: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  --fs-body: 1rem;
  --fs-small: 0.875rem;
  --fs-micro: 0.75rem;

  --measure: 62ch;
  --container: 1120px;

  font-size: 16px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #101613;
    --surface: #18201c;
    --surface-sunken: #1f2924;
    --border: #2b3833;
    --border-strong: #3c4c45;
    --control-border: #8a9c92;
    --text: #e6ece8;
    --text-muted: #9dada4;

    --accent: #6cc48d;
    --accent-strong: #8ad6a6;
    --accent-tint: #1b2c23;
    --accent-contrast: #08130c;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -12px rgba(0, 0, 0, 0.6);
  }
}

/* ---------- Reset and base ---------------------------------------------- */

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

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.6;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  /* Kill the 300ms double-tap-zoom delay, and pick the tap highlight rather
     than inheriting the platform's translucent blue-black. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: rgba(44, 106, 70, 0.18);
}

h1,
h2,
h3 {
  margin: 0;
  line-height: 1.15;
  text-wrap: balance;
}

/* In-page anchors (the hero's "See what it does" jump) must not land with the
   target heading flush against the top edge. */
[id] {
  scroll-margin-top: var(--space-5);
}

p {
  margin: 0;
  text-wrap: pretty;
}

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

a {
  color: var(--accent);
  text-underline-offset: 0.18em;
}

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

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

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

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  /* Respect notches and rounded display corners on full-bleed sections. */
  padding-inline: max(var(--space-4), env(safe-area-inset-left))
    max(var(--space-4), env(safe-area-inset-right));
}

/* Grid hygiene: grid and flex children default to `min-width: auto`, which
   resolves to min-content and lets a wide child push the page past the
   viewport. Every layout child on this site is allowed to shrink. */
.hero__copy,
.hero__grid > *,
.split > *,
.duo > *,
.bento__cell,
.facts > *,
.site-footer__inner > * {
  min-width: 0;
}

.section {
  padding-block: var(--space-7);
}

.section--tight {
  padding-block: var(--space-6);
}

.section--divided {
  border-top: 1px solid var(--border);
}

.section__head {
  display: grid;
  gap: var(--space-3);
  max-width: var(--measure);
  margin-bottom: var(--space-5);
}

.section__title {
  font-size: var(--fs-h2);
  font-weight: 680;
  letter-spacing: -0.022em;
}

.section__intro {
  color: var(--text-muted);
  font-size: var(--fs-lead);
}

.section__more {
  margin-top: var(--space-4);
  font-size: var(--fs-small);
  font-weight: 560;
}

/* Clip-path rather than a -9999px offset: the offset version is an element
   sitting far outside the viewport, which shows up as horizontal overflow in
   layout audits and can affect scroll extents in some engines. */
.skip-link {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link:focus-visible {
  position: fixed;
  inset-block-start: var(--space-3);
  inset-inline-start: var(--space-3);
  width: auto;
  height: auto;
  clip-path: none;
  z-index: 100;
  background: var(--surface);
  color: var(--text);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-sm);
}

/* ---------- Wordmark ----------------------------------------------------- */

/* The mark is three rising ticks: a measure, for "ruler". Drawn in CSS rather
   than SVG because it is three rectangles and nothing more. */
.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--text);
  font-weight: 660;
  font-size: 1.0625rem;
  letter-spacing: -0.028em;
  text-decoration: none;
}

.wordmark:hover {
  color: var(--text);
}

.wordmark__mark {
  flex: none;
  width: 1.0625rem;
  height: 1.0625rem;
  background-image: linear-gradient(var(--accent), var(--accent)),
    linear-gradient(var(--accent), var(--accent)),
    linear-gradient(var(--accent), var(--accent));
  background-size: 3px 45%, 3px 72%, 3px 100%;
  background-position: 0 100%, 50% 100%, 100% 100%;
  background-repeat: no-repeat;
}

/* ---------- Header ------------------------------------------------------- */

.site-header {
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 64px;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.site-nav__link {
  color: var(--text-muted);
  font-size: var(--fs-small);
  font-weight: 560;
  text-decoration: none;
  padding: var(--space-1) 0;
  white-space: nowrap;
}

.site-nav__link:hover {
  color: var(--accent);
}

.site-nav__link[aria-current="page"] {
  color: var(--text);
  box-shadow: inset 0 -2px 0 var(--accent);
}

.site-nav__link--cta {
  color: var(--accent);
}

@media (max-width: 26rem) {
  .site-nav {
    gap: var(--space-2);
  }
  .site-nav__link,
  .linkbutton {
    font-size: 0.8125rem;
  }
}

/* With the Wave 11 pages added the signed-in nav holds ten items, which
   needs roughly 820px of content width on a single line and cannot stay on
   one line below that. The header wraps rather than overflowing or hiding
   items behind a menu (there is no JavaScript on this site): the wordmark
   keeps its own line and the nav takes the full width below it, wrapping its
   items onto as many lines as they need. Above 62rem nothing changes. */
@media (max-width: 62rem) {
  .site-header__inner {
    flex-wrap: wrap;
    row-gap: var(--space-2);
    padding-block: var(--space-3);
  }
  .site-nav {
    flex-wrap: wrap;
    flex-basis: 100%;
    row-gap: var(--space-1);
  }
}

/* ---------- Buttons ------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 0.7rem 1.25rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font: inherit;
  font-weight: 620;
  font-size: var(--fs-small);
  line-height: 1.2;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 140ms ease, border-color 140ms ease,
    color 140ms ease, transform 140ms ease;
}

.btn:active {
  transform: translateY(1px);
}

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}

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

.btn--quiet {
  background: transparent;
  border-color: var(--control-border);
  color: var(--text);
}

.btn--quiet:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.btn--large {
  padding: 0.875rem 1.6rem;
  font-size: var(--fs-body);
}

/* A form-submit styled to sit in the nav next to text links. */
.linkbutton {
  background: none;
  border: 0;
  padding: var(--space-1) 0;
  margin: 0;
  font: inherit;
  font-size: var(--fs-small);
  font-weight: 560;
  color: var(--text-muted);
  cursor: pointer;
}

.linkbutton:hover {
  color: var(--accent);
  text-decoration: underline;
}

.inline-form {
  display: inline;
  margin: 0;
}

/* ---------- Hero --------------------------------------------------------- */

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

.hero__grid {
  display: grid;
  gap: var(--space-6);
  align-items: center;
}

@media (min-width: 62rem) {
  .hero {
    padding-block: var(--space-8) var(--space-7);
  }
  .hero__grid {
    grid-template-columns: 7fr 5fr;
    gap: var(--space-7);
  }
}

.hero__copy {
  display: grid;
  gap: var(--space-4);
  justify-items: start;
}

.hero__title {
  font-size: var(--fs-display);
  font-weight: 700;
  letter-spacing: -0.035em;
  max-width: 14ch;
}

.hero__lead {
  font-size: var(--fs-lead);
  color: var(--text-muted);
  max-width: 46ch;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-2);
}

.hero__secondary {
  font-size: var(--fs-small);
  font-weight: 560;
  color: var(--accent);
}

/* ---------- Ruling (the signature element) -------------------------------
   A worked example of what the product actually returns: a question a new
   player really asks, a plain-language answer, and the rule it came from.
   Presented as a <figure> with a visible caption so nobody mistakes it for a
   live widget.
   ------------------------------------------------------------------------ */

.ruling {
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--space-5);
  display: grid;
  gap: var(--space-3);
  position: relative;
}

/* The accent edge is the only ornament on the page. */
.ruling::before {
  content: "";
  position: absolute;
  inset-block: var(--space-5);
  inset-inline-start: 0;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}

.ruling__question {
  font-size: 1.1875rem;
  font-weight: 640;
  letter-spacing: -0.018em;
  line-height: 1.35;
}

.ruling__answer {
  color: var(--text-muted);
  font-size: var(--fs-body);
}

.ruling__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  margin-top: var(--space-1);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}

.citation {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--accent);
  background: var(--accent-tint);
  border-radius: var(--radius-sm);
  padding: 0.3rem 0.55rem;
}

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

.ruling__caption {
  color: var(--text-muted);
  font-size: var(--fs-micro);
}

/* ---------- Capability grid (bento) -------------------------------------- */

.bento {
  display: grid;
  gap: var(--space-3);
}

@media (min-width: 48rem) {
  .bento {
    grid-template-columns: repeat(6, 1fr);
  }
  .bento__cell--lead {
    grid-column: span 4;
  }
  .bento__cell--aside {
    grid-column: span 2;
  }
  .bento__cell--half {
    grid-column: span 3;
  }
}

.bento__cell {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.bento__cell--accent {
  background: var(--accent-tint);
  border-color: transparent;
}

.bento__title {
  font-size: var(--fs-h3);
  font-weight: 660;
  letter-spacing: -0.016em;
}

.bento__body {
  color: var(--text-muted);
  font-size: var(--fs-small);
  max-width: 44ch;
}

.bento__cell--accent .bento__body {
  color: var(--text);
}

/* The constructed-deck limits, in mono, because they are checkable facts. */
.limits {
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
}

.limits__item {
  display: grid;
  gap: 0.15rem;
}

.limits__value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
}

.limits__label {
  font-size: var(--fs-micro);
  color: var(--text-muted);
}

/* ---------- Statement ---------------------------------------------------- */

.statement {
  background: var(--surface-sunken);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

/* Note: this sits INSIDE .container, it is not a .container itself. Putting
   both classes on one element makes .container's `margin-inline: auto` centre
   the narrower box, which visibly breaks the page's left alignment. */
.statement__inner {
  display: grid;
  gap: var(--space-4);
  max-width: 46rem;
}

.statement__title {
  font-size: var(--fs-h2);
  font-weight: 680;
  letter-spacing: -0.024em;
}

.statement__body {
  font-size: var(--fs-lead);
  color: var(--text-muted);
  max-width: var(--measure);
}

.statement__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* ---------- Signed-in panel ---------------------------------------------- */

.welcome {
  padding-block: var(--space-7);
}

.welcome__panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--space-6);
  display: grid;
  gap: var(--space-4);
  justify-items: start;
  max-width: 44rem;
}

.welcome__title {
  font-size: var(--fs-h2);
  font-weight: 690;
  letter-spacing: -0.026em;
}

.welcome__body {
  color: var(--text-muted);
  max-width: var(--measure);
}

.welcome__identity {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.welcome__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-1);
}

/* ---------- Dashboard quick links ----------------------------------------
   The signed-in dashboard's four destinations as whole-card links. The card
   is the link itself, so the entire tile is one tap target. Same surface,
   border and radius vocabulary as .bento__cell, so nothing new is introduced;
   the only affordance change is the accent border on hover, which matches
   .checkfield's focus-within and .btn--quiet's hover.
   ------------------------------------------------------------------------ */

.quicklinks {
  display: grid;
  gap: var(--space-3);
  margin: 0;
}

@media (min-width: 48rem) {
  .quicklinks {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.quicklink {
  min-width: 0;
  display: grid;
  gap: var(--space-1);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  text-decoration: none;
  transition: border-color 140ms ease;
}

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

.quicklink__title {
  font-size: var(--fs-h3);
  font-weight: 660;
  letter-spacing: -0.016em;
  color: var(--text);
}

.quicklink:hover .quicklink__title {
  color: var(--accent);
}

.quicklink__body {
  color: var(--text-muted);
  font-size: var(--fs-small);
  max-width: 44ch;
}

/* ---------- Card artwork -------------------------------------------------
   Real Magic card art hotlinked from Scryfall (permitted). Always art crops,
   never full card frames: a card frame reads as a product screenshot, the
   artwork alone reads as atmosphere.

   Every frame carries a fixed aspect-ratio and a sunken background, so the
   image never causes layout shift and a failed load leaves a tinted panel
   rather than a hole in the page.
   ------------------------------------------------------------------------ */

.art {
  display: block;
  margin: 0;
  background: var(--surface-sunken);
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 4 / 3;
}

.art img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* If the image fails to load, the alt text is what the reader gets. Style it
     so it reads as a small caption inside the tinted frame rather than as
     oversized broken-image text. */
  font-size: var(--fs-micro);
  line-height: 1.45;
  color: var(--text-muted);
}

.art--wide {
  aspect-ratio: 20 / 7;
}

.art--square {
  aspect-ratio: 1 / 1;
}

/* Horizontal band of art crops. Scrolls sideways on narrow screens rather
   than shrinking each crop into an unreadable sliver.

   `min-width: 0` is load-bearing, not decoration: this is a grid item whose
   default `min-width: auto` resolves to its min-content width (five 11rem
   columns), which pushes the whole page wider than a phone viewport and breaks
   every other section's layout with it. */
.artband {
  min-width: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(11rem, 1fr);
  gap: var(--space-3);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: var(--space-2);
  overscroll-behavior-x: contain;
}

.artband > * {
  scroll-snap-align: start;
}

@media (min-width: 62rem) {
  .artband {
    overflow-x: visible;
  }
}

.art-figure,
.artband-figure {
  margin: 0;
  display: grid;
  gap: var(--space-2);
}

/* Artist credits. Not decoration: these name real illustrators whose work is
   on the page, and the card names are what the images actually depict. */
.credits {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  color: var(--text-muted);
  font-size: var(--fs-micro);
  line-height: 1.5;
}

/* ---------- Media + prose split ------------------------------------------ */

.split {
  display: grid;
  gap: var(--space-5);
  align-items: center;
}

/* Placement is explicit rather than done with `order`, so source order can stay
   body-first (which is also the order it stacks in on mobile and the order a
   screen reader hears) while either side can carry the media visually. Text
   always gets the wider column. */
@media (min-width: 52rem) {
  .split {
    grid-template-columns: 7fr 5fr;
    gap: var(--space-6);
  }
  .split__body {
    grid-column: 1;
  }
  .split__media {
    grid-column: 2;
  }
  .split--reverse {
    grid-template-columns: 5fr 7fr;
  }
  .split--reverse .split__body {
    grid-column: 2;
  }
  .split--reverse .split__media {
    grid-column: 1;
  }
}

.split__body {
  display: grid;
  gap: var(--space-3);
  max-width: var(--measure);
}

/* ---------- Page hero (features / about) --------------------------------- */

.page-hero {
  padding-block: var(--space-6) var(--space-5);
}

.page-hero__copy {
  display: grid;
  gap: var(--space-3);
  max-width: 42rem;
  margin-bottom: var(--space-5);
}

.page-hero__title {
  font-size: var(--fs-display);
  font-weight: 700;
  letter-spacing: -0.035em;
}

.page-hero__lead {
  font-size: var(--fs-lead);
  color: var(--text-muted);
}

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

.prose {
  display: grid;
  gap: var(--space-3);
  max-width: var(--measure);
}

.prose p {
  color: var(--text-muted);
}

.prose h3 {
  font-size: var(--fs-h3);
  font-weight: 660;
  letter-spacing: -0.016em;
  color: var(--text);
  margin-top: var(--space-2);
}

/* Two-column prose. Used where a section has exactly two peer explanations
   and neither should dominate. */
.duo {
  display: grid;
  gap: var(--space-5);
}

@media (min-width: 52rem) {
  .duo {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-6);
  }
}

/* ---------- Plain fact list ---------------------------------------------- */

/* Deliberately not a card grid and not a bulleted <ul> with a hairline under
   every row. Each entry is a term plus a short definition, grouped, with one
   divider above the group only. */
.facts {
  display: grid;
  gap: var(--space-4);
  margin: 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

@media (min-width: 52rem) {
  .facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-5) var(--space-6);
  }
}

.facts__term {
  font-weight: 640;
  letter-spacing: -0.012em;
  margin-bottom: var(--space-1);
}

.facts__def {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--fs-small);
  max-width: 46ch;
}

/* A citation sitting inside running text rather than in a ruling footer. */
.facts__def .citation {
  vertical-align: baseline;
  margin-inline-start: 0.15rem;
}

/* ---------- Honest "not built yet" note ---------------------------------- */

.note {
  border-inline-start: 3px solid var(--border-strong);
  padding: var(--space-1) 0 var(--space-1) var(--space-4);
  color: var(--text-muted);
  font-size: var(--fs-small);
  max-width: var(--measure);
  display: grid;
  gap: var(--space-2);
}

.note strong {
  color: var(--text);
  font-weight: 640;
}

/* The one positive variant. There is still only ONE accent on this site, so a
   good outcome is the accent tint and a problem is the plain grey .note above.
   No red, no green-vs-red pair: adding semantic status colours here would mean
   inventing two new hues for one page, and the neutral note already reads as
   "something to deal with" without shouting. */
.note--accent {
  border-inline-start-color: var(--accent);
  background: var(--accent-tint);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: var(--space-3) var(--space-4);
  color: var(--text);
  font-size: var(--fs-small);
}

/* ---------- Interstitial (post-registration "check your email") -----------
   A dead-end page: one panel, one message, one recovery action. It is the only
   place on the public site where the content is centred rather than
   left-aligned, and that is the point -- there is no page to read here, so
   nothing should suggest scrolling on. The text inside the panel still rags
   left like everywhere else.
   ------------------------------------------------------------------------ */

.interstitial {
  padding-block: var(--space-7);
}

.interstitial__panel {
  position: relative;
  max-width: 34rem;
  margin-inline: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--space-4);
  display: grid;
  gap: var(--space-4);
}

/* Padding grows in two steps rather than one. The smallest step is not
   cosmetic: on a 320px screen the panel's own padding is what decides whether
   the button below still fits on a single line. */
@media (min-width: 24rem) {
  .interstitial__panel {
    padding: var(--space-5);
  }
}

@media (min-width: 34rem) {
  .interstitial__panel {
    padding: var(--space-6);
  }
}

/* The same accent edge the homepage's ruling card carries: this site has one
   ornament and this is it. */
.interstitial__panel::before {
  content: "";
  position: absolute;
  inset-block: var(--space-5);
  inset-inline-start: 0;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}

.interstitial__title {
  font-size: var(--fs-h2);
  font-weight: 690;
  letter-spacing: -0.026em;
}

.interstitial__lead {
  font-size: var(--fs-lead);
  color: var(--text-muted);
}

.interstitial__body {
  color: var(--text-muted);
  font-size: var(--fs-small);
}

/* The address is set in mono for the same reason rule numbers are: it is a
   fact the reader is being asked to check, character by character, and a
   proportional face makes rn/m and l/I harder to tell apart. `anywhere` rather
   than `break-word` so a long address wraps inside the box on a phone instead
   of widening the panel. */
.interstitial__address {
  font-family: var(--font-mono);
  font-size: var(--fs-body);
  color: var(--text);
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  overflow-wrap: anywhere;
}

.interstitial__help {
  display: grid;
  gap: var(--space-3);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.interstitial__subtitle {
  font-size: var(--fs-h3);
  font-weight: 660;
  letter-spacing: -0.016em;
}

.interstitial__help .prose {
  gap: var(--space-2);
  font-size: var(--fs-small);
}

.resend {
  margin: 0;
  justify-self: start;
}

/* The one button on the page carries a long, unambiguous label. Overriding
   .btn's nowrap lets it wrap on a very narrow phone rather than push out of
   the panel; it stays on one line at every size that matters. */
.resend__button {
  white-space: normal;
  text-align: center;
}

.interstitial__aside {
  max-width: 34rem;
  margin: var(--space-4) auto 0;
  text-align: center;
  font-size: var(--fs-small);
  color: var(--text-muted);
}

/* ---------- Long-form document pages ------------------------------------- */

/* /privacy, /terms and /disclosures are the first public pages that contain
   running lists and tabular data, and the reset above deliberately strips list
   markers site-wide. Everything in this block is ELEMENT-scoped inside .prose
   or .section rather than a new class vocabulary, on purpose: no page shipped
   before these three contains a <ul>, <ol> or <table>, so nothing existing
   changes appearance, and a legal document does not earn its own components. */

.prose ul,
.prose ol {
  margin: 0;
  padding-inline-start: var(--space-4);
  color: var(--text-muted);
  list-style: disc;
}

.prose ol {
  list-style: decimal;
}

/* Rows in a legal document are often a full sentence each, so they need real
   separation from one another, not just line spacing. */
.prose li + li {
  margin-top: var(--space-2);
}

.prose li > ul,
.prose li > ol {
  margin-top: var(--space-2);
}

/* A wide data table inside a long-form document. Hairline-and-space rather
   than a boxed grid: one rule per row is enough separation, and a bordered
   cell grid would be the densest thing on the whole site.

   On narrow viewports the table keeps its real semantics and the WRAPPER
   scrolls. Reflowing a <table> into stacked blocks with display:block is the
   common trick and it silently destroys the row/column associations assistive
   tech depends on. The wrapper is a labelled, focusable region instead, so the
   table can be reached and scrolled from the keyboard as well as by touch.
   Selected by [role="region"] because that role is what makes it reachable;
   nothing else on the public site uses it. */
.section [role="region"] {
  overflow-x: auto;
  margin-block-start: var(--space-4);
  /* Scroll shadows, CSS only. The two --bg layers are attached to the content
     ("local") so they slide away as you scroll; the two tinted layers are
     attached to the frame ("scroll") and stay put. The result is a soft edge
     that appears only on the side that still has hidden columns, so a table
     that fits shows nothing at all. Without this the clipped column reads as a
     broken layout rather than as something you can push sideways. */
  background:
    linear-gradient(to right, var(--bg) 40%, rgba(0, 0, 0, 0)) 0 0 / 2.5rem 100% no-repeat local,
    linear-gradient(to left, var(--bg) 40%, rgba(0, 0, 0, 0)) 100% 0 / 2.5rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, var(--border-strong), rgba(0, 0, 0, 0)) 0 0 / 0.75rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, var(--border-strong), rgba(0, 0, 0, 0)) 100% 0 / 0.75rem 100% no-repeat scroll;
}

.section table {
  width: 100%;
  min-width: 40rem;
  border-collapse: collapse;
  font-size: var(--fs-small);
}

.section th,
.section td {
  padding: var(--space-3) var(--space-4) var(--space-3) 0;
  text-align: start;
  vertical-align: top;
  border-bottom: 1px solid var(--border);
}

.section thead th {
  color: var(--text);
  font-weight: 640;
  letter-spacing: -0.012em;
  border-bottom-color: var(--border-strong);
}

/* The row header is the thing being described, so it stays full-strength ink
   while the cells explaining it drop to muted, exactly like .facts. */
.section tbody th {
  color: var(--text);
  font-weight: 640;
  width: 24%;
}

.section td {
  color: var(--text-muted);
}

.section tbody tr:last-child th,
.section tbody tr:last-child td {
  border-bottom: 0;
}

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

.site-footer {
  margin-top: auto;
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding-block: var(--space-5);
}

.site-footer__inner {
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 48rem) {
  .site-footer__inner {
    grid-template-columns: auto 1fr;
    align-items: start;
    gap: var(--space-6);
  }
}

.site-footer__brand {
  display: grid;
  gap: var(--space-3);
  justify-items: start;
}

.site-footer__nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  font-size: var(--fs-small);
}

.site-footer__nav a {
  color: var(--text-muted);
  text-decoration: none;
}

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

.site-footer__legal {
  display: grid;
  gap: var(--space-2);
  color: var(--text-muted);
  font-size: var(--fs-micro);
  line-height: 1.65;
  max-width: 70ch;
}

.site-footer__version {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: calc(var(--fs-micro) * 0.9);
  letter-spacing: 0.08em;
  line-height: 1.6;
  white-space: nowrap;
  margin-top: var(--space-1);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border);
  /* The stamp is the footer's terminal build marker, not a third legal
     paragraph. A hairline rule above and a one-step size drop below
     --fs-micro pull it out of the legal-text flow; wide mono tracking
     gives the machine its visible character; the muted colour is
     inherited so it stays quieter than the legal copy, never louder.
     Deliberately not a link and not accent-coloured, per plan. */
}

/* ---------- Utilities ---------------------------------------------------- */

/* Same clip-path technique as .skip-link, but for text that must never become
   visible on focus (screen-reader-only clarifications, e.g. "opens in a new
   tab"). Kept as a utility because the register/verify-email forms will want
   the same thing. */
.u-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Inline messages ---------------------------------------------- */

/* One message component, not one per page. The tinted-panel-with-an-edge
   shape deliberately echoes .note (the "not built yet" aside) so a warning
   does not arrive as a foreign object from another design language.

   Colour alone never carries the meaning: the copy inside always states the
   problem, per WCAG 1.4.1. */
.alert {
  margin: 0;
  border-inline-start: 3px solid var(--border-strong);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--surface-sunken);
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-small);
  max-width: var(--measure);
}

.alert--error {
  /* Not tokens: the palette has exactly one accent by design, and an error is
     the one state on the public site that must not be evergreen or it stops
     reading as a problem. Kept to a single desaturated red per scheme, and
     the tint replaces --surface-sunken so a red message is never set on a
     green-tinted panel. Text on tint measures 7.5:1 (light) and 8.7:1
     (dark). */
  background: #fdf0ee;
  border-inline-start-color: #a3352c;
  color: #8c2c24;
}

@media (prefers-color-scheme: dark) {
  .alert--error {
    background: #2a1a18;
    border-inline-start-color: #e2887f;
    color: #f0aaa2;
  }
}

/* ---------- Consent gate (/consent) --------------------------------------
   A hard gate, per decision D3: no dismiss, no "later", no skip link past it.
   So the page is deliberately one column, one panel, one decision. There is
   no second call to action competing with "Accept and continue" -- signing
   out is styled as the quiet alternative it is, not as an equal choice.
   ------------------------------------------------------------------------ */

.gate {
  padding-block: var(--space-6) var(--space-7);
}

.gate__panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--space-5);
  display: grid;
  gap: var(--space-5);
  /* Narrower than .welcome__panel: this is a reading-and-deciding surface,
     and the checkbox rows below need a short line to stay scannable. Centred
     rather than flush-left like every other panel on the site, because this
     page has exactly one thing on it and a left-hugging card leaves a large
     dead area that reads as a broken layout rather than as breathing room. */
  max-width: 38rem;
  margin-inline: auto;
}

@media (min-width: 40rem) {
  .gate__panel {
    padding: var(--space-6);
  }
}

.gate__intro {
  display: grid;
  gap: var(--space-3);
}

.gate__title {
  font-size: var(--fs-h2);
  font-weight: 690;
  letter-spacing: -0.026em;
}

.gate__lead {
  color: var(--text-muted);
  font-size: var(--fs-lead);
}

.gate__form {
  display: grid;
  gap: var(--space-5);
}

/* A fieldset is the right grouping element for "these checkboxes are one
   question", but its default border and inline padding are not. */
.gate__fieldset {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.gate__legend {
  padding: 0;
  margin-bottom: var(--space-3);
  color: var(--text-muted);
  font-size: var(--fs-small);
  font-weight: 600;
}

.gate__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* The refusal path. Separated by a rule and set small, because it must be
   findable (consent is only real if declining is possible) without reading
   as an equally weighted option. */
.gate__decline {
  display: grid;
  justify-items: start;
  gap: var(--space-3);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--fs-small);
  max-width: var(--measure);
}

.gate__aside {
  color: var(--text-muted);
  font-size: var(--fs-micro);
}

/* ---------- Checkbox field ------------------------------------------------
   Shared component, not consent-specific: the registration form's own terms
   checkbox (REG-1) should reuse .checkfield rather than growing a second
   checkbox style. Checkbox first, then label, then a supporting line -- the
   label is the accept statement itself, so it stays full-strength ink while
   the explanation drops to muted.

   The native control is kept and merely enlarged. A custom-drawn checkbox
   would have to re-earn focus, high-contrast-mode and forced-colors
   behaviour that the platform control already has.
   ------------------------------------------------------------------------ */

.checkfields {
  display: grid;
  gap: var(--space-3);
}

.checkfield {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  align-items: start;
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-4);
  transition: border-color 140ms ease;
}

.checkfield:focus-within {
  border-color: var(--accent);
}

.checkfield__input {
  /* 20px. Under WCAG 2.5.8's 24px minimum on its own, which is allowed here
     via the spacing exception: the row padding and the --space-3 gap between
     rows keep a 24px circle around each box clear of every other target, and
     the `for`-associated label gives a much larger second target for the same
     action. Sizing it up further starts to look like a checkbox pretending to
     be a button. */
  width: 1.25rem;
  height: 1.25rem;
  margin: 0;
  /* Nudge onto the label's first-line baseline rather than its box top. */
  margin-block-start: 0.2rem;
  accent-color: var(--accent);
  flex: none;
  cursor: pointer;
}

.checkfield__text {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}

.checkfield__label {
  font-weight: 620;
  letter-spacing: -0.012em;
  cursor: pointer;
}

.checkfield__detail {
  color: var(--text-muted);
  font-size: var(--fs-small);
}

/* The link out and the version stamp are metadata about the document, not
   part of the sentence describing it, so they get their own row rather than
   trailing the summary and wrapping mid-phrase. */
.checkfield__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-3);
  margin-top: var(--space-1);
  font-size: var(--fs-small);
  font-weight: 560;
}

/* Mono, because a document version is a checkable fact, exactly like the
   rule numbers and deck limits elsewhere on this site. */
.checkfield__version {
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ---------- Collection & deck management ---------------------------------
   /dashboard/collections (PAGES-3) and /dashboard/decks (PAGES-4).

   Both pages render the signed-in user's rows as a data table via
   .section table (see "Long-form document pages" above) and act on each row
   with small plain-HTML POST forms. Five things are genuinely new here and
   land together because they share one job: turn a data table into a small
   workspace without introducing cards, pills or a second accent.

   * .mono        -- a checkable fact set in the mono stack: set codes,
                     collector numbers and card quantities. site.css reserves
                     mono for facts the reader can verify (rule numbers, deck
                     limits, footer version) but until now baked it into whole
                     components; these pages are the first to need it as a span
                     inside a table cell.
   * .table-form  -- an inline row form: a number input and its action button
                     on one line that wraps instead of widening the table.
   * .qty-input   -- a compact numeric input, the same single-input look as
                     auth.css's .field__input (--control-border outline,
                     --radius-sm, hover to accent), sized to a cell.
   * .btn--row    -- a small outline button for row actions, because .btn's
                     padding is built for nav and forms, not a data row. Its
                     --danger variant reuses .alert--error's one red per scheme
                     so the site does not grow a second red.
   * .empty       -- an invitation-to-act empty state: a title and a pointer,
                     no card, no icon.

   No new tokens: every value comes from :root, including dark-scheme
   overrides.
   ------------------------------------------------------------------------ */

/* Checkable facts inside table cells. tabular-nums so a column of set codes
   or collector numbers lines up digit-for-digit. */
.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

/* Inline row form: input and button share one line, wrapping rather than
   pushing the cell (and with it the whole table) wider. */
.table-form {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

/* Compact numeric input, sized to a cell. Same single-input look as
   .field__input: --control-border is the affordance (3:1 per WCAG 1.4.11),
   hover moves it to the accent, and the global :focus-visible outline still
   owns focus. */
.qty-input {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  width: 5ch;
  padding: 0.35rem 0.5rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-sm);
  text-align: right;
  font-variant-numeric: tabular-nums;
  transition: border-color 140ms ease;
}

.qty-input:hover {
  border-color: var(--accent);
}

/* Row-action button. Extends .btn (radius, cursor, transitions, active press)
   with the size of a data cell rather than a nav item. */
.btn--row {
  padding: 0.35rem 0.75rem;
  font-size: var(--fs-micro);
  line-height: 1.4;
  background: transparent;
  border-color: var(--control-border);
  color: var(--text);
}

.btn--row:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* The destructive row action (remove a card, delete a deck). The calm outline
   stays; only the ink and edge change to .alert--error's one red per scheme,
   so it reads as distinct from Save without the heavy filled red account.css
   reserves for deleting the whole account. The word Delete carries the meaning;
   the red only reinforces it (WCAG 1.4.1). */
.btn--row--danger {
  border-color: #a3352c;
  color: #8c2c24;
}

.btn--row--danger:hover {
  border-color: #8c2c24;
  color: #8c2c24;
}

@media (prefers-color-scheme: dark) {
  .btn--row--danger {
    border-color: #e2887f;
    color: #f0aaa2;
  }

  .btn--row--danger:hover {
    border-color: #f0aaa2;
    color: #f0aaa2;
  }
}

/* Page-level flash messages (an import result: a success note, optionally a
   "some lines skipped" note, or a single error). One grid so two notes keep
   their own identity but share one rhythm; left-aligned so a message never
   stretches to a full-width band. */
.flash {
  display: grid;
  gap: var(--space-2);
  justify-items: start;
  margin: 0 0 var(--space-4);
}

/* The paste-a-list import control. A textarea and its label/hint/actions in a
   left-aligned grid, matching the .field rhythm auth.css uses for its forms
   without importing that file. The textarea inherits the site font (browsers
   default textareas to a mono 13px that reads off-brand). */
.import-form {
  display: grid;
  gap: var(--space-3);
  max-width: 46rem;
  justify-items: start;
}

.import-form__label {
  font-weight: 620;
  letter-spacing: -0.012em;
}

.import-form__textarea {
  font: inherit;
  width: 100%;
  min-height: 9rem;
  padding: 0.7rem 0.85rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-sm);
  resize: vertical;
  transition: border-color 140ms ease;
}

.import-form__textarea:hover {
  border-color: var(--accent);
}

.import-form__hint {
  color: var(--text-muted);
  font-size: var(--fs-small);
  max-width: var(--measure);
}

.import-form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

/* Empty state: a title and a pointer to the next action, not a card and not
   an icon. */
.empty {
  display: grid;
  gap: var(--space-1);
  justify-items: start;
  max-width: var(--measure);
}

.empty__title {
  font-size: var(--fs-h3);
  font-weight: 660;
  letter-spacing: -0.016em;
}

.empty__body {
  color: var(--text-muted);
  font-size: var(--fs-small);
  max-width: 46ch;
}

/* ---------- Search + browse surfaces (PAGES-7 / PAGES-8) -----------------
   The card catalogue (/catalogue) and rules search (/rules). Two public,
   indexable content pages sharing one search form and a hairline-separated
   result list each. No new tokens: every value below comes from :root,
   including the dark-scheme overrides, so these pages inherit light/dark
   for free.

   The result lists are hairline-and-space rather than boxed grids, matching
   the data-table treatment the long-form pages already use: this is a browse
   surface, and a wall of framed tiles would be the densest thing on the
   site. The mono face stays reserved for checkable facts (mana costs, set
   codes, rule numbers, source versions), never decoration.
   ------------------------------------------------------------------------ */

/* One search form for both pages: a visible label, then one row of input
   plus button. The input is the same native-control treatment as .field__input
   in auth.css (font: inherit so it never drops to the browser's 13px default;
   --control-border as the affordance, which clears WCAG 1.4.11's 3:1 rule;
   hover moves the edge to the accent). It lives here rather than importing
   auth.css because these public pages do not load that file. */
.searchform {
  display: grid;
  gap: var(--space-2);
  max-width: 36rem;
  min-width: 0;
}

.searchform__label {
  font-weight: 620;
  letter-spacing: -0.012em;
}

.searchform__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.searchform__input {
  font: inherit;
  flex: 1 1 16rem;
  min-width: 0;
  padding: 0.7rem 0.85rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-sm);
  transition: border-color 140ms ease;
}

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

.searchform__input::placeholder {
  color: var(--text-muted);
}

/* The global :focus-visible rule owns focus here, as everywhere else. */

/* Catalogue result list. A single column of cards, each a thumbnail plus the
   card's identity line, separated by hairlines rather than boxed. */
.catlist {
  display: grid;
  gap: var(--space-3);
  margin: 0;
}

.catcard {
  min-width: 0;
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border);
}

.catlist > :last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

/* Card thumbnail. Uses the .art frame (sunken background, no layout shift
   on missing images) but overrides its 4:3 ratio to the MTG card's portrait
   5:7, because catalogue.image_uri stores Scryfall's `normal` (full-frame
   portrait) image, not `art_crop`. */
.catcard__art {
  flex: none;
  width: 7rem;
  align-self: start;
  aspect-ratio: 5 / 7;
}

@media (max-width: 26rem) {
  .catcard__art {
    width: 5.5rem;
  }
}

.catcard__body {
  min-width: 0;
  display: grid;
  gap: var(--space-1);
}

.catcard__name {
  font-size: var(--fs-h3);
  font-weight: 660;
  letter-spacing: -0.016em;
}

.catcard__type {
  color: var(--text-muted);
  font-size: var(--fs-small);
}

/* The card's identifying facts: mana cost and set code + collector number in
   mono (checkable), rarity as a word. Muted like the table cells the other
   data pages use, so the name stays the strong ink on the line. */
.catcard__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-4);
  color: var(--text-muted);
  font-size: var(--fs-small);
}

.catcard__arena {
  font-size: var(--fs-micro);
}

/* Pagination. Prev/next as quiet buttons, left-aligned with the list. */
.pager {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

/* Rules result list. Numberless, hairline-separated passages, each with its
   citation line underneath. */
.ruleslist {
  display: grid;
  gap: var(--space-4);
  margin: 0;
}

.rule {
  display: grid;
  gap: var(--space-3);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--border);
}

.ruleslist > :last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

/* The passage is plain text from the source; pre-line keeps the rule's own
   line breaks without injecting markup, while still wrapping to the measure. */
.rule__content {
  max-width: var(--measure);
  white-space: pre-line;
}

/* The "show your work" line: a citation chip, the heading path, and the
   source version. All muted except the chip, which carries the site's one
   accent. */
.rule__cite {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-4);
  color: var(--text-muted);
  font-size: var(--fs-small);
}

.rule__path {
  font-size: var(--fs-micro);
}

.rule__version {
  font-size: var(--fs-micro);
}
