/* ═══════════════════════════════════════════════════════════════
   FOCUS: the article-reader and app-chrome design language
   ═══════════════════════════════════════════════════════════════

   GRADUATED 2026-08-05 from the ?css=violet experiment (decision in
   docs/plans/color-system-rebuild.md): the single-accent language is the
   design, in both views, on the surfaces this file covers. The variant
   switcher, the ?css= cookie opt-in, and the per-theme accent list were
   deleted with the graduation; body carries .focus-shell unconditionally
   (index.php). The accent itself moved from the mockup violet to the
   brand China Rose #b46277 on 2026-08-11; prose below that still says
   "violet" is describing the experiment's history, not the live value.

   Scope: the library article reader (.library-reading), the Today
   surface (.today-view, the TODAY section below), PLUS the global
   top bar and tool rail (the APP CHROME section at the end, which
   carries its own scope warning). The article rail markup is shared
   with the toolkit reader, which reaches it through
   `.toolkit-reader-rail`, so that surface is untouched. Other surfaces
   converge toward this language stage by stage (see the plan).

   Concept: content sits on one raised panel; both rails are quiet,
   chromeless typographic lists; a single accent does all the
   wayfinding. Light mode (driven by the app's own Dark/Light control)
   inverts the elevation ladder: the panel is white and sits proud of a
   gray canvas, while the chrome deliberately stays dark in both modes,
   matching the stock rail (css/layout.css: "the rail is dark in both
   modes").

   TOKENS: the --exp-* palette below is scoped to body.focus-shell and
   lives here, next to its consumers, rather than in theme-variables.css:
   every value is mode-split in this file and nothing outside this file
   consumes them. The name prefix is historical.

   SPECIFICITY NOTE: every rule below mirrors the selector it overrides
   and prefixes `body.focus-shell`, which adds exactly one class and
   guarantees the override wins. Do not shorten these selectors; several
   of the originals in css/tools.css carry three classes, and a trimmed
   selector here silently loses.
   ─────────────────────────────────────────────────────────────── */


body.focus-shell {
    /* ── THE ONE INPUT ── */
    /* China Rose #b46277, the brand solid (it also rides in
       theme-variables.css as --rose-mid). Replaced the 1e mockup's violet
       #8b7cf8 on 2026-08-11 (Jim named the hex). The value is the brand hex
       verbatim: it carries enough chroma to do accent work on the dark
       chrome and the dark canvas without lifting.

       NOTE ON SCOPE: this is the DEFAULT accent. The PER-GROUP ACCENT block
       at the end of this file still overrides --exp-accent to the content
       group's own color while a Library group surface is open, but that
       override reaches CONTENT tints only (cover, washes, links). The
       chrome accent (--exp-accent-chrome below) never varies: since
       2026-08-23 the top bar and rail stay brand rose on every page, and
       page identity lives in the content. */
    --exp-accent: #b46277;

    /* ── Fixed neutrals ── */
    --exp-canvas: #101015;
    --exp-panel: #16161d;
    --exp-panel-border: #232330;
    --exp-nested: #1c1c26;

    --exp-text: #f1f0f8;
    --exp-body: #dcdbe8;
    --exp-body-summary: #d9d8e6;
    --exp-secondary: #82819a;
    --exp-muted: #5f5e74;

    --exp-rail-link: #8f8ea6;
    --exp-ghost-text: #b9b8c9;
    --exp-ghost-border: #26262f;
    --exp-hairline: #222230;
    --exp-rail-title: #e9e8f4;

    /* App chrome (top bar + tool rail). A hair darker than the canvas, so
       the three surfaces read as one ladder: chrome, then canvas, then the
       raised article panel. This is the DARK value; since 2026-08-29 the
       chrome follows the mode and the light block redeclares it. The stock
       dark chrome is #15181C tinted 12% with --primary, which is why it
       reads blue next to a violet canvas. */
    --exp-chrome: #0c0c11;
    /* The top bar alone, split off from the rail on 2026-09-02 so the light
       chrome can carry two values (a white bar over a grey rail). In dark
       mode there is nothing to gain from the split (a step off #0c0c11 in
       either direction loses the chrome), so this pins the same value and
       the two surfaces stay identical. Pinned rather than aliased to
       --exp-chrome, for the same reason every other chrome token here is a
       hex. */
    --exp-chrome-top: #0c0c11;

    /* ── Derived from --exp-accent ── */
    /* Percentages were fitted against the mockup's hand-picked violet
       tints, so the default variant lands within a point or two of the
       original values (#b9aeff, #cfc9ff, #191527, #2a2542) while every
       other accent gets the same relationships for free. Mixing the two
       surface tints toward --exp-canvas rather than toward black keeps a
       swapped accent from muddying into the page background. */
    --exp-accent-text:  color-mix(in srgb, var(--exp-accent) 62%, #ffffff);
    --exp-toc-active:   color-mix(in srgb, var(--exp-accent) 38%, #ffffff);
    --exp-accent-wash:  color-mix(in srgb, var(--exp-accent) 16%, transparent);
    --exp-cover:        color-mix(in srgb, var(--exp-accent) 8%, var(--exp-canvas));
    --exp-cover-border: color-mix(in srgb, var(--exp-accent) 18%, var(--exp-canvas));
    /* The cover's ghost icon is its own token rather than reusing the pill
       wash: the two sit on different backgrounds and need different
       strengths, and only the ghost has to survive a light card.

       An alpha, not a color-mix, and that is load bearing. The Tabler
       marks are stroked multi-path SVGs (tk-hierarchy is 12 paths, six
       node circles and six connectors, js/icons.js:189), and SVG
       composites each path on its own. Carry the transparency in the
       stroke color and every crossing paints alpha over alpha: 30% over
       30% lands at 51%, so the mark renders as a patchwork of bright
       overlap blobs with the ring holes filled in. Carried as opacity on
       the wrapper instead, the whole SVG composites as one group and the
       wash stays flat. The Library grid card has always done it this way
       (css/tools.css:9822). */
    --exp-ghost-alpha:  0.16;

    /* The accent as used ON the chrome. A pinned hex per mode rather than
       a mode-flipped theme token: the value must track the CHROME's
       polarity, not the content surfaces', and the tokens that carry this
       hue (--rose-mid, --c-assessment) flip with the content. Binding it
       to --exp-accent-text once produced the pale-pink chrome bug: the
       light mode darkened the accent for white content surfaces, the old
       rule lightened that darkened value 55% back toward white for the
       then-dark chrome, and the round trip overshot. Since 2026-08-29 the
       chrome follows the mode, so this base-block pin is the dark value
       and the light block pins the light one.

       The page accent NEVER overrides this value in either mode. It used
       to swap per content group (cyan on toolkit pages, violet on reading
       pages), which made the chrome recolor on navigation and read as a
       bug; since 2026-08-23 the chrome accent is one constant and the
       PER-GROUP ACCENT block at the end of this file deliberately leaves
       it alone. */
    --exp-accent-chrome: #b46277;   /* = the dark --exp-accent */

    /* Semantic, deliberately NOT derived from the accent. Green means
       "complete" throughout the app, so it has to survive an accent swap.
       A pin rather than var(--c-done) so the value tracks the chrome's
       polarity explicitly: this base block pins the dark done green, and
       the light block pins the darkened-for-light one. */
    --exp-done: #7FC775;   /* = dark --c-done */

    /* The hairline as used ON the chrome, and the reason it is its own
       token: --exp-hairline is a CONTENT-surface value, tuned for the
       panel, and using it on the chrome once drew a bright line under
       the top bar and down the rail's right edge in light mode. Same
       reasoning as --exp-accent-chrome and --exp-done above: a token
       that lands on the chrome is pinned per mode, dark here, light in
       the light block. */
    --exp-chrome-hairline: #222230;
}


/* ── LIGHT MODE ────────────────────────────────────────────────
   Driven by the app's own Dark/Light control, not by a separate URL
   param: the Appearance panel already owns that choice, and Focus
   should answer to it rather than compete with it. Everything keys off
   `:not(.dark-mode)`, the same class css/theme-variables.css:401 uses.

   The elevation ladder inverts. In dark, the raised panel is the
   LIGHTEST surface on a darker canvas. In light, the panel is white and
   the canvas is a gray it sits proud of, so the panel is still the one
   raised thing on the page.

   The chrome follows the mode (2026-08-29; Jim reversed the 2026-05-27
   always-dark chrome). The stock rail and top bar in css/layout.css
   split their base and ink tokens by mode the same way, so a light
   Focus with light chrome is the light NCS structure. The four
   chrome-pinned tokens (--exp-chrome, --exp-chrome-hairline,
   --exp-accent-chrome, --exp-done) are therefore redeclared at the end
   of this block with their light values.

   The derived percentages invert with the mode. On a dark surface the
   accent has to get LIGHTER to carry small type; on white it has to get
   DARKER. The light accents below are the real light-mode --primary of
   each theme, which are already dark enough to sit on white, so the
   text token is the accent itself rather than a mix. */
body.focus-shell:not(.dark-mode) {
    /* The light China Rose. In dark mode the accent is set in the base
       block; light mode darkens it one step to sit on white. This is the
       same value the palette already ships as --rose (the AA-on-white
       sibling of --rose-mid): the brand solid itself is 4.2:1 on white,
       and --exp-accent-text below is the accent verbatim in light mode, so
       the undarkened hex would put small type under AA on the reader panel. */
    --exp-accent: #a4576c;

    --exp-canvas: #f1f1f6;
    --exp-panel: #ffffff;
    --exp-panel-border: #e3e3ec;
    --exp-nested: #f6f6fa;

    --exp-text: #17171f;
    --exp-body: #3c3c4a;
    --exp-body-summary: #3c3c4a;
    --exp-secondary: #6a6a7e;
    --exp-muted: #8b8b9c;

    --exp-rail-link: #6a6a7e;
    --exp-ghost-text: #4a4a5a;
    --exp-ghost-border: #dcdce6;
    --exp-hairline: #e3e3ec;
    --exp-rail-title: #1c1c26;

    --exp-accent-text:  var(--exp-accent);
    --exp-toc-active:   color-mix(in srgb, var(--exp-accent) 82%, #000000);
    --exp-accent-wash:  color-mix(in srgb, var(--exp-accent) 12%, transparent);
    /* Stronger than the dark equivalents. A tint that reads clearly against
       near-black all but disappears against a near-white canvas, so the
       cover card needs more accent in it to stay a card. */
    --exp-cover:        color-mix(in srgb, var(--exp-accent) 15%, var(--exp-canvas));
    --exp-cover-border: color-mix(in srgb, var(--exp-accent) 36%, var(--exp-canvas));
    --exp-ghost-alpha:  0.24;

    /* ── Chrome pins, light values (2026-08-29) ──
       The chrome follows the mode now, so the four chrome-pinned tokens
       ARE redeclared here, each with the value fit for a light chrome.
       Same discipline as the base block: pinned hexes, never mode-flipped
       theme tokens, and the page accent still never reaches them. */
    /* Darker than --exp-canvas, so the chrome/canvas/panel ladder holds in
       light terms too. It first shipped at #e9e9f0, one hair off the
       canvas, and read as empty space rather than as chrome: 3 L* of
       separation is enough for a hairline to do the work but not enough
       for the frame to hold the page. At #dedee9 the step is ~6 L* and
       the bar and rail read as a frame while staying quiet under the
       content.
       2026-09-02/03: the chrome split into two tokens and went through
       three hues in two days before landing here (Jim: "everything grey
       makes it all seem very same same", then a Midnight Green tint, then a
       warm sand, then this). The settle is white over grey: the top bar is
       the same #FFFFFF as the raised content panel (--exp-panel), and the
       rail is a grey one clear step DARKER than the --exp-canvas the
       reader's left column sits on. The two were rendered against the
       thinking-model reader, where the rail, the "Back to Library" column
       and the panel all show at once; #E8E8EF was indistinguishable from
       the canvas at a glance, #E3E3EB is the smallest step that reads.
       What this buys over the old single #dedee9: the frame has TWO values
       instead of one. The bar is the brightest surface on the screen and
       the rail the darkest light surface, so the page reads as bar over
       (rail | canvas | panel) rather than as one grey slab with a white
       card in it. Same lightness logic as the dark chrome, inverted.
       Rejected along the way, each rendered rather than argued: tinting
       the canvas to match a tinted chrome (it repainted the whole app);
       a China Rose chrome (it flattened the rose active pill into its own
       background); Midnight Green at 14% and warm sand from the Gamboge
       family, both of which shipped on this branch and both of which Jim
       looked at and moved past. The mixes for those two are in the branch
       history if either is ever wanted back. */
    --exp-chrome: #E3E3EB;
    --exp-chrome-top: #FFFFFF;
    --exp-chrome-hairline: #D4D4DF;  /* separates chrome from canvas, and
                                        the white bar from the grey below it;
                                        one step darker than the rail */
    --exp-accent-chrome: #a4576c;    /* = the light --exp-accent: on a light
                                        chrome the accent needs its
                                        darkened-for-light value */
    --exp-done: #35762D;             /* = light --c-done, same reasoning */
}

/* The panel is the one raised thing, and on white a border alone does
   not say "raised" the way it does against a dark canvas. */
body.focus-shell:not(.dark-mode) .library-reading-main {
    box-shadow: 0 1px 3px rgba(20, 20, 40, 0.06), 0 8px 24px rgba(20, 20, 40, 0.05);
}
/* Code and pre invert: on dark they sat darker than the panel, on light
   they need to sit darker than white, not black. */
body.focus-shell:not(.dark-mode) .library-reading-content pre {
    background: var(--exp-nested);
    border-color: var(--exp-panel-border);
}
body.focus-shell:not(.dark-mode) .library-reading-content pre code {
    color: var(--exp-body);
}


/* ── Canvas ────────────────────────────────────────────────────
   The content area behind the panel. :has() keeps this to the
   article reader without needing a JS-managed body class: the app
   shell's own background is untouched on every other view. */
body.focus-shell:has(.library-reading) .main-area,
/* The Library grid and the topic-bundle page take the same canvas. A browse
   wall and the page a card opens are one surface as far as a reader is
   concerned, and the grid used to sit on --canvas-bg (#0F0F12 dark), which
   read as a third background between the reader's canvas and its panel.
   Both render a .lib-home container; My Shelf renders .my-shelf-view, which
   is its page root rather than its grid, so an empty shelf keeps the canvas
   instead of falling back to a different background than a full one. */
body.focus-shell:has(.lib-home) .main-area,
body.focus-shell:has(.my-shelf-view) .main-area,
/* Today joins the same ladder: chrome, canvas, then its one raised panel
   (the daily rep). See the TODAY section below. */
body.focus-shell:has(.today-view) .main-area,
/* Narratives, its Garden tab, and State of You (.home-view--wide is rendered
   by js/all-narratives.js and js/garden-view.js; State of You renders a plain
   .home-view, which this selector also matches). They were the flattest page
   in the app: the page, the section panel, and the narrative card all painted
   --bg-surface, so a card was separated from the panel holding it by one
   hairline and from the page behind it by nothing at all, and in light mode
   the whole screen was #FFFFFF end to end. Joining this ladder gives the cards
   the same ground a Library card has. See .home-section[data-section="narratives"]
   in css/views.css for the other half: the browse section drops its own panel
   so the grid sits on this canvas rather than on a second surface.

   State of You joined on 2026-08-16, when its dashboard tiles took the Library
   card's chrome: a white card on a white page was the exact flatness this rule
   was written to fix, and the tiles had been reading as one continuous sheet. */
body.focus-shell:has(.home-view) .main-area {
    background-color: var(--exp-canvas);
}


/* ── Layout ────────────────────────────────────────────────────
   Original: grid 220px / 1fr / 280px, gap 2rem (css/tools.css:10012).
   Spec: 224 / 1fr / 250, gap 22px, padding 20px. */
body.focus-shell .library-view.library-reading {
    padding: 20px;
    font-family: Manrope, sans-serif;
}
/* The left column is --lib-card-w plus a --cover-col-pad gutter each side
   (was a hand-set 224px until 2026-08-24): the rail's side padding eats
   the extra, so the cover inside renders at the Library card's exact
   width while sitting a step in from the page edge and the panel. */
body.focus-shell .library-reading-layout {
    grid-template-columns: calc(var(--lib-card-w) + 2 * var(--cover-col-pad)) minmax(0, 1fr);
    gap: 22px;
}
body.focus-shell .library-reading-layout--has-rail {
    grid-template-columns: calc(var(--lib-card-w) + 2 * var(--cover-col-pad)) minmax(0, 1fr) var(--content-rail-w);
    gap: 22px;
}
/* The reading-measure cap, restated at this file's column widths and gap (the
 * originals in css/tools.css use 220px tracks and a 2rem gap, so their number
 * lands ~30px off here). The extra 60px is the raised panel's own side padding
 * on .library-reading-main below: the measure names the TEXT column, so the
 * padding has to be added back or the text lands 60px short of it. */
body.focus-shell .library-reading--prose > .library-reading-layout {
    max-width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad) + 22px + var(--reading-measure) + 60px);
}
body.focus-shell .library-reading--prose > .library-reading-layout--has-rail {
    max-width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad) + 22px + var(--reading-measure) + 60px + 22px + var(--content-rail-w));
}
/* Same two rules for a card page, which takes --card-page-measure instead
   (the split is documented at the cap in css/tools.css). */
body.focus-shell .library-reading--cards > .library-reading-layout {
    max-width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad) + 22px + var(--card-page-measure) + 60px);
}
body.focus-shell .library-reading--cards > .library-reading-layout--has-rail {
    max-width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad) + 22px + var(--card-page-measure) + 60px + 22px + var(--content-rail-w));
}


/* ── Left rail ─────────────────────────────────────────────────
   Chromeless: no background, no border. All elevation budget goes
   to the main panel. */
body.focus-shell .library-reading-toc {
    border-right: none;
    padding: 0 var(--cover-col-pad);
    font-family: Manrope, sans-serif;
}

/* Back link. Deliberately quiet: sentence case, neutral gray, no
   accent color and no button chrome. */
body.focus-shell .library-back-btn.library-reading-toc-back {
    padding: 0;
    margin-bottom: 14px;
    border: none;
    background: none;
    color: var(--exp-rail-link);
    font-family: Manrope, sans-serif;
    font-size: 13px;
    font-weight: 600;
}
body.focus-shell .library-back-btn.library-reading-toc-back:hover {
    background: none;
    border: none;
    color: var(--exp-text);
}

/* The heart/star/PDF icon row (.surface-actions-row, css/views.css)
   replaced the full-width Download PDF ghost button here 2026-08-22; its
   quiet ghost-square styling already fits the Focus language, so the rail
   only sets spacing. */
body.focus-shell .library-reading-toc-actions .surface-actions-row {
    margin-bottom: 16px;
}

/* THE PAGE COVER. Every reader and topic page carries the item's Library
   cover in its rail or cover column (renderFullCover / renderResourceCover
   in js/library-home.js), so the card the user clicked and the page they
   land on open on the same object.

   The max-width is not decoration and does not belong in a media query.
   It is --lib-card-w, the Library grid's own track width and the reading
   rails' shared column width, because "the same object" includes its
   size: the rails used to run wider than the grid card and each showed
   the cover at its own width, so the card grew on the way from the grid
   to its page (Jim, 2026-08-24). Inside the rail the cap is a no-op (the
   column IS this width); it earns its keep at every breakpoint that
   collapses the rail, where the cover would otherwise take the FULL page
   width and turn into a billboard the reader has to scroll past to reach
   the article. Centered, matching .library-reading-cover, for the same
   collapsed-rail case. */
body.focus-shell .library-reading-cover-full {
    width: 100%;
    max-width: var(--lib-card-w);
    margin: 0 auto 20px;
}

/* The card-unit frame. Alone on a page, the cover has no lattice of
   neighbors to say "card" for it, and the old frame rule replaced the
   grid's kind-colored edge with the neutral panel hairline, so the cover
   read as stacked text inside a thin outline (Jim, 2026-08-22). The
   kind-tinted ground that answers the same complaint lives on .lib-card
   itself (css/tools.css), where the grid card shares it; what is left
   here is what only a page cover needs.

   max-width is the SHAPE, not decoration. --lib-card-w is the reading
   rails' own track width and the workbook cover's cap (.wb-reader-nav
   .wb-reader-cover below), so the cover fills its column edge to edge and
   every individual page opens on the same set-width left column as the
   workbook reader, with the raised panel starting one 22px gutter to its
   right (Jim, 2026-08-23). Until 2026-08-24 that shared width was a
   hand-set 224px; it is now the Library grid's own track width, because
   the grid became fixed-width the same day and a 224px page cover no
   longer blended into a fluid card range: the card visibly grew on the way
   from the grid to its page (Jim, 2026-08-24). Both earlier rulings
   survive: the cover still fills its column with no dead track (the
   2026-08-23 fix), and it is back to the grid card's exact portrait (what
   the 190px cap of 2026-08-22 wanted), because the column itself moved.
   A cap is still required: every breakpoint that collapses the rail gives
   the cover the full page width, and this is what stops that from
   becoming a billboard.

   The border is the kind-colored edge the grid card already wears in dark
   mode, at full 1px weight, plus a soft lift shadow. The :hover selectors
   are grouped in because a page cover is not a button: without them the
   grid card's own dark-mode hover (border swap, shadow cancel) wins on
   specificity and the cover flickers under the pointer.

   Scoped to .lib-card.resource-cover, which is every page cover and no
   grid card: the reading rails, the coaching module page, the assessment
   page's cover column, a topic bundle. */
body.focus-shell .lib-card.resource-cover,
body.focus-shell .lib-card.resource-cover:hover {
    max-width: var(--lib-card-w);
    border: 1px solid color-mix(in srgb, var(--kind-c) 55%, var(--exp-panel));
    border-radius: 14px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22), 0 10px 24px rgba(0, 0, 0, 0.16);
}
/* Light needs less edge: a border that whispers on near-black shouts on
   white, so it backs off, and the shadow goes gray-blue to sit on the
   light canvas. */
body.focus-shell:not(.dark-mode) .lib-card.resource-cover,
body.focus-shell:not(.dark-mode) .lib-card.resource-cover:hover {
    border-color: color-mix(in srgb, var(--kind-c) 38%, var(--exp-panel));
    box-shadow: 0 1px 3px rgba(20, 20, 40, 0.07), 0 10px 24px rgba(20, 20, 40, 0.06);
}

/* The condensed cover card that used to sit in the reader rail was removed on
   2026-08-09 with the museum-plate card redesign. Its rules keyed on
   .lib-card-head and .lib-card-ghost, both of which the new card anatomy
   dropped, and nothing had emitted .library-reading-cover since the full
   portrait cover took over every reader (2026-08-08 entries in
   docs/plans/color-system-rebuild.md). .library-reading-cover-full, the
   portrait cover, is a different class and is styled above. */
/* Reading progress. Not in the mockup, but it is a real feature rather
   than chrome, so it is kept and tinted to match. */
body.focus-shell .library-reading-toc-progress {
    height: 2px;
    background: var(--exp-hairline);
    margin-bottom: 18px;
}
body.focus-shell .library-reading-toc-progress-fill {
    background: var(--exp-accent);
}

/* ON THIS PAGE */
body.focus-shell .library-reading-toc-label {
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.14em;
    color: var(--exp-muted);
    margin-bottom: 10px;
}
body.focus-shell .library-reading-toc-link {
    padding: 5px 0;
    border-left: none;
    border-radius: 0;
    font-family: Manrope, sans-serif;
    font-size: 12px;
    line-height: 1.4;
    color: var(--exp-secondary);
}
body.focus-shell .library-reading-toc-link:hover {
    background: none;
    color: var(--exp-text);
}
/* Active item: violet dot bullet, no fill, no left border. */
body.focus-shell .library-reading-toc-link.active {
    position: relative;
    background: none;
    border-left-color: transparent;
    color: var(--exp-toc-active);
    font-size: 12.5px;
    font-weight: 700;
}
/* The dot sits inside the link's own left padding rather than hanging off
   it. The rail is overflow:hidden, so a negative offset here is clipped
   away entirely and the bullet silently never appears. */
body.focus-shell .library-reading-toc-link.active::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: 5px;
    height: 5px;
    margin-top: -2.5px;
    border-radius: 50%;
    background: var(--exp-accent);
}
/* The whole ladder shifts right by 11px to make room for that dot, keeping
   the 13px-per-level steps the spec calls for. */
body.focus-shell .library-reading-toc-level-1 { padding-left: 11px; font-weight: 600; }
body.focus-shell .library-reading-toc-level-2 { padding-left: 24px; }
body.focus-shell .library-reading-toc-level-3 {
    padding-left: 37px;
    font-size: 11.5px;
    color: var(--exp-secondary);
}


/* ── Main column: the raised panel ─────────────────────────────
   The signature move. The only elevated surface on the page. */
body.focus-shell .library-reading-main {
    padding: 26px 30px;
    border: 1px solid var(--exp-panel-border);
    border-radius: 18px;
    background: var(--exp-panel);
}

/* H1. The original colors this by content type (--library-type-color,
   set inline on the reading root); Violet Focus keeps the title neutral
   and lets the accent do wayfinding instead. */
body.focus-shell .library-reading-content h1 {
    font-family: Manrope, sans-serif;
    font-size: 42px;
    font-weight: 800;
    letter-spacing: -0.025em;
    line-height: 1.08;
    color: var(--exp-text);
    margin: 0;
}
body.focus-shell .library-reading-content .library-reading-dek {
    font-family: Manrope, sans-serif;
    font-size: 15px;
    color: var(--exp-secondary);
    margin: 10px 0 0;
}
/* Frontmatter subtitle: the second half of the name, so it keeps the title's
   weight class rather than the dek's body face. */
body.focus-shell .library-reading-content .library-reading-standfirst {
    font-family: Manrope, sans-serif;
    font-weight: 600;
    font-size: 19px;
    line-height: 1.25;
    color: var(--exp-secondary);
    margin: 10px 0 0;
}

/* Meta row. The header block is moved under the H1 by js/library-view.js;
   see the note there. */
body.focus-shell .library-reading-header {
    margin: 0;
}
body.focus-shell .library-reading-meta {
    gap: 5px 14px;
    margin: 14px 0 24px;
}
/* Exactly one pill. The type chip carries an inline background from
   _libraryTypeColor(), and an inline style can only be beaten by
   !important. Violet is the page's only accent, so the per-type color
   has to go. */
body.focus-shell .library-reading-meta .library-card-type {
    background: var(--exp-accent-wash) !important;
    color: var(--exp-accent-text) !important;
    padding: 4px 9px;
    border-radius: 6px;
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.08em;
}
/* Everything else in the row is a plain metadata chip. Articles can carry
   eight or more tags, and pilling them all buries the one pill that is
   meant to be read. */
body.focus-shell .library-reading-category,
body.focus-shell .library-reading-meta .library-card-tag {
    padding: 0;
    border: none;
    border-radius: 0;
    background: none;
    color: var(--exp-secondary);
    font-family: Manrope, sans-serif;
    font-size: 11.5px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
}
body.focus-shell .library-reading-category:hover,
body.focus-shell .library-reading-meta .library-card-tag:hover {
    color: var(--exp-accent-text);
    background: none;
}


/* ── "IN SHORT..." summary block ───────────────────────────────
   A nested panel rather than the gamboge left-rule callout the
   original paints. Built by _wrapArticleRecap in js/library-view.js
   from an `## In Short...` heading. */
body.focus-shell .library-recap {
    margin: 0 0 22px;
    padding: 20px 22px;
    border-left: none;
    border-radius: 14px;
    background: var(--exp-nested);
}
body.focus-shell .library-reading-content .library-recap > h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 12px;
    font-family: Manrope, sans-serif;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.16em;
    color: var(--exp-accent);
}
body.focus-shell .library-recap > h2::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 2px;
    background: var(--exp-accent);
    flex: none;
}
body.focus-shell .library-reading-content .library-recap > p,
body.focus-shell .library-reading-content .library-recap > ul,
body.focus-shell .library-reading-content .library-recap > ol,
body.focus-shell .library-reading-content .library-recap li {
    font-size: 14.5px;
    line-height: 1.7;
    color: var(--exp-body-summary);
}
body.focus-shell .library-recap ul {
    list-style: none;
    padding-left: 14px;
}
/* Hanging violet dot on each key point. */
body.focus-shell .library-recap ul > li {
    position: relative;
    padding-left: 14px;
    margin-bottom: 8px;
}
body.focus-shell .library-recap ul > li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.65em;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--exp-accent);
}
/* Bold lead-in phrase brightens; the rest of the sentence stays body weight. */
body.focus-shell .library-recap strong {
    color: var(--exp-text);
    font-weight: 700;
}


/* ── Article body ──────────────────────────────────────────────
   The original colors H2 green and H3 violet by convention. Violet
   Focus keeps headings neutral so the accent stays scarce. */
body.focus-shell .library-reading-content {
    font-family: Manrope, sans-serif;
    font-size: 16px;
    line-height: 1.8;
    /* Manrope's own word space is 0.20em, against 0.26em in Open Sans and
       0.28em in Inter. At article length that reads tight enough to close
       word pairs up ("sub points", "sit down"), so prose gets a little
       back. Measured, not guessed; 0.06em was tried and opens visible
       gaps. The Focus Reader overrides this per typeface via
       --fr-word-spacing (#frOverlay wins on specificity), because the
       serif option must keep Georgia's natural spacing. */
    word-spacing: 0.045em;
    color: var(--exp-body);
}
body.focus-shell .library-reading-content > *:first-child {
    margin-top: 0;
}
body.focus-shell .library-reading-content .library-recap + p,
body.focus-shell .library-reading-content .library-recap-divider + p {
    margin-top: 22px;
}
body.focus-shell .library-reading-content h2 {
    font-family: Manrope, sans-serif;
    font-size: 24px;
    font-weight: 800;
    letter-spacing: -0.015em;
    color: var(--exp-text);
    margin: 34px 0 10px;
}
body.focus-shell .library-reading-content h3 {
    font-family: Manrope, sans-serif;
    font-size: 17px;
    font-weight: 700;
    color: var(--exp-text);
    margin: 24px 0 8px;
}
body.focus-shell .library-reading-content strong {
    color: var(--exp-text);
}
body.focus-shell .library-reading-content a {
    color: var(--exp-accent-text);
}
body.focus-shell .library-reading-content blockquote {
    border-left: 2px solid var(--exp-accent);
    color: var(--exp-secondary);
}
body.focus-shell .library-reading-content hr {
    border-top: 1px solid var(--exp-hairline);
}
body.focus-shell .library-reading-content code {
    background: var(--exp-accent-wash);
    color: var(--exp-accent-text);
}
body.focus-shell .library-reading-content pre {
    background: var(--exp-canvas);
    border: 1px solid var(--exp-panel-border);
}
body.focus-shell .library-reading-content pre code {
    background: none;
    color: var(--exp-body);
}


/* ── Right rail ────────────────────────────────────────────────
   One block for all three rails (article/tutorial/module, workbook, thinking
   model). They used to be three near-identical copies of these overrides, one
   per wrapper, which is the same drift the shared markup exists to end: the
   rail markup is now one shape (js/content-rail.js), so its focus treatment is
   one block. Quiet lists on the canvas: no card boxes, hairlines only. */
/* No panel behind a section: the rail stays a quiet list on the canvas, the way
   the rest of this shell works. The icon tiles take the raised surface instead
   (see .library-related-card-icon below), which is what lets them read with
   nothing behind the section. */
body.focus-shell .library-related-section {
    background: none;
    border: none;
    border-radius: 0;
    padding: 0;
    margin-top: 0;
}
body.focus-shell .library-related-section + .library-related-section {
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--exp-hairline);
}
body.focus-shell .library-related-eyebrow {
    color: var(--exp-accent-text);
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.14em;
}
body.focus-shell .library-related-section--explore .library-related-title {
    font-family: Manrope, sans-serif;
    font-size: 13.5px;
    font-weight: 700;
    line-height: 1.3;
    color: var(--exp-rail-title);
}
body.focus-shell .library-related-section--related .library-related-title {
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.14em;
    color: var(--exp-muted);
}
body.focus-shell .library-related-section--related .library-related-title::after {
    background: var(--exp-hairline);
}
body.focus-shell .library-related-sub {
    font-family: Manrope, sans-serif;
    font-size: 11px;
    color: var(--exp-secondary);
}
body.focus-shell .library-related-card {
    padding: 8px 2px;
    border: none;
    border-bottom: 1px solid var(--exp-hairline);
    border-radius: 0;
    background: none;
    box-shadow: none;
    gap: 9px;
}
body.focus-shell .library-related-card:hover {
    background: none;
    border-color: transparent;
    border-bottom-color: var(--exp-accent);
    box-shadow: none;
}
body.focus-shell .library-related-card-text { gap: 3px; }
/* The mark takes the page accent rather than the row's own --c-kind-* hue,
   extending to every focus rail the rule the thinking-model column already
   had: on this surface the page accent is the one identity color, and a rail
   mixing six kind hues against pinned rose chrome reads as unrelated colors
   rather than one page. The kicker beside it is pinned for the same reason.
   Outside the focus shell the kind hue stands. */
body.focus-shell .library-related-card-icon {
    background: none;
    color: var(--exp-accent);
}
/* The kicker carries an inline per-kind color from contentRailRow. */
body.focus-shell .library-related-card-type {
    color: var(--exp-accent) !important;
    font-family: Manrope, sans-serif;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.16em;
}
body.focus-shell .library-related-card-title {
    font-family: Manrope, sans-serif;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--exp-rail-title);
}
body.focus-shell .library-related-card-subtitle {
    font-family: Manrope, sans-serif;
    font-size: 11px;
    line-height: 1.45;
    color: var(--exp-secondary);
}
body.focus-shell .library-related-card-count {
    color: var(--exp-accent-text);
    background: var(--exp-accent-wash);
}
body.focus-shell .library-related-card-go { color: var(--exp-muted); }
body.focus-shell .library-related-browse {
    color: var(--exp-accent-text);
    font-family: Manrope, sans-serif;
    font-size: 12px;
}
body.focus-shell .library-related-more {
    color: var(--exp-accent-text);
    font-family: Manrope, sans-serif;
}



/* ── Responsive ────────────────────────────────────────────────
   The originals collapse the rails at three breakpoints. Media and
   container queries add no specificity, so without these mirrors the
   three-column rule above would beat them and the layout would stay
   wide on a narrow screen. Keep these in sync with css/tools.css. */

/* Right rail drops under the main column (.main-area is the container).
   1050 rather than 980 since 2026-09-01: the rail went from 250px to 320px
   (--content-rail-w), so the reading column hits the same floor 70px earlier
   and the drop has to happen 70px sooner. */
@container (max-width: 1000px) {
    body.focus-shell .library-reading-layout--has-rail {
        grid-template-columns: calc(var(--lib-card-w) + 2 * var(--cover-col-pad)) minmax(0, 1fr);
    }
    body.focus-shell .library-reading--prose > .library-reading-layout--has-rail {
        max-width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad) + 22px + var(--reading-measure) + 60px);
    }
    body.focus-shell .library-reading--cards > .library-reading-layout--has-rail {
        max-width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad) + 22px + var(--card-page-measure) + 60px);
    }
}

@media (max-width: 900px) {
    body.focus-shell .library-reading-layout,
    body.focus-shell .library-reading-layout--has-rail {
        grid-template-columns: minmax(0, 1fr);
        gap: 16px;
    }
    body.focus-shell .library-reading-toc {
        border-bottom: 1px solid var(--exp-hairline);
        padding: 0 0 12px;
    }
    body.focus-shell .library-reading-main {
        padding: 20px 18px;
    }
    /* One column, and the panel's side padding is 18px here rather than 30. */
    body.focus-shell .library-reading--prose > .library-reading-layout,
    body.focus-shell .library-reading--prose > .library-reading-layout--has-rail {
        max-width: calc(var(--reading-measure) + 36px);
    }
    body.focus-shell .library-reading--cards > .library-reading-layout,
    body.focus-shell .library-reading--cards > .library-reading-layout--has-rail {
        max-width: calc(var(--card-page-measure) + 36px);
    }
    body.focus-shell .library-reading-content h1 {
        font-size: 32px;
    }
}

/* Phone: css/tools.css keeps the rail's two actions and drops the outline
   and the cover. Mirror the one rule that would otherwise fight it: the
   ghost PDF button is full-width in the rail above, and at equal specificity
   this file loads last, so without this the two actions stack into two rows
   on the narrowest screen instead of sharing one. */
@media (max-width: 600px) {
    body.focus-shell .library-reading-toc-actions .surface-actions-row {
        margin: 0;
    }
}


/* ═══════════════════════════════════════════════════════════════
   TODAY: the daily-action surface on the Focus language
   ═══════════════════════════════════════════════════════════════

   The first content surface after the reader to converge (the header
   note's "stage by stage"). Same grammar, translated:

   - The page sits on the Focus canvas (the :has() rule above).
   - The daily rep is the ONE raised panel. Everything else on the page
     is quiet: the work list is a chromeless typographic list, the
     footer pointer is a hairline-topped line, and the elevation budget
     is spent exactly once, the way the reader spends it on the article
     panel.
   - The violet accent does all the wayfinding: the rep's kicker and
     Save button, the selected choice, the primary row's button and
     question preview, the links. Per-kind color survives only inside
     each row's icon chip, restated as the Library card's museum-plate
     recipe (14% tint fill, 38% tint frame, object in the kind color),
     so a row's chip and that content's Library card read as the same
     object at two sizes.
   - Section heads speak the card-kicker voice: small caps, wide
     tracking, muted. The greeting stays the page's identity (the
     2026-08-06 decision: views that lead with their own name render
     no extra header).
   - Status stays green. The done banner, check chips, and rep done
     state keep --c-done, which is exempt from every accent system
     (decisions.md 2026-08-05). Only their stage changes: they sit on
     panel surfaces with the status color as tint and edge.

   Selector rule, same as the whole file: mirror the original
   (css/views.css Today block, css/daily-rep.css) and prefix
   body.focus-shell so the override wins at one extra class. */

/* ── Hero ──────────────────────────────────────────────────────── */
body.focus-shell .today-greeting { color: var(--exp-text); }
body.focus-shell .today-date { color: var(--exp-secondary); }

/* ── Section heads: the card-kicker voice ──────────────────────────
   Scoped to .today-view so State of You's dashboard sections (which
   share the grouped title rule in views.css) keep their current heads;
   the committed-bundles block reuses home-dash markup inside Today and
   converges with it here. */
body.focus-shell .today-view .today-checklist-title,
body.focus-shell .today-view .home-dash-section-title {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--exp-secondary);
}
body.focus-shell .today-view .today-checklist-count,
body.focus-shell .today-view .today-checklist-dismiss {
    color: var(--exp-muted);
}
body.focus-shell .today-view .today-checklist-dismiss:hover,
body.focus-shell .today-view .today-checklist-dismiss:focus-visible {
    color: var(--exp-ghost-text);
}
body.focus-shell .today-view .today-checklist-bar {
    background: var(--exp-hairline);
}
body.focus-shell .today-view .today-checklist-bar-fill {
    background: var(--exp-accent);
}
body.focus-shell .today-view .today-checklist-empty {
    color: var(--exp-secondary);
}

/* ── The daily rep: the page's one raised panel ────────────────── */
body.focus-shell .daily-rep-card--pending {
    padding: 1.05rem 1.2rem 1.15rem;
    border-radius: 14px;
    background: var(--exp-panel);
    border: 1px solid var(--exp-panel-border);
    box-shadow: 0 2px 10px var(--shadow-sm);
}

/* The rep's kicker takes the accent, the way a Library card's kicker
   takes its kind color: the raised panel is the one violet-labelled
   thing on the page. (The base grouped rule in views.css sets the
   1.05rem title style; this restates the kicker scale on top.) */
body.focus-shell .today-view .daily-rep-eyebrow {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--exp-accent-text);
}
body.focus-shell .today-view .daily-rep-eyebrow-note {
    color: var(--exp-muted);
}

body.focus-shell .daily-rep-question {
    font-size: 1.02rem;
    color: var(--exp-text);
}

body.focus-shell .daily-rep-input {
    background: var(--exp-nested);
    border-color: var(--exp-panel-border);
    color: var(--exp-body);
}
body.focus-shell .daily-rep-input::placeholder { color: var(--exp-muted); }
body.focus-shell .daily-rep-input:focus { border-color: var(--exp-accent); }

body.focus-shell .daily-rep-choice {
    background: transparent;
    border-color: var(--exp-ghost-border);
    color: var(--exp-ghost-text);
}
body.focus-shell .daily-rep-choice:hover {
    background: color-mix(in srgb, var(--exp-accent) 8%, transparent);
    border-color: color-mix(in srgb, var(--exp-accent) 55%, transparent);
    color: var(--exp-accent-text);
}
body.focus-shell .daily-rep-choice.selected,
body.focus-shell .daily-rep-choice.selected:hover {
    background: var(--exp-accent);
    border-color: var(--exp-accent);
    color: var(--on-brand);
}

body.focus-shell .daily-rep-submit {
    background: var(--exp-accent);
    color: var(--on-brand);
}
body.focus-shell .daily-rep-submit:hover {
    background: color-mix(in srgb, var(--exp-accent) 86%, var(--charcoal));
}

body.focus-shell .daily-rep-hint { color: var(--exp-muted); }
body.focus-shell .daily-rep-link { color: var(--exp-rail-link); }
body.focus-shell .daily-rep-link:hover { color: var(--exp-accent-text); }

/* Done and skipped states: still status-green (and neutral), restaged
   on the panel surface so the slim card matches the page's geometry. */
body.focus-shell .daily-rep-card--done {
    border-radius: 14px;
    background: color-mix(in srgb, var(--c-done) 6%, var(--exp-panel));
    border-color: color-mix(in srgb, var(--c-done) 38%, transparent);
}
body.focus-shell .daily-rep-card--skipped {
    border-radius: 14px;
    background: var(--exp-panel);
    border-color: var(--exp-panel-border);
}
body.focus-shell .daily-rep-done-title { color: var(--exp-text); }
body.focus-shell .daily-rep-done-snippet { color: var(--exp-secondary); }

/* ── Quote ─────────────────────────────────────────────────────── */
body.focus-shell .today-quote {
    border-left: 2px solid color-mix(in srgb, var(--exp-accent) 45%, transparent);
}
body.focus-shell .today-quote-text { color: var(--exp-body-summary); }
body.focus-shell .today-quote-author { color: var(--exp-muted); }

/* ── The work list: quiet rows, museum-plate chips ─────────────────
   :not() keeps the done check-chip green: this selector out-weighs the
   one-class .today-step-icon--done rule in views.css, and status color
   must survive the accent system. */
body.focus-shell .today-view .today-step-icon:not(.today-step-icon--done) {
    background: color-mix(in srgb, var(--row-accent) 14%, var(--exp-panel));
    border-color: color-mix(in srgb, var(--row-accent) 38%, transparent);
}
body.focus-shell .today-view .today-step-title { color: var(--exp-text); }
body.focus-shell .today-view .today-step-sub { color: var(--exp-secondary); }
body.focus-shell .today-view .today-step--done .today-step-title { color: var(--exp-muted); }

body.focus-shell .today-view .today-step[role="button"]:hover {
    background: var(--exp-panel);
}

/* Ghost buttons on non-primary rows; the accent stays reserved. */
body.focus-shell .today-view .today-step-btn {
    background: transparent;
    border-color: var(--exp-ghost-border);
    color: var(--exp-ghost-text);
}
body.focus-shell .today-view .today-step-btn:hover {
    background: color-mix(in srgb, var(--exp-accent) 8%, transparent);
    border-color: color-mix(in srgb, var(--exp-accent) 55%, transparent);
    color: var(--exp-accent-text);
}

/* The primary row: chip stays a plate (a touch firmer on the frame,
   the lib-card dark-edge weight), and the button is the page's one
   filled accent control outside the rep panel. */
body.focus-shell .today-view .today-step--primary .today-step-icon {
    background: color-mix(in srgb, var(--row-accent) 14%, var(--exp-panel));
    border-color: color-mix(in srgb, var(--row-accent) 70%, transparent);
    color: var(--row-accent);
}
body.focus-shell .today-view .today-step--primary .today-step-btn {
    background: var(--exp-accent);
    border-color: var(--exp-accent);
    color: var(--on-brand);
}
body.focus-shell .today-view .today-step--primary .today-step-btn:hover {
    background: color-mix(in srgb, var(--exp-accent) 86%, var(--charcoal));
    border-color: color-mix(in srgb, var(--exp-accent) 86%, var(--charcoal));
    color: var(--on-brand);
}

/* The question preview: nested surface, accent-labelled. */
body.focus-shell .today-view .today-step-preview {
    border-left: 2px solid color-mix(in srgb, var(--exp-accent) 55%, transparent);
    background: var(--exp-nested);
    border-radius: 0 8px 8px 0;
}
body.focus-shell .today-view .today-step-preview-label { color: var(--exp-accent-text); }
body.focus-shell .today-view .today-step-preview-pos { color: var(--exp-muted); opacity: 1; }
body.focus-shell .today-view .today-step-preview-text { color: var(--exp-body); }

/* ── Done surfaces: status green, panel stage ──────────────────── */
body.focus-shell .today-view .today-done-banner {
    background: color-mix(in srgb, var(--c-done) 6%, var(--exp-panel));
    border-color: color-mix(in srgb, var(--c-done) 32%, transparent);
}
body.focus-shell .today-view .today-done-label { color: var(--exp-text); }
body.focus-shell .today-view .today-done-toggle { color: var(--exp-rail-link); }
body.focus-shell .today-view .today-done-banner-label { color: var(--exp-text); }
body.focus-shell .today-view .today-done-clear-btn {
    background: transparent;
}
body.focus-shell .today-view .today-done-summary:hover {
    background: var(--exp-panel);
}

/* ── Links and the footer pointer ──────────────────────────────── */
body.focus-shell .today-view .home-dash-link { color: var(--exp-accent-text); }

/* The boxed strip becomes a hairline-topped footer line, the reader's
   quiet-chrome idiom (same move the Back to Library link makes: no
   button dress, just type). */
body.focus-shell .today-getting-started-pointer,
body.focus-shell.dark-mode .today-getting-started-pointer {
    background: transparent;
    border: none;
    border-top: 1px solid var(--exp-hairline);
    border-radius: 0;
    padding: 1rem 0 0;
    margin-top: 1.75rem;
    color: var(--exp-secondary);
}
body.focus-shell .today-getting-started-pointer-label {
    color: var(--exp-secondary);
    font-weight: 600;
}


/* ═══════════════════════════════════════════════════════════════
   APP CHROME: top bar + tool rail
   ═══════════════════════════════════════════════════════════════

   SCOPE WARNING: unlike everything above, this section is NOT limited
   to the article reader. The top bar and the tool rail are global, and
   scoping them with :has(.library-reading) would repaint the chrome on
   every navigation, which reads as a bug rather than a design. So with
   the experiment on, the chrome is Violet Focus everywhere.

   Content surfaces outside the article reader still carry their own
   teal and per-type accents, so other views will look half-converted.
   That is expected at this stage, not an oversight.

   Both surfaces derive their background from the same mode-split
   formulas in css/layout.css (.tool-rail, .view-toggle-bar): a light
   neutral tinted 8% with --primary in light mode, a fixed #15181C base
   tinted 12% in dark. Overriding the two background tokens and
   --primary is most of the work; the rest is flattening shadows and
   moving the hairlines onto the spec's divider color.

   Every color that lands on this chrome comes from a chrome-pinned
   token (--exp-chrome, --exp-chrome-hairline, --exp-accent-chrome,
   --exp-done), never from a content-surface token. Since 2026-08-29
   the pins are per mode (the light block redeclares each), so the
   chrome follows the mode while still never following the page accent.
   ─────────────────────────────────────────────────────────────── */

/* ── Top bar ─────────────────────────────────────────────────── */
body.focus-shell .view-toggle-bar {
    /* The bar takes --exp-chrome-top, not --exp-chrome: in light mode it is
       white while the rail beside it is grey. In dark mode the two tokens
       hold the same value, so the split costs nothing there. */
    --topbar-bg: var(--exp-chrome-top);
    /* The bar's own chrome accents (focus rings, active buttons) follow
       --primary. The palette tokens the bar overrides for badges and
       status dots are deliberately left alone: the unread-notification
       dot has to stay legible as an alert, not become more violet. */
    --primary: var(--exp-accent-chrome);
    /* Pinned like --exp-accent-chrome above it, and for the same reason:
       this lands on the chrome and never follows the page accent. Bound
       to --exp-accent-text it made the +Insight button rest rose and
       hover the page's color. This is the dark-chrome value (the base
       block's dark accent-text formula applied to the rose); the light
       counterpart is pinned in the light rule below. */
    --primary-mid: color-mix(in srgb, #b46277 62%, #ffffff);
    border-bottom: 1px solid var(--exp-chrome-hairline);
    box-shadow: none;
}
body.focus-shell:not(.dark-mode) .view-toggle-bar {
    /* Light counterpart of the --primary-mid pin above: on the light
       chrome the accent moves DARKER for hover and small type, the same
       direction as the light block's --exp-toc-active, applied to the
       light rose. */
    --primary-mid: color-mix(in srgb, #a4576c 82%, #000000);
}
body.focus-shell .top-bar-brand-text {
    font-family: Manrope, sans-serif;
    letter-spacing: -0.01em;
}

/* ── Tool rail ───────────────────────────────────────────────── */
body.focus-shell .tool-rail {
    --rail-bg: var(--exp-chrome);
    /* Drives the rail's section labels (ALL TOOLS, Recent, FAVORITES). */
    --primary: var(--exp-accent-chrome);
    border-right: 1px solid var(--exp-chrome-hairline);
    box-shadow: none;
    font-family: Manrope, sans-serif;
    /* Align the rail's first entry with the article page's first element.
       The reader's "Back to Library" text sits 23px under the top bar (20px
       page padding + line-height lead); a rail item's icon and label sit 7px
       inside their button box, so 16px of rail padding lands the first
       icon/label top at the same 23px. Wins over the stock 5px (and the
       expanded rail's 4px) on file order at equal specificity. */
    padding-top: 16px;
}

/* Every rail item resolves its hover and active tint from --tool-color,
   which css/layout.css assigns per workflow group (Toolkit teal, Library
   green, Workshop violet). Violet Focus allows one accent, so they all
   collapse to it. The rail already reads monochrome at rest, so this only
   changes hover and active states.

   TO RESTORE the per-group color coding, delete this one rule.

   !important is required, not sloppiness: renderDynamicRail() in
   js/navigation.js writes style="--tool-color:..." inline on rail chips
   (js/navigation.js:782, :861, :904), and an inline custom property
   cannot be beaten by any selector. */
body.focus-shell .tool-rail .tool-rail-item,
body.focus-shell .tool-rail .rail-group-header,
body.focus-shell .tool-rail .rail-standalone-item {
    --tool-color: var(--exp-accent-chrome) !important;
}

/* ONE exemption from that collapse, and it matters. The rail's completion
   badge paints itself `var(--tool-color, var(--green))` (css/layout.css:645),
   so collapsing --tool-color quietly repainted every "done" badge in the
   accent and threw away the green that carried the meaning. Green means
   complete across at least eight surfaces here (workbook steps, phase
   checks, synthesis coverage, My Shelf status, the completed-journey rail
   row), so it is semantic, not decorative, and a brand accent should not
   be able to overwrite it.

   This also decides what a green ACCENT would cost: with Forest selected,
   the badge and the accent become the same green and the badge stops
   distinguishing anything, even though the rest of the page is fine. */
body.focus-shell .tool-rail .tool-complete-badge {
    background: var(--exp-done);
}

/* Hairline separators between rail sections. The stock rules paint these
   with the rail-scoped border token, which is tuned for the stock chrome.
   These sit inside the Focus rail, so they take the chrome hairline, not
   the content one. */
body.focus-shell .tool-rail .rail-separator,
body.focus-shell .tool-rail .rail-tier-1-section::before,
body.focus-shell .tool-rail .rail-tier-recent-section::before,
body.focus-shell .tool-rail .rail-tier-favorites-section::before {
    border-top-color: var(--exp-chrome-hairline);
    opacity: 1;
}

/* Section labels: same quiet typographic treatment as the article rails,
   so the chrome and the content rails read as one family. */
body.focus-shell .tool-rail .rail-tier-label,
body.focus-shell .tool-rail .my-tools-label-text {
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.14em;
    color: var(--exp-muted);
}
/* Legibility floor at the usage, not a darkened token (the CHECK G rule in
   tools/audit-palette.py). --exp-muted is #8b8b9c, tuned for the reader's
   near-white panel, and on the rail it lands on chrome instead: 2.51:1 on
   the old #dedee9, 2.7:1 on #E3E3EB. Not a regression any retune
   introduced, a floor the rail's one piece of 10px type never had. #525A66
   clears AA (5.6:1) on the rail grey while staying a quiet slate rather
   than a heading. Light mode only: the dark chrome is unchanged and its
   muted value already carries there. */
body.focus-shell:not(.dark-mode) .tool-rail .rail-tier-label,
body.focus-shell:not(.dark-mode) .tool-rail .my-tools-label-text {
    color: #525A66;
}
body.focus-shell .tool-rail .rail-group-header {
    font-family: Manrope, sans-serif;
}


/* ═══════════════════════════════════════════════════════════════
   PER-GROUP ACCENT
   ═══════════════════════════════════════════════════════════════
   The page accent follows the open surface's content GROUP (the Stage 2
   library colors), set as data-focus-accent on <body> by renderApp().
   With no attribute the default China Rose above holds. That default and
   --c-reading used to be the same violet, so the reading group's surfaces
   looked identical with or without their attribute; since the 2026-08-11
   accent change they differ, and a reading-group surface repaints the
   chrome violet where the rest of the app is rose. Leaving --c-reading
   alone is deliberate: it is the Library grid's group hue, and moving it
   to rose would collide with --c-assessment, which is already China Rose.
   The --c-* tokens flip per mode on their own, and every derived tint
   (cover, washes, chrome accent, small type) recomputes from the one
   input. These sit AFTER the light-mode block on purpose: equal
   specificity, later in the file, so the group accent wins in both
   modes.

   These set the CONTENT accent only. --exp-accent-chrome is deliberately
   NOT set here: the chrome (top bar + rail) stays on the pinned brand
   rose on every page (see the base block), so opening a workbook or a
   thinking model recolors the page, never the frame. The per-group
   chrome hexes that briefly lived here (2026-08-23, same-day) made the
   chrome swap cyan/blue/violet per section and were removed the same
   day Jim called the constant-chrome design. */
body.focus-shell[data-focus-accent="reading"]     { --exp-accent: var(--c-reading); }
body.focus-shell[data-focus-accent="interactive"] { --exp-accent: var(--c-interactive); }
body.focus-shell[data-focus-accent="workbook"]    { --exp-accent: var(--c-workbook); }
body.focus-shell[data-focus-accent="assessment"]  { --exp-accent: var(--c-assessment); }
body.focus-shell[data-focus-accent="coaching"]    { --exp-accent: var(--c-coaching); }

/* ── Per-KIND accents ────────────────────────────────────────────
   Two surfaces take the KIND color instead of their group's, because
   their group answer is wrong for the page: the reader shows the item's
   own cover card, and a cover wearing one hue under an accent wearing
   another reads as two objects.

   Tutorials sat in the reading group beside articles, so a tutorial page
   accented --c-reading (Ultra Violet) above cards wearing
   --c-kind-tutorial (a purple 40 degrees away). No value of --c-reading
   could fix that, because the kind palette put articles at hue 237 and
   tutorials at 288: one group token cannot match both.

   Thinking models were already doing this, but imperatively, via a
   --exp-accent override in updateFocusAccent() (js/render.js). That
   worked and hid the problem: the group token stayed 68 degrees off the
   kind token for every consumer that was not the reader. The rule now
   lives here with the others, and render.js just names the accent.

   Added 2026-08-26 off tools/audit-palette.py CHECK B. */
body.focus-shell[data-focus-accent="tutorial"]    { --exp-accent: var(--c-kind-tutorial); }
body.focus-shell[data-focus-accent="toolkit"]     { --exp-accent: var(--c-kind-toolkit); }

/* The practice surfaces. One tool, surface-detail, serves three kinds, so
   its accent cannot be named in FOCUS_ACCENT_BY_TOOL the way the others
   are: js/render.js reads the open item's kind and writes it here. Those
   three were the last place a group token was knowably wrong, all sharing
   an "interactive" teal while their cards are rust, magenta and teal. */
body.focus-shell[data-focus-accent="game"]        { --exp-accent: var(--c-kind-game); }
body.focus-shell[data-focus-accent="app"]         { --exp-accent: var(--c-kind-app); }
body.focus-shell[data-focus-accent="deck"]        { --exp-accent: var(--c-kind-deck); }

/* Deck is the one kind token that cannot be read as small text on a light
   panel: #2E86A6 measures 4.14 on white, under AA's 4.5. Every other kind
   used as an accent clears it (game 5.01, app 6.05, tutorial 6.78, toolkit
   4.70).
   Darkening the TOKEN was the obvious move and is wrong. Deck is a muted
   teal sitting deliberately close to --c-kind-workbook (dE 10.6, "a deck is
   practice for a skill a workbook teaches"). Every darkened value either
   collapses into workbook (dE 4-7), slides into --c-kind-bundle's blue, or
   desaturates into grey, and all of them repaint every deck card to fix one
   page's text. So the token keeps its identity and the ACCENT takes a
   legibility floor, light mode only, where the accent is ink. The washes
   derived from it move too, by 22% of one darkening step, which is not
   visible. Dark mode needs none of this: deck measures 8.04 there. */
body.focus-shell:not(.dark-mode)[data-focus-accent="deck"] {
    --exp-accent: color-mix(in srgb, var(--c-kind-deck) 78%, var(--charcoal));
}

/* The cover card must wear the group color the way the mockup's cover
   wore violet. The base percentages were fitted to the Focus violet, a
   high-chroma light accent; the group colors are darker and quieter, so
   at 8%/15% the tile reads nearly colorless. When a group accent is
   active, the cover mixes deeper so the tile is unmistakably the group's
   color while staying the mockup's tinted-card shape (not a solid slab). */
body.focus-shell[data-focus-accent] {
    --exp-cover:        color-mix(in srgb, var(--exp-accent) 22%, var(--exp-canvas));
    --exp-cover-border: color-mix(in srgb, var(--exp-accent) 42%, var(--exp-canvas));
    --exp-ghost-alpha:  0.30;
}
body.focus-shell:not(.dark-mode)[data-focus-accent] {
    --exp-cover:        color-mix(in srgb, var(--exp-accent) 26%, var(--exp-canvas));
    --exp-cover-border: color-mix(in srgb, var(--exp-accent) 52%, var(--exp-canvas));
    --exp-ghost-alpha:  0.36;
}


/* ═══════════════════════════════════════════════════════════════
   THINKING-MODEL READER (first convergence surface)
   ═══════════════════════════════════════════════════════════════
   The toolkit reader takes the Focus ladder: chrome, then canvas, then
   the work column as the one raised panel. Its left rail already shares
   the article rail's markup (.library-reading-toc via
   .toolkit-reader-rail) and its cover carries .library-reading-cover
   (added in _tkReaderRail), so those pick up the Focus treatment from
   the rules above; the rules here cover what is unique to this surface.
   Inner tool furniture (inputs, chains, disclosure cards) is deliberately
   untouched: this pass converges the frame, not the tool. */
body.focus-shell:has(.toolkit-view.toolkit-reader) .main-area {
    background-color: var(--exp-canvas);
}
body.focus-shell .toolkit-view.toolkit-reader {
    padding: 20px;
    gap: 22px;
}
/* Column geometry, converged onto the workbook reader's (Jim, 2026-08-23:
   every individual page opens on the same set-width left column, with the
   center starting just to its right). Three moves, each against a base
   rule in css/tools.css that made this the one reader whose panel floated:
   the rail's 240px goes to the shared --lib-card-w track; the work area drops its
   justify-content: center and 1rem right padding so the panel starts one
   22px gutter after the rail instead of centering in the leftover width;
   and the panel's 860px cap comes off so it fills to the side rail the way
   .library-reading-main and .wb-front-main fill. The side rail takes the
   250px the article and workbook right rails use (base: 280px). */
body.focus-shell .toolkit-reader .toolkit-work-area {
    justify-content: flex-start;
    gap: 22px;
    padding-right: 0;
}
body.focus-shell .toolkit-reader .toolkit-viz-area {
    max-width: none;
    background: var(--exp-panel);
    border: 1px solid var(--exp-panel-border);
    border-radius: 14px;
}
body.focus-shell:not(.dark-mode) .toolkit-reader .toolkit-viz-area {
    box-shadow: 0 1px 3px rgba(20, 20, 40, 0.06), 0 8px 24px rgba(20, 20, 40, 0.05);
}
body.focus-shell .toolkit-reader .toolkit-reader-rail {
    /* Side padding rides in via the shared .library-reading-toc rule. */
    width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad));
    background: transparent;
    border-bottom: none;
    padding-top: 0;
}
body.focus-shell .toolkit-reader .toolkit-side-rail {
    width: var(--content-rail-w);
}
/* Responsive mirror, same rule as the workbook section below: the width and
   gap set above outweigh the ≤1024px collapse in css/tools.css (media
   queries add no specificity), so the stacked layout has to be restated at
   this weight. The rail's full-width collapse was also losing inside
   tools.css itself (its base 240px rule sits later in that file than the
   media block), so this mirror is what actually delivers it. */
@media (max-width: 1050px) {
    body.focus-shell .toolkit-reader .toolkit-reader-rail {
        width: 100%;
        height: auto;
    }
    body.focus-shell .toolkit-reader .toolkit-work-area {
        gap: 0;
    }
    body.focus-shell .toolkit-reader .toolkit-side-rail {
        width: 100%;
    }
}
/* Container twin of the mirror above, and for the same specificity reason.
   The viewport query cannot see the case that actually squeezes this
   reader: opening both narrative panels (the N key) takes ~620px out of the
   content column while the window stays the size it was, which left a 240px
   rail, a work column and a 250px sibling rail inside 672px and ran the
   guide text one word per line. .main-area declares container-type:
   inline-size, so this reads the column's real width. */
@container (max-width: 1050px) {
    body.focus-shell .toolkit-reader .toolkit-reader-rail {
        width: 100%;
        height: auto;
    }
    body.focus-shell .toolkit-reader .toolkit-work-area {
        gap: 0;
    }
    body.focus-shell .toolkit-reader .toolkit-side-rail {
        width: 100%;
    }
}


/* ═══════════════════════════════════════════════════════════════
   WORKBOOK READER (second convergence surface)
   ═══════════════════════════════════════════════════════════════
   Brings the workbook reader onto the same three-column Focus shape
   as the article reader: chrome, then canvas, then ONE raised panel
   holding the work. The accent is the Workbooks group blue, set by
   renderApp() as data-focus-accent="workbook" (js/render.js), so every
   derived tint recomputes from that one input and flips per mode for
   free.

   Column map, matching .library-reading-layout above:
     LEFT   .wb-reader-nav    back link, PDF exports, cover, progress,
                              phase/step ladder. Chromeless.
     CENTER .wb-front-main    the raised panel. The only elevated
                              surface on the page.
     RIGHT  .wb-front-rail    related items as a quiet hairline list
                              on the canvas, no card boxes.

   Two markup moves came with this pass (js/workbook-view.js): the two
   PDF export buttons moved from the right rail into the left one, where
   the article reader keeps its Download PDF; and the three front-matter
   eyebrow colors moved from inline styles onto modifier classes so they
   can be collapsed here without !important.

   SPECIFICITY NOTE: same rule as the rest of this file. Every selector
   mirrors the one it overrides in css/views.css and prefixes
   `body.focus-shell`. That also means these rules beat the responsive
   blocks in css/views.css (media and container queries add no
   specificity), so the RESPONSIVE subsection at the end of this section
   has to mirror every collapse. Keep them in sync.
   ─────────────────────────────────────────────────────────────── */

/* The per-phase color cycler collapses onto the one accent.
   _WB_PHASE_COLORS (js/workbook-view.js) rotates six hues by phase index,
   which is the same "color encodes an index that means nothing" pattern
   the canvas lineage work retired; Focus allows one accent, and the phase
   ladder in the rail already says which phase you are in.

   !important is required, not sloppiness: _renderWorkbookReader writes
   style="--wb-phase-color:..." inline on .wb-reader, and an inline custom
   property cannot be beaten by any selector. Same reason the tool rail's
   --tool-color collapse needs it above.

   TO RESTORE the per-phase colors, delete this one rule. */
body.focus-shell .wb-reader {
    --wb-phase-color: var(--exp-accent) !important;
}

/* ── Canvas ────────────────────────────────────────────────────
   :has() keeps this to the reader; the workbook GRID view keeps the
   app shell's own background, exactly as the Library grid does. */
body.focus-shell:has(.wb-reader) .main-area {
    background-color: var(--exp-canvas);
}


/* ── Frame ─────────────────────────────────────────────────────
   20px page padding and a 22px gutter, the article's spec. The
   height and the inner scroller are left alone: the workbook rail
   is a working nav that has to stay put while the step scrolls,
   which is why this surface scrolls its column rather than its page. */
body.focus-shell .wb-reader {
    padding: 20px;
    gap: 22px;
    font-family: Manrope, sans-serif;
    /* Center the whole reader, not just the panel inside it. The nav rail is a
       flex sibling of the scroller, so capping the panel alone leaves the rail
       pinned to the far left of a wide monitor with a canyon between them; the
       article reader centers its cover rail with its text for the same reason.
       Same three columns as the article, plus this element's own 20px padding
       either side. The step bar is display:none on desktop and only turns
       fixed on phones, below this cap's reach. The width: 100% is required,
       not belt-and-braces: .main-area is a flex row and this is a flex item,
       so with a max-width and an auto width it sizes to its own content, and
       its content is a flex:1 scroller with no intrinsic width. That collapsed
       the whole reader to the nav rail plus nothing. */
    width: 100%;
    max-width: calc(40px + var(--lib-card-w) + 2 * var(--cover-col-pad) + 22px + var(--reading-measure) + 60px + 22px + var(--content-rail-w));
    margin-inline: auto;
}


/* ── Left rail ─────────────────────────────────────────────────
   Chromeless: no panel background, no divider. All of the elevation
   budget goes to the center panel. --lib-card-w to match
   .library-reading-toc's track, with the stock padding dropped, so the
   cover fills the rail at the Library card's own width. */
body.focus-shell .wb-reader-nav {
    width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad));
    min-width: calc(var(--lib-card-w) + 2 * var(--cover-col-pad));
    padding: 0 var(--cover-col-pad);
    border-right: none;
    background: none;
}

/* Back link: sentence case, neutral gray, no chrome. Mirrors
   .library-reading-toc-back. */
body.focus-shell .wb-reader-nav .wb-back-btn {
    margin-bottom: 14px;
    font-family: Manrope, sans-serif;
    font-size: 13px;
    font-weight: 600;
    color: var(--exp-rail-link);
}
body.focus-shell .wb-reader-nav .wb-back-btn:hover {
    color: var(--exp-text);
}

/* The workbook rail's PDF exports are now icon buttons inside the
   heart/star row (.surface-actions-row, css/views.css); only spacing is
   set here. */
body.focus-shell .wb-rail-downloads {
    margin-bottom: 16px;
}

/* Cover. The workbook's own designed cover stays: it is the product
   artifact, and the reading cover exists precisely so the card a reader
   clicked and the page they land on are visibly the same thing. Only the
   frame is brought onto the Focus radius and hairline. */
body.focus-shell .wb-reader-nav .wb-reader-cover {
    max-width: var(--lib-card-w);
    margin-bottom: 16px;
    border: 1px solid var(--exp-panel-border);
    border-radius: 14px;
}

/* Progress. Kept, and flattened to the 2px hairline the article rail
   uses for reading progress. */
body.focus-shell .wb-reader-progress {
    padding: 0;
    margin-bottom: 16px;
    border-bottom: none;
}
body.focus-shell .wb-reader-progress-bar {
    height: 2px;
    border-radius: 0;
    background: var(--exp-hairline);
}
body.focus-shell .wb-reader-progress-fill {
    border-radius: 0;
    background: var(--exp-accent);
}
body.focus-shell .wb-reader-progress-label {
    margin-top: 6px;
    font-family: Manrope, sans-serif;
    font-size: 10.5px;
    color: var(--exp-muted);
}

/* Pass switcher. A rail control, so it takes the rail's quiet type. */
body.focus-shell .wb-run-chip {
    font-family: Manrope, sans-serif;
    font-size: 11px;
    color: var(--exp-muted);
}
body.focus-shell .wb-run-chip:hover,
body.focus-shell .wb-run-switcher[open] > summary {
    color: var(--exp-text);
}
body.focus-shell .wb-run-list {
    border-color: var(--exp-hairline);
}
body.focus-shell .wb-run-row + .wb-run-row {
    border-top-color: var(--exp-hairline);
}
body.focus-shell .wb-run-name {
    color: var(--exp-rail-title);
    font-family: Manrope, sans-serif;
}
body.focus-shell .wb-run-meta,
body.focus-shell .wb-run-current {
    color: var(--exp-muted);
}
body.focus-shell .wb-run-open:hover,
body.focus-shell .wb-run-new:hover {
    background: var(--exp-accent-wash);
}


/* ── Phase and step ladder ─────────────────────────────────────
   The workbook's equivalent of ON THIS PAGE. Same treatment: no fills,
   no rounded chips, one accent dot marking where you are. */
body.focus-shell .wb-nav-phase {
    margin-bottom: 2px;
}
/* The ladder shifts right by 11px, and steps by 24px, so it steps the way
   .library-reading-toc-level-1 / -level-2 do and leaves room for the accent
   dot in the item's own left padding. */
body.focus-shell .wb-nav-phase-title {
    padding: 5px 0 5px 11px;
    border-radius: 0;
    font-family: Manrope, sans-serif;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
    color: var(--exp-secondary);
}
/* Introduction, Closing and Further Reading have no steps under them, so
   the phase title itself is the "you are here" item and takes the dot.
   Phases with steps leave it to the active step below. */
body.focus-shell .wb-nav-phase.current:not(:has(.wb-nav-steps)) .wb-nav-phase-title {
    position: relative;
}
body.focus-shell .wb-nav-phase.current:not(:has(.wb-nav-steps)) .wb-nav-phase-title::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: 5px;
    height: 5px;
    margin-top: -2.5px;
    border-radius: 50%;
    background: var(--exp-accent);
}
body.focus-shell .wb-nav-phase-title:hover {
    background: none;
    color: var(--exp-text);
}
body.focus-shell .wb-nav-phase.current .wb-nav-phase-title {
    color: var(--exp-toc-active);
    font-weight: 700;
}
/* The count reads as data, so it keeps its tinted pill, mixed off the
   accent instead of the retired phase color. */
body.focus-shell .wb-nav-phase-count {
    font-family: Manrope, sans-serif;
    font-size: 9.5px;
    color: var(--exp-accent-text);
    background: var(--exp-accent-wash);
}
/* Green means complete across the app and survives every accent swap,
   the same exemption the tool rail's completion badge carries. */
body.focus-shell .wb-nav-phase.done .wb-nav-phase-count {
    color: var(--c-done);
    background: color-mix(in srgb, var(--c-done) 14%, transparent);
}
body.focus-shell .wb-nav-steps {
    padding: 0 0 4px 0;
}
body.focus-shell .wb-nav-step {
    padding: 5px 0 5px 24px;
    border-radius: 0;
    font-family: Manrope, sans-serif;
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--exp-secondary);
}
body.focus-shell .wb-nav-step:hover {
    background: none;
    color: var(--exp-text);
}
/* Active step: accent dot bullet, no fill. Mirrors
   .library-reading-toc-link.active. The dot sits inside the item's own
   left padding, not hanging off it: the rail scrolls, and a negative
   offset would be clipped away. */
body.focus-shell .wb-nav-step.active {
    position: relative;
    background: none;
    color: var(--exp-toc-active);
    font-size: 12px;
    font-weight: 700;
}
body.focus-shell .wb-nav-step.active::before {
    content: '';
    position: absolute;
    left: 13px;
    top: 50%;
    width: 5px;
    height: 5px;
    margin-top: -2.5px;
    border-radius: 50%;
    background: var(--exp-accent);
}
body.focus-shell .wb-nav-step-dot {
    font-family: Manrope, sans-serif;
    font-size: 10px;
    color: var(--exp-muted);
}
body.focus-shell .wb-nav-step.active .wb-nav-step-dot {
    color: var(--exp-accent);
}
body.focus-shell .wb-nav-step.done .wb-nav-step-dot {
    color: var(--c-done);
}


/* ── Layout: scroller, panel, right rail ───────────────────────
   .wb-reader-content is the scroller and stays transparent; the panel
   is .wb-front-main inside it. Doing it that way is what puts the
   related-items rail OUT on the canvas beside the panel, the way the
   article's right rail sits, with no markup change.

   The 250px right column matches .library-reading-layout--has-rail.
   When a workbook has nothing related, _wbBuildRail returns '' and the
   stock 700px cap on .wb-reader-content applies, which is a fine
   measure for a single-column panel. */
body.focus-shell .wb-reader-content {
    padding: 0 0 40px;
}
body.focus-shell .wb-front-layout--has-rail {
    grid-template-columns: minmax(0, calc(var(--reading-measure) + 60px)) var(--content-rail-w);
    gap: 22px;
    max-width: calc(var(--reading-measure) + 60px + 22px + var(--content-rail-w));
    margin-inline: auto;
}
/* No related items, so the grid above never applies and the stock cap on the
   scroller is the only thing holding the panel in. 700px was that cap; at this
   file's type it is 82 characters a line, so the measure takes over, plus the
   panel's own side padding. The :not() matters: this selector carries
   body.focus-shell and would otherwise beat the `max-width: none` that
   css/views.css puts on the front-matter scroller, capping the scroller AND
   the grid inside it and squeezing the rail. */
body.focus-shell .wb-reader-content:not(.wb-reader-content--front) {
    max-width: calc(var(--reading-measure) + 60px);
    margin-inline: auto;
}
/* The panel. The signature move: the only elevated surface on the page. */
body.focus-shell .wb-front-main {
    padding: 26px 30px;
    border: 1px solid var(--exp-panel-border);
    border-radius: 18px;
    background: var(--exp-panel);
}
body.focus-shell .wb-front-rail {
    top: 0;
    padding-top: 0;
}


/* ── Panel content: front matter, closing, further reading ─────
   Same type ramp as the article body: Manrope throughout, headings
   neutral so the accent stays scarce. */
body.focus-shell .wb-front-header {
    margin-bottom: 22px;
}
body.focus-shell .wb-series-kicker {
    margin-bottom: 12px;
    padding: 3px 9px;
    border: none;
    border-radius: 6px;
    background: var(--exp-accent-wash);
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.08em;
    color: var(--exp-accent-text);
}
body.focus-shell .wb-series-kicker:hover {
    border: none;
    background: var(--exp-accent-wash);
    color: var(--exp-text);
}
body.focus-shell .wb-front-subtitle {
    margin-bottom: 10px;
    font-family: Manrope, sans-serif;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.16em;
}
body.focus-shell .wb-front-subtitle--accent {
    color: var(--exp-accent);
}
body.focus-shell .wb-front-main-title {
    font-family: Manrope, sans-serif;
    font-size: 42px;
    font-weight: 800;
    letter-spacing: -0.025em;
    line-height: 1.08;
    color: var(--exp-text);
}
body.focus-shell .wb-front-title {
    font-family: Manrope, sans-serif;
    font-size: 24px;
    font-weight: 800;
    letter-spacing: -0.015em;
    color: var(--exp-text);
    margin-bottom: 10px;
}
body.focus-shell .wb-front-text,
body.focus-shell .wb-reading-book {
    font-family: Manrope, sans-serif;
    font-size: 16px;
    line-height: 1.8;
    color: var(--exp-body);
}
body.focus-shell .wb-front-text p strong,
body.focus-shell .wb-front-text strong {
    color: var(--exp-text);
}
body.focus-shell .wb-front-text .wb-prose-list li::marker,
body.focus-shell .wb-elem-instruction .wb-prose-list li::marker {
    color: var(--exp-accent);
}
body.focus-shell .wb-front-description {
    font-family: Manrope, sans-serif;
    font-size: 15px;
    line-height: 1.7;
    color: var(--exp-secondary);
}
/* Callout and pull quote become nested panels, the treatment the
   article's "In Short..." block gets, rather than tinted left rules. */
body.focus-shell .wb-front-callout,
body.focus-shell .wb-front-quote,
body.focus-shell .wb-phase-intro {
    padding: 20px 22px;
    border-left: none;
    border-radius: 14px;
    background: var(--exp-nested);
}
body.focus-shell .wb-front-callout h3 {
    font-family: Manrope, sans-serif;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--exp-accent);
}
body.focus-shell .wb-front-callout p,
body.focus-shell .wb-phase-intro {
    font-family: Manrope, sans-serif;
    font-size: 14.5px;
    line-height: 1.7;
    color: var(--exp-body-summary);
}
body.focus-shell .wb-phase-intro strong {
    color: var(--exp-text);
}
body.focus-shell .wb-front-quote p {
    color: var(--exp-body-summary);
}
body.focus-shell .wb-front-quote cite {
    font-family: Manrope, sans-serif;
    color: var(--exp-muted);
}

/* Assessment / guide shortcuts under the cover. */
body.focus-shell .wb-context-btn {
    border: 1px solid var(--exp-ghost-border);
    border-radius: 10px;
    background: none;
    font-family: Manrope, sans-serif;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--exp-ghost-text);
}
body.focus-shell .wb-context-btn:hover {
    border-color: var(--exp-accent);
    color: var(--exp-accent-text);
    background: var(--exp-accent-wash);
}

/* "About this series" disclosure. */
body.focus-shell .wb-series-about {
    border: none;
    border-radius: 14px;
    background: var(--exp-nested);
}
body.focus-shell .wb-series-about-label {
    font-family: Manrope, sans-serif;
    font-size: 13px;
    font-weight: 700;
    color: var(--exp-text);
}
body.focus-shell .wb-series-about-tagline,
body.focus-shell .wb-series-about-chevron {
    color: var(--exp-secondary);
}
body.focus-shell .wb-series-about-body {
    color: var(--exp-body);
}
body.focus-shell .wb-series-about-body p {
    font-family: Manrope, sans-serif;
    font-size: 14.5px;
    line-height: 1.7;
    color: var(--exp-body-summary);
}
body.focus-shell .wb-series-about-link {
    font-family: Manrope, sans-serif;
    color: var(--exp-accent-text);
}

/* Closing and further-reading sections. */
body.focus-shell .wb-closing-section + .wb-closing-section {
    border-top-color: var(--exp-hairline);
}
body.focus-shell .wb-reading-cat-title {
    font-family: Manrope, sans-serif;
    font-size: 17px;
    font-weight: 700;
    color: var(--exp-text);
    border-bottom-color: var(--exp-hairline);
}
body.focus-shell .wb-reading-desc {
    font-family: Manrope, sans-serif;
    color: var(--exp-secondary);
}


/* ── Step view: the work itself ────────────────────────────────
   The toolkit convergence above deliberately stopped at the frame and
   left the tool's own furniture alone. This one does not: on a workbook
   step the furniture IS the page, and leaving the inputs on the stock
   rose against a blue accent would read as two designs stacked. */
body.focus-shell .wb-reader-phase-label {
    font-family: Manrope, sans-serif;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.16em;
    margin-bottom: 10px;
    color: var(--exp-accent);
}
body.focus-shell .wb-reader-step-title {
    font-family: Manrope, sans-serif;
    font-size: 26px;
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.2;
    color: var(--exp-text);
    margin: 0 0 22px;
    padding-left: 0;
    border-left: none;
}
body.focus-shell .wb-reader-elements {
    gap: 18px;
}
body.focus-shell .wb-elem-instruction {
    font-family: Manrope, sans-serif;
    font-size: 15.5px;
    line-height: 1.75;
    color: var(--exp-body);
}
body.focus-shell .wb-elem-label {
    font-family: Manrope, sans-serif;
    font-size: 13.5px;
    font-weight: 700;
    color: var(--exp-text);
    margin-bottom: 6px;
}
body.focus-shell .wb-elem-example {
    padding: 14px 16px;
    border-left: 2px solid var(--exp-accent);
    border-radius: 0 12px 12px 0;
    background: var(--exp-nested);
}
body.focus-shell .wb-elem-example-label {
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.14em;
    color: var(--exp-accent);
}
body.focus-shell .wb-elem-example-text {
    font-family: Manrope, sans-serif;
    font-size: 14px;
    color: var(--exp-secondary);
}
body.focus-shell .wb-elem-recap {
    padding: 14px 16px;
    border: 1px solid var(--exp-panel-border);
    border-radius: 12px;
    background: var(--exp-nested);
}
body.focus-shell .wb-elem-recap-label {
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.14em;
    color: var(--exp-muted);
}
body.focus-shell .wb-elem-recap-list li {
    font-family: Manrope, sans-serif;
    font-size: 14px;
    color: var(--exp-secondary);
}
body.focus-shell .wb-elem-recap-list b {
    color: var(--exp-body);
}
body.focus-shell .wb-elem-textarea textarea {
    padding: 12px 14px;
    border: 1px solid var(--exp-panel-border);
    border-radius: 12px;
    background: var(--exp-nested);
    font-family: Manrope, sans-serif;
    font-size: 15px;
    color: var(--exp-body);
}
body.focus-shell .wb-elem-textarea textarea:focus {
    border-color: var(--exp-accent);
    box-shadow: 0 0 0 3px var(--exp-accent-wash);
}
body.focus-shell .wb-elem-check,
body.focus-shell .wb-elem-radio,
body.focus-shell .wb-elem-completion {
    font-family: Manrope, sans-serif;
    font-size: 15px;
    color: var(--exp-body);
}
body.focus-shell .wb-elem-check input,
body.focus-shell .wb-elem-radio input {
    accent-color: var(--exp-accent);
}
body.focus-shell .wb-elem-completion-input {
    border-bottom-color: var(--exp-accent);
    font-family: Manrope, sans-serif;
    color: var(--exp-body);
}
body.focus-shell .wb-rating-anchor,
body.focus-shell .wb-rating-context-low,
body.focus-shell .wb-rating-context-high {
    font-family: Manrope, sans-serif;
    color: var(--exp-secondary);
}
body.focus-shell .wb-rating-context-low b,
body.focus-shell .wb-rating-context-high b {
    font-family: Manrope, sans-serif;
    color: var(--exp-text);
}
body.focus-shell .wb-rating-btn span,
body.focus-shell .wb-scale-btn {
    border: 1px solid var(--exp-ghost-border);
    border-radius: 10px;
    background: var(--exp-nested);
    font-family: Manrope, sans-serif;
    color: var(--exp-secondary);
}
body.focus-shell .wb-rating-btn:hover span,
body.focus-shell .wb-scale-btn:hover {
    border-color: var(--exp-accent);
    color: var(--exp-accent-text);
}
body.focus-shell .wb-rating-btn.selected span,
body.focus-shell .wb-rating-btn:has(input:checked) span,
body.focus-shell .wb-scale-btn.selected {
    border-color: var(--exp-accent);
    background: var(--exp-accent);
    color: var(--exp-canvas);
}
body.focus-shell .wb-elem-divider {
    border-top-color: var(--exp-hairline);
    font-family: Manrope, sans-serif;
    color: var(--exp-muted);
}

/* Drill offer. An offer, not an assignment, so it stays a quiet nested
   block rather than anything that reads like a required next step. */
body.focus-shell .wb-drill-link {
    padding: 16px 18px;
    border: none;
    border-left: 2px solid var(--exp-accent);
    border-radius: 0 12px 12px 0;
    background: var(--exp-nested);
}
body.focus-shell .wb-drill-text {
    font-family: Manrope, sans-serif;
    font-size: 14px;
    color: var(--exp-secondary);
}
body.focus-shell .wb-drill-title {
    font-family: Manrope, sans-serif;
    font-size: 14px;
    color: var(--exp-text);
}
body.focus-shell .wb-drill-sub {
    font-family: Manrope, sans-serif;
    color: var(--exp-muted);
}
body.focus-shell .wb-drill-add {
    border: 1px solid var(--exp-ghost-border);
    border-radius: 8px;
    font-family: Manrope, sans-serif;
    color: var(--exp-ghost-text);
}
body.focus-shell .wb-drill-add:hover {
    background: var(--exp-accent-wash);
    color: var(--exp-text);
}
body.focus-shell .wb-drill-on {
    color: var(--c-done);
}


/* ── Step actions ──────────────────────────────────────────────
   Ghost previous, filled accent forward. The forward button is the one
   filled accent surface in the panel. */
body.focus-shell .wb-reader-actions {
    margin-top: 26px;
    padding-top: 18px;
    border-top: 1px solid var(--exp-hairline);
}
body.focus-shell .wb-prev-btn,
body.focus-shell .wb-next-btn {
    padding: 8px 16px;
    border: 1px solid var(--exp-ghost-border);
    border-radius: 10px;
    font-family: Manrope, sans-serif;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--exp-ghost-text);
}
body.focus-shell .wb-prev-btn:hover,
body.focus-shell .wb-next-btn:hover {
    border-color: var(--exp-accent);
    color: var(--exp-accent-text);
}
body.focus-shell .wb-complete-btn {
    padding: 9px 20px;
    border-radius: 10px;
    background: var(--exp-accent);
    color: var(--exp-canvas);
    font-family: Manrope, sans-serif;
    font-size: 13px;
    font-weight: 800;
}


/* ── Phase transition card ─────────────────────────────────────
   Shown between phases, in its own .wb-reader with no rails, so the
   card itself has to be the panel. */
body.focus-shell .wb-phase-transition {
    padding: 32px 30px;
    border: 1px solid var(--exp-panel-border);
    border-radius: 18px;
    background: var(--exp-panel);
}
body.focus-shell:not(.dark-mode) .wb-phase-transition {
    box-shadow: 0 1px 3px rgba(20, 20, 40, 0.06), 0 8px 24px rgba(20, 20, 40, 0.05);
}
body.focus-shell .wb-phase-transition h2 {
    font-family: Manrope, sans-serif;
    font-weight: 800;
    color: var(--exp-text);
}
body.focus-shell .wb-phase-transition-label {
    font-family: Manrope, sans-serif;
    color: var(--exp-muted);
}
body.focus-shell .wb-phase-transition-title,
body.focus-shell .wb-phase-transition-next h4 {
    font-family: Manrope, sans-serif;
    color: var(--exp-text);
}
body.focus-shell .wb-phase-transition-insights {
    border-radius: 14px;
    background: var(--exp-nested);
}
body.focus-shell .wb-phase-transition-insights h4 {
    font-family: Manrope, sans-serif;
    color: var(--exp-text);
}
body.focus-shell .wb-phase-transition-insight {
    font-family: Manrope, sans-serif;
    color: var(--exp-body);
}
body.focus-shell .wb-phase-transition-preview {
    font-family: Manrope, sans-serif;
    color: var(--exp-secondary);
}




/* ── Light mode ────────────────────────────────────────────────
   The ladder inverts exactly as it does for the article reader: on
   white a border alone does not say "raised", so the panel takes the
   same soft shadow. */
body.focus-shell:not(.dark-mode) .wb-front-main {
    box-shadow: 0 1px 3px rgba(20, 20, 40, 0.06), 0 8px 24px rgba(20, 20, 40, 0.05);
}


/* ── Responsive ────────────────────────────────────────────────
   css/views.css collapses this reader at four breakpoints. Media and
   container queries add no specificity, so without these mirrors the
   rules above would beat them and the layout would stay wide on a
   narrow screen. Keep in sync with css/views.css (~line 8478). */
/* Stays at 900 with the 320px rail: this grid caps the reading column at
   minmax(0, --reading-measure) rather than letting it take the slack, so at a
   900px container it lands on exactly 544px (900 - 320 rail - 36 gap) and is
   never squeezed below its measure. Raising it only cost the two-column
   layout a 100px band. */
@container (max-width: 900px) {
    body.focus-shell .wb-front-layout--has-rail {
        grid-template-columns: minmax(0, 1fr);
        gap: 22px;
        /* One column: no rail track or gap left to add, only the panel's
           own side padding. */
        max-width: calc(var(--reading-measure) + 60px);
    }
    body.focus-shell .wb-front-rail {
        position: static;
    }
}
@media (max-width: 1100px) {
    body.focus-shell .wb-front-layout--has-rail {
        grid-template-columns: minmax(0, 1fr);
        gap: 22px;
        /* One column: no rail track or gap left to add, only the panel's
           own side padding. */
        max-width: calc(var(--reading-measure) + 60px);
    }
    body.focus-shell .wb-front-rail {
        position: static;
    }
}
@container (max-width: 800px) {
    body.focus-shell .wb-reader-nav {
        width: 180px;
        min-width: 180px;
    }
}
@container (max-width: 640px) {
    body.focus-shell .wb-reader-nav {
        width: 100%;
        min-width: 0;
        border-bottom: 1px solid var(--exp-hairline);
        padding: 0 0 14px;
    }
}
@media (max-width: 768px) {
    body.focus-shell .wb-reader {
        padding: 16px;
        gap: 16px;
    }
    body.focus-shell .wb-reader-nav {
        width: 100%;
        min-width: 0;
        border-bottom: 1px solid var(--exp-hairline);
        padding: 0 0 14px;
    }
    body.focus-shell .wb-front-main {
        padding: 20px 18px;
    }
    body.focus-shell .wb-front-main-title {
        font-size: 32px;
    }
}

/* Phone: the position line and the sticky step bar, translated onto the
   Focus tokens. The structural half of both lives in css/views.css; this
   only restates color and type, the way every block in this file does. */
@media (max-width: 600px) {
    body.focus-shell .wb-position-line {
        font-family: Manrope, sans-serif;
        font-size: 11px;
        font-weight: 800;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--exp-muted);
    }
    /* In the bar it drops the caps and the tracking: at 390px those two
       together pushed "Phase 1 of 6 - Step 2 of 5" onto a second row and
       made the bar change height between steps. */
    body.focus-shell .wb-step-bar .wb-position-line {
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 0;
        text-transform: none;
    }
    body.focus-shell .wb-step-bar {
        background: var(--exp-panel);
        border-top: 1px solid var(--exp-panel-border);
    }
    body.focus-shell .wb-step-bar-btn {
        font-family: Manrope, sans-serif;
        font-size: 13px;
        font-weight: 700;
        border: 1px solid var(--exp-panel-border);
        border-radius: 12px;
        color: var(--exp-body);
    }
    body.focus-shell .wb-step-bar .wb-position-line { color: var(--exp-secondary); }
    body.focus-shell .wb-sheet-extra { border-top: 1px solid var(--exp-panel-border); }
}


/* ═══════════════════════════════════════════════════════════════
   COACHING MODULE READER (third convergence surface)
   ═══════════════════════════════════════════════════════════════
   The page reuses the article reader's whole layout vocabulary
   (.library-reading, .library-reading-toc, .library-reading-main,
   .library-reading-rail), so the canvas, the panel, the two quiet rails,
   the cover, the outline and the type ramp all arrive from the sections
   above with no new rules. The accent is the Coaching group amber, set by
   renderApp() as data-focus-accent="coaching" (js/render.js).

   What is left here is the module's own furniture: the one action, the
   starter-card chips, and the coaching questions. Those are page content
   now rather than a preview behind a toggle, so they are typed like body
   copy instead of boxed like cards. A card inside the panel would be two
   boxes saying the same thing.
   ─────────────────────────────────────────────────────────────── */

/* The one action, and the only filled accent surface on the page. It sits
   in the panel, directly under the summary of what it does, rather than in
   the rail with the other readers' actions: the rail is display:none on a
   phone (css/tools.css), and this button is the whole point of the page.
   Same treatment the workbook reader gives its forward button. */
/* The deck page's shelf button is deliberately quieter than the open buttons
   beside it (js/surface-detail.js): opening the deck is the primary act on that
   page, taking it on is the commitment, and two accent-filled buttons stacked
   read as one decision made twice. Scoped under focus-shell because the rule
   above owns .module-load-btn here and outranks the plain one in tools.css. */
body.focus-shell .surface-shelf-row .module-load-btn {
    background: transparent;
    color: var(--exp-ghost-text);
    border: 1px solid var(--exp-ghost-border);
}
body.focus-shell .surface-shelf-row .module-load-btn:hover {
    color: var(--exp-text);
    border-color: var(--exp-accent);
    opacity: 1;
}
body.focus-shell .module-load-btn {
    margin: 0 0 26px;
    padding: 10px 20px;
    border-radius: 10px;
    background: var(--exp-accent);
    color: var(--exp-canvas);
    font-family: Manrope, sans-serif;
    font-size: 13px;
    font-weight: 800;
    letter-spacing: 0;
}

body.focus-shell .module-reading .module-section-note {
    font-family: Manrope, sans-serif;
    font-size: 14.5px;
    line-height: 1.7;
    color: var(--exp-secondary);
    margin: 0 0 6px;
}

/* Starter cards. Twelve short prompts, so they read as a set of chips
   rather than as twelve paragraphs. */
body.focus-shell .module-chip-group {
    margin: 14px 0 18px;
}
body.focus-shell .module-chip-group-label {
    font-family: Manrope, sans-serif;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.14em;
    color: var(--exp-muted);
    margin-bottom: 8px;
}
body.focus-shell .module-chips {
    gap: 6px;
}
body.focus-shell .module-chip {
    padding: 5px 11px;
    border: 1px solid var(--exp-panel-border);
    border-radius: 99px;
    background: var(--exp-nested);
    font-family: Manrope, sans-serif;
    font-size: 13px;
    color: var(--exp-body);
}

/* Coaching questions. The question is the thing to read, the hint is the
   reason it is asked, so the two split on weight and color rather than on
   a box. */
body.focus-shell .module-q {
    margin: 0 0 20px;
    padding-left: 14px;
    border-left: 2px solid var(--exp-hairline);
}
body.focus-shell .module-q-label {
    font-family: Manrope, sans-serif;
    font-size: 16px;
    font-weight: 700;
    line-height: 1.5;
    color: var(--exp-text);
    margin-bottom: 5px;
}
body.focus-shell .module-q-hint {
    font-family: Manrope, sans-serif;
    font-size: 14.5px;
    line-height: 1.7;
    color: var(--exp-secondary);
}

/* The empty state, for a deep link to a module id that no longer exists. */
body.focus-shell:has(.module-reading-empty) .main-area {
    background-color: var(--exp-canvas);
}
