/* =============================================================================
   Arcanum Site Kit (ASK) — arcanum.css — v1.6
   v1.6 (2026-08-15): TWO defect repairs, both in §18. Both surfaced by wiring
     ark-table.js on a site that had it vendored but never loaded, and both are
     the same shape as the v1.5 numeric-alignment item: a §8 DATA-GRID rule
     reaching a §18 NARRATIVE table through the shared `.ark-table` class.
     (a) The narrow-width `.ark-table-wrap { overflow-x: hidden !important }`
         rule was UNSCOPED: it killed panning on EVERY wrap at ≤680px, including
         wraps whose table is NOT an .ark-table and therefore never reflows to
         label-stacked cards. Such a table keeps its columns, exceeds the wrap,
         and its right-hand columns become CUT AND UNREACHABLE — measured on
         shaikh /download at 390px: five catalogue tables 472-604px wide inside
         a 332px wrap, computed overflow-x `hidden`, page `scrollX === 0`. Now
         scoped with `:has()` to wraps that actually contain a reflowing
         .ark-table, which is what the rule was written for. Render-neutral
         wherever ark-table.js runs (every wrap it builds holds an .ark-table);
         strictly a repair wherever a hand-written wrap holds a site-local
         table. Degrades safely — a browser without `:has()` drops the rule and
         keeps `overflow-x: auto`.
     (b) §8's `white-space: nowrap` was inherited by every narrative table §18
         governs, because §18 re-declared padding, borders and alignment but not
         wrapping. An enhanced prose table therefore stopped wrapping its cells
         and became a horizontal scroller (measured: the same 4-column README
         table 597px and fitting before enhancement, 867px and scrolling after).
         ark-table.js is now v1.1 and marks what it enhances `.ark-table-prose`;
         the reset is scoped to that class, so §8's grids keep nowrap columns.
     ⚠ Vendored into the shaikh site only (2026-08-15, staged not deployed).
     The other ~25 vendored copies still hold v1.4/v1.5.
   v1.5 (2026-08-14): TWO changes, both additive, both render-neutral for
     every existing site (verified by construction — the new tokens carry the
     old literal values, and no shipped markup uses the new class).
     (a) Hover-lift tokenised: `--ark-lift-card` (-2px), `--ark-lift-btn`
         (-1px), `--ark-lift-arrow` (3px) replace the three hard-coded
         translate values at .ark-card:hover, .ark-card:hover .ark-arrow and
         .ark-triad-btn:hover. A site whose hover convention is NOT a lift
         (CURRENT_STYLE_AUDIT marker A6) now opts out with three tokens in
         its own site.css, instead of overriding three :hover rules inside a
         vendored copy and losing the fix at the next re-vendor.
     (b) §8/§18 numeric-alignment collision repaired ADDITIVELY: `.ark-table
         th.num / td.num` are right-aligned in tabular figures. §18's
         `text-align:left` re-declaration had silently killed §8's numeric
         alignment estate-wide; restoring §8 wholesale would right-align text
         columns as well, so the convention is made explicit instead.
     ⚠ Vendored into the shaikh site only (2026-08-14, staged not deployed).
     The other ~25 vendored copies still hold v1.4; because both changes are
     render-neutral there, propagation is a hygiene task, not a fix.
   v1.4 (2026-07-31): kit-debt pass. THREE changes, no token changes.
     (a) .ark-fineprint / .ark-explore-controls adopted upstream, byte-identical
         to the marked block erwin and myrdal each carried site-locally. Both
         site-local copies become deletable once this propagates.
     (b) .ark-lede / .ark-note rescoped from descendant-only to standalone, so
         the same class used outside .ark-hero / .ark-section-head stops
         rendering unstyled. Scoped appearance is unchanged by construction.
     (c) .ark-gallery-grid narrow-viewport overflow fixed (min-width:0 on grid
         items); measured at 390px, 104px of horizontal body scroll.
     ✅ PROPAGATED 2026-08-04 to all 26 vendored copies (deploy/ + sites_source/ +
     PublicRepos/), after the /carson-visual regression pass that gated it.
     VERDICT: PASS — 0 regressions in 51 tested page×width combinations across
     erwin, myrdal, heterodata, gordon and lewis at 1440/834/390 in BOTH themes.
     The candidate CSS was applied by intercepting the arcanum.css request so it
     kept its cascade position (site-local theme.css/site.css still load after and
     still win) — appending it instead would have produced false regressions.
     Findings, screenshots and the negative-control run:
     reviews/kit_v14_regression_20260804/.
     What the pass actually established, per change:
       (a) no-op where it lands — erwin's and myrdal's site-local blocks are
           byte-identical and load AFTER the kit, so they still win. Their local
           copies are now deletable (gordon keeps its own .ark-fineprint, which
           differs deliberately and still overrides).
       (b) the ONLY rendering change is the standalone case, which was previously
           unstyled: 10 pages on erwin/myrdal. Scoped usage (heterodata,
           nickanderson) measured ZERO change, as constructed. No site-local bare
           .ark-lede/.ark-note rule exists anywhere that could newly win on
           source order — that was the real regression vector and it is empty.
           Contrast after dimming: 7.71 dark / >4.5 light, WCAG AA clear.
       (c) independently reproduced: stripping gordon's site-local override with
           the OLD kit brings the 104px overflow back at 390px; with v1.4 it does
           not. The kit rule genuinely substitutes, so gordon's local override is
           now deletable too. lewis's gallery never overflowed either way.
     ⚠ Vendored files are on disk only. The 14 live sites still SERVE v1.3 until
     their containers are rebuilt — see Technical/reports/queue_entries_T2.md.
     nickanderson.us was UNTESTED (DNS SERVFAIL from the workstation), not passed.
   v1.3 (2026-06-12): header-density breakpoint (≤1100px) so 9-10-item navs
   don't wrap the theme toggle onto a second row; no token changes.
   v1.2 (Heterodata rebrand)
   The single, vendored, versioned design system for Arcanum Research sites.
   ONE visual identity across ~12 sites; themeable per-site by ONE accent color.

   Promoted from the heterodata.org hub palette (dark default + light via
   prefers-color-scheme, the card grid, the accent system). No CDN, no web-font
   hosting — body font is the system-ui stack (offline rule).

   A per-site theme is just 1-2 lines overriding --ark-accent / --ark-accent-soft.
   See themes/<site>.css and README.md.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. TOKENS  (:root — dark default; light via prefers-color-scheme)
   --------------------------------------------------------------------------- */
:root {
  color-scheme: light dark;

  /* --- Identity — NEVER override per site ----------------------------------- */
  --ark-font: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --ark-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --ark-radius: 14px;
  --ark-radius-sm: 8px;
  --ark-maxw: 1080px;

  /* Hover-lift, tokenised (v1.5, 2026-08-14). The estate default is the
     lift the kit has always drawn, so this change is byte-equivalent in
     render for every existing site. A site that has decided its hover
     convention is NOT a lift (CURRENT_STYLE_AUDIT marker A6 — six
     independent implementations of one recipe) sets these to 0 in its own
     site.css instead of overriding three :hover rules and re-acquiring the
     defect at the next re-vendor. */
  --ark-lift-card:  -2px;
  --ark-lift-btn:   -1px;
  --ark-lift-arrow:  3px;

  /* Type scale (rem, ~1.2 minor-third) */
  --ark-text-xs:   0.75rem;
  --ark-text-sm:   0.85rem;
  --ark-text-base: 1rem;
  --ark-text-md:   1.08rem;
  --ark-text-lg:   1.18rem;
  --ark-text-xl:   1.5rem;
  --ark-text-2xl:  2rem;
  --ark-text-3xl:  clamp(2.1rem, 5vw, 3rem);
  --ark-leading: 1.6;
  --ark-leading-tight: 1.2;

  /* Spacing scale */
  --ark-space-1: 0.25rem;
  --ark-space-2: 0.5rem;
  --ark-space-3: 0.75rem;
  --ark-space-4: 1rem;
  --ark-space-5: 1.5rem;
  --ark-space-6: 2.5rem;

  --ark-shadow: 0 6px 22px -12px rgba(0, 0, 0, .4);
  --ark-shadow-lg: 0 8px 28px rgba(0, 0, 0, .35);

  /* --- Neutrals — dark default ---------------------------------------------- */
  --ark-bg:       #0e1116;
  --ark-bg-soft:  #161b22;
  --ark-fg:       #e7edf3;
  --ark-fg-dim:   #9aa7b4;
  --ark-line:     #2a313b;
  --ark-tag:      #1f2733;

  /* --- THE per-site knob — override these two only (default = hub blue) ------ */
  --ark-accent:      #1565c0;
  --ark-accent-soft: #1b3a5c;
  /* v1.2 contrast token: the text/ink color to place ON a solid --ark-accent
     fill (buttons, badges-on-accent, download controls, skip-link). EVERY theme
     sets this so accent-on-accent (invisible text) can never happen. White for
     dark/saturated accents; a theme with a light accent sets it to a dark ink.
     --ark-accent-ink is kept as a back-compat alias. */
  --ark-on-accent:   #ffffff;
  --ark-accent-ink:  var(--ark-on-accent);

  /* Semantic status colors (stable across themes) */
  --ark-ok:    #2ea043;
  --ark-warn:  #d29922;
  --ark-danger:#f85149;
}

@media (prefers-color-scheme: light) {
  :root {
    --ark-bg:       #f7f9fc;
    --ark-bg-soft:  #ffffff;
    --ark-fg:       #14181d;
    --ark-fg-dim:   #5a6673;
    --ark-line:     #dde3ea;
    --ark-tag:      #eef2f7;

    --ark-accent:      #1565c0;
    --ark-accent-soft: #d9e8fb;
    --ark-on-accent:   #ffffff;
    --ark-accent-ink:  var(--ark-on-accent);

    --ark-shadow: 0 6px 22px -12px rgba(0, 0, 0, .18);
    --ark-shadow-lg: 0 8px 28px rgba(0, 0, 0, .14);
  }
}

/* Manual override hooks (a site/user can force a scheme without prefers query).
   v2.0.1 dark-toggle fix: the dark neutral palette above lives on :root as the
   default, but the JS toggle sets [data-theme="dark"] to force dark for a
   light-OS visitor. Previously [data-theme="dark"] only set color-scheme, so on
   a light OS the palette never flipped. Re-apply the dark tokens on the explicit
   attribute so the toggle works regardless of the OS preference. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --ark-bg:       #0e1116;
  --ark-bg-soft:  #161b22;
  --ark-fg:       #e7edf3;
  --ark-fg-dim:   #9aa7b4;
  --ark-line:     #2a313b;
  --ark-tag:      #1f2733;
  --ark-accent-soft: #1b3a5c;
  --ark-shadow: 0 6px 22px -12px rgba(0, 0, 0, .4);
  --ark-shadow-lg: 0 8px 28px rgba(0, 0, 0, .35);
}
:root[data-theme="light"] {
  color-scheme: light;
  --ark-bg: #f7f9fc; --ark-bg-soft: #fff; --ark-fg: #14181d;
  --ark-fg-dim: #5a6673; --ark-line: #dde3ea; --ark-tag: #eef2f7;
  --ark-accent-soft: #d9e8fb;
}

/* -----------------------------------------------------------------------------
   2. RESET / BASE
   --------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--ark-font);
  font-size: var(--ark-text-base);
  line-height: var(--ark-leading);
  background: var(--ark-bg);
  color: var(--ark-fg);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--ark-accent); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4, h5, h6 { line-height: var(--ark-leading-tight); letter-spacing: -.01em; }

img, svg, video { max-width: 100%; height: auto; }
hr { border: 0; border-top: 1px solid var(--ark-line); margin: var(--ark-space-5) 0; }

code, kbd, samp, pre { font-family: var(--ark-mono); }

/* Baseline a11y: visible keyboard focus everywhere. */
:focus-visible {
  outline: 2px solid var(--ark-accent);
  outline-offset: 2px;
  border-radius: 3px;
}

.ark-visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.ark-skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 1000;
  background: var(--ark-accent); color: var(--ark-on-accent);
  padding: var(--ark-space-2) var(--ark-space-4); border-radius: 0 0 var(--ark-radius-sm) 0;
}
.ark-skip-link:focus { left: 0; }

/* -----------------------------------------------------------------------------
   3. LAYOUT HELPERS
   --------------------------------------------------------------------------- */
.ark-wrap {
  max-width: var(--ark-maxw);
  margin: 0 auto;
  padding: 0 1.25rem;
}
.ark-main { padding: var(--ark-space-6) 0; min-height: 50vh; }

.ark-section-head {
  display: flex; align-items: baseline; gap: var(--ark-space-3);
  margin: var(--ark-space-6) 0 var(--ark-space-5);
  padding-bottom: var(--ark-space-3);
  border-bottom: 1px solid var(--ark-line);
  flex-wrap: wrap;
}
.ark-section-head h2 { margin: 0; font-size: var(--ark-text-lg); }

/* Hero / landing intro */
.ark-hero { padding: var(--ark-space-6) 0 var(--ark-space-5); }
.ark-hero h1 { font-size: var(--ark-text-3xl); margin: 0 0 .6rem; line-height: 1.1; }

/* v1.4 — .ark-lede and .ark-note are STANDALONE utilities.
   Until v1.4 each existed only as a descendant selector (`.ark-hero .ark-lede`,
   `.ark-section-head .ark-note`), so the same class used anywhere else on a page
   rendered completely unstyled. erwin, myrdal, heterodata and nickanderson all
   use them outside those two containers. The declarations below are the SAME
   values that were inside the scoped rules, lifted out; the container rules that
   follow keep only what is genuinely container-specific (margin reset), so a
   lede inside a hero and a note inside a section head render exactly as before.
   Nothing about the scoped appearance changes — the standalone case stops being
   a no-op. */
.ark-lede { max-width: 62ch; color: var(--ark-fg-dim); font-size: var(--ark-text-md); }
.ark-note { font-size: var(--ark-text-sm); color: var(--ark-fg-dim); }
.ark-hero .ark-lede { margin: 0; }
.ark-section-head .ark-note { margin: 0; }

/* v1.4 — .ark-fineprint / .ark-explore-controls, adopted upstream.
   Byte-adopted from the marked block that erwin and myrdal each carried in their
   site-local theme.css (both copies byte-identical, both marked "delete when the
   kit gains them"). Every value derives from an --ark-* token, so both themes
   follow the toggle automatically (D10: no hardcoded light-mode colours). */
.ark-fineprint {
  font-size: var(--ark-text-sm);
  color: var(--ark-fg-dim);
  max-width: 78ch;
}
.ark-explore-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ark-space-2);
  margin: var(--ark-space-4) 0;
}
.ark-explore-controls label {
  font-size: var(--ark-text-sm);
  color: var(--ark-fg-dim);
}
.ark-explore-controls select {
  background: var(--ark-bg-soft);
  color: var(--ark-fg);
  border: 1px solid var(--ark-line);
  border-radius: var(--ark-radius);
  padding: .4rem .6rem;
  font: inherit;
  max-width: 100%;
}

/* Prose measure for readability */
.ark-prose { max-width: 72ch; font-size: var(--ark-text-md); line-height: 1.75; }
.ark-prose p { margin: 0 0 1.1em; }
.ark-prose h2 { margin-top: 2.2em; }
.ark-prose h3 { margin-top: 1.7em; }
.ark-prose a { text-decoration: underline; text-underline-offset: 2px; }

/* -----------------------------------------------------------------------------
   4. HEADER  /  STICKY NAV
   .ark-header > .ark-wrap > [.ark-brand] [.ark-site-title] [.ark-switcher] <nav.ark-nav>
   --------------------------------------------------------------------------- */
.ark-header {
  position: sticky; top: 0; z-index: 100;
  background: color-mix(in srgb, var(--ark-bg) 92%, transparent);
  -webkit-backdrop-filter: saturate(160%) blur(8px);
  backdrop-filter: saturate(160%) blur(8px);
  border-bottom: 1px solid var(--ark-line);
}
/* Fallback for browsers without backdrop-filter / color-mix */
@supports not (backdrop-filter: blur(1px)) {
  .ark-header { background: var(--ark-bg); }
}

.ark-header-inner {
  display: flex; align-items: center; gap: var(--ark-space-4);
  max-width: var(--ark-maxw); margin: 0 auto;
  padding: .7rem 1.25rem;
  flex-wrap: wrap;
}

/* Brand mark — links to the hub (heterodata.org) */
.ark-brand {
  display: inline-flex; align-items: center; gap: .55rem;
  color: var(--ark-fg); font-weight: 700; flex-shrink: 0;
}
.ark-brand:hover { text-decoration: none; }
.ark-brand .ark-mark {
  width: 26px; height: 26px; flex-shrink: 0;
  color: var(--ark-accent); /* favicon.svg tints via currentColor */
}
.ark-brand .ark-brand-text { display: flex; flex-direction: column; line-height: 1.05; }
.ark-brand .ark-brand-name { font-size: .98rem; letter-spacing: -.01em; }
.ark-brand .ark-brand-sub {
  font-size: .58rem; font-weight: 500; color: var(--ark-fg-dim);
  letter-spacing: .08em; text-transform: uppercase;
}

/* Site title (current site, accent-tinted divider) */
.ark-site-title {
  font-weight: 600; font-size: .98rem; color: var(--ark-fg);
  padding-left: var(--ark-space-4);
  border-left: 2px solid var(--ark-accent);
  flex-shrink: 0;
}
.ark-site-title:hover { text-decoration: none; }

/* Per-site nav links */
.ark-nav { display: flex; gap: var(--ark-space-4); margin-left: auto; flex-wrap: wrap; align-items: center; }
.ark-nav-a {
  color: var(--ark-fg-dim); font-size: .92rem; padding: 2px 0;
  border-bottom: 2px solid transparent; transition: color .12s, border-color .12s;
}
.ark-nav-a:hover { color: var(--ark-accent); text-decoration: none; }
.ark-nav-a.active { color: var(--ark-fg); border-bottom-color: var(--ark-accent); font-weight: 600; }

/* -----------------------------------------------------------------------------
   5. ECOSYSTEM SWITCHER  (<details>-based, no-JS-required dropdown)
   --------------------------------------------------------------------------- */
.ark-switcher { position: relative; flex-shrink: 0; }
.ark-switcher > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .88rem; color: var(--ark-fg-dim);
  border: 1px solid var(--ark-line); border-radius: 999px;
  padding: .3rem .75rem; background: var(--ark-bg-soft);
  transition: border-color .12s, color .12s;
}
.ark-switcher > summary::-webkit-details-marker { display: none; }
.ark-switcher > summary:hover { color: var(--ark-fg); border-color: var(--ark-accent); }
.ark-switcher > summary .ark-caret { font-size: .7rem; transition: transform .15s; }
.ark-switcher[open] > summary .ark-caret { transform: rotate(180deg); }

.ark-switcher-menu {
  position: absolute; top: calc(100% + .4rem); right: 0;
  width: min(340px, 86vw); max-height: 70vh; overflow-y: auto;
  background: var(--ark-bg-soft); border: 1px solid var(--ark-line);
  border-radius: var(--ark-radius); box-shadow: var(--ark-shadow-lg);
  z-index: 200; padding: .4rem;
}
.ark-switcher-group {
  font-size: var(--ark-text-xs); font-weight: 600; text-transform: uppercase;
  letter-spacing: .07em; color: var(--ark-fg-dim);
  padding: .6rem .6rem .3rem;
}
.ark-switcher-item {
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .6rem; border-radius: var(--ark-radius-sm);
  color: var(--ark-fg); font-size: .9rem; text-decoration: none;
  transition: background .1s;
}
.ark-switcher-item:hover { background: var(--ark-tag); text-decoration: none; }
.ark-switcher-item.current { background: var(--ark-accent-soft); }
.ark-switcher-item .ark-dot {
  width: 10px; height: 10px; border-radius: 999px; flex-shrink: 0;
  background: var(--ark-si-accent, var(--ark-accent));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--ark-si-accent, var(--ark-accent)) 22%, transparent);
}
.ark-switcher-item .ark-si-name { font-weight: 500; }
.ark-switcher-item .ark-si-host {
  margin-left: auto; font-family: var(--ark-mono);
  font-size: .74rem; color: var(--ark-fg-dim);
}
.ark-switcher-item .ark-si-pill {
  font-size: .6rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ark-fg-dim); background: var(--ark-tag);
  border-radius: 999px; padding: .1rem .4rem;
}
/* v1.2: "affiliated" suffix tag on switcher/cards (external-owner sites). */
.ark-affiliated {
  font-size: .58rem; letter-spacing: .04em; text-transform: lowercase;
  color: var(--ark-fg-dim); background: var(--ark-tag);
  border: 1px solid var(--ark-line);
  border-radius: 999px; padding: .08rem .4rem; white-space: nowrap;
}

/* v1.2: indented subpage links under each site in the detailed dropdown. */
.ark-si-sub {
  display: flex; align-items: center;
  padding: .25rem .6rem .25rem 2.05rem; border-radius: var(--ark-radius-sm);
  color: var(--ark-fg-dim); font-size: .8rem; text-decoration: none;
  transition: background .1s, color .1s;
}
.ark-si-sub::before {
  content: ""; width: 4px; height: 4px; border-radius: 999px;
  background: currentColor; opacity: .5; margin-right: .5rem; flex-shrink: 0;
}
.ark-si-sub:hover { background: var(--ark-tag); color: var(--ark-fg); text-decoration: none; }
.ark-si-sub .ark-si-sub-label { line-height: 1.3; }

/* v1.2: greyed-out "planned" entries (sites or subpages not yet routed). */
.ark-planned {
  opacity: .5; pointer-events: none; cursor: default;
  filter: grayscale(0.6);
}

/* -----------------------------------------------------------------------------
   6. CARDS  /  GRID  (ported from the hub)
   --------------------------------------------------------------------------- */
.ark-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: var(--ark-space-4);
}
.ark-card {
  border: 1px solid var(--ark-line); border-radius: var(--ark-radius);
  padding: 1.4rem 1.45rem; text-decoration: none; color: inherit;
  display: flex; flex-direction: column; background: var(--ark-bg-soft);
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.ark-card:hover, .ark-card:focus-visible {
  border-color: var(--ark-accent); transform: translateY(var(--ark-lift-card));
  box-shadow: var(--ark-shadow); outline: none; text-decoration: none;
}
.ark-card .ark-card-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: .5rem; margin-bottom: .5rem;
}
.ark-card h3 { margin: 0; font-size: var(--ark-text-lg); }
.ark-card .ark-arrow { color: var(--ark-accent); font-size: 1.05rem; opacity: .8; transition: transform .15s ease; }
.ark-card:hover .ark-arrow { transform: translateX(var(--ark-lift-arrow)); }
.ark-card p { margin: 0 0 1rem; color: var(--ark-fg-dim); font-size: .92rem; flex: 1; }
.ark-card .ark-url {
  font-size: .82rem; color: var(--ark-accent);
  font-family: var(--ark-mono); word-break: break-all;
}

.ark-pill {
  font-size: .66rem; letter-spacing: .08em; text-transform: uppercase; font-weight: 600;
  color: var(--ark-fg-dim); background: var(--ark-tag);
  border-radius: 999px; padding: .2rem .55rem; white-space: nowrap;
}
.ark-pill.draft { color: var(--ark-warn); background: color-mix(in srgb, var(--ark-warn) 16%, transparent); }

/* -----------------------------------------------------------------------------
   7. BUTTONS  +  DOWNLOAD CLUSTER
   --------------------------------------------------------------------------- */
.ark-btn {
  display: inline-flex; align-items: center; gap: .4rem;
  font-family: inherit; font-size: .9rem; font-weight: 600; line-height: 1;
  padding: .6rem 1.1rem; border-radius: var(--ark-radius-sm);
  border: 1px solid var(--ark-accent); background: var(--ark-accent);
  /* !important so a site's own `.prose a {color}` can't make button text accent-on-accent (invisible) */
  color: var(--ark-on-accent) !important; cursor: pointer; text-decoration: none;
  transition: filter .12s, background .12s, color .12s;
}
.ark-btn:hover { filter: brightness(1.08); text-decoration: none; }
.ark-btn:active { filter: brightness(.94); }
.ark-btn[disabled], .ark-btn:disabled { opacity: .55; cursor: default; filter: none; }

.ark-btn-outline {
  /* fg text (always readable on any bg, light or dark accent) + accent border; fills on hover */
  background: transparent; color: var(--ark-fg) !important; border-color: var(--ark-accent);
}
.ark-btn-outline:hover { background: var(--ark-accent); color: var(--ark-on-accent) !important; filter: none; }

.ark-btn-ghost {
  background: transparent; border-color: var(--ark-line); color: var(--ark-fg) !important;
}
.ark-btn-ghost:hover { border-color: var(--ark-accent); color: var(--ark-accent) !important; background: transparent; }

.ark-btn-sm { font-size: .78rem; padding: .35rem .7rem; }

.ark-btn-group { display: inline-flex; flex-wrap: wrap; gap: var(--ark-space-2); }

/* Download cluster — labelled group of format buttons */
.ark-download {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--ark-space-2);
  padding: var(--ark-space-3) 0;
}
.ark-download .ark-download-label {
  font-size: var(--ark-text-xs); text-transform: uppercase; letter-spacing: .06em;
  color: var(--ark-fg-dim); margin-right: var(--ark-space-2);
}
/* v1.3 FIX: scope the outline-chip style to plain links only. The previous
   `.ark-download a` selector (0,1,1) beat `.ark-btn` (0,1,0) and repainted the
   ArkDownloads.buttons() chips' text in the accent color ON the accent fill —
   invisible labels in production. */
.ark-download a:not(.ark-btn) {
  display: inline-block; font-size: .76rem; font-family: var(--ark-mono);
  border: 1px solid var(--ark-line); border-radius: var(--ark-radius-sm);
  padding: .25rem .6rem; color: var(--ark-accent); text-decoration: none;
  transition: background .12s, color .12s, border-color .12s;
}
.ark-download a:not(.ark-btn):hover { background: var(--ark-accent); color: var(--ark-on-accent); border-color: var(--ark-accent); }

/* -----------------------------------------------------------------------------
   8. DATA TABLE
   --------------------------------------------------------------------------- */
.ark-table-wrap {
  width: 100%; overflow-x: auto;
  border: 1px solid var(--ark-line); border-radius: var(--ark-radius);
  background: var(--ark-bg-soft);
}
.ark-table {
  width: 100%; border-collapse: collapse;
  font-size: .85rem; font-variant-numeric: tabular-nums;
}
.ark-table caption {
  text-align: left; padding: .7rem 1rem; color: var(--ark-fg-dim);
  font-size: var(--ark-text-sm); border-bottom: 1px solid var(--ark-line);
}
.ark-table th, .ark-table td {
  padding: .5rem .8rem; border-bottom: 1px solid var(--ark-line);
  text-align: right; white-space: nowrap;
}
.ark-table th:first-child, .ark-table td:first-child { text-align: left; }
.ark-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--ark-tag); color: var(--ark-fg-dim);
  font-size: .76rem; letter-spacing: .02em; font-weight: 600;
}
.ark-table tbody tr:hover td { background: var(--ark-tag); }
.ark-table tbody tr:last-child td { border-bottom: 0; }

/* -----------------------------------------------------------------------------
   9. PLOTLY CHART CONTAINER (responsive)
   --------------------------------------------------------------------------- */
.ark-chart {
  width: 100%; min-height: 440px;
  border: 1px solid var(--ark-line); border-radius: var(--ark-radius);
  background: var(--ark-bg-soft);
  padding: var(--ark-space-2);
  display: flex; flex-direction: column;
}
.ark-chart > .js-plotly-plot, .ark-chart > .plotly, .ark-chart > * { flex: 1 1 auto; min-width: 0; }
.ark-chart-meta {
  display: flex; justify-content: space-between; align-items: center; gap: var(--ark-space-3);
  flex-wrap: wrap; font-size: var(--ark-text-sm); color: var(--ark-fg-dim);
  padding: var(--ark-space-2) var(--ark-space-3) 0;
}
.ark-chart-loading { color: var(--ark-fg-dim); padding: var(--ark-space-5); text-align: center; font-style: italic; }
.ark-chart-error { color: var(--ark-danger); padding: var(--ark-space-5); text-align: center; font-size: .9rem; }

/* -----------------------------------------------------------------------------
   10. PROVENANCE  /  DPR PANEL  ("How this was built")
   --------------------------------------------------------------------------- */
.ark-provenance {
  border: 1px solid var(--ark-line);
  border-left: 4px solid var(--ark-accent);
  border-radius: var(--ark-radius);
  background: var(--ark-bg-soft);
  padding: var(--ark-space-5);
  margin: var(--ark-space-5) 0;
}
.ark-provenance > h2, .ark-provenance > h3 {
  margin: 0 0 var(--ark-space-3); font-size: var(--ark-text-lg);
  display: flex; align-items: center; gap: .5rem;
}
.ark-provenance dl {
  display: grid; grid-template-columns: max-content 1fr;
  gap: .4rem var(--ark-space-4); margin: 0;
}
.ark-provenance dt {
  font-size: var(--ark-text-xs); text-transform: uppercase; letter-spacing: .06em;
  font-weight: 600; color: var(--ark-fg-dim); padding-top: .15rem;
}
.ark-provenance dd { margin: 0; font-size: .92rem; }
.ark-provenance dd a { color: var(--ark-accent); }
.ark-provenance .ark-prov-updated {
  margin-top: var(--ark-space-4); padding-top: var(--ark-space-3);
  border-top: 1px solid var(--ark-line);
  font-size: var(--ark-text-sm); color: var(--ark-fg-dim);
}
@media (max-width: 560px) {
  .ark-provenance dl { grid-template-columns: 1fr; gap: 0 0; }
  .ark-provenance dd { margin-bottom: var(--ark-space-3); }
}

/* -----------------------------------------------------------------------------
   11. BADGES  (Reproducible · Offline · Real data · Draft)
   --------------------------------------------------------------------------- */
.ark-badge {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: var(--ark-text-xs); font-weight: 600;
  letter-spacing: .04em; line-height: 1;
  padding: .3rem .6rem; border-radius: 999px;
  color: var(--ark-fg-dim); background: var(--ark-tag);
  border: 1px solid var(--ark-line);
}
/* 2026-08-16 (volcker browser re-pilot, D10 class): the semantic color moved from
   the TEXT to the dot. At --ark-text-xs the ok/accent inks measured 2.89:1 and
   3.00:1 in light theme — under WCAG AA. The dot keeps the semantic color (a
   non-text indicator has no 4.5:1 requirement at this size); the label stays on
   the badge's base ink (--ark-fg-dim, measured >=4.5:1 both themes). Estate-wide
   by design: every site's footer carries these badges. */
.ark-badge::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: var(--ark-badge-dot, currentColor); opacity: .9; }
.ark-badge.reproducible { --ark-badge-dot: var(--ark-ok); }
.ark-badge.offline { --ark-badge-dot: var(--ark-accent); }
.ark-badge.real-data { --ark-badge-dot: var(--ark-fg); }
.ark-badge.draft { --ark-badge-dot: var(--ark-warn); }
.ark-badge-row { display: inline-flex; flex-wrap: wrap; gap: var(--ark-space-2); align-items: center; }

/* -----------------------------------------------------------------------------
   12. CODE BLOCK  +  COPY BUTTON
   --------------------------------------------------------------------------- */
.ark-code {
  position: relative;
  background: var(--ark-bg-soft);
  border: 1px solid var(--ark-line);
  border-radius: var(--ark-radius);
  margin: var(--ark-space-4) 0;
  overflow: hidden;
}
.ark-code-head {
  display: flex; align-items: center; gap: .5rem;
  padding: .45rem .8rem; background: var(--ark-tag);
  border-bottom: 1px solid var(--ark-line);
  font-family: var(--ark-mono); font-size: .76rem; color: var(--ark-fg-dim);
  flex-wrap: wrap;
}
.ark-code-head .ark-code-path { word-break: break-all; }
.ark-copy {
  margin-left: auto;
  background: var(--ark-bg-soft); color: var(--ark-accent);
  border: 1px solid var(--ark-line); border-radius: var(--ark-radius-sm);
  padding: .2rem .65rem; font-family: inherit; font-size: .74rem;
  cursor: pointer; white-space: nowrap; transition: background .12s, color .12s;
}
.ark-copy:hover { background: var(--ark-accent); color: var(--ark-on-accent); border-color: var(--ark-accent); }
.ark-copy:disabled { opacity: .6; cursor: default; }
.ark-code pre { margin: 0; padding: var(--ark-space-4); overflow-x: auto; font-size: .87rem; line-height: 1.55; }
.ark-code pre[hidden] { display: none; }
.ark-code code { font-family: var(--ark-mono); }

/* A6 dual-language extension (ark-code.js): R | Python toggle + Download.
   Reuses the .ark-code box + .ark-copy button above; only adds toggle chrome. */
.ark-code-toggle {
  display: inline-flex; align-items: stretch;
  border: 1px solid var(--ark-line); border-radius: var(--ark-radius-sm);
  overflow: hidden;
}
.ark-code-lang {
  background: var(--ark-bg-soft); color: var(--ark-fg-dim);
  border: 0; border-right: 1px solid var(--ark-line);
  padding: .2rem .7rem; font-family: inherit; font-size: .74rem;
  cursor: pointer; white-space: nowrap; transition: background .12s, color .12s;
}
.ark-code-lang:last-child { border-right: 0; }
.ark-code-lang:hover { color: var(--ark-fg); }
.ark-code-lang.is-active {
  background: var(--ark-accent); color: var(--ark-on-accent); cursor: default;
}
.ark-code-dl { margin-left: var(--ark-space-2); }

/* Inline code */
:not(pre) > code.ark-inline, .ark-prose :not(pre) > code {
  background: var(--ark-tag); padding: .1rem .35rem;
  border-radius: 4px; font-size: .88em;
}

/* -----------------------------------------------------------------------------
   13. FOOTER  (mandated — dual anchors: heterodata.org + nickanderson.us)
   --------------------------------------------------------------------------- */
.ark-footer {
  border-top: 1px solid var(--ark-line);
  background: var(--ark-bg-soft);
  color: var(--ark-fg-dim);
  font-size: var(--ark-text-sm);
  margin-top: var(--ark-space-6);
}
.ark-footer-inner {
  max-width: var(--ark-maxw); margin: 0 auto;
  padding: var(--ark-space-5) 1.25rem;
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem .75rem;
  line-height: 1.7;
}
.ark-footer a { color: var(--ark-accent); }
.ark-footer strong { color: var(--ark-fg); }
.ark-footer .ark-sep { color: var(--ark-line); user-select: none; }
.ark-footer .ark-foot-badges { display: inline-flex; flex-wrap: wrap; gap: .4rem; }
/* Educational disclaimer — site-wide footer placement. */
.ark-footer-disclaimer {
  max-width: var(--ark-maxw); margin: 0 auto;
  padding: var(--ark-space-4) 1.25rem 0;
  font-size: var(--ark-text-xs); color: var(--ark-fg-dim);
  line-height: 1.6; text-wrap: pretty;
}
.ark-footer-disclaimer .ark-disclaimer-source { color: var(--ark-fg); }

/* -----------------------------------------------------------------------------
   14. RESPONSIVE
   --------------------------------------------------------------------------- */
/* v1.3: density step — keep long navs (9-10 items) on one header row before
   the full mobile stack kicks in; prevents the theme toggle wrapping onto a
   second row that overlaps content under the translucent sticky header. */
@media (max-width: 1100px) {
  .ark-header-inner { gap: var(--ark-space-2) var(--ark-space-3); }
  .ark-nav { gap: .65rem; }
  .ark-nav-a { font-size: .85rem; }
  .ark-brand .ark-brand-sub { display: none; }
}

@media (max-width: 680px) {
  .ark-header-inner { gap: .6rem .9rem; }
  .ark-site-title { padding-left: .7rem; }
  .ark-nav { gap: .9rem; font-size: .85rem; width: 100%; order: 3; }
  .ark-hero h1 { font-size: 1.9rem; }
  .ark-grid { grid-template-columns: 1fr; }
}

/* -----------------------------------------------------------------------------
   15. MOTION / PREFERS-REDUCED-MOTION
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
}

/* -----------------------------------------------------------------------------
   16. LIGHT/DARK TOGGLE (v1.1) — button + sun/moon swap by effective theme
   --------------------------------------------------------------------------- */
.ark-theme-toggle {
  margin-left: auto; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: 999px;
  background: transparent; border: 1px solid var(--ark-line);
  color: var(--ark-fg-dim); cursor: pointer; font-size: 1rem; line-height: 1;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.ark-theme-toggle:hover { color: var(--ark-fg); border-color: var(--ark-accent); }
.ark-theme-toggle:focus-visible { outline: 2px solid var(--ark-accent); outline-offset: 2px; }
/* When a per-site nav exists it has margin-left:auto; keep the toggle to its right.
   v1.7 (2026-08-16): `margin-left:auto`, NOT a fixed .5rem. `.ark-header-inner` wraps,
   and on a site with a long nav row 1 fills exactly to the container edge (measured on
   volcker at 1440px: nav right edge 1240 == container right 1240), so the toggle is
   pushed to row 2 — where a fixed left margin left it at the FAR LEFT of the header
   (measured left 208 / right-offset 1200 at 1440px, left 28 at 390px; LENS_visual P2).
   An auto left margin absorbs the free space on whichever row the toggle lands on, so
   it is flush right when wrapped AND still flush right when it shares row 1 with the
   nav (the toggle is the last flex item, so nothing sits to its right either way). */
.ark-header .ark-nav + .ark-theme-toggle { margin-left: auto; }
/* Glyph visibility: show the icon for the mode you'd switch TO. Default kit = dark → show sun. */
.ark-theme-moon { display: none; }
.ark-theme-sun  { display: inline; }
:root[data-theme="light"] .ark-theme-sun  { display: none; }
:root[data-theme="light"] .ark-theme-moon { display: inline; }
:root[data-theme="dark"]  .ark-theme-sun  { display: inline; }
:root[data-theme="dark"]  .ark-theme-moon { display: none; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .ark-theme-sun  { display: none; }
  :root:not([data-theme]) .ark-theme-moon { display: inline; }
}

/* ── §17 ArkChart — the single chart entry point (ark-chart.js) ───────────────
   Universal Graph Contract: one chart per row (full width), title left +
   controls (transform + Download CSV) pinned top-right, plot, then downloads row. */
.ark-chart-wrap { display: block; width: 100%; margin: 0 0 var(--ark-space-5, 24px); }
.ark-chart-head {
  display: flex; align-items: center; gap: var(--ark-space-2, 8px);
  justify-content: space-between; flex-wrap: wrap; margin-bottom: var(--ark-space-2, 8px);
}
.ark-chart-title { font-weight: 600; font-size: var(--ark-text-lg, 1.125rem); color: var(--ark-fg); }
.ark-chart-controls { display: flex; align-items: center; gap: var(--ark-space-2, 8px); margin-left: auto; }
.ark-chart-csv { white-space: nowrap; }
.ark-chart-transform { padding: 2px 8px; }
/* NOTE: `.ark-chart` itself is declared ONCE, in §9 (PLOTLY CHART CONTAINER) — it owns
   width/min-height/border/background/padding/flex. A second `.ark-chart` block used to
   live here with `min-height:320px`; being later in the file it silently won the cascade
   and shrank every kit chart estate-wide by 120px. ark-plotly.js renders autosize
   (responsive:true, no layout.height) into this box with a fixed b:44 bottom margin and a
   responsiveTitle() that raises margin.t to 52-70px, so the plot needs the full 440px of
   vertical room or the x-axis title clips. Do NOT re-declare `.ark-chart` here; if a
   surface genuinely needs a shorter chart, add a MODIFIER (e.g. `.ark-chart--compact`). */
.ark-chart-downloads { margin-top: var(--ark-space-2, 8px); }
/* never two charts sharing a row */
.ark-chart-row, .ark-charts { display: block; }
/* v1.7 (2026-08-16): the narrow-width head KEEPS Download CSV top-RIGHT.
   The previous rule stacked the head into a column and zeroed the controls' auto
   margin, which put the button flush LEFT at mobile — measured on volcker /aggregate
   at 390px: csv box x24/right132 inside a block whose right edge is 366, i.e. 234px
   off the right edge (LENS_visual P2). That contradicts the Universal Graph Contract
   ("Download CSV top-right of every chart") exactly where the affordance is hardest
   to find. Instead: stay a wrapping ROW, let the title claim the row and wrap to two
   lines, and keep `margin-left:auto` on the controls so they right-align whether they
   share the title's row or drop to the next one. */
@media (max-width: 680px) {
  .ark-chart-head { flex-direction: row; flex-wrap: wrap; align-items: flex-start; }
  .ark-chart-title { flex: 1 1 12rem; min-width: 0; }
  .ark-chart-controls { margin-left: auto; }
}

/* ── §18 ArkTable — responsive narrative tables (ark-table.js) ────────────────
   Table-rendering rule: at narrow widths a narrative table reflows to
   label-stacked cards (each cell shows its column header via data-label) instead
   of a horizontally-scrolling mystery. Wide data grids belong in the Explorer. */
.ark-table-wrap { width: 100%; overflow-x: auto; }
.ark-table { width: 100%; border-collapse: collapse; font-size: var(--ark-text-sm, .92rem); }
.ark-table th, .ark-table td {
  padding: 6px 10px; border-bottom: 1px solid var(--ark-line); text-align: left; vertical-align: top;
}
.ark-table thead th { color: var(--ark-fg-dim); font-weight: 600; }
/* §8/§18 collision repair #2 (v1.6, 2026-08-15). §8 sets `white-space: nowrap`
   on .ark-table cells — right for the DATA GRID it was written for, where a
   column must not reflow. §18 re-declares padding, borders and alignment for
   narrative tables but never reset the wrapping, so every prose table ArkTable
   enhanced became an unwrappable horizontal scroller: a 4-column README table
   measured 597px (wrapped, fitting its column) before enhancement and 867px
   (nowrap, scrolling) after — the "horizontally-scrolling mystery table"
   TABLE_RENDERING_STANDARD §"what broken means" names. ark-table.js v1.1 marks
   what it enhances with `.ark-table-prose`, so the reset lands ONLY on
   narrative tables and §8's grids keep their nowrap columns. */
.ark-table-prose th, .ark-table-prose td { white-space: normal; }
/* §8/§18 collision repair (v1.5, 2026-08-14). §8 gave .ark-table numeric
   right-alignment; the rule above re-declares text-align:left at equal
   specificity and later source position, so §8's alignment has been dead
   estate-wide (CURRENT_STYLE_AUDIT, Appendix). Restoring §8 wholesale would
   right-align TEXT columns too, so the convention is made explicit instead:
   a cell marked .num is a value and is right-aligned, in tabular figures.
   Additive — no existing markup carries .num, so no site changes render. */
.ark-table th.num, .ark-table td.num {
  text-align: right; font-variant-numeric: tabular-nums;
}
@media (max-width: 680px) {
  /* Scoped under .ark-table-wrap (ArkTable always wraps) + !important so the reflow beats a
     site's own .doc-table/.stat-table/.grid/.prose table CSS regardless of source order. */
  .ark-table-wrap .ark-table,
  .ark-table-wrap .ark-table tbody,
  .ark-table-wrap .ark-table tr,
  .ark-table-wrap .ark-table td {
    display: block !important; width: 100% !important; box-sizing: border-box !important;
  }
  /* keep the header for screen readers but take it out of the visual flow */
  .ark-table-wrap .ark-table thead { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .ark-table-wrap .ark-table tr {
    margin: 0 0 12px !important; border: 1px solid var(--ark-line) !important;
    border-radius: var(--ark-radius, 10px); padding: 4px 0 !important; background: var(--ark-bg-soft);
  }
  .ark-table-wrap .ark-table td {
    border-bottom: 1px solid var(--ark-line); padding: 6px 10px 6px 44% !important;
    position: relative; min-height: 1.6em; overflow-wrap: anywhere; white-space: normal !important;
  }
  .ark-table-wrap .ark-table td:last-child { border-bottom: 0; }
  .ark-table-wrap .ark-table td::before {
    content: attr(data-label); position: absolute; left: 10px; top: 6px; width: 38%;
    font-weight: 600; color: var(--ark-fg-dim);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  /* The wrap must not force a min-width from the old table layout — but ONLY
     where the reflow above actually applies. Scoped with :has() (v1.6,
     2026-08-15): an unscoped rule also hid the overflow of wraps holding a
     NON-.ark-table table, which keeps its columns and is then cut with no way
     to pan to the rest (shaikh /download, five catalogue tables at 390px).
     Browsers without :has() drop this rule and keep overflow-x:auto — the safe
     direction. */
  .ark-table-wrap:has(.ark-table) { overflow-x: hidden !important; }
}

/* ── §19 ArkGallery — curated featured-chart gallery (ark-gallery.js) ──────────
   A standardized "Chart Gallery" section rendered FROM a human-approved
   gallery_manifest.json. Responsive grid of cards; ONE chart per card (each card
   reuses the site's standard live `.chart-embed`, so legend-below + top-right
   Download-CSV + tokens are inherited by construction — DNA-compliant). The card
   grid is responsive (never two charts crammed into one card). */
.ark-gallery { display: block; width: 100%; }
.ark-gallery-heading { margin: 0 0 var(--ark-space-3, 12px); font-size: var(--ark-text-xl, 1.5rem); }
.ark-gallery-intro { margin: 0 0 var(--ark-space-5, 24px); color: var(--ark-fg-dim); max-width: 64ch; }
.ark-gallery-grid {
  display: grid; gap: var(--ark-space-5, 24px);
  /* responsive: 1 column on phones, 2 on wide screens — but each card is a full,
     standalone chart (the per-CARD chart is never split into side-by-side plots). */
  grid-template-columns: 1fr;
  /* v1.1: cards size to their own content. Without this a media-less deep-link card
     stretches to the height of the tall figure card beside it and reads as a broken
     image slot. Chart cards keep their own min-height, so they are unaffected. */
  align-items: start;
}
@media (min-width: 900px) { .ark-gallery-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* v1.4 — narrow-viewport overflow fix (measured at 390px on gordon, 2026-07-30:
   the grid was 104px wider than its 304px track, and the page body scrolled
   sideways). A grid ITEM defaults to min-width:auto, so a Plotly chart's
   intrinsic width pushes the 1fr track open however narrow the viewport gets.
   min-width:0 on the items lets the track win. Gordon carries a byte-equivalent
   site-local override in its own site.css, kept until this ships so the two can
   be compared; delete it there once this is propagated. */
.ark-gallery-grid > * { min-width: 0; }
.ark-gallery-chart { min-width: 0; max-width: 100%; }
.ark-gallery-card {
  margin: 0; display: flex; flex-direction: column;
  border: 1px solid var(--ark-line); border-radius: var(--ark-radius, 10px);
  background: var(--ark-bg-soft); padding: var(--ark-space-3, 12px);
}
.ark-gallery-card-title {
  margin: 0 0 var(--ark-space-2, 8px); font-size: var(--ark-text-lg, 1.125rem);
  font-weight: 600; color: var(--ark-fg); line-height: 1.25;
}
.ark-gallery-chart { width: 100%; min-height: 360px; }
.ark-gallery-card-caption {
  margin-top: var(--ark-space-3, 12px); font-size: var(--ark-text-sm, .92rem);
  color: var(--ark-fg-dim); display: flex; flex-direction: column; gap: var(--ark-space-2, 8px);
}
.ark-gallery-card-link { color: var(--ark-accent); font-weight: 600; align-self: flex-start; text-decoration: none; }
.ark-gallery-card-link:hover { text-decoration: underline; }
.ark-gallery-pending { color: var(--ark-fg-dim); font-style: italic; padding: var(--ark-space-5, 24px) 0; }

/* v1.1 (additive) — two more card kinds for sites whose figures are NOT served
   from a /api/chart registry: a static-figure card and a deep-link card.
   `image` cards show the figure itself; deep-link cards deliberately carry no
   media (a live map/dashboard is linked, never re-embedded inside a card). */
.ark-gallery-card-kicker {
  margin: 0 0 var(--ark-space-1, 4px); font-size: var(--ark-text-xs, .78rem);
  letter-spacing: .06em; text-transform: uppercase; color: var(--ark-fg-dim); font-weight: 600;
}
.ark-gallery-card-media {
  width: 100%; background: var(--ark-bg, #fff); border-radius: var(--ark-radius-sm, 6px);
  overflow: hidden; border: 1px solid var(--ark-line);
}
.ark-gallery-img-link { display: block; }
.ark-gallery-img { display: block; width: 100%; height: auto; max-width: 100%; }
/* A media-less deep-link card should not read as a broken image card: it gets a
   little more breathing room so title + caption + link fill it evenly. */
.ark-gallery-card--link { padding: var(--ark-space-4, 16px); }
.ark-gallery-card--link .ark-gallery-card-caption { margin-top: var(--ark-space-2, 8px); }

/* ── §20 ArkTriad — the Research Triad (hero action row) + compact footer form ─
   The Code & Data First layout. Data + Code = PRIMARY (accent fill,
   --ark-on-accent ink — text is NEVER accent-on-accent, the v1.2 contrast lesson);
   Outputs = SECONDARY (outline, fills on hover). Stacked full-width < 768px; one
   equal-width row ≥ 768px. AA in both themes; visible focus rings. Filled by
   ark-triad.js from the site's ecosystem `cdf` block. */
.ark-triad {
  display: grid;
  grid-template-columns: 1fr;                 /* mobile: stacked, full width */
  gap: var(--ark-space-3);
  margin: var(--ark-space-5) 0;
  width: 100%;
}
@media (min-width: 768px) {
  .ark-triad { grid-template-columns: repeat(3, minmax(0, 1fr)); }  /* one row, equal cols */
}
.ark-triad[hidden], .ark-triad-btn[hidden] { display: none; }

.ark-triad-btn {
  display: flex; align-items: center; gap: var(--ark-space-3);
  padding: var(--ark-space-4) var(--ark-space-5);
  border-radius: var(--ark-radius-sm);
  border: 1px solid var(--ark-accent);
  background: var(--ark-accent);
  color: var(--ark-on-accent) !important;
  text-decoration: none; cursor: pointer;
  transition: filter .12s ease, transform .12s ease, box-shadow .12s ease;
  min-height: 56px;
}
.ark-triad-btn:hover { filter: brightness(1.08); text-decoration: none; transform: translateY(var(--ark-lift-btn)); box-shadow: var(--ark-shadow); }
.ark-triad-btn:active { filter: brightness(.94); transform: none; }
.ark-triad-btn:focus-visible { outline: 3px solid var(--ark-accent); outline-offset: 2px; }

.ark-triad-icon { font-size: 1.25rem; line-height: 1; flex: none; }
.ark-triad-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ark-triad-label { font-weight: 600; font-size: var(--ark-text-md); line-height: 1.2; }
.ark-triad-sub {
  font-size: var(--ark-text-sm); line-height: 1.2;
  color: var(--ark-on-accent); opacity: .88;   /* AA-safe: the on-accent pair is AA by token contract */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ark-triad-sub:empty { display: none; }

/* Outputs = SECONDARY (outline). --ark-fg ink on transparent; fills accent on hover. */
.ark-triad-secondary {
  background: transparent;
  color: var(--ark-fg) !important;
  border-color: var(--ark-accent);
}
.ark-triad-secondary .ark-triad-icon,
.ark-triad-secondary .ark-triad-label { color: var(--ark-fg); }
.ark-triad-secondary .ark-triad-sub { color: var(--ark-fg-dim); opacity: 1; }
.ark-triad-secondary:hover { background: var(--ark-accent); color: var(--ark-on-accent) !important; filter: none; }
.ark-triad-secondary:hover .ark-triad-icon,
.ark-triad-secondary:hover .ark-triad-label,
.ark-triad-secondary:hover .ark-triad-sub { color: var(--ark-on-accent); opacity: 1; }

/* Compact form — the footer triad (smaller, tighter). */
.ark-triad-compact { gap: var(--ark-space-2); margin: 0; }
.ark-triad-compact .ark-triad-btn { padding: var(--ark-space-2) var(--ark-space-3); min-height: 0; }
.ark-triad-compact .ark-triad-icon { font-size: 1rem; }
.ark-triad-compact .ark-triad-label { font-size: var(--ark-text-sm); }
.ark-triad-compact .ark-triad-sub { font-size: .72rem; }

/* ── §21 ArkActionFooter — the footer v2 useful-buttons bar ────────────────────
   The Code & Data First layout. A compact triad + "Website source" + "Cite
   this site", ABOVE the existing dual-anchor colophon (which is preserved exactly
   — heterodata.org hub + nickanderson.us author). One footer per page. */
.ark-action-footer .ark-action-bar {
  max-width: var(--ark-maxw); margin: 0 auto;
  padding: var(--ark-space-5) 1.25rem var(--ark-space-4);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--ark-space-4) var(--ark-space-5);
  border-bottom: 1px solid var(--ark-line);
}
.ark-action-footer .ark-triad-compact { flex: 1 1 320px; max-width: 680px; }
.ark-action-tools { display: inline-flex; flex-wrap: wrap; gap: var(--ark-space-2); align-items: center; }
.ark-action-tools [hidden] { display: none; }
