/* ============================================================================
   Canvas bridge — one visual language across the whole site.
   ============================================================================

   The redesign added new sections and left the old ones beside them, so a page
   carried two visual languages at once: flat wells recessed into the surface,
   next to glass cards floating on gradients with blue borders and heavy
   shadows. Each looked deliberate alone. Together they read as a mess, which
   is exactly what they were.

   Rewriting every old template to the new markup would be weeks of churn on
   pages that work. It is also unnecessary, because the old language turns out
   to be centralised: sixteen `--am-*` tokens define every surface, border,
   radius and shadow it uses, and every old component reads them. Redirecting
   those tokens re-skins the entire site without touching one line of markup.

   This file must load last. theme-foundation.css and page-unification.css
   define `--am-*` after canvas-2026.css does, so an override placed there
   would lose the cascade.

   What changes, and why each one:

     gradients → flat        A gradient on a data panel is decoration that
                             competes with the data. The canvas rule is that
                             the container is the quiet part.
     blue borders → hairline The old borders were tinted (118,181,255) which
                             reads as an accent. Accent means something here:
                             cyan is verification. A border is not a claim.
     shadows → none          Shadows belong to things that float — overlays,
                             menus. A shadow under every card says everything
                             is floating, which says nothing.
     radii → the same scale  8/12/16 was already close; this pins it exactly
                             so two panels side by side match.
   ============================================================================ */

:root {
  /* Surfaces: flat, one step up from the canvas. */
  --am-glass-bg:            var(--c-surface);
  --am-glass-bg-soft:       var(--c-surface);
  --am-card-bg:             var(--c-surface);
  --am-panel-bg:            var(--c-inset);
  --am-surface:             var(--c-surface);
  --am-surface-muted:       var(--c-inset);
  --am-surface-soft:        var(--c-inset);
  --am-surface-soft-token:  var(--c-inset);
  --am-bg:                  var(--c-canvas);
  --am-bg-muted:            var(--c-inset);

  /* Borders: a hairline is a separator, not an accent. */
  --am-glass-border:        var(--c-line);
  --am-glass-border-strong: var(--c-line-strong);
  --am-glass-highlight:     transparent;
  --am-hairline:            var(--c-line);
  --am-hairline-soft:       var(--c-line);
  --am-line:                var(--c-line);
  --am-line-strong:         var(--c-line-strong);

  /* Text: four levels, matching the canvas. */
  --am-text:                var(--c-text);
  --am-text-secondary:      var(--c-text-secondary);
  --am-muted:               var(--c-text-muted);

  /* Shadows: only overlays float. */
  --am-shadow:              none;
  --am-shadow-soft:         none;
  --am-shadow-lift:         var(--c-shadow-overlay);

  /* Radii pinned to one scale. */
  --am-radius-xs:           var(--c-r-control);
  --am-radius-sm:           var(--c-r-control);
  --am-radius-md:           var(--c-r-panel);
  --am-radius-lg:           var(--c-r-feature);
}

/* ---------------------------------------------------------------------------
   The older token family.

   The note at the top of this file said sixteen --am-* tokens define every
   surface the old language uses. That was wrong, and the mistake cost a day.
   Underneath --am-* sits an older family from dashboard.css -- --text-*,
   --bg-*, --accent*, --glass-*, --border* -- read about seven hundred times
   across the stylesheets and templates, and never redirected.

   Two consequences, both of which showed up as "the design is a mess":

   1. The legacy light theme is a warm cream palette (#faf7f2 ground, #2c2417
      ink) while the canvas light theme is cool (#f7f9fc). Every page mixed
      the two, so the same page had warm cards on a cool ground.

   2. --accent is #2563EB in BOTH themes. On the cream ground that passes; on
      the dark canvas it is 3.6:1, which is why the symbol tags and the
      methodology version pill failed the contrast audit while looking fine
      to a designer's eye on the light mock.

   Redirecting the family fixes both at once, and -- more to the point -- it
   means there is now exactly one palette. A colour cannot drift between
   themes if only one place defines it.

   Specificity is deliberate: dashboard.css sets these under [data-theme="x"],
   which ties with a bare :root. :root[data-theme="x"] outranks it, so the
   redirect wins wherever it is loaded from. */
:root {
  --bg-primary:     var(--c-canvas);
  --bg-secondary:   var(--c-surface);
  --bg-tertiary:    var(--c-overlay);
  --bg-surface:     var(--c-canvas);
  --bg-card:        var(--c-surface);
  --card-bg:        var(--c-surface);
  --glass-bg:       var(--c-surface);
  --glass-border:   var(--c-line);

  --text:           var(--c-text);
  --text-primary:   var(--c-text);
  --text-secondary: var(--c-text-secondary);
  --text-muted:     var(--c-text-muted);

  --border:         var(--c-line);
  --border-color:   var(--c-line);

  /* Cyan is the verification accent in the canvas language; the old blue
     said nothing in particular and failed on the dark ground. */
  --accent:         var(--c-evidence);
  --accent-color:   var(--c-evidence);
  --accent-primary: var(--c-evidence);
  --accent-hover:   var(--c-evidence-strong, var(--c-evidence));

  --skeleton-base:  var(--c-overlay);
  --skeleton-shine: var(--c-surface);

  --shadow-sm:      none;
  --shadow-md:      none;
  --shadow-lg:      var(--c-shadow-overlay);
}

:root[data-theme="dark"],
:root[data-theme="light"] {
  --bg-primary:     var(--c-canvas);
  --bg-secondary:   var(--c-surface);
  --bg-tertiary:    var(--c-overlay);
  --bg-surface:     var(--c-canvas);
  --bg-card:        var(--c-surface);
  --card-bg:        var(--c-surface);
  --glass-bg:       var(--c-surface);
  --glass-border:   var(--c-line);

  --text:           var(--c-text);
  --text-primary:   var(--c-text);
  --text-secondary: var(--c-text-secondary);
  --text-muted:     var(--c-text-muted);

  --border:         var(--c-line);
  --border-color:   var(--c-line);

  --accent:         var(--c-evidence);
  --accent-color:   var(--c-evidence);
  --accent-primary: var(--c-evidence);
  --accent-hover:   var(--c-evidence-strong, var(--c-evidence));

  --skeleton-base:  var(--c-overlay);
  --skeleton-shine: var(--c-surface);

  --shadow-sm:      none;
  --shadow-md:      none;
  --shadow-lg:      var(--c-shadow-overlay);
}

/* The same mapping for the light theme. The canvas tokens already carry the
   light values, so redirecting is enough — no second set of decisions, and no
   way for the two themes to drift apart. */
:root[data-theme="light"] {
  --am-glass-bg:            var(--c-surface);
  --am-glass-bg-soft:       var(--c-surface);
  --am-card-bg:             var(--c-surface);
  --am-panel-bg:            var(--c-inset);
  --am-surface:             var(--c-surface);
  --am-surface-muted:       var(--c-inset);
  --am-bg:                  var(--c-canvas);
  --am-glass-border:        var(--c-line);
  --am-hairline:            var(--c-line);
  --am-line:                var(--c-line);
  --am-text:                var(--c-text);
  --am-text-secondary:      var(--c-text-secondary);
  --am-muted:               var(--c-text-muted);
  --am-shadow:              none;
  --am-shadow-soft:         none;
}

/* A few components hardcode a gradient or a shadow rather than reading a
   token. Named individually so the override stays auditable — a blanket
   `* { background-image: none }` would also kill the chart fills and the
   heatmap tiles, which are data. */
.dashboard-cockpit,
.cockpit-primary,
.analysis-command-center,
.am-card,
.dashboard-card,
.market-card,
.stat-card,
.quick-action-card,
.lb-stat-card,
.vol-card,
.dr-index-card {
  background-image: none !important;
  background-color: var(--c-surface);
  border: 1px solid var(--c-line);
  box-shadow: none;
}

/* The decorative top bar on stat cards was a gradient stripe. Colour there
   carried no meaning, and in this system colour is meaning. */
.lb-stat-card__top-bar,
.stat-card__top-bar {
  display: none;
}

/* Nested panels inside those cards become wells, so the hierarchy reads
   canvas → surface → inset rather than card → card. */
.dashboard-cockpit .stat-item,
.cockpit-primary .cockpit-stat,
.am-card .am-card__inner,
.market-card .market-card__body {
  background: var(--c-inset);
  border: 1px solid var(--c-line);
  border-radius: var(--c-r-control);
  box-shadow: none;
}

/* The header's freshness pill. Its markup and class names are untouched; this
   only colours the dot to agree with the word beside it, so the two cannot
   contradict each other the way "Live Data" over a Stale panel did. */
.live-indicator--stale .live-dot,
.live-indicator--historical .live-dot { background: var(--c-text-muted); }
.live-indicator--delayed .live-dot,
.live-indicator--refreshing .live-dot,
.live-indicator--partial .live-dot { background: var(--c-attention); }
.live-indicator--unavailable .live-dot,
.live-indicator--error .live-dot,
.live-indicator--offline .live-dot { background: var(--c-down); }

/* The pulse says "something is arriving right now". Over stale data it is a
   second claim on top of the word, and the more persuasive of the two --
   motion reads before text does. It runs only while the feed is actually
   current. */
.live-indicator:not(.live-indicator--live) .live-dot {
  animation: none;
  box-shadow: none;
}

/* ============================================================================
   Full unification.
   ============================================================================

   Redirecting the sixteen --am-* tokens fixed the surfaces that read them.
   It did nothing for the components that write their own colours, and
   measured on the rendered home page there were 665 elements still carrying
   a gradient background. That is what "old and new mixed together" looked
   like: my flat wells above the fold, and below it gradient panels, tinted
   icon tiles, coloured stripes and a purple-to-cyan pill.

   The brief's avoid list names most of them directly: AI purple/blue
   gradients, universal glassmorphism, oversized rounded cards, nested card
   soup, animation without information value.

   So the rule is inverted here too, for the same reason it was inverted for
   tabular numerals: a list of 665 selectors is never finished and goes stale
   on the next template edit. Decorative gradients are off by default, and
   the exceptions are named — because they are the ones that carry data.

   The allowlist was read off the rendered page, not guessed: heatmap tiles
   encode change, sparkline and chart bars encode series, fill and range
   elements encode a proportion, and the legend gradient is the scale those
   tiles are read against. Every one of those is information. Everything else
   was decoration.
   ============================================================================ */

/* Off by default -- and the allowlist is excluded from the selector rather
   than re-enabled after it.
 
   The first version was `body * { background-image: none }` followed by an
   allowlist using `revert !important`. Both halves were wrong. `body *` is
   specificity (0,0,2), so any component rule with a single class beat it and
   586 of the 665 gradients survived; and `revert` returns to the user-agent
   value, which would have discarded the author's gradient on exactly the
   elements meant to keep it.
 
   Excluding the exceptions from the selector means the allowed elements are
   never touched at all, and !important can win everywhere else without
   needing to restate a value it cannot know.
 
   The allowlist was read off the rendered page rather than guessed: heatmap
   tiles encode change, sparkline and chart bars encode a series, fill and
   range elements encode a proportion, and the legend gradient is the scale
   the tiles are read against. Every one is information. The rest was
   decoration. */

/* The same rule for decorative pseudo-elements.
 *
 * `body *` does not match ::before or ::after, so 64 gradient bars,
 * glows and sheens survived the unification untouched -- including the
 * three-colour rule across the top of the accuracy explainer, which is
 * the one piece of the old visual language still visible on a page that
 * otherwise reads as the new one. The allowlist is the same: anything
 * whose gradient carries a value keeps it. */
body *:not(svg):not(svg *):not(canvas):not(.heatmap-tile):not(.heatmap-tile *):not(.legend-gradient-bar):not(.sparkline-bar):not(.chart-bar):not(.fg-fill):not(.commodity-range-fill):not([class*="progress-fill"]):not([class*="confidence-fill"]):not([class*="conf-fill"]):not([class*="-gauge"]):not([class*="-meter"]):not([class*="-fill"])::before,
body *:not(svg):not(svg *):not(canvas):not(.heatmap-tile):not(.heatmap-tile *):not(.legend-gradient-bar):not(.sparkline-bar):not(.chart-bar):not(.fg-fill):not(.commodity-range-fill):not([class*="progress-fill"]):not([class*="confidence-fill"]):not([class*="conf-fill"]):not([class*="-gauge"]):not([class*="-meter"]):not([class*="-fill"])::after {
  background-image: none !important;
}
body *:not(svg):not(svg *):not(canvas):not(.heatmap-tile):not(.heatmap-tile *):not(.legend-gradient-bar):not(.sparkline-bar):not(.chart-bar):not(.fg-fill):not(.commodity-range-fill):not([class*="progress-fill"]):not([class*="confidence-fill"]):not([class*="conf-fill"]):not([class*="-gauge"]):not([class*="-meter"]):not([class*="-fill"]) {
  background-image: none !important;
}

/* Surfaces that lost their gradient need a ground, or they inherit whatever
   is behind them. Structural panels sit one step up from the canvas; the
   regions inside them sit one step down, so the hierarchy still reads
   canvas → surface → inset without a single shadow. */
.dashboard-container,
.dashboard-footer,
.market-summary-card,
.market-detail-section,
.quick-symbols-strip,
.tab-nav-container,
.dashboard-tab-nav,
.section-header,
.cockpit-pulse,
.cockpit-alerts,
.verified-trust-banner,
.pg-modal {
  background-color: var(--c-surface);
  border: 1px solid var(--c-line);
  box-shadow: none;
}

.metric-cell,
.quick-action-card,
.stat-item,
.detail-stat,
.overview-stat,
.vol-card-stat {
  background-color: var(--c-inset);
  border: 1px solid var(--c-line);
  box-shadow: none;
}

/* Icon tiles were saturated gradient squares -- the most 2023 thing on the
   page, and the least informative: every one of them was the same colour
   regardless of what it sat beside. A tinted well with the icon in the
   evidence colour says the same thing in one step less. */
[class*="-icon-wrap"],
[class*="__icon-wrap"],
[class*="qa-icon"],
[class*="card-icon"],
[class*="stat-icon"],
[class*="feature-icon"] {
  background-color: var(--c-inset) !important;
  border: 1px solid var(--c-line);
  color: var(--c-evidence);
  box-shadow: none;
}

/* Pills and badges that were gradient-filled. Colour on a badge should mean
   something; on these it meant nothing, so they read as chrome now and the
   ones that do carry state -- health, lifecycle, agreement -- keep their
   colour and stand out because everything around them stopped competing. */
.category-badge,
.section-tag,
.tab-nav-item,
[class*="__top-bar"],
[class*="-badge"]:not(.health):not(.lifecycle__step):not(.narrative__agree) {
  background-color: var(--c-inset);
  color: var(--c-text-secondary);
  border: 1px solid var(--c-line);
}

/* Text painted with a gradient through background-clip. With the gradient
   gone the text would be transparent and therefore invisible, so these have
   to be returned to a solid colour explicitly. */
[class*="gradient-text"],
[style*="background-clip"],
[class*="-title"][style*="-webkit-background-clip"] {
  -webkit-text-fill-color: var(--c-text) !important;
  color: var(--c-text) !important;
}

/* The primary action keeps a fill, because a button that does the main thing
   on a page should look different from one that does not. Solid, in the
   accent, rather than a two-colour ramp. */
.btn-primary,
.am-hero__btn--primary,
button[class*="primary"],
a[class*="btn"][class*="primary"] {
  background-color: var(--c-evidence) !important;
  color: var(--c-canvas) !important;
  border: 1px solid var(--c-evidence);
}

/* The cockpit's pulsing dot was a third assertion of freshness beside a
   kicker and a badge that already disagreed with each other. The badge is
   the one wired to an assessment, so it is the one that stays. */
.cockpit-live-dot { display: none; }

/* Decorative top stripes. Colour on these encoded nothing -- the same ramp
   appeared above a market panel, a newsletter form and a workspace card. In
   a system where cyan means verified, a coloured bar that means nothing
   spends the reader's attention on nothing. */
[class*="__top-bar"],
[class*="-top-bar"],
.cockpit-primary::before,
.cockpit-secondary::before,
.newsletter-inline::before { display: none !important; }

/* The More menu, grouped.
 *
 * Twelve links in one flat run meant a reader looking for one of them had to
 * read all twelve, because nothing said which part of the list to read.
 * Three groups of four: the answer is usually in one, and the eye can skip
 * the other two.
 *
 * Two columns above 46rem -- twelve items in one column is a tall menu that
 * reaches for the bottom of the viewport on a laptop. */
.dropdown-menu { padding: var(--c-space-2); min-width: 15rem; }
.dropdown-group + .dropdown-group {
  margin-block-start: var(--c-space-2);
  padding-block-start: var(--c-space-2);
  border-block-start: 1px solid var(--c-line);
}
.dropdown-group__label {
  margin: 0 0 0.2rem;
  padding-inline: 0.6rem;
  font-size: var(--c-t-label);
  font-weight: 650;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--c-text-faint);
}
.dropdown-group__list { list-style: none; margin: 0; padding: 0; }

/* No two-column variant.

   I wrote one, raised its specificity to beat page-unification's
   `display: block !important`, and it still did not apply -- and measuring
   showed it was not needed: at 1280x640, the shortest desktop viewport worth
   designing for, the grouped menu is 448px tall against 640px of room.

   So it is deleted rather than debugged. Two columns would have made the
   menu four times wider than the button it hangs from, to solve a height
   problem that does not exist. And shipping CSS I believed was working while
   it silently did nothing is the exact failure this engagement kept finding
   elsewhere. The grouping is what the reader needed; the columns were what I
   assumed they needed. */

/* Movement colours from the old palette, brought onto the canvas ones.
 *
 * Measured on the rendered home page: `.stat-value.negative` was 3.75:1
 * against the 4.5 AA needs -- a price, in the colour that tells a reader it
 * fell, that a reader with low vision cannot reliably read. The canvas red
 * and green are 6.68:1 and 9.62:1 on the same surface.
 *
 * Same tokens as .c-up / .c-down, so a fall is the same red everywhere on
 * the site rather than two reds that nearly match. */
.negative, .text-negative, .change-negative, [class*="--down"], [class*="-down"]:not([class*="dropdown"]) {
  color: var(--c-down);
}
.positive, .text-positive, .change-positive, [class*="--up"] {
  color: var(--c-up);
}

/* The page ground itself.
 *
 * In the light theme --c-canvas correctly resolved to #f7f9fc while body
 * stayed rgb(7, 11, 18) -- a hardcoded dark background that reads no token.
 * So switching to light gave dark text on a dark ground: an h2 at 1.19:1,
 * a nav item at 1.09:1. Invisible, not merely low contrast.
 *
 * This is why the text-colour rescue below looked like it was not applying:
 * the text had gone dark correctly and the floor underneath it had not moved.
 * I spent two measurements chasing the wrong half.
 *
 * html is included because the viewport paints its background from whichever
 * of html/body declares one, and a mismatch shows as a band of the other
 * theme past the end of short pages. */
html, body {
  background-color: var(--c-canvas);
  color: var(--c-text-secondary);
}

/* ---------------------------------------------------------------------------
   Light theme rescue.
 
   Measured on /reports/brief/ with the theme switched to light: 19 of 176
   text nodes below AA, one at 1.09:1 -- white on white, invisible. The site
   is dark-first and several older components hardcode a pale text colour
   with no light override, so switching theme leaves their text on a ground
   the same brightness as itself.
 
   Every visual check I had run until now was in the dark theme, which is why
   this survived: a second theme fails silently, in the half nobody is
   looking at.
 
   Headings and table headers inherit the canvas text tokens here rather than
   being restated per component, so this cannot drift out of step with the
   palette the contrast test enforces.
   --------------------------------------------------------------------------- */

:root[data-theme="light"] h1,
:root[data-theme="light"] h2,
:root[data-theme="light"] h3,
:root[data-theme="light"] h4,
:root[data-theme="light"] th,
:root[data-theme="light"] .rb-card__value,
:root[data-theme="light"] .rb-dossier__full-narrative,
:root[data-theme="light"] [class*="__value"],
:root[data-theme="light"] [class*="-value"],
:root[data-theme="local-none"] { color: var(--c-text); }

:root[data-theme="light"] td,
:root[data-theme="light"] p,
:root[data-theme="light"] li,
:root[data-theme="light"] .rb-pill,
:root[data-theme="light"] [class*="-desc"],
:root[data-theme="light"] [class*="__desc"],
:root[data-theme="light"] [class*="-sub"] { color: var(--c-text-secondary); }

:root[data-theme="light"] [class*="-label"],
:root[data-theme="light"] [class*="__label"],
:root[data-theme="light"] [class*="-meta"],
:root[data-theme="light"] [class*="__meta"] { color: var(--c-text-muted); }

/* Movement and state keep their own meaning in both themes -- these must not
   be flattened to body text by the rules above. */
:root[data-theme="light"] .c-up,
:root[data-theme="light"] .positive,
:root[data-theme="light"] [class*="--up"] { color: var(--c-up); }
:root[data-theme="light"] .c-down,
:root[data-theme="light"] .negative,
:root[data-theme="light"] [class*="--down"]:not([class*="dropdown"]) { color: var(--c-down); }
:root[data-theme="light"] .health,
:root[data-theme="light"] .lifecycle__step,
:root[data-theme="light"] .narrative__agree { color: inherit; }

/* ---------------------------------------------------------------------------
   Elements whose only background was a gradient.

   The blanket `background-image: none` above is right about decoration and
   wrong about the handful of elements where the gradient WAS the surface. A
   badge or a button styled with `background: linear-gradient(...); color:
   white` and no background-color loses its ground entirely: white text on
   whatever is behind it. In the dark theme that stayed legible by accident,
   so it went unnoticed; in the light theme the verified checkmark, the
   category badge and the footer's Subscribe button became white on white.

   Each of these is a flat fill now, taken from the same tokens as everything
   else. Text is --c-canvas rather than white so it stays readable in both
   themes: cyan carries near-black ink on the dark ground and near-white on
   the light one, and neither has to be stated twice. */
.verified-icon,
.newsletter-input-group button,
.footer-utility .newsletter-input-group button,
.dashboard-footer .newsletter-input-group button,
.btn.primary,
.category-btn.active,
.tg-float-btn {
  background-color: var(--c-evidence) !important;
  background-image: none !important;
  color: var(--c-canvas) !important;
  border-color: transparent !important;
}

/* The badge rule above colours the badge; a span inside it kept its own
   white, which is the colour that was measured at 1.05:1. Colour the
   contents too -- except the state pills, which mean something. */
.category-badge,
.section-tag {
  color: var(--c-text-secondary) !important;
}

/* Contents inherit rather than repeat the colour. Naming a token here fought
   the filled variants -- .category-badge.crypto paints itself with the
   evidence colour and sets a matching ink, and a span inside it was being
   forced back to the muted text colour: 1.04:1 on cyan. Inheriting means the
   badge decides once, for itself and for whatever it contains. */
.category-badge *,
.section-tag * {
  color: inherit !important;
}

/* Brand chips keep their brand, at a shade that passes AA against the white
   text they carry. Telegram's #0088cc is 3.89:1; #006da3 -- the colour this
   chip already used on hover -- is 5.1:1, so the brand survives the fix. */
.social-banner--tg {
  background-color: #006da3 !important;
  background-image: none !important;
  color: #ffffff !important;
}

/* The X chip is the same shape of thing: a brand tile that has to carry its
   label in both themes. */
.social-banner--x {
  background-color: var(--c-inset) !important;
  background-image: none !important;
  color: var(--c-text) !important;
}

/* The label inside a chip is a separate element, and the global link colour
   was reaching it: evidence-coloured text on the evidence-coloured tile,
   1.05:1. Chips decide their own ink, once, and their contents follow. */
.social-banner .social-banner-chip.social-banner--tg,
.social-banner .social-banner-chip.social-banner--tg * {
  color: #ffffff !important;
}

.social-banner .social-banner-chip.social-banner--x,
.social-banner .social-banner-chip.social-banner--x * {
  color: var(--c-text) !important;
}

/* And everything inside any chip inherits from it. No rule sets a colour on
   these spans, so they take one from an ancestor that is not the chip --
   which is how a label inside a Telegram-blue tile came out muted grey at
   2.65:1. Naming the chip's own two colours above is not enough; the
   contents have to be told to follow the tile they sit on. */
.social-banner-chip * {
  color: inherit !important;
}

/* The skip link is left to page-unification.css, which already pins it to
   white on #245b83 -- 5.2:1, and correct in both themes because the chip is
   a fixed dark tile rather than a themed surface. My own rule here fought it
   and lost on specificity, leaving the fill from one rule and the ink from
   another. One owner is the fix; a fourth opinion was the problem. */

/* ---------------------------------------------------------------------------
   Targets that sit two pixels under the minimum.

   WCAG 2.2 asks for 24x24 unless the target is inline in a sentence or has
   24px of clear space around it. A few links in dense rows -- the movers
   table's tickers, the contact page's mail link -- come out at 22px because
   their line box is exactly the text. Padding rather than height, so nothing
   in the row moves; the extra two pixels come off the existing gaps. */
.dr-mover-row__symbol,
.contact-method a,
.footer-links a,
.narrative__title,
a.narrative__title,
.am-auth-link,
.spine__claim a,
.thread__step a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

/* A 14px checkbox is a 14px target. The sign-in form's "remember me" was the
   smallest control on the site; 24px is the floor the guideline sets and the
   size a finger actually needs. */
input[type="checkbox"],
input[type="radio"] {
  /* The auth form sets a width on every input, which a bare
     input[type=checkbox] rule loses to. These need the override: a 14px box
     is the smallest target on the site and the guideline's floor is 24. */
  width: 24px !important;
  height: 24px !important;
  min-width: 24px;
  accent-color: var(--c-evidence);
}

/* Letters inside a filled disc follow the disc.
 *
 * A broad `... :is(span, svg, i) { color: #ffffff !important }` rule reaches
 * spans nested inside tiles it was never written for. On the about page the
 * initial inside each cyan avatar came out white at 1.81:1. These containers
 * already choose an ink that works against their own fill, so the contents
 * inherit it rather than being told a colour of their own.
 *
 * -webkit-text-fill-color has to be reset too: it overrides color when set,
 * and the rule doing the damage sets both. */
.creator-avatar .avatar-text,
.vol-sym-avatar > *,
.lb-explainer__num > * {
  color: inherit !important;
  -webkit-text-fill-color: inherit !important;
}
