/* =========================================================================
   The feature explainer — one record, rendered on Help AND on the marketing
   feature page. Design 2.0, Batch 17 (canvas 19 Help).

   ⚠️ **LOADED BY TWO SHELLS THAT SHARE NO TOKENS.** The app loads
   themes/default.css; the marketing site loads marketing-theme.css, and the
   two name their tokens differently. So every token here carries a fallback
   that is the app's light value — the block renders correctly on marketing,
   which has no dark mode, and follows the app's theme where it has one.
   ⛔ Never add a rule here without a fallback: on the marketing page it would
   simply not apply, and nothing in the test suite reads computed styles.
   ⚠️ **ONE EXCEPTION, AND IT IS ENFORCED THE OTHER WAY.** `--text-muted` is
   declared as `#61705C` in BOTH themes/default.css and marketing-theme.css, so
   a fallback for it is dead code that hardcodes a hex — and
   `tests/core/test_ux_components.py::TestThemeVariables::
   test_text_muted_references_carry_no_hardcoded_fallback` walks every app
   sheet and goes RED on any reference to that token that carries one — the
   test matches the literal text, so it cannot be named here either. A
   fallback was added on 2026-09-05 by reading the blanket rule above, and
   reverted the same day. Check whether marketing-theme.css declares a token
   before giving it a fallback.

   ⭐ **IN THE GRAMMAR — 2026-09-05** (docs/admin/design_system.md, *the card
   goes on the item; the name goes on the ground*).

   ⛔ **AND THE ONE PLACE THE GRAMMAR IS RE-DECLARED RATHER THAN COMPOSED.**
   Every other ported screen writes `class="section-heading"` and
   `class="list-surface"` and lets `components/type.css` and
   `components/cards.css` paint them. These partials cannot: the marketing
   shell links neither sheet, so a composed class would be an unstyled word on
   half of its consumers — the exact failure the header above exists to
   prevent. The rungs below therefore carry the primitives' NUMBERS under
   `.explainer__*` names, and they must be changed together:

       section heading   20 / 500 / Outfit / ink   type.css .section-heading
       item title        16 / 600 / Outfit / ink   cards.css .item__title
       body              15 / 400 / secondary      cards.css .item__desc
       meta              12 / 400 / muted          type.css .meta
       list surface      white, hairline, 20px radius, 44px rows, the measure
       card              white, hairline, 20px radius, 20px padding

   ⚠️ It is a restatement of VALUES, never of a selector: writing
   `.section-heading` in this file would fail
   tests/core/test_shared_css_is_actually_loaded.py, and rightly — a second
   definition of a shared class is the bug that test was written for.
   ========================================================================= */

/* ── The head: the title, then two rungs, not two sizes of one ─────────── */

/* ⛔ THE SUMMARY WAS 17px INK AND THE WHY 16px SECONDARY — one pixel and one
   step of grey apart, which is the "adjacent rungs differ on one axis"
   failure the ladder names. The summary is the reader's sentence (prose:
   18/1.75 ink, 66ch); the why is the lede (16 secondary, 60ch). */
.explainer__head {
    margin-bottom: var(--space-2xl, 2rem);
}

.explainer__name {
    display: flex;
    align-items: center;
    gap: var(--space-xs, 0.5rem);
    margin: 0 0 var(--space-2xs, 0.25rem);
    font-family: var(--font-heading, 'Outfit', sans-serif);
    font-size: 1.75rem;
    font-weight: 400;
    letter-spacing: -0.02em;
    line-height: 1.15;
    color: var(--text-primary, #232820);
    text-wrap: balance;
}

.explainer__icon {
    display: inline-flex;
    color: var(--primary, #5C6B59);
}

.explainer__summary {
    margin: 0 0 var(--space-sm, 0.5rem);
    max-width: 66ch;
    color: var(--text-primary, #232820);
    font-size: var(--text-lg, 1.125rem);
    line-height: 1.75;
}

.explainer__why {
    margin: 0;
    max-width: 60ch;
    color: var(--text-secondary, #4A5448);
    font-size: var(--text-base, 1rem);
    line-height: 1.6;
}

/* ── The name of a run, ON THE GROUND ──────────────────────────────────── */

/* ⛔ THIS WAS 18/400 OVER 16/500 ROWS — a heading LIGHTER than the thing it
   labels — and on a phone it shrank again to 16 inside a box that held it,
   which is the Memory collapse exactly. It is the section-heading rung at
   every width now: 20/500 ink, with the hairline rule beside the name. It
   sits on the ground; the surface beneath it is the container, so no section
   gets a box of its own.

   ⚠️ TWO TAGS, ONE RUNG. The heading level is a template parameter now, because
   the record sits one level deeper on the marketing page than on /help/ — h2
   there, h3 embedded. The LOOK does not change with the level, so both tags
   carry this rule; matching only h2 made every marketing section heading fall
   back to the browser's default and shrink. */
.explainer__section h2,
.explainer__section h3 {
    display: flex;
    align-items: baseline;
    gap: var(--space-2xs, 0.25rem) var(--space-md, 0.75rem);
    margin: 0 0 var(--space-md, 0.75rem);
    font-family: var(--font-heading, 'Outfit', sans-serif);
    font-size: var(--text-xl, 1.25rem);
    font-weight: 500;
    letter-spacing: -0.01em;
    line-height: 1.3;
    color: var(--text-primary, #232820);
}

.explainer__heading-name {
    flex-shrink: 0;
}

.explainer__heading-rule {
    flex: 1;
    min-width: var(--space-2xl, 2rem);
    height: var(--border-width, 1px);
    background: var(--border-color, rgba(35, 40, 32, 0.09));
    align-self: center;
}

/* ── The run ───────────────────────────────────────────────────────────── */

.explainer__section + .explainer__section {
    margin-top: var(--space-2xl, 2rem);
}

/* ── The folds (Help on a phone) ──
   A `<details>` whose summary is the section heading. Open by default, so with
   no JS every section is simply there; help-folds.js closes them below 45rem.
   The marker is our own chevron, not the browser's triangle.

   ⛔ THE FOLD IS NO LONGER A BOX. It used to grow a border, a background and
   a radius below 45rem — with the heading INSIDE it, which is the one thing
   the rule forbids. The box is on the run of items now (`.explainer__pairs`),
   at every width, and the heading stays on the ground on both. */
.explainer__fold > summary {
    list-style: none;
    cursor: pointer;
}

.explainer__fold > summary::-webkit-details-marker {
    display: none;
}

.explainer__summary-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-xs, 0.5rem);
    min-height: 44px;   /* 📐 the standing touch target; a fold is a control */
}

/* Both tags, same reason as the section heading above: the fold is only used by
   /help/ today, where the level is h2, but the level is a parameter and a
   selector that pins one tag is how the look drifts from the outline. */
.explainer__summary-row h2,
.explainer__summary-row h3 {
    flex: 1;
    margin: 0;
}

.explainer__fold[open] > summary {
    margin-bottom: var(--space-md, 0.75rem);
}

.explainer__chevron {
    display: none;
    color: var(--text-muted);
    transition: transform var(--duration-quick, 120ms) var(--ease-out, ease-out);
}

.explainer__fold[open] > summary .explainer__chevron {
    transform: rotate(180deg);
}

/* ── The list surface: ONE box per run, rows on hairlines ──────────────── */

/* Every run on this block is the same shape — a name with a fact — so it is
   one surface and one row, and the section names stay as modifiers on it
   rather than five copies of one declaration.

   ⛔ `.explainer__answers` / `-item` AND `.explainer__step-desc` HAD NO
   DECLARATION AT ALL. The old rule listed `kinds`, `can`, `where` and `limits`
   by hand, and a hand-kept list of the sections that exist goes stale the day
   a fifth is added — `_pairs.html` had been rendering `answers` since Batch 17
   with nothing to paint it, and `__step-desc` ran on into its own title.

   ⛔ AND THE HOOKS WENT WITH THE RULE. `_pairs.html` no longer writes a class
   per section name at all: `.explainer__limits-item` below is the only
   modifier any run needs, so `_limits.html` passes it by name and every other
   section emits `.explainer__pair` alone. A class in the markup with no rule
   anywhere is that same hand-kept list, spelled in HTML.

   ⚠️ **AND NOBODY SAW IT, BECAUSE THE SECTION NEVER REACHES A PAGE.**
   `core/feature_explainer/__init__.py::explainer_for` builds the dict the two
   surfaces render and omits `answers`, so `feature.answers` is always empty
   and neither the section nor its rail entry has ever appeared — while
   `mcp.py` builds seven rows for it off the tool registry. That is a content
   bug, not a grammar one; it is left for its own change, and the shape is
   ready for the day the field arrives. */
.explainer__pairs {
    list-style: none;
    margin: 0;
    padding: 0;
    /* ⛔ **THE FALLBACK IS NOT DEAD CODE — DO NOT TIDY IT AWAY.** It was
       removed as a stale literal on 2026-09-06 and
       `test_every_template_resolves_every_token_it_references` caught it
       within the hour: `marketing/feature_page.html` links THIS sheet but
       not `themes/default.css`, because the marketing site is a separate
       token system by design (CLAUDE.md -> Frontend conventions). With no
       fallback `--measure-page` is undefined there, the declaration is
       invalid at computed-value time, and `max-width` falls back to `none`
       — the explainer runs the full width of a marketing page.
       ⚠️ The value must equal the token; a guard in test_css_extraction.py
       compares them. */
    max-width: var(--measure-page, 52rem);
    background: var(--surface-raised, #fff);
    border: var(--border-width, 1px) solid var(--border-color, rgba(35, 40, 32, 0.09));
    border-radius: var(--radius-card, 20px);
    overflow: hidden;
}

.explainer__pairs > * + * {
    border-top: var(--border-width, 1px) solid var(--border-color, rgba(35, 40, 32, 0.09));
}

.explainer__pair {
    min-height: 44px;
    padding: var(--space-md, 0.75rem) var(--space-lg, 1.25rem);
}

/* The item title rung. */
.explainer__pair dt,
.explainer__step-title {
    display: block;
    margin: 0;
    font-family: var(--font-heading, 'Outfit', sans-serif);
    font-size: var(--text-base, 1rem);
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: 0;
    color: var(--text-primary, #232820);
    overflow-wrap: anywhere;
}

/* The body rung. */
.explainer__pair dd,
.explainer__step-desc {
    display: block;
    margin: var(--space-2xs, 0.25rem) 0 0;
    font-size: var(--text-base-sm, 0.9375rem);
    font-weight: 400;
    line-height: 1.6;
    color: var(--text-secondary, #4A5448);
}

/* ⛔ The limits are the honest edges: a terra accent, never a warning colour.
   It runs down the inside of the surface's left edge, which is what the box's
   `overflow: hidden` is for — five stripes must not end raggedly on the
   radius. */
.explainer__limits-item {
    border-left: var(--border-width-lg, 3px) solid var(--terra, #CAB99E);
}

.explainer__kind-what {
    display: block;
}

/* The real example from the doc, not a category description. */
.explainer__kind-example {
    display: block;
    margin-top: var(--space-2xs, 0.25rem);
    color: var(--text-muted);
    font-family: var(--font-serif, 'Lora', Georgia, serif);
    font-style: italic;
    font-size: var(--text-base-sm, 0.9375rem);
}

/* ── How it works: the same rows, with the step number as the lead ─────── */

/* The numeral is a counter, not a list marker, so it sits INSIDE the
   surface's padding beside its step instead of hanging outside the box. */
.explainer__steps {
    counter-reset: explainer-step;
}

.explainer__step {
    counter-increment: explainer-step;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
        "num title"
        "num desc";
    column-gap: var(--space-md, 0.75rem);
}

.explainer__step::before {
    content: counter(explainer-step);
    grid-area: num;
    align-self: start;
    font-size: var(--text-base, 1rem);
    line-height: 1.35;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.explainer__step-title {
    grid-area: title;
}

.explainer__step-desc {
    grid-area: desc;
}

/*
 * ⭐ **ONE REAL MOMENT FROM ONE REAL JOURNAL.** Set in the reading face, because
 * it is her writing and everything around it is ours. It is the one CARD on
 * the block — a thing read as a single item — so it carries the card's own
 * numbers: 20px radius, 20px padding, hairline, no resting shadow.
 */
.explainer__example {
    margin: 0;
    max-width: var(--measure-page, 52rem);
    padding: var(--space-lg, 1.25rem);
    background: var(--surface-raised, #fff);
    border: var(--border-width, 1px) solid var(--border-color, rgba(35, 40, 32, 0.09));
    border-radius: var(--radius-card, 20px);
}

.explainer__example figcaption {
    margin-bottom: var(--space-2xs, 0.25rem);
    color: var(--text-muted);
    font-size: var(--text-xs, 0.75rem);
    line-height: 1.5;
}

.explainer__example blockquote {
    margin: 0 0 var(--space-sm, 0.75rem);
    color: var(--text-primary, #232820);
    font-family: var(--font-serif, 'Lora', Georgia, serif);
    font-style: italic;
    font-size: var(--text-lg, 1.125rem);
    line-height: 1.5;
}

.explainer__kept {
    list-style: none;
    margin: 0 0 var(--space-sm, 0.75rem);
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs, 0.25rem) var(--space-xs, 0.5rem);
}

.explainer__kept li {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs, 0.25rem);
    padding: 0.25rem 0.75rem;
    border-radius: var(--radius-pill, 100px);
    background: var(--surface-inset, #F5F5F2);
    color: var(--text-primary, #232820);
    font-size: var(--text-base-sm, 0.9375rem);
}

/* The eyebrow rung, tinted: 11 / 600 / 0.09em caps, body face. */
.explainer__tag {
    font-family: var(--font-body, 'Plus Jakarta Sans', sans-serif);
    font-size: var(--text-2xs, 0.6875rem);
    font-weight: 600;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--primary, #5C6B59);
}

.explainer__outcome {
    margin: 0;
    color: var(--text-secondary, #4A5448);
    font-size: var(--text-base-sm, 0.9375rem);
    line-height: 1.6;
}

@media (max-width: 45rem) {
    /*
     * ⭐ **THE EXAMPLE COMES FIRST ON A PHONE**, because the concrete thing has
     * to. Everything after it is reference, and "Worth knowing" is never the
     * section dropped to make room — it folds, it is not removed.
     *
     * ⛔ `#answers` WAS MISSING FROM THIS LIST, and an unlisted flex item is
     * `order: 0` — so *What you can ask it* rendered ABOVE the head, before
     * the name of the feature, on every phone. It sits between the vocabulary
     * and *What you can do*, which is the reading order the composer states.
     */
    .explainer--full {
        display: flex;
        flex-direction: column;
    }

    .explainer--full .explainer__head { order: 1; }
    .explainer--full #example { order: 2; }
    .explainer--full #kinds { order: 3; }
    .explainer--full #answers { order: 4; }
    .explainer--full #can { order: 5; }
    .explainer--full #where { order: 6; }
    .explainer--full #how { order: 7; }
    .explainer--full #limits { order: 8; }

    .explainer--full .explainer__section + .explainer__section {
        margin-top: var(--space-xl, 1.5rem);
    }

    .explainer__chevron {
        display: block;
    }
}
