/* ==========================================================================
   KeepersNook design system.
   White ground, teal primary, one amber signal accent.
   Literata display + Plus Jakarta Sans body + IBM Plex Mono micro-labels.
   Field-guide authority: flat cards, hairline rules, mono labels, calm bands.

   Anti-patterns this file must never drift back into (references/design-tokens.md):
     - cream or beige page grounds; the ground is white
     - drop shadows, pill cards, or hover-lift on cards; cards are flat with a
       hairline border and a top accent bar revealed on hover
     - ad-hoc rem spacing; every gap is a --sp-* step
     - recoloring the semantic care scale to a brand hue
     - the warm accent as a large fill behind running text; it is a signal only

   Ownership rules, inherited from the reference base and NOT to be re-decided here:
     - .shell is the ONLY container width owner. Nothing else sets a page max-width.
     - .card-grid is the variable-count owner. A lone card is capped, never balloons.
     - .article-col fills the shell; only prose lines take the reading measure.
     - Section rhythm, breakpoints (900px / 560px), and the spacing scale are fixed.
   Brand tokens come from docs/authority/kn-brand.json. Semantic colors (care level,
   safe/unsafe, compatible/incompatible) are separate from brand color on purpose.
   ========================================================================== */

:root {
    /* ---------------------------------------------------------------- COLOR
       Four roles: primary/dark, secondary, warm signal accent, neutrals. Plus a
       SEPARATE semantic care scale (green to red) that is never recolored to brand.
       Hues come from docs/authority/kn-brand.json; the role structure is fixed. */

    /* Primary / dark: buttons, active nav, dark section and footer bands */
    --primary: #2A7B6F;
    --primary-press: #1F5F55;
    --primary-deep: #14332E;   /* dark bands and footer, carries white text at AA */
    --primary-soft: #7FC9BB;   /* primary on dark grounds */
    --primary-dust: #E8F2F0;   /* faintest tint, icon tiles only */

    /* Secondary: supporting shade of the primary */
    --secondary: #4A8C74;

    /* Warm signal accent. A SIGNAL, never a large fill behind running text.
       --accent is the marker/kicker hue; --accent-deep is the AA-safe text variant,
       because #D08B3A on white is ~2.5:1 and fails for anything text-sized. */
    --accent: #D08B3A;
    --accent-deep: #A5661F;
    --accent-dust: #FAF1E3;

    /* Neutrals: WHITE ground, warm-neutral grays. Not cream. */
    --ink: #201E1B;
    --ink-2: #575651;
    --ink-3: #807C74;
    --paper: #FFFFFF;
    --paper-2: #F4F4F2;
    --surface: #FFFFFF;
    --surface-2: #F4F4F2;
    --band: #F4F4F2;
    --dark: var(--primary-deep);
    --line: #E6E6E3;
    --line-strong: #D2D2CE;

    /* Semantic care scale (green to red). Mirrors data/care-level.php.
       Separate family from brand: never recolor these to teal or amber. */
    --care-beginner: #3F8F4E;
    --care-intermediate: #B8862F;
    --care-advanced: #C2611F;
    --care-expert: #A32F2B;

    /* Verdict states, same semantic family */
    --ok: #3F8F4E;
    --ok-dust: #EAF3EB;
    --caution: #B8862F;
    --caution-dust: #FAF2E1;
    --danger: #A32F2B;
    --danger-dust: #F8EAE8;

    /* -------------------------------------------------------------- SPACING
       One 8px-based ladder. Every band pad, heading margin, and grid gap maps to a
       step. Never introduce an ad-hoc rem value. */
    --sp-1: .5rem;    /*  8px */
    --sp-2: .75rem;   /* 12px */
    --sp-3: 1rem;     /* 16px */
    --sp-4: 1.5rem;   /* 24px */
    --sp-5: 2rem;     /* 32px */
    --sp-6: 3rem;     /* 48px */
    --sp-7: 4rem;     /* 64px */
    --sp-8: 5rem;     /* 80px */
    --band-pad: var(--sp-7);

    /* ---------------------------------------------------------------- SHAPE
       One restrained elevation token, used ONLY for overlays that float above the
       page (the nav dropdown). Cards stay flat by rule. */
    /* Corner rounding is owned here. --card-radius and ~40 rules resolve back to these
       two, so the whole site rounds or squares from one edit. Keep it light: enough to
       read as intentional, not enough to turn editorial cards into pills. */
    --r: 10px;
    --r-sm: 6px;
    --shadow: 0 14px 34px -22px rgba(32,30,27,.5);
    /* ---------------------------------------------------------------- WIDTH
       Every width in the site resolves to one of these three. No template and no
       component may restate a literal width. */
    --nav-h: 72px;
    --maxw: 1200px;        /* THE shell width. Never hardcode 1200px elsewhere. */
    --content: 46rem;      /* THE readable article column. ~69ch at a 19px body. */
    --card-min: 250px;     /* THE card min width. Never restate 260/280 per grid. */
    --measure: 66ch;       /* standalone prose in hubs and profiles */
    --layout-gutter: clamp(16px, 3vw, 1.75rem);

    /* ------------------------------------------------------------ TYPOGRAPHY
       Three roles, one family each. Display carries the brand character, body is a
       humanist sans at 20px, mono gives the field-guide texture on micro-labels. */
    --font-display: 'Literata', Georgia, serif;
    --font-body: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
    --font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', monospace;

    --fs-2xs: .68rem;    /* ~11px  micro mono labels: stat keys, toc counters */
    --fs-xs: .8rem;      /* ~13px  mono labels, badges, nav, kickers */
    --fs-ui: .92rem;     /* ~15px  UI chrome: card copy, list items, meta */
    --fs-sm: 1.05rem;    /* ~17px  secondary text, captions */
    --fs-base: 1.1875rem; /* 19px  body */
    --fs-lg: 1.45rem;    /* ~23px  lead / intro / h3 */
    --fs-xl: 1.9rem;     /* ~30px  h2 */
    --fs-2xl: 2.5rem;    /* 40px */
    --fs-3xl: 3.35rem;   /* ~54px  h1 max */

    /* Icon glyph sizes. A separate ladder from the type scale on purpose: an icon is
       sized to its optical context, not to a text step. */
    --icon-sm: 1.15rem;
    --icon-md: 1.3rem;
    --icon-lg: 1.6rem;

    --lh-snug: 1.14;
    --lh-body: 1.6;
    --tracking-caps: .14em;

    /* Card semantic layer: every card resolves back to these, so borders, radius and
       padding never drift per component. These alias base tokens, never a new palette. */
    --card-surface: var(--surface);
    --card-surface-2: var(--surface-2);
    --card-border-color: var(--line);
    --card-border-hover: var(--primary);
    --card-radius: var(--r);
    --card-pad: 1.15rem;
    --card-gap: .5rem;
    --card-media-ratio: 16 / 10;
}

*, *::before, *::after { box-sizing: border-box; }

/* Base stays at the browser default so the rem ladder above resolves to real px:
   1rem = 16px, so --fs-base 1.1875rem = a 19px body. */
html { font-size: 100%; -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
    margin: 0;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    font-family: var(--font-body);
    font-size: var(--fs-base);
    line-height: var(--lh-body);
    color: var(--ink);
    background: var(--paper);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* Near-invisible paper grain: depth on white without tinting it beige. */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: .015;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

img { max-width: 100%; height: auto; display: block; }
a { color: var(--primary); text-decoration: none; }
a:hover { color: var(--primary-press); text-decoration: underline; text-underline-offset: 2px; }

h1, h2, h3, h4 {
    font-family: var(--font-display);
    font-weight: 700;
    line-height: var(--lh-snug);
    color: var(--ink);
    text-wrap: balance;
    margin: 0 0 .6rem;
}
h1 { font-size: clamp(2.1rem, 5.2vw, var(--fs-3xl)); line-height: 1.12; letter-spacing: -.015em; }
h2 { font-size: var(--fs-xl); letter-spacing: -.01em; }
h3 { font-size: var(--fs-lg); font-weight: 600; }
h4 { font-size: var(--fs-base); font-weight: 600; }
/* em-based so paragraph rhythm scales with its own font size */
p { margin: 0 0 1.15em; }

/* The single container width owner. Header, footer, hero, bands, and article all use
   this one class, which is what keeps their left edges aligned. */
.shell { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--layout-gutter); }

.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.skip-link { position: absolute; left: -999px; }
.skip-link:focus { left: 1rem; top: 1rem; z-index: 100; background: var(--ink); color: #fff; padding: .6rem 1rem; border-radius: var(--r-sm); }

a:focus-visible, button:focus-visible, summary:focus-visible, input:focus-visible, [tabindex]:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Emphasis system: bold for key terms, one highlight per article for the single
   decision-driving takeaway. Both are authored, never decorative. */
strong { font-weight: 600; color: inherit; }
mark { background: transparent; color: inherit; }
.highlight { background: linear-gradient(transparent 58%, rgba(208,139,58,.38) 58%); font-weight: 600; padding: 0 .05em; }

/* Section kicker: mono, uppercase, with a diamond marker. A leading horizontal rule
   here is the common editorial-template tell, so the marker is a glyph instead. */
.kicker {
    display: block;
    font-family: var(--font-mono);
    font-size: var(--fs-xs); font-weight: 700;
    letter-spacing: var(--tracking-caps); text-transform: uppercase;
    color: var(--accent-deep); margin: 0 0 var(--sp-2);
}
.kicker::before { content: "\25C6\00a0\00a0"; color: var(--accent); }
.kicker i { display: none; }
.kicker--onDark { color: var(--accent); }
.kicker--onDark::before { color: var(--accent); }

.ext-link::after { content: "\2197"; font-size: .8em; margin-left: .15em; color: var(--ink-3); }

/* ============================ Masthead ============================ */
.masthead { background: var(--surface); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 50; }

/* Reading progress, article pages only.
   Rides the masthead's bottom edge so it travels with the sticky header instead of
   floating as a second fixed bar. Scroll-driven in CSS where the browser supports it,
   which keeps it off the main thread; the small fallback in footer.php feeds the same
   --read property everywhere else. Both paths write one property, so there is one
   owner of the fill width. */
.read-progress { position: absolute; left: 0; right: 0; bottom: -1px; height: 3px; overflow: hidden; z-index: 1; }
.read-progress__fill {
    height: 100%;
    transform: scaleX(var(--read, 0));
    transform-origin: 0 50%;
    background: linear-gradient(90deg, var(--primary), var(--accent));
}
@supports (animation-timeline: scroll()) {
    .read-progress__fill { animation: read-progress linear both; animation-timeline: scroll(root block); }
}
@keyframes read-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.masthead-inner { display: flex; align-items: center; gap: 1.5rem; min-height: 72px; }

.brand { display: inline-flex; align-items: center; gap: .6rem; color: var(--ink); }
.brand:hover { text-decoration: none; color: var(--ink); }
.brand-mark { width: 40px; height: 40px; border-radius: 9px; flex: none; }
.brand-accent { color: var(--primary); }
.brand--footer .brand-accent { color: var(--primary-soft); }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-name { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-lg); letter-spacing: -.02em; }
.brand-tag { font-family: var(--font-mono); font-size: var(--fs-2xs); color: var(--ink-3); letter-spacing: .02em; }

.nav { display: flex; align-items: center; gap: var(--sp-3); margin-left: auto; }
.nav-list { display: flex; align-items: center; gap: 0; list-style: none; margin: 0; padding: 0; }
.nav-item { position: relative; }
.nav-link { display: inline-flex; align-items: center; gap: .3rem; white-space: nowrap; padding: var(--sp-1) var(--sp-2); border-radius: var(--r-sm); font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-2); cursor: pointer; }
.nav-link:hover { background: var(--surface-2); color: var(--primary); text-decoration: none; }

/* Above the reading progress bar. Both are positioned children of the masthead, so
   without an explicit order the later one in the DOM wins, and the bar drew its 3px
   line straight across the open dropdown. The dropdown hangs at top:100% and the bar
   sits at bottom:-1px, which is the same pixel row. */
.nav-sub {
    position: absolute; top: 100%; left: 0; min-width: 200px; z-index: 5;
    list-style: none; margin: 0; padding: .4rem;
    background: var(--surface); border: 1px solid var(--line); border-radius: var(--r);
    box-shadow: var(--shadow); opacity: 0; visibility: hidden; transform: translateY(4px);
    transition: opacity .14s ease, transform .14s ease, visibility .14s;
}
.nav-item.has-children:hover .nav-sub,
.nav-item.has-children:focus-within .nav-sub { opacity: 1; visibility: visible; transform: translateY(0); }
.nav-sub a { display: block; padding: .5rem .65rem; border-radius: var(--r-sm); font-size: var(--fs-ui); color: var(--ink-2); }
.nav-sub a:hover { background: var(--primary-dust); color: var(--primary-press); text-decoration: none; }

.nav-cta { white-space: nowrap; padding: var(--sp-2) var(--sp-4); border-radius: var(--r-sm); background: var(--primary); color: #fff; font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.nav-cta:hover { background: var(--primary-press); color: #fff; text-decoration: none; }

.nav-search { display: flex; align-items: center; gap: .3rem; background: var(--surface-2); border: 1px solid var(--line); border-radius: 999px; padding: .25rem .3rem .25rem .8rem; }
.nav-search input { border: 0; background: transparent; font: inherit; font-size: var(--fs-xs); font-family: var(--font-mono); width: 118px; color: var(--ink); }
.nav-search input:focus { outline: none; }
.nav-search button { border: 0; background: var(--primary); color: #fff; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; cursor: pointer; }

.nav-toggle, .nav-burger { display: none; }

/* ============================ Buttons ============================ */
.btn { display: inline-flex; align-items: center; gap: var(--sp-1); padding: var(--sp-2) var(--sp-4); border-radius: var(--r); font-weight: 700; font-size: var(--fs-ui); border: 1.5px solid transparent; cursor: pointer; }
.btn--primary { background: var(--primary); color: #fff; }
.btn { font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .06em; text-transform: uppercase; }
.btn--primary:hover { background: var(--primary-press); color: #fff; text-decoration: none; }
.btn--ghost { border-color: currentColor; color: inherit; background: transparent; }
.btn--ghost:hover { background: rgba(255,255,255,.1); text-decoration: none; }

.read-more { display: inline-flex; align-items: center; gap: .35rem; font-weight: 700; font-size: var(--fs-ui); }
.read-more:hover { gap: .55rem; text-decoration: none; }

/* ============================ Bands ============================ */
.band { padding: var(--band-pad) 0; }
.band--soft { background: var(--band); }
.band--dark { background: var(--dark); color: rgba(255,255,255,.82); }
.band--dark h2, .band--dark h3 { color: #fff; }
.band--author { background: var(--primary-dust); }

.section-title { font-size: var(--fs-2xl); margin: 0 0 .6rem; }
.section-title--onDark { color: #fff; }
.section-lede { max-width: 52ch; color: var(--ink-2); font-size: var(--fs-lg); margin: 0 0 2rem; }
.section-lede--onDark { color: rgba(255,255,255,.72); }
.section-more { margin: 1.8rem 0 0; }

.split { display: grid; grid-template-columns: 1.1fr .9fr; gap: 3rem; align-items: center; }
.split-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .85rem; }
.split-list li { font-size: var(--fs-ui); line-height: 1.5; }
.split-list i { color: var(--primary); font-size: var(--icon-sm); vertical-align: -.15em; margin-right: .5em; }
.band--dark .split-list i { color: var(--primary-soft); }

.source-badges { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.source-badges li { font-size: var(--fs-ui); line-height: 1.5; }
.source-badges i { color: var(--primary-soft); vertical-align: -.15em; margin-right: .5em; }

/* ============================ Homepage ============================ */
.band--muted { background: var(--paper-2); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }

/* Section head: title left, lead right. Gives every band a consistent entry point
   without repeating a centered stack ten times. */
.band-head { display: flex; justify-content: space-between; align-items: flex-end; gap: var(--sp-5); margin-bottom: var(--sp-5); flex-wrap: wrap; }
.band-head .section-title { margin: 0; }
.band-lead { max-width: 44ch; margin: 0; color: var(--ink-2); }
.band--dark .band-lead { color: rgba(255,255,255,.72); }

/* Split hero: headline column + art column. Collapses to text-only cleanly. */
.hero-band { padding: var(--sp-8) 0 var(--sp-7); border-bottom: 1px solid var(--line); }
.hero-grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: var(--sp-7); align-items: center; }
.hero-title { font-size: clamp(2.1rem, 5.2vw, var(--fs-3xl)); line-height: 1.08; margin: 0 0 var(--sp-3); }
.hero-lede { max-width: 52ch; font-size: var(--fs-lg); color: var(--ink-2); margin: 0 0 var(--sp-5); }
.hero-actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
/* Same rule as .hub-hero-art: one hero per page, so the frame takes the art's shape
   instead of forcing a ratio the art does not have. */
.hero-media img { display: block; width: 100%; height: auto; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r); }

/* Credential ribbon. Four equal tiles; a fixed count that matches its content. */
.cred-strip { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-5); }
.cred i { font-size: var(--icon-lg); color: var(--accent); display: block; margin-bottom: var(--sp-2); }
.cred h3 { font-size: var(--fs-sm); color: #fff; margin: 0 0 var(--sp-1); }
.cred p { margin: 0; font-size: var(--fs-ui); line-height: 1.5; color: rgba(255,255,255,.68); }

/* Coverage tiles. An equal-tile metric strip may use auto-fit: a stretched metric
   tile is acceptable, unlike a stretched content card. */
.stat-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); gap: var(--sp-3); }
.stat-tiles.cols-3 { grid-template-columns: repeat(3, 1fr); }
.stat-tiles.cols-2 { grid-template-columns: repeat(2, 1fr); }
.stat-tile { display: flex; flex-direction: column; gap: .15rem; padding: var(--sp-4); background: var(--surface); border: 1px solid var(--line-strong); border-top: 3px solid var(--accent); border-radius: var(--r); }
.stat-tile i { font-size: var(--icon-md); color: var(--primary); margin-bottom: var(--sp-1); }
.st-value { font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 700; line-height: 1; color: var(--ink); }
.st-label { font-family: var(--font-mono); font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); }

/* Closing section: author block + CTA block. */
.closing { display: grid; grid-template-columns: 1.3fr .7fr; gap: var(--sp-7); align-items: center; }
.closing-author { display: flex; gap: var(--sp-4); align-items: flex-start; }
.closing-cta { padding: var(--sp-5); border: 1px solid rgba(255,255,255,.18); border-radius: var(--r); }
.closing-cta h3 { color: #fff; margin: 0 0 var(--sp-2); font-size: var(--fs-lg); }
.closing-cta p { color: rgba(255,255,255,.68); font-size: var(--fs-ui); margin: 0 0 var(--sp-4); }
.read-more--onDark { color: var(--primary-soft); }

/* Outline button reads on both grounds; the old ghost variant only worked on dark. */
.btn--outline { border-color: currentColor; background: transparent; color: inherit; }
.btn--outline:hover { background: var(--primary); border-color: var(--primary); color: #fff; text-decoration: none; }
.band--dark .btn--outline { color: #fff; }

/* ============================ Page heroes ============================ */
.page-hero { padding: 2rem 0 2.5rem; background: var(--surface); border-bottom: 1px solid var(--line); }
.page-hero--article { background: linear-gradient(180deg, var(--primary-dust), var(--surface)); }
.page-hero--hub { background: linear-gradient(180deg, var(--primary-dust), var(--surface)); }
.page-title { margin: 0 0 .7rem; }
.page-standfirst { max-width: 62ch; font-size: var(--fs-lg); color: var(--ink-2); margin: 0; }
.hub-count { font-family: var(--font-mono); margin: 1.1rem 0 0; font-size: var(--fs-ui); color: var(--ink-3); }
.hub-count strong { color: var(--primary); font-size: var(--fs-sm); }

/* Hub hero: copy left, art right. Falls back to a single full-width column when the
   silo has no artwork, so the text hero stays correct rather than half-empty. */
.hub-hero-inner { display: grid; grid-template-columns: 1fr; gap: 2rem; align-items: center; }
.page-hero--art .hub-hero-inner { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); }
.hub-hero-copy { min-width: 0; }
/* No fixed ratio here. The silo art is ~1:1 (measured 0.936-1.172) while a 4/3 frame
   is 1.333, so `contain` left the art filling only 70-88% of the width with a grey
   --paper-2 band down each side against the art's own white ground. One hero per page
   means the frame can simply take the art's shape: fills edge to edge, nothing cropped,
   and it stays correct if a future silo ships art at a different ratio. */
.hub-hero-art { margin: 0; border-radius: var(--r); overflow: hidden; border: 1px solid var(--line); background: var(--surface); line-height: 0; }
.hub-hero-art img { display: block; width: 100%; height: auto; }

/* ===================== Silo hub: accent, context bands, type index =====================
   --silo-accent is a per-hub SUPPORT hue set inline from kn_silo_meta(), not a second
   brand colour. It falls back to brand teal so a silo shipped without one still renders.
   Brand teal keeps nav, buttons, links, and the footer; the accent only marks the hub's
   own furniture. Never use it as a large fill behind running text, and never reuse the
   care-level ramp here: that ramp means difficulty and must not read as a silo. */
.page-hero--hub, .hub-context, .hub-index, .hub-listing { --silo-accent: var(--primary); }
.page-hero--hub .kicker::before { color: var(--silo-accent); }
.page-hero--hub .hub-count strong { color: var(--silo-accent); }
.hub-context .section-title, .hub-index .section-title, .hub-listing .section-title { position: relative; }
.hub-context:not(.band--dark) .kicker::before,
.hub-index .kicker::before { color: var(--silo-accent); }

.hub-context-inner { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: var(--sp-6); align-items: start; }
.hub-context-copy { display: flex; flex-direction: column; gap: var(--sp-2); }
.hub-context-body { margin: 0; color: var(--ink-2); font-size: var(--fs-ui); line-height: 1.6; max-width: 46ch; }
.band--dark .hub-context-body { color: rgba(255,255,255,.82); }
.hub-context-copy .read-more { margin-top: var(--sp-2); align-self: flex-start; }
/* The context grid carries 3 cards beside the copy, so it stacks tighter than a full band. */
.hub-context-cards { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }

.type-index { list-style: none; margin: var(--sp-4) 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.type-chip { display: inline-flex; align-items: baseline; gap: .5rem; padding: .5rem .9rem; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-sm); color: var(--ink); font-size: var(--fs-sm); }
.type-chip:hover { border-color: var(--silo-accent); color: var(--ink); text-decoration: none; }
.type-chip.is-active { background: var(--silo-accent); border-color: var(--silo-accent); color: #fff; }
.type-chip-count { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; color: var(--silo-accent); }
.type-chip.is-active .type-chip-count { color: rgba(255,255,255,.85); }

.pagination { padding-top: var(--sp-5); }
.pagination-inner { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: var(--sp-3); }
.page-step { display: inline-flex; align-items: center; gap: .4rem; font-size: var(--fs-sm); color: var(--ink); }
.page-step:hover { color: var(--silo-accent); text-decoration: none; }
.page-step.is-disabled { color: var(--ink-3); opacity: .5; }
.page-numbers { list-style: none; display: flex; align-items: center; gap: .35rem; margin: 0; padding: 0; }
.page-number { display: grid; place-items: center; min-width: 38px; height: 38px; padding: 0 .5rem; border: 1px solid var(--line-strong); border-radius: var(--r-sm); font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink); }
.page-number:hover { border-color: var(--silo-accent); color: var(--silo-accent); text-decoration: none; }
.page-number.is-current { background: var(--silo-accent); border-color: var(--silo-accent); color: #fff; }
.page-gap { color: var(--ink-3); padding: 0 .25rem; }

.article-shell > .breadcrumb, .page-hero--article .breadcrumb { max-width: none; }
.breadcrumb { font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: .04em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 1.1rem; }
.breadcrumb ol { list-style: none; display: flex; flex-wrap: wrap; gap: .5rem; margin: 0; padding: 0; }
.breadcrumb li + li::before { content: "/"; margin-right: .5rem; color: var(--accent); }
.breadcrumb a { color: var(--ink-2); }

.byline { font-family: var(--font-mono); display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.2rem; margin-top: 1.3rem; font-size: var(--fs-xs); color: var(--ink-3); }
.byline-author { font-weight: 600; color: var(--ink-2); }

.review-note { display: flex; gap: .6rem; align-items: flex-start; margin: 1.4rem 0 0; padding: .8rem 1rem; background: var(--ok-dust); border-left: 3px solid var(--ok); border-radius: var(--r-sm); font-size: var(--fs-ui); color: var(--ink-2); }
.review-note i { color: var(--ok); font-size: var(--fs-base); flex: none; }

/* ============================ Cards ============================ */
/* Variable-count owner: tracks share the shell evenly while auto-fill preserves empty
   tracks on short rows, so an orphan card never balloons to full width. */
.card-grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fill, minmax(min(var(--card-min), 100%), 1fr)); }
.card-grid > .card:only-child { max-width: 380px; }

/* Fixed column counts. Use ONLY when the item count is an exact multiple of N
   (cols-3 for 3/6/9). A leftover orphan on the last row means the wrong tool was
   used: switch that grid back to the auto-fill default. */
.card-grid.cols-2, .silo-grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.card-grid.cols-3, .silo-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.card-grid.cols-4, .silo-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }

/* Flat card, hairline border, accent bar revealed on hover. No shadow and no lift:
   shadow + rounded pill + hover-lift is the generic-SaaS signature. */
.card { position: relative; display: flex; flex-direction: column; min-width: 0; background: var(--card-surface); border: 1px solid var(--line-strong); border-radius: var(--card-radius); overflow: hidden; transition: border-color .16s ease; }
.card::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--accent); transform: scaleX(0); transform-origin: left; transition: transform .18s ease; z-index: 2; }
.card:hover { border-color: var(--ink-3); }
.card:hover::before { transform: scaleX(1); }
.card-link { display: flex; flex-direction: column; height: 100%; color: inherit; }
.card-link:hover { text-decoration: none; color: inherit; }
.card-media { aspect-ratio: var(--card-media-ratio); background: var(--card-surface-2); display: grid; place-items: center; color: var(--primary-soft); font-size: var(--fs-2xl); overflow: hidden; }
.card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; }
.card:hover .card-media img { transform: scale(1.04); }
.card-body { display: flex; flex: 1; flex-direction: column; gap: var(--card-gap); padding: var(--card-pad); }
.card-kicker { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--accent-deep); }
/* A card brings its own surface, so it owns its own text colour. Band-level rules such
   as `.band--dark h3` are written for text sitting ON the dark ground and must never
   reach inside a component that carries a background: on the dark context band that
   descendant selector set every card title to #fff against a white card, 1.00:1, so the
   titles simply vanished. Specificity here (0,2,0) beats `.band--dark h3` (0,1,1). */
.card .card-title { font-size: var(--fs-sm); margin: 0; color: var(--ink); transition: color .15s ease; }
.card:hover .card-title { color: var(--primary); }
/* .card-excerpt removed with the markup that used it. Cards now carry media, type,
   title, and care level only, so the grid scans on titles rather than on truncated
   sentences. Leaving the rule behind would be a style with no element. */

/* ============================ Silo grid ============================ */
.silo-grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(auto-fill, minmax(min(var(--card-min), 100%), 1fr)); }
.silo-grid > .silo-card:only-child { max-width: 360px; }
.silo-card { position: relative; display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r); color: var(--ink); overflow: hidden; transition: border-color .16s ease; }
.silo-card::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--accent); transform: scaleX(0); transform-origin: left; transition: transform .18s ease; z-index: 2; }
.silo-card:hover { border-color: var(--ink-3); text-decoration: none; color: var(--ink); }
.silo-card:hover::before { transform: scaleX(1); }
/* Silo art is illustration, not photography: the subject fills the frame edge to edge,
   so cover crops the animal itself. The source files are ~1:1 (0.94-1.17) on a pure
   #FFFFFF ground, so 16/9 + cover was cutting 40%+ of every card. Contain on a white
   media box shows the whole illustration with no visible letterbox. Any replacement art
   must keep the white ground.
   Unlike the single heroes, a grid needs one fixed ratio so cards stay level, so this
   frame takes the art's own ~1:1 shape rather than 4/3: at 4/3 the art filled only
   70-88% of the width, at 1/1 it fills 93-100%. */
.silo-media { display: block; aspect-ratio: 1 / 1; background: var(--surface); overflow: hidden; }
.silo-media img { width: 100%; height: 100%; object-fit: contain; transition: transform .4s ease; }
.silo-card:hover .silo-media img { transform: scale(1.04); }
.silo-body { display: flex; flex: 1; flex-direction: column; gap: .45rem; padding: 1.25rem 1.4rem 1.4rem; }
/* Icon-only cards carry their own padding since they have no media block above. */
.silo-card:not(.silo-card--art) .silo-body { padding-top: 0; }
.silo-icon { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 12px; background: var(--primary-dust); color: var(--primary); font-size: var(--fs-xl); margin: 1.4rem 1.4rem .35rem; }
.silo-name { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-base); }
.silo-card:hover .silo-name { color: var(--primary); }
.silo-blurb { font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.5; }
.silo-count { font-family: var(--font-mono); margin-top: auto; padding-top: .5rem; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--accent-deep); }

/* ============================ Care ladder ============================ */
.care-ladder { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 1.2rem; }
/* The ladder renders on two grounds: band--muted on the homepage and band--dark on
   /start/. The base is therefore light-ground and the dark ground is an override, the
   same shape as .band--dark .band-lead below. Hardcoding white text here made the
   homepage copy invisible on --paper-2. */
.care-step { padding: 1.4rem; border-radius: var(--r); background: var(--surface); border: 1px solid var(--line-strong); border-top: 3px solid var(--care-color); }
.care-step-icon { display: inline-grid; place-items: center; width: 38px; height: 38px; border-radius: 10px; background: var(--care-color); color: #fff; font-size: var(--fs-base); margin-bottom: .7rem; }
.care-step-name { font-size: var(--fs-base); margin: 0 0 .4rem; }
.care-step-summary { font-size: var(--fs-sm); margin: 0 0 .6rem; color: var(--ink); }
.care-step-commit { font-size: var(--fs-xs); margin: 0; color: var(--ink-2); }

.band--dark .care-step { background: rgba(255,255,255,.05); border-color: rgba(255,255,255,.12); border-top-color: var(--care-color); }
.band--dark .care-step-summary { color: rgba(255,255,255,.82); }
.band--dark .care-step-commit { color: rgba(255,255,255,.7); }

/* Fill uses the ramp hue; the label uses its AA-safe variant. Setting both from
   --care-color put three of the four rungs at 2.8-3.5:1 against their own tint.
   --care-text is emitted by kn_care_badge() and falls back to the ramp hue. */
.care-badge { font-family: var(--font-mono); display: inline-flex; align-items: center; gap: .35rem; padding: .2rem .6rem; border-radius: var(--r-sm); background: color-mix(in srgb, var(--care-color) 14%, transparent); color: var(--care-text, var(--care-color)); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; align-self: flex-start; }

/* ============================ Article ============================ */
.article { padding: var(--sp-6) 0 var(--sp-7); }
.article-shell { display: grid; grid-template-columns: minmax(0, 1fr) 280px; gap: var(--sp-6); align-items: start; }
.article-shell > .article-col:only-child { grid-column: 1 / -1; }

/* THE readable-column owner. The column owns the width and every child fills it.
   Capping children individually is the width-disparity bug: any block not on the
   list (a hero image, a new block type) escapes and renders wider than the prose
   beside it. One owner, no exceptions. */
.article-col { width: 100%; min-width: 0; max-width: var(--content); margin-inline: auto; }
/* In the docs-style layout (main column + TOC sidebar) the column is left-aligned in
   its track so its left edge matches the breadcrumb and the page hero above it.
   Centering it here would inset the prose ~40px past the breadcrumb, which is the
   width disparity this rule exists to prevent. A column with no sidebar stays
   centred, per the single-column rule. */
.article-shell > .article-col { margin-inline: 0; }
.article-shell > .article-col:only-child { margin-inline: auto; }
.article-col > * { max-width: none; }
.article-col > h2 { margin: var(--sp-6) 0 var(--sp-3); padding-bottom: .5rem; border-bottom: 1px solid var(--line); scroll-margin-top: calc(var(--nav-h) + var(--sp-3)); }
.article-col > h3 { margin: var(--sp-5) 0 var(--sp-2); scroll-margin-top: calc(var(--nav-h) + var(--sp-3)); }
.article-col > p { margin-bottom: 1.15em; }

.article-hero { margin: 0 0 1.8rem; border-radius: var(--r); overflow: hidden; border: 1px solid var(--line); }
/* The frame takes the art's shape, it does not impose one. Forcing 16/9 here cropped
   about 16% of the height off every article hero, because the artwork is 3:2. Same
   decision already made for silo art: art that is made to fit a frame it was not shot
   for loses the part of the subject the photo was chosen for. */
.article-hero img { width: 100%; height: auto; }

/* Spec strip: the label/value facts that used to run together in one paragraph.
   Columns come from the item count, not from auto-fit. auto-fit packed four specs into
   three columns at mid widths and left a dead grey cell on the second row, which reads
   as a broken table rather than a deliberate one. Every rule below divides evenly. */
.spec-strip {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1px;
    margin: var(--sp-4) 0;
    background: var(--line);
    border: 1px solid var(--line);
    border-radius: var(--r);
    overflow: hidden;
}
.spec-strip[data-specs="3"] { grid-template-columns: repeat(3, 1fr); }
.spec-strip[data-specs="4"] { grid-template-columns: repeat(2, 1fr); }
.spec-strip[data-specs="5"],
.spec-strip[data-specs="6"] { grid-template-columns: repeat(3, 1fr); }

/* Wide enough for one clean row: 4 across, 5 across. Still never 3 + 1. */
@media (min-width: 1180px) {
    .spec-strip[data-specs="4"] { grid-template-columns: repeat(4, 1fr); }
    .spec-strip[data-specs="5"] { grid-template-columns: repeat(5, 1fr); }
}
/* One column on narrow screens, where two would squeeze "Mediterranean (Italy)". */
@media (max-width: 520px) {
    .spec-strip, .spec-strip[data-specs] { grid-template-columns: 1fr; }
}
/* An odd count in an even grid would leave a hole, so the last cell takes the space. */
.spec-strip[data-specs="5"] > :last-child { grid-column: auto; }
@media (min-width: 521px) and (max-width: 1179px) {
    .spec-strip[data-specs="5"] > :last-child { grid-column: span 2; }
}

.spec-strip__item { background: var(--surface); padding: .7rem .9rem; }
.spec-strip dt {
    display: flex;
    align-items: center;
    gap: .38em;
    font-family: var(--font-mono);
    font-size: var(--fs-2xs);
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-3);
    margin-bottom: .2rem;
}
.spec-strip dt i { font-size: 1.15em; color: var(--primary); flex: none; }
.spec-strip dd { margin: 0; font-size: var(--fs-ui); font-weight: 600; color: var(--ink); line-height: 1.35; }

.prose-list { list-style: none; padding-left: 0; margin: 0 0 var(--sp-4); }
.prose-list li { position: relative; padding-left: 1.4rem; margin-bottom: .55rem; color: var(--ink-2); }
.prose-list li::before { content: ""; position: absolute; left: 0; top: .68em; width: 8px; height: 2px; background: var(--accent); }
.prose-list li strong { color: var(--ink); }

/* Sidebar: a stack of bordered cards, sticky as a unit. A bare bordered-left list
   reads as unstyled leftover space; a card gives the column a reason to exist. */
.article-sidebar { position: relative; min-width: 0; }
.sidebar-stack { position: sticky; top: calc(var(--nav-h) + var(--sp-3)); display: grid; gap: var(--sp-4); }

.sidebar-card { border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); overflow: hidden; }
.sidebar-card__title { margin: 0; padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--line); background: var(--paper-2); font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2); }

.toc-list { list-style: none; margin: 0; padding: var(--sp-1); display: grid; counter-reset: toc; max-height: calc(100vh - 18rem); overflow-y: auto; }
.toc-list li { margin: 0; counter-increment: toc; }
/* Icon instead of a counter. The labels are topic names now, so a reader scans for the
   one they want rather than counting to it, and the glyph is the faster target. */
.toc-list a { display: flex; align-items: center; gap: .5rem; padding: .45rem .65rem; font-size: var(--fs-ui); font-weight: 600; line-height: 1.35; color: var(--ink-2); border-left: 2px solid transparent; }
.toc-list a i { font-size: var(--icon-sm); color: var(--ink-3); flex: none; }
.toc-list a:hover i { color: var(--primary); }
.toc-list a:hover { color: var(--primary); background: var(--paper-2); border-left-color: var(--primary); text-decoration: none; }
.toc-list a:hover::before { color: var(--primary); }

.sidebar-stats { margin: 0; padding: var(--sp-1) var(--sp-3); }
.sidebar-stats > div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2); padding: .6rem 0; border-bottom: 1px dashed var(--line); }
.sidebar-stats > div:last-child { border-bottom: 0; }
.sidebar-stats dt { font-family: var(--font-mono); font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
.sidebar-stats dd { margin: 0; max-width: 62%; text-align: right; font-size: var(--fs-xs); font-weight: 600; }

.sidebar-back-link { display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-1); padding: .7rem var(--sp-3); border: 1px solid var(--line-strong); border-radius: var(--r); background: var(--surface); font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-2); }
.sidebar-back-link:hover { border-color: var(--primary); color: var(--primary); text-decoration: none; }

/* ============================ Block library ============================ */
/* Every block below is emitted by src/Template.php. Design-system classes only:
   no inline styles reach these elements, so appearance has exactly one owner. */

/* Callouts: tip, note, warning, verdict */
.callout { margin: var(--sp-6) 0; padding: 1.1rem 1.3rem; border-radius: var(--r); border-left: 4px solid var(--primary); background: var(--primary-dust); }
.callout-label { font-family: var(--font-mono); display: flex; align-items: center; gap: .5rem; margin: 0 0 .5rem; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--primary-press); }
.callout-label i { font-size: var(--fs-base); }
.callout-body > *:last-child { margin-bottom: 0; }
.callout-body p { font-size: var(--fs-ui); color: var(--ink-2); }
.callout-tip { border-left-color: var(--primary); background: var(--primary-dust); }
.callout-note { border-left-color: var(--ink-3); background: var(--surface-2); }
.callout-note .callout-label { color: var(--ink-2); }
.callout-warning { border-left-color: var(--danger); background: var(--danger-dust); }
.callout-warning .callout-label { color: var(--danger); }
.callout-verdict { border-left-color: var(--accent); background: var(--accent-dust); }
.callout-verdict .callout-label { color: var(--accent-press); }

/* At-a-glance summary */
.tldr { margin: 0 0 2rem; padding: 1.3rem 1.5rem; border-radius: var(--r); background: var(--dark); color: rgba(255,255,255,.85); }
.tldr-label { font-family: var(--font-mono); margin: 0 0 .6rem; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: var(--tracking-caps); color: var(--primary-soft); }
.tldr p { margin: 0 0 .6rem; font-size: var(--fs-sm); }
.tldr p:last-child { margin-bottom: 0; }
.tldr ul { margin: 0; padding-left: 1.2rem; }
.tldr li { margin-bottom: .4rem; }
.tldr strong { color: #fff; }
.tldr .highlight { background: linear-gradient(transparent 58%, rgba(208,139,58,.5) 58%); color: #fff; }

/* Key facts */
.kv-list { margin: var(--sp-6) 0; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--surface); }
.kv-label { font-family: var(--font-mono); margin: 0; padding: .7rem 1.1rem; background: var(--surface-2); border-bottom: 1px solid var(--line); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2); }
/* Separators are the container's background showing through a 1px gap, not borders on
   the cells. Borders cannot do this correctly here: the grid uses auto-fit, so which
   cell ends a visual row changes with the viewport. `border-right` left a rule dangling
   down the last column, and `+ .kv-row` would put one on the first cell of every wrapped
   row instead, because a sibling selector follows source order and not visual position.
   The gap technique closes the grid at any column count. */
.kv-list dl { margin: 0; display: grid; grid-template-columns: repeat(var(--kv-tracks, 2), minmax(0, 1fr)); gap: 1px; background: var(--line); }
.kv-row { display: flex; flex-direction: column; gap: .2rem; padding: .85rem 1.1rem; background: var(--surface); }
/* A prime count leaves one item over. It spans the row so the strip closes flush. */
.kv-row--full { grid-column: 1 / -1; }
.kv-row dt { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-2); }
.kv-row dd { margin: 0; font-weight: 600; color: var(--ink); }

/* ============================ Author portrait ============================
   The photo keeps its own 4:5 shape rather than being cropped to a frame, the same rule
   the silo heroes now follow. A portrait cropped to a square loses the shoulders and
   reads as a stock avatar, which defeats the point of using a real face. */
.page-hero--author .author-hero-inner { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, .6fr); gap: var(--sp-6); align-items: center; }
.author-portrait { margin: 0; border-radius: var(--r); overflow: hidden; border: 1px solid var(--line); background: var(--surface); line-height: 0; }
.author-portrait img { display: block; width: 100%; height: auto; }

.founder-card { display: flex; gap: var(--sp-4); align-items: center; margin: var(--sp-6) 0; padding: var(--sp-4); background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r); }
.founder-card-photo { flex: none; width: 88px; height: 88px; border-radius: 50%; object-fit: cover; }
.founder-card-name { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: var(--fs-lg); color: var(--ink); }
.founder-card-role { margin: .1rem 0 .4rem; font-family: var(--font-mono); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-2); }
.founder-card-note { margin: 0; font-size: var(--fs-sm); line-height: 1.55; color: var(--ink-2); }

/* ============================ Contact box ============================
   One reachable route to a named person. Sits inside the reading column, so it uses a
   tinted ground rather than a heavy card: it is a destination, not a card in a grid. */
.contact-box { margin: var(--sp-6) 0; padding: var(--sp-5); background: var(--primary-dust); border: 1px solid var(--line); border-radius: var(--r); }
.contact-box-head { display: flex; gap: var(--sp-3); align-items: flex-start; }
.contact-box-head > i { flex: none; font-size: var(--icon-lg); color: var(--primary); line-height: 1; margin-top: .1rem; }
.contact-box-title { margin: 0 0 .25rem; font-family: var(--font-display); font-weight: 700; font-size: var(--fs-lg); color: var(--ink); }
.contact-box-lead { margin: 0; color: var(--ink-2); font-size: var(--fs-ui); line-height: 1.55; }
.contact-box-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); margin: var(--sp-4) 0; }
.contact-box-facts div { display: flex; flex-direction: column; gap: .15rem; }
.contact-box-facts dt { display: flex; align-items: center; gap: .35rem; font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-2); }
.contact-box-facts dd { margin: 0; font-weight: 600; color: var(--ink); }
.contact-box-cta { display: inline-flex; align-items: center; gap: .5rem; }
.contact-box-note { display: flex; gap: .5rem; margin: var(--sp-4) 0 0; padding-top: var(--sp-3); border-top: 1px solid var(--line); font-size: var(--fs-sm); line-height: 1.55; color: var(--ink-2); }
.contact-box-note i { flex: none; color: var(--danger); font-size: var(--icon-md); line-height: 1.3; }
/* In an article footer the box is support, not the point of the page. */
.contact-box--compact { padding: var(--sp-4); }
.contact-box--compact .contact-box-facts, .contact-box--compact .contact-box-note { display: none; }

/* Content-type icon on a card kicker. Registry-driven, see kn_content_type_icon(). */
.card-kicker { display: inline-flex; align-items: center; gap: .4rem; }
.card-kicker i { font-size: 1em; line-height: 1; }

/* Data table */
/* Editorial table, not a data dump. The previous version stacked a solid teal header
   bar, zebra striping, and a full border box, which is the default-framework look and
   fights the prose it sits inside. Structure now comes from rules and rhythm: a strong
   rule under the header, hairlines between rows, and no fill. The caption also moved off
   --ink-3 (4.16:1 on white, below AA) onto --ink-2 at 7.36:1. */
.data-table-wrap { margin: var(--sp-6) 0; overflow-x: auto; }
.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-ui); text-align: left; }
.data-table caption { font-family: var(--font-mono); padding: 0 0 .6rem; text-align: left; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2); }
/* Headers wrap. `white-space: nowrap` forced a horizontal scrollbar on narrow screens
   for a three-column table that had room to breathe. */
/* Column headers only. A `th scope="row"` inside tbody is a row label, not a column
   header, and must not inherit the uppercase mono treatment or the 2px rule. */
.data-table thead th { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-2); padding: 0 1.1rem .6rem 0; border-bottom: 2px solid var(--ink); vertical-align: bottom; }
.data-table td, .data-table tbody th { padding: .85rem 1.1rem .85rem 0; border-bottom: 1px solid var(--line); vertical-align: top; line-height: 1.55; }
.data-table th:last-child, .data-table td:last-child { padding-right: 0; }
/* The first column is the row's subject, so it carries the weight the header fill used
   to provide. This is what makes the table scannable without a coloured band. */
.data-table tbody td:first-child, .data-table tbody th { font-weight: 600; color: var(--ink); text-align: left; }
.data-table tbody tr:last-child td, .data-table tbody tr:last-child th { border-bottom: 0; }

/* Pros and cons */
.proscons { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: var(--sp-6) 0; }
.pc-pros, .pc-cons { padding: 1.1rem 1.3rem; border-radius: var(--r); border: 1px solid var(--line); }
.pc-pros { background: var(--ok-dust); border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.pc-cons { background: var(--danger-dust); border-color: color-mix(in srgb, var(--danger) 26%, transparent); }
.proscons h3 { display: flex; align-items: center; gap: .45rem; margin: 0 0 .7rem; font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: .08em; }
.pc-pros h3 { color: var(--ok); }
.pc-cons h3 { color: var(--danger); }
.proscons ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.proscons li { font-size: var(--fs-ui); color: var(--ink-2); padding-left: 1.1rem; position: relative; }
.pc-pros li::before { content: "\2713"; position: absolute; left: 0; color: var(--ok); font-weight: 700; }
.pc-cons li::before { content: "\2715"; position: absolute; left: 0; color: var(--danger); font-weight: 700; }

/* Ordered steps */
.steps { margin: var(--sp-6) 0; }
.steps-label { font-family: var(--font-mono); margin: 0 0 .8rem; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-3); }
.step-list { list-style: none; counter-reset: step; margin: 0; padding: 0; display: grid; gap: .9rem; }
.step-item { counter-increment: step; position: relative; padding: 1rem 1.2rem 1rem 3.4rem; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); }
.step-item::before { content: counter(step); position: absolute; left: 1.1rem; top: 1rem; width: 26px; height: 26px; border-radius: 50%; background: var(--primary); color: #fff; display: grid; place-items: center; font-size: var(--fs-xs); font-weight: 700; }
.step-title { display: block; font-weight: 700; margin-bottom: .2rem; }
.step-detail { display: block; font-size: var(--fs-ui); color: var(--ink-2); }

/* Sources */
.sources { margin: 2.5rem 0 0; padding: 1.5rem; background: var(--surface-2); border-radius: var(--r); border: 1px solid var(--line); }
.sources-label { font-family: var(--font-mono); display: flex; align-items: center; gap: .5rem; margin: 0 0 1rem; font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2); font-family: var(--font-body); border: 0; padding: 0; }
.source-list { margin: 0; padding-left: 1.3rem; display: grid; gap: .7rem; }
.source-item { font-size: var(--fs-ui); color: var(--ink-2); }
.source-pub { display: block; font-size: var(--fs-xs); color: var(--ink-3); }

/* Feeding safety */
.feedsafe { margin: var(--sp-6) 0; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--surface); }
.feedsafe-label { font-family: var(--font-mono); margin: 0; padding: .8rem 1.1rem; background: var(--surface-2); border-bottom: 1px solid var(--line); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2); }
.feed-list { list-style: none; margin: 0; padding: 0; }
.feed-row { display: grid; grid-template-columns: minmax(0, 1.2fr) auto minmax(0, 1.4fr); gap: .8rem; align-items: baseline; padding: .75rem 1.1rem; border-bottom: 1px solid var(--line); border-left: 3px solid transparent; }
.feed-row:last-child { border-bottom: 0; }
.feed-item { font-weight: 600; }
.feed-verdict { font-family: var(--font-mono); display: inline-flex; align-items: center; gap: .3rem; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; white-space: nowrap; }
.feed-note { font-size: var(--fs-ui); color: var(--ink-3); }
.feed-row--safe { border-left-color: var(--ok); }
.feed-row--safe .feed-verdict { color: var(--ok); }
.feed-row--moderation { border-left-color: var(--caution); background: var(--caution-dust); }
.feed-row--moderation .feed-verdict { color: var(--caution); }
.feed-row--unsafe { border-left-color: var(--danger); background: var(--danger-dust); }
.feed-row--unsafe .feed-verdict { color: var(--danger); }

/* Compatibility */
.compat { margin: var(--sp-6) 0; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; background: var(--surface); }
.compat-label { font-family: var(--font-mono); margin: 0; padding: .8rem 1.1rem; background: var(--surface-2); border-bottom: 1px solid var(--line); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2); }
.compat-list { list-style: none; margin: 0; padding: 0; }
.compat-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: .5rem 1rem; padding: .9rem 1.1rem; border-bottom: 1px solid var(--line); border-left: 3px solid transparent; }
.compat-row:last-child { border-bottom: 0; }
.compat-subject { font-weight: 700; }
.compat-verdict { font-family: var(--font-mono); display: inline-flex; align-items: center; gap: .3rem; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; white-space: nowrap; }
.compat-note { grid-column: 1 / -1; font-size: var(--fs-ui); color: var(--ink-2); }
.compat-row--compatible { border-left-color: var(--ok); }
.compat-row--compatible .compat-verdict { color: var(--ok); }
.compat-row--risky { border-left-color: var(--caution); background: var(--caution-dust); }
.compat-row--risky .compat-verdict { color: var(--caution); }
.compat-row--incompatible { border-left-color: var(--danger); background: var(--danger-dust); }
.compat-row--incompatible .compat-verdict { color: var(--danger); }

/* Toggle and FAQ, both native details/summary so they work without JavaScript */
.toggle, .faq-item { margin: 1rem 0; border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); overflow: hidden; }
.toggle-summary, .faq-q { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .9rem 1.1rem; font-weight: 600; cursor: pointer; list-style: none; }
.toggle-summary::-webkit-details-marker, .faq-q::-webkit-details-marker { display: none; }
.toggle-summary::after, .faq-q::after { content: "+"; font-size: var(--fs-lg); color: var(--primary); flex: none; line-height: 1; }
details[open] > .toggle-summary::after, details[open] > .faq-q::after { content: "\2212"; }
.toggle-summary:hover, .faq-q:hover { background: var(--surface-2); }
.toggle-body, .faq-a { padding: 0 1.1rem 1rem; }
.toggle-body > *:last-child, .faq-a > *:last-child { margin-bottom: 0; }
.toggle-body p, .faq-a p { font-size: var(--fs-ui); color: var(--ink-2); }

.faq { margin: 2.5rem 0 0; }
.faq-label { font-family: var(--font-display); margin: 0 0 1rem; }

/* Checklist */
.checklist { margin: var(--sp-6) 0; padding: 1.2rem 1.4rem; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); }
.checklist-label { font-family: var(--font-mono); margin: 0 0 .8rem; font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-3); }
.check-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .6rem; }
.check-item { display: flex; gap: .6rem; align-items: flex-start; font-size: var(--fs-ui); color: var(--ink-2); }
.check-item i { color: var(--primary); font-size: var(--fs-base); flex: none; margin-top: .05rem; }

/* Pull quote, in-content image, inline CTA */
.pullquote { margin: 2rem 0; padding: 0 0 0 1.4rem; border-left: 4px solid var(--accent); }
.pullquote blockquote { margin: 0; font-family: var(--font-display); font-size: var(--fs-base); line-height: 1.45; color: var(--ink); }
.pullquote figcaption { margin-top: .6rem; font-size: var(--fs-sm); color: var(--ink-3); }

.article-image { margin: var(--sp-6) 0; border-radius: var(--r); overflow: hidden; border: 1px solid var(--line); }
.article-image figcaption { font-family: var(--font-mono); padding: .7rem 1rem; background: var(--surface-2); border-top: 1px solid var(--line); font-size: var(--fs-sm); color: var(--ink-3); }

.cta-inline { margin: var(--sp-6) 0; }
.cta-inline-btn { display: inline-flex; align-items: center; gap: var(--sp-1); padding: var(--sp-2) var(--sp-4); border-radius: var(--r); background: var(--primary); color: #fff; font-weight: 700; font-size: var(--fs-ui); }
.cta-inline-btn:hover { background: var(--primary-press); color: #fff; text-decoration: none; }

/* ============================ Pagination ============================ */
/* Pagination now lives with the silo-hub block above, where it sits inside the listing
   band rather than as a detached bar under the page. The old .page-prev/.page-next/
   .page-status rules were removed with the markup that used them; leaving them here
   would be a second, silently diverging definition of the same control. */

/* ============================ Search, sitemap, author ============================ */
.search-form { display: flex; gap: .6rem; margin-top: 1.3rem; max-width: 34rem; }
.search-form input { flex: 1; padding: .7rem 1rem; border: 1px solid var(--line-strong); border-radius: 999px; font: inherit; font-size: var(--fs-ui); background: var(--surface); color: var(--ink); }

.sitemap-group { margin-bottom: 2.8rem; }
.sitemap-count { font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700; color: var(--accent-deep); vertical-align: middle; }
.sitemap-list { list-style: none; margin: 0; padding: 0; columns: 3; column-gap: 2rem; }
.sitemap-list li { break-inside: avoid; margin-bottom: .45rem; font-size: var(--fs-ui); }

.author-strip { display: flex; gap: 1.5rem; align-items: flex-start; }
.author-avatar { display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%; background: var(--primary); color: #fff; font-size: var(--fs-xl); flex: none; }
.author-name { margin: 0 0 .2rem; font-size: var(--fs-lg); }
.author-role { margin: 0 0 .6rem; font-size: var(--fs-ui); color: var(--primary-press); font-weight: 600; }
.author-line { margin: 0 0 .8rem; color: var(--ink-2); max-width: 58ch; }

/* ============================ Footer ============================ */
#main { flex: 1 0 auto; }
.site-footer { flex-shrink: 0; background: var(--dark); color: rgba(255,255,255,.72); margin-top: auto; }
/* Track count comes from the inline --footer-tracks the template derives from the
   nav registry, so tracks and children can never desync. */
.footer-inner { display: grid; grid-template-columns: var(--footer-tracks, 1.5fr repeat(3, 1fr)); gap: var(--sp-6) var(--sp-5); padding-block: var(--sp-7) var(--sp-5); }
.brand--footer { color: #fff; margin-bottom: 1rem; }
.brand--footer:hover { color: #fff; }
.brand--footer .brand-name { color: #fff; }
.footer-blurb { font-size: var(--fs-ui); line-height: 1.6; color: rgba(255,255,255,.6); max-width: 42ch; }
.footer-author { font-size: var(--fs-xs); color: rgba(255,255,255,.6); }
.footer-author a { color: var(--primary-soft); }
.footer-head { font-family: var(--font-body); font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase; letter-spacing: var(--tracking-caps); color: #fff; margin: 0 0 .9rem; }
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.footer-col a { color: rgba(255,255,255,.72); font-size: var(--fs-ui); }
.footer-col a:hover { color: #fff; }

.footer-legal { border-top: 1px solid rgba(255,255,255,.12); }
.footer-legal-inner { display: flex; flex-wrap: wrap; gap: .5rem 2rem; justify-content: space-between; padding-block: 1.3rem; }
.footer-legal p { margin: 0; font-size: var(--fs-xs); color: rgba(255,255,255,.5); }
.footer-disclaimer { max-width: 58ch; }

/* ============================ Responsive ============================ */




/* ============================ Responsive ============================
   Four breakpoints, no others. A component that only works at an off-ladder width
   has a content problem, not a breakpoint problem. */

/* 1140: the dense mono nav stops fitting the shell and collapses to a menu button. */
@media (max-width: 1140px) {
    .nav-burger { display: grid; place-items: center; width: 42px; height: 42px; margin-left: auto; border-radius: var(--r-sm); font-size: var(--icon-lg); cursor: pointer; color: var(--ink); }
    .nav { position: fixed; inset: var(--nav-h) 0 auto; flex-direction: column; align-items: stretch; gap: var(--sp-2); padding: var(--sp-4) var(--layout-gutter) var(--sp-5); background: var(--surface); border-bottom: 1px solid var(--line); box-shadow: var(--shadow); display: none; overflow-y: auto; max-height: calc(100vh - var(--nav-h)); }
    .nav-toggle:checked ~ .nav { display: flex; }
    .nav-list { flex-direction: column; align-items: stretch; gap: .15rem; }
    .nav-sub { position: static; opacity: 1; visibility: visible; transform: none; box-shadow: none; border: 0; padding: 0 0 var(--sp-1) var(--sp-4); }
    .nav-search, .nav-search input { width: 100%; }
    .nav-cta { text-align: center; justify-content: center; }
}

/* 900: fixed column grids step to 2; wide split layouts stack. */
@media (max-width: 900px) {
    .card-grid.cols-3, .card-grid.cols-4, .silo-grid.cols-3, .silo-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
    .split { grid-template-columns: 1fr; gap: var(--sp-5); }
    .hero-grid { grid-template-columns: 1fr; gap: var(--sp-5); }
    .hero-media { order: -1; }
    /* No ratio override on mobile either: forcing 16/9 squeezed the 4:3 hero art into
       75% of the width and put a band down both sides on the narrowest screens. */
    .hub-context-inner { grid-template-columns: 1fr; gap: var(--sp-4); }
    .page-hero--author .author-hero-inner { grid-template-columns: 1fr; }
    .author-portrait { max-width: 280px; }
    .founder-card { flex-direction: column; align-items: flex-start; text-align: left; }
    .cred-strip { grid-template-columns: repeat(2, 1fr); }
    .closing { grid-template-columns: 1fr; gap: var(--sp-5); }
    .page-hero--art .hub-hero-inner { grid-template-columns: 1fr; }
    .hub-hero-art { order: -1; }
    .trust-inner { grid-template-columns: repeat(2, 1fr); }
    .stat-tiles.cols-3 { grid-template-columns: repeat(2, 1fr); }
    .article-shell { grid-template-columns: minmax(0, 1fr); gap: 0; }
    .sidebar-stack { position: static; margin-bottom: var(--sp-5); }
    .toc-list { columns: 2; column-gap: var(--sp-4); max-height: none; }
    .toc-list li { break-inside: avoid; }
    .sidebar-meta, .sidebar-back-link { display: none; }
    .article-sidebar { order: -1; }
}

/* 760: footer to 2 columns; two-column content and wide tables stack. */
@media (max-width: 760px) {
    .footer-inner { grid-template-columns: repeat(2, 1fr); gap: var(--sp-5); }
    .footer-brand { grid-column: 1 / -1; }
    .sitemap-list { columns: 2; }
    .proscons { grid-template-columns: 1fr; }
    .brand-tag { display: none; }
}

/* 560: everything to a single column. */
@media (max-width: 560px) {
    .card-grid, .silo-grid,
    .card-grid.cols-2, .card-grid.cols-3, .card-grid.cols-4,
    .silo-grid.cols-2, .silo-grid.cols-3, .silo-grid.cols-4 { grid-template-columns: 1fr; }
    .footer-inner { grid-template-columns: 1fr; }
    .trust-inner { grid-template-columns: 1fr; }
    .cred-strip { grid-template-columns: 1fr; }
    .stat-tiles.cols-3, .stat-tiles.cols-2 { grid-template-columns: 1fr; }
    .closing-author { flex-direction: column; }
    .kv-list dl { grid-template-columns: 1fr; }
    .sitemap-list { columns: 1; }
    .feed-row { grid-template-columns: 1fr; gap: .25rem; }
    .feed-verdict { justify-self: start; }
    .hero-stats { gap: var(--sp-5); }
    .author-strip { flex-direction: column; }
    .toc-list { columns: 1; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; scroll-behavior: auto !important; }
}

@media print {
    .masthead, .site-footer, .toc, .nav, .pagination { display: none; }
    body { background: #fff; font-size: 12pt; }
    .article-shell { display: block; }
}

/* Nav icons: Phosphor only, from the siloIcon map. One icon library site-wide. */
.nav-icon { font-size: var(--fs-sm); color: var(--primary); }
.nav-caret { font-size: var(--fs-xs); opacity: .55; }
.nav-link:hover .nav-icon { color: var(--primary-press); }
.nav-sub a { display: flex; align-items: center; gap: var(--sp-2); }
.nav-sub a i { font-size: var(--fs-sm); color: var(--primary); flex: none; }
