/* ============================================================
   DEFEX Learn — adapted from assets/web-tutorials/assets/
   tutorials.css + combined.css. Design tokens are mapped onto
   the MudBlazor palette (--mud-palette-*) so the page tracks the
   live theme. Everything is scoped under .learn-root to avoid
   leaking the generic class names (.grid, .card, .step, …).
   ============================================================ */

.learn-root {
    /* token bridge: design --color-* → MudBlazor palette */
    --lc-primary: var(--mud-palette-primary);
    --lc-secondary: var(--mud-palette-secondary);
    --lc-success: var(--mud-palette-success);
    --lc-surface: var(--mud-palette-surface);
    --lc-bg-gray: var(--mud-palette-background-grey);
    --lc-fg-1: var(--mud-palette-text-primary);
    --lc-fg-2: var(--mud-palette-text-secondary);
    --lc-fg-3: var(--mud-palette-text-secondary);
    --lc-lines: var(--mud-palette-lines-default);
    --lc-border: var(--mud-palette-divider);
    --lc-border-strong: var(--mud-palette-lines-inputs);
    --lc-gray-light: var(--mud-palette-background-grey);
    /* a brand-tinted "info" wash that reads on both light and dark */
    --lc-info-bg: rgba(21, 93, 252, 0.08);
    --lc-info-border: rgba(21, 93, 252, 0.28);
    /* The same cobalt at full strength, for the places that need an OPAQUE version of that wash —
       anything sitting over the flywheel, where a translucent fill lets the ring draw through it. */
    --lc-info: rgb(21, 93, 252);
    /* …and the ink to go on it. Mixed toward the body text rather than used raw: the palette's
       info hue is tuned to fill a chip, and as 11px uppercase type on a pale wash it reads as
       disabled. Mixing toward --text-primary darkens it on light and lightens it on dark, so one
       declaration stays legible in both. Reserved for one meaning: "DEFEX does this". */
    --lc-info-fg: color-mix(in srgb, var(--mud-palette-info) 60%, var(--mud-palette-text-primary));

    --lc-radius: 5px;
    --lc-radius-sm: 3px;
    --lc-shadow-1: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .06);
    --lc-shadow-2: 0 3px 6px rgba(0, 0, 0, .08), 0 1px 3px rgba(0, 0, 0, .06);
    --lc-shadow-3: 0 10px 20px rgba(0, 0, 0, .08), 0 3px 6px rgba(0, 0, 0, .06);
    --lc-dur: 120ms;
    --lc-ease: cubic-bezier(0.4, 0.0, 0.2, 1);

    position: relative;
    transition: padding-right var(--lc-dur) var(--lc-ease);
}

/* ---- generic helpers (scoped) ----------------------------- */
.learn-root .stack { display: flex; flex-direction: column; gap: 24px; }
.learn-root .row { display: flex; align-items: center; }
.learn-root .gap8 { gap: 8px; }
.learn-root .grow { flex: 1; }
.learn-root .muted { color: var(--lc-fg-3); }
.learn-root .kicker { font: 500 11px var(--mud-typography-default-family, sans-serif); letter-spacing: .07em; text-transform: uppercase; color: var(--lc-fg-3); }
.learn-root .section-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 14px; }
.learn-root .section-title { font: 600 16px var(--mud-typography-default-family, sans-serif); color: var(--lc-fg-1); letter-spacing: .005em; }
.learn-root .dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; flex: 0 0 auto; background: var(--lc-secondary); }


/* ---- navy thumbnail (shared visual DNA) ------------------- */
.learn-root .thumb {
    position: relative; aspect-ratio: 16 / 9; border-radius: var(--lc-radius); overflow: hidden;
    background: radial-gradient(120% 140% at 85% 15%, rgba(21,93,252,.30), transparent 55%), linear-gradient(150deg, #1d2a4a 0%, #0f172b 70%);
    display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.learn-root .thumb-watermark { position: absolute; right: -6px; bottom: -10px; font-size: 78px; color: rgba(255,255,255,.10); line-height: 1; }
.learn-root .pip .thumb-watermark { font-size: 46px; }
.learn-root .thumb-play {
    position: relative; z-index: 1; width: 46px; height: 46px; border-radius: 50%;
    background: rgba(255,255,255,.94); display: flex; align-items: center; justify-content: center;
    box-shadow: 0 4px 14px rgba(0,0,0,.30); transition: transform var(--lc-dur) var(--lc-ease), background var(--lc-dur) var(--lc-ease);
}
.learn-root .thumb-play .mud-icon-root { font-size: 26px; color: var(--lc-secondary); }
.learn-root .thumb-dur { position: absolute; bottom: 8px; right: 8px; z-index: 2; background: rgba(8,12,24,.78); color: #fff; font: 500 11px sans-serif; letter-spacing: .02em; padding: 2px 7px; border-radius: 4px; }
.learn-root .thumb-cat { position: absolute; top: 8px; left: 8px; z-index: 2; display: inline-flex; align-items: center; gap: 6px; background: rgba(255,255,255,.12); color: #fff; font: 500 10.5px sans-serif; letter-spacing: .04em; text-transform: uppercase; padding: 3px 8px; border-radius: 999px; }
.learn-root .thumb-cat .dot { width: 6px; height: 6px; border-radius: 50%; }
.learn-root .thumb-done { position: absolute; inset: 0; z-index: 3; background: rgba(11,17,32,.55); display: flex; align-items: center; justify-content: center; }
.learn-root .thumb-done .mud-icon-root { font-size: 30px; color: #fff; background: var(--lc-success); border-radius: 50%; padding: 4px; }

/* Category accent dots. The colour comes inline from the manifest's `accent` so authoring a new
   category is a content change, not a CSS deploy — this is only the shape + a neutral fallback. */
/* ---- search hero ------------------------------------------ */
.learn-root .hub-search { background: linear-gradient(135deg,#172036,#0f172b); border-radius: var(--lc-radius); box-shadow: var(--lc-shadow-1); padding: 26px 26px 24px; color: #fff; }
.learn-root .hub-search h2 { font: 600 22px sans-serif; letter-spacing: .01em; margin: 0 0 4px; }
.learn-root .hub-search p { font-size: 13px; color: rgba(255,255,255,.6); margin: 0 0 16px; }
.learn-root .search-box { display: flex; align-items: center; gap: 10px; background: #fff; border-radius: var(--lc-radius); padding: 0 14px; max-width: 560px; }
.learn-root .search-box .mud-icon-root { color: #6B7280; font-size: 22px; }
.learn-root .search-box input { border: 0; outline: 0; padding: 13px 0; font: 400 14.5px sans-serif; flex: 1; color: #252525; background: transparent; }
.learn-root .sugg { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.learn-root .sugg button { background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.16); color: #fff; cursor: pointer; font: 500 12px sans-serif; text-transform: none; letter-spacing: .01em; padding: 6px 12px; border-radius: 999px; transition: background var(--lc-dur); }
.learn-root .sugg button:hover { background: rgba(255,255,255,.2); }
.learn-root .hero-links { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 16px; }
.learn-root .hero-link { background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.18); color: #fff; cursor: pointer; font: 500 12.5px sans-serif; text-transform: none; letter-spacing: .01em; padding: 8px 14px; border-radius: var(--lc-radius); display: inline-flex; align-items: center; gap: 7px; transition: background var(--lc-dur); }
.learn-root .hero-link:hover { background: rgba(255,255,255,.18); }
.learn-root .hero-link .mud-icon-root { font-size: 18px; }

/* ---- continue rail ---------------------------------------- */
.learn-root .rail { display: flex; gap: 16px; overflow-x: auto; padding-bottom: 4px; }
.learn-root .rcard { width: 236px; flex-shrink: 0; background: var(--lc-surface); border-radius: var(--lc-radius); box-shadow: var(--lc-shadow-1); overflow: hidden; cursor: pointer; transition: box-shadow var(--lc-dur), transform var(--lc-dur); }
.learn-root .rcard:hover { box-shadow: var(--lc-shadow-2); transform: translateY(-2px); }
.learn-root .rcard .thumb { border-radius: 0; }
.learn-root .rprog { height: 4px; background: var(--lc-lines); }
.learn-root .rprog > span { display: block; height: 100%; background: var(--lc-secondary); }
.learn-root .rcard-b { padding: 10px 12px 12px; }
.learn-root .rcard-t { font: 500 13px sans-serif; color: var(--lc-fg-1); line-height: 1.35; }
.learn-root .rcard-m { font-size: 11px; color: var(--lc-fg-3); margin-top: 4px; }

/* ---- path cards ------------------------------------------- */
.learn-root .paths { display: grid; grid-template-columns: repeat(4,1fr); gap: 16px; }
.learn-root .path { background: var(--lc-surface); border-radius: var(--lc-radius); box-shadow: var(--lc-shadow-1); padding: 18px; cursor: pointer; border-top: 3px solid transparent; transition: box-shadow var(--lc-dur), transform var(--lc-dur); display: flex; flex-direction: column; gap: 10px; }
.learn-root .path:hover { box-shadow: var(--lc-shadow-2); transform: translateY(-2px); }
.learn-root .path.is-sel { box-shadow: 0 0 0 2px var(--lc-secondary), var(--lc-shadow-2); }
.learn-root .path-top { display: flex; align-items: center; justify-content: space-between; }
.learn-root .path-ic { width: 40px; height: 40px; border-radius: var(--lc-radius); display: flex; align-items: center; justify-content: center; }
.learn-root .path-ic .mud-icon-root { font-size: 22px; color: #fff; }

/* Optional header banner (authored per path in _shell.json, served as a signed blob URL). Bleeds to
   the card edges by cancelling the card's padding, and the icon/ring row is pulled up to straddle
   its lower edge — both get a surface-coloured halo so they stay legible over the artwork. */
.learn-root .path-banner { margin: -18px -18px 0; height: 108px; border-radius: var(--lc-radius) var(--lc-radius) 0 0; overflow: hidden; background: var(--lc-gray-light); }
.learn-root .path-banner img { display: block; width: 100%; height: 100%; object-fit: cover; }
.learn-root .path.has-banner .path-top { margin-top: -30px; }
.learn-root .path.has-banner .path-ic { box-shadow: 0 0 0 3px var(--lc-surface), var(--lc-shadow-1); }
.learn-root .path.has-banner .ring { box-shadow: 0 0 0 3px var(--lc-surface), var(--lc-shadow-1); }
/* The artwork is drawn light; knock it back a touch so it doesn't glare against a dark card. */
.defex-theme-dark .learn-root .path-banner img,
.mud-theme-dark .learn-root .path-banner img { filter: brightness(0.88) saturate(0.94); }
.learn-root .path-label { font: 600 15px sans-serif; color: var(--lc-fg-1); }
.learn-root .path-blurb { font-size: 12.5px; color: var(--lc-fg-3); line-height: 1.5; flex: 1; }
.learn-root .path-foot { display: flex; align-items: center; justify-content: space-between; font-size: 11.5px; color: var(--lc-fg-3); margin-top: 2px; }

/* conic progress ring */
.learn-root .ring { --p: 0; position: relative; width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; background: conic-gradient(var(--rc) calc(var(--p)*1%), var(--lc-lines) 0); display: flex; align-items: center; justify-content: center; }
.learn-root .ring::after { content: ''; width: 26px; height: 26px; border-radius: 50%; background: var(--lc-surface); position: absolute; }
.learn-root .ring span { position: relative; z-index: 1; font: 600 9.5px sans-serif; color: var(--lc-fg-1); }

/* ---- path detail stepper ---------------------------------- */
.learn-root .path-detail { background: var(--lc-surface); border-radius: var(--lc-radius); box-shadow: var(--lc-shadow-1); overflow: hidden; }
.learn-root .pd-head { display: flex; align-items: center; gap: 14px; padding: 18px 20px; border-bottom: 1px solid var(--lc-lines); }
.learn-root .pd-ic { width: 44px; height: 44px; border-radius: var(--lc-radius); display: flex; align-items: center; justify-content: center; }
.learn-root .pd-ic .mud-icon-root { color: #fff; font-size: 24px; }
.learn-root .pd-title { font: 600 17px sans-serif; color: var(--lc-fg-1); }
.learn-root .pd-meta { font-size: 12px; color: var(--lc-fg-3); margin-top: 2px; }

/* ---- path search (path detail header) ----------------------
   Sits where "Enter the cinema" used to, scoped to the selected path. The results panel is
   absolutely positioned so it overlays the lesson list rather than pushing the stepper down. */
.learn-root .pd-search { position: relative; flex: 0 0 auto; width: 300px; max-width: 42vw; }
.learn-root .pd-search-box {
    display: flex; align-items: center; gap: 8px;
    background: var(--lc-surface);
    border: 1px solid var(--lc-lines);
    border-radius: var(--lc-radius); padding: 0 10px;
    transition: border-color var(--lc-dur);
}
.learn-root .pd-search-box:focus-within { border-color: var(--mud-palette-primary); }
.learn-root .pd-search-box > .mud-icon-root { font-size: 19px; color: var(--lc-fg-3); flex: 0 0 auto; }
.learn-root .pd-search-box input {
    border: 0; outline: 0; background: transparent; flex: 1; min-width: 0;
    padding: 8px 0; font: 400 13.5px sans-serif; color: var(--lc-fg-1);
}
.learn-root .pd-search-box input::placeholder { color: var(--lc-fg-3); }
.learn-root .pd-search-clear {
    border: 0; background: transparent; cursor: pointer; padding: 0; display: flex;
    align-items: center; color: var(--lc-fg-3);
}
.learn-root .pd-search-clear:hover { color: var(--lc-fg-1); }
.learn-root .pd-search-clear .mud-icon-root { font-size: 16px; }

.learn-root .pd-search-results {
    position: absolute; z-index: 20; top: calc(100% + 6px); right: 0; width: 380px; max-width: 78vw;
    background: var(--lc-surface); border: 1px solid var(--lc-lines);
    border-radius: var(--lc-radius); box-shadow: var(--lc-shadow-2, var(--lc-shadow-1));
    overflow: hidden;
}
.learn-root .pd-search-hit {
    display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
    border: 0; background: transparent; cursor: pointer; padding: 9px 12px;
    border-bottom: 1px solid var(--lc-lines);
}
.learn-root .pd-search-hit:last-child { border-bottom: 0; }
.learn-root .pd-search-hit.is-hit { background: var(--mud-palette-action-default-hover); }
.learn-root .pd-search-hit .mud-icon-root { font-size: 19px; color: var(--lc-fg-3); flex: 0 0 auto; }
.learn-root .pd-search-hit .grow { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.learn-root .pd-search-t {
    font: 500 13.5px sans-serif; color: var(--lc-fg-1);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.learn-root .pd-search-m { font: 400 11.5px sans-serif; color: var(--lc-fg-3); margin-top: 1px; }
.learn-root .pd-search-empty { padding: 14px 12px; font: 400 12.5px sans-serif; color: var(--lc-fg-3); }

/* The card clips its children for the rounded corners, which would also clip the results panel —
   so it un-clips for exactly as long as that panel is on screen. */
.learn-root .path-detail:has(.pd-search-results) { overflow: visible; }

/* Two columns via multi-column layout: rows fill down the left, then continue down the right, and
   the browser balances them (15 lessons → 8/7). column-rule draws the divider between.
   A border-BOTTOM per row rather than the old `.step + .step` top border — with columns, the first
   row of the right-hand column is still an adjacent sibling and would wear a stray rule. */
.learn-root .steps { column-count: 2; column-gap: 0; column-rule: 1px solid var(--lc-lines); }

/* Anti-flash for the GSAP step cascade (gsapInterop.animateCascade). The list starts hidden so the
   rows can't paint in their final positions before the from-states land; the interop adds
   .gsap-ready once they have. The delayed keyframe is the safety net — if GSAP never runs (CDN
   blocked, JS error) the lessons still appear. Own keyframe name, per the house pattern: each
   cascade root owns its fallback so one root's failure can't reveal another's. */
.learn-root .steps-cascade-root { opacity: 0; animation: learnStepsFallback 0.01s linear 1.2s forwards; }
.learn-root .steps-cascade-root.gsap-ready { opacity: 1; animation: none; }
@keyframes learnStepsFallback { to { opacity: 1; } }
.learn-root .step { display: flex; gap: 14px; align-items: center; padding: 13px 18px; cursor: pointer; transition: background var(--lc-dur); border-bottom: 1px solid var(--lc-lines); break-inside: avoid; }
.learn-root .step:hover { background: var(--lc-gray-light); }
.learn-root .step.is-playing { background: var(--lc-info-bg); }
/* inset shadow, not a border-left, so the marker can't shift the row's contents */
.learn-root .step.current { background: var(--lc-info-bg); box-shadow: inset 3px 0 0 var(--lc-secondary); }
.learn-root .step-dur { margin-left: auto; flex-shrink: 0; font: 500 12px sans-serif; font-variant-numeric: tabular-nums; color: var(--lc-fg-3); }
.learn-root .step.current .step-dur { color: var(--lc-secondary); }
.learn-root .step-kind { font-size: 16px !important; color: var(--lc-fg-3); margin-right: 7px; vertical-align: -3px; }
.learn-root .step-node { width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center; font: 600 12px sans-serif; border: 2px solid var(--lc-border-strong); color: var(--lc-fg-3); background: var(--lc-surface); }
.learn-root .step.done .step-node { background: var(--lc-success); border-color: var(--lc-success); color: #fff; }
.learn-root .step.current .step-node { border-color: var(--lc-secondary); color: var(--lc-secondary); }
.learn-root .step.done .step-node .mud-icon-root { font-size: 18px; color: #fff; }
.learn-root .step.current .step-node .mud-icon-root { font-size: 20px; }

/* Numberless row (a browsable path, e.g. Concepts): the node keeps its 30px footprint so titles
   stay aligned with the done/up-next rows above and below, but reads as a plain bullet. */
.learn-root .step-node.is-blank { border-color: transparent; background: transparent; }
.learn-root .step-node.is-blank::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--lc-border-strong); }

.learn-root .step-body { flex: 1; }
.learn-root .step-t { font: 500 14px sans-serif; color: var(--lc-fg-1); min-width: 0; }
.learn-root .step.done .step-t { color: var(--lc-fg-2); }
.learn-root .step-m { font-size: 11.5px; color: var(--lc-fg-3); margin-top: 2px; display: flex; gap: 8px; align-items: center; }
.learn-root .step-go { color: var(--lc-secondary); font-size: 20px; opacity: 0; transition: opacity var(--lc-dur); }
.learn-root .step:hover .step-go { opacity: 1; }
/* flex-shrink/nowrap because the narrower rows inside a phase card would otherwise break
   "UP NEXT" over two lines and grow the row. */
.learn-root .chip-info { flex-shrink: 0; white-space: nowrap; background: var(--lc-info-bg); color: var(--lc-secondary); font: 600 10px sans-serif; letter-spacing: .03em; text-transform: uppercase; padding: 2px 7px; border-radius: 999px; }

/* Cinema shortcut on a concept step — sits between the body and the go arrow. */
.learn-root .step-cinema { flex-shrink: 0; white-space: nowrap; }

/* ---- phase section cards -----------------------------------
   A path whose lessons declare a `phase:` is drawn as one card per act ("Welcome", "Create work",
   …) instead of one long list, so a 14-step onboarding reads as five short commitments rather than
   one long one. Same multi-column trick as .steps — tiles fill down the left column and continue
   down the right, and the browser balances them — but each act is a self-contained tile, sitting on
   a recessed field so it lifts off the panel in both themes. The path's accent arrives inline as
   --pa, so authoring a new path is still a content change rather than a CSS deploy. */
.learn-root .phases { column-count: 2; column-gap: 18px; padding: 18px 20px 0; background: var(--lc-gray-light); }
.learn-root .phase {
    --pa: var(--lc-secondary);
    break-inside: avoid; margin: 0 0 18px;
    background: var(--lc-surface); border: 1px solid var(--lc-lines); border-radius: var(--lc-radius);
    overflow: hidden;
    transition: box-shadow var(--lc-dur) var(--lc-ease), border-color var(--lc-dur) var(--lc-ease);
}
/* The act holding "up next" is lit, so the eye lands on where you actually are instead of scanning
   five identical tiles for the one unfinished row. */
.learn-root .phase.is-current { border-color: var(--lc-info-border); box-shadow: 0 0 0 3px var(--lc-info-bg), var(--lc-shadow-2); }

.learn-root .phase-head { display: flex; align-items: center; gap: 12px; padding: 13px 15px 12px; }
.learn-root .phase-num {
    width: 28px; height: 28px; border-radius: var(--lc-radius-sm); flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: var(--pa); color: #fff;
    font: 700 11.5px sans-serif; letter-spacing: .04em; font-variant-numeric: tabular-nums;
}
.learn-root .phase.is-done .phase-num { background: var(--lc-success); }
.learn-root .phase-label { font: 600 14.5px sans-serif; color: var(--lc-fg-1); letter-spacing: .005em; line-height: 1.25; }
.learn-root .phase-meta { font-size: 11.5px; color: var(--lc-fg-3); margin-top: 2px; }
/* A section fronted by a concept talk says what the act is FOR before it says how long it takes.
   Clamped to two lines: the blurb is an orientation, and a long one would push the first lesson row
   off the fold in a two-column stepper. */
.learn-root .phase-talk-blurb {
    margin-top: 3px; font-size: 12px; line-height: 1.4; color: var(--lc-fg-2);
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
/* The meta line carries the watch action, so it wraps rather than crushing the counts on a narrow
   column. */
.learn-root .phase-head .phase-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; }
/* Tinted with the path accent (via colour-mix off --pa) rather than a fixed hue, so a new path stays
   a content change. Quiet by default — it sits under a heading, not on top of one. */
.learn-root .phase-watch {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 9px 3px 6px; border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--pa) 45%, transparent);
    background: color-mix(in srgb, var(--pa) 12%, transparent);
    color: var(--pa); font: 600 11.5px sans-serif; cursor: pointer;
    transition: background var(--lc-dur) var(--lc-ease), border-color var(--lc-dur) var(--lc-ease);
}
.learn-root .phase-watch:hover { background: color-mix(in srgb, var(--pa) 22%, transparent); border-color: var(--pa); }
.learn-root .phase-watch .mud-icon-root { font-size: 14px; }
/* Once seen it is a way back, not a call to action — it drops the accent and reads as done. */
.learn-root .phase-watch.is-watched {
    color: var(--lc-success);
    border-color: color-mix(in srgb, var(--lc-success) 40%, transparent);
    background: color-mix(in srgb, var(--lc-success) 10%, transparent);
}
.learn-root .phase-watch.is-watched:hover { background: color-mix(in srgb, var(--lc-success) 18%, transparent); border-color: var(--lc-success); }

.learn-root .phase-count { flex-shrink: 0; font: 600 12.5px sans-serif; color: var(--lc-fg-3); font-variant-numeric: tabular-nums; }
/* The slash is punctuation, not data — knocked back so "2" and "3" read first. */
.learn-root .phase-count i { font-style: normal; opacity: .45; margin: 0 1px; }
.learn-root .phase.is-current .phase-count { color: var(--lc-secondary); }
.learn-root .phase-tick { width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0; background: var(--lc-success); display: flex; align-items: center; justify-content: center; }
.learn-root .phase-tick .mud-icon-root { font-size: 15px; color: #fff; }

/* Hairline completion rail for the act, tinted with the path accent. */
.learn-root .phase-bar { height: 2px; background: var(--lc-lines); }
.learn-root .phase-bar > span { display: block; height: 100%; background: var(--pa); transition: width 260ms var(--lc-ease); }
.learn-root .phase.is-done .phase-bar > span { background: var(--lc-success); }

/* Rows sit tighter inside a tile than in the full-width list, and the last one drops its rule so
   the card closes on its own border rather than a stray hairline. */
.learn-root .phase-steps { padding: 2px 0; }
.learn-root .phase .step { padding: 10px 15px; gap: 12px; }
.learn-root .phase .step:last-child { border-bottom: 0; }
.learn-root .phase .step-node { width: 26px; height: 26px; font-size: 11px; }
.learn-root .phase .step-t { font-size: 13.5px; }

/* ---- workflow flywheel -------------------------------------
   A path whose phases carry a `slug` is a set of WORKFLOWS: the stepper lists only the headings,
   and each one opens /learn/workflow/{slug} where its steps are drawn as a wheel.

   Two accents are in play and they mean different things. --pa is the PATH accent, inherited as it
   is everywhere else on this screen. --sa is the SEGMENT accent, authored per band in _shell.json
   and set inline on each band, node and rail — so adding a band stays a content change, exactly the
   argument --pa already makes. Everything tinted is a colour-mix off one of the two; no hue is
   written here. The one exception is the automation treatment, which uses --lc-info-*: it is not a
   band, it is a single meaning ("DEFEX does this") that must read identically across every
   workflow, and a per-workflow colour would break that. */

/* ---- "Recommended for you", on the Getting Started path ----
   Sits BELOW the path's own steps: the steps are the same for everyone and come first, this is the
   part that isn't. Deliberately a DIFFERENT surface to the phase list above it (a tinted panel
   rather than cards on grey) so it reads as an aside off the path, not as one of its sections — the
   material it points at lives on the other two paths and opens there. */
.learn-root .reco {
    padding: 18px 20px; border-top: 1px solid var(--lc-lines);
    background: color-mix(in srgb, var(--lc-secondary) 5%, var(--lc-surface));
    display: flex; flex-direction: column; gap: 16px;
}
.learn-root .reco-head { display: flex; align-items: flex-start; gap: 12px; }
.learn-root .reco-ic {
    width: 34px; height: 34px; border-radius: var(--lc-radius); flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--lc-secondary) 14%, transparent); color: var(--lc-secondary);
}
.learn-root .reco-ic .mud-icon-root { font-size: 19px; }
.learn-root .reco-head > .grow { flex: 1; min-width: 0; }
.learn-root .reco-title { font: 600 15px sans-serif; color: var(--lc-fg-1); }
.learn-root .reco-sub { font-size: 12.5px; line-height: 1.45; color: var(--lc-fg-3); margin-top: 2px; }
.learn-root .reco-edit {
    flex-shrink: 0; display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
    background: transparent; border: 1px solid var(--lc-lines); border-radius: var(--lc-radius);
    padding: 6px 10px; font: 500 12px sans-serif; color: var(--lc-fg-2);
    transition: background var(--lc-dur), border-color var(--lc-dur);
}
.learn-root .reco-edit:hover { background: var(--lc-gray-light); border-color: var(--lc-border-strong); }
.learn-root .reco-edit .mud-icon-root { font-size: 16px; }

.learn-root .reco-group { display: flex; flex-direction: column; gap: 10px; }
.learn-root .reco-group-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; }
.learn-root .reco-group-head > .mud-icon-root { font-size: 17px; color: var(--lc-fg-3); align-self: center; }
.learn-root .reco-group-t { font: 600 12.5px sans-serif; letter-spacing: .04em; text-transform: uppercase; color: var(--lc-fg-2); }
.learn-root .reco-group-m { font-size: 11.5px; color: var(--lc-fg-3); }

/* Two up on a wide screen, one on a narrow one. auto-fit rather than a fixed count so an odd
   card stretches instead of leaving a hole. */
.learn-root .reco-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 10px; }
.learn-root .reco-card {
    display: flex; align-items: center; gap: 12px; text-align: left; cursor: pointer;
    padding: 12px 14px; background: var(--lc-surface);
    border: 1px solid var(--lc-lines); border-radius: var(--lc-radius); color: inherit; overflow: hidden;
    transition: box-shadow var(--lc-dur) var(--lc-ease), border-color var(--lc-dur) var(--lc-ease),
                transform var(--lc-dur) var(--lc-ease);
}
.learn-root .reco-card:hover {
    box-shadow: var(--lc-shadow-2); transform: translateY(-1px);
    border-color: color-mix(in srgb, var(--lc-secondary) 45%, var(--lc-lines));
}
.learn-root .reco-card > .grow { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.learn-root .reco-card-ic {
    width: 34px; height: 34px; border-radius: var(--lc-radius); flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--lc-secondary) 12%, transparent); color: var(--lc-secondary);
}
.learn-root .reco-card-ic .mud-icon-root { font-size: 19px; }
.learn-root .reco-card.is-done .reco-card-ic { background: color-mix(in srgb, var(--lc-success) 14%, transparent); color: var(--lc-success); }
.learn-root .reco-card-t { font: 600 13.5px sans-serif; color: var(--lc-fg-1); line-height: 1.3; }
/* Two lines: the blurb orients, and a longer one would make the cards ragged against each other. */
.learn-root .reco-card-b {
    font-size: 12px; line-height: 1.4; color: var(--lc-fg-2);
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.learn-root .reco-card-m { font-size: 11.5px; color: var(--lc-fg-3); }
.learn-root .reco-card-go { font-size: 20px; color: var(--lc-fg-3); flex-shrink: 0; }
.learn-root .reco-card:hover .reco-card-go { color: var(--lc-secondary); }
.learn-root .reco-bar { display: block; height: 3px; border-radius: 3px; background: var(--lc-lines); margin-top: 6px; overflow: hidden; }
.learn-root .reco-bar > span { display: block; height: 100%; background: var(--lc-secondary); }

/* The never-answered nudge: one row, not a section — there is nothing to recommend yet. */
.learn-root .reco-invite { flex-direction: row; align-items: center; gap: 14px; }
.learn-root .reco-invite > .grow { flex: 1; min-width: 0; }
.learn-root .reco-invite .lc-btn { flex-shrink: 0; }

@media (max-width: 720px) {
    .learn-root .reco-invite { flex-direction: column; align-items: flex-start; }
}

/* ---- the list of workflows, on /learn ---- */
.learn-root .wf-cards { display: flex; flex-direction: column; gap: 12px; padding: 18px 20px; background: var(--lc-gray-light); }
.learn-root .wf-card {
    --pa: var(--lc-secondary);
    display: flex; align-items: center; gap: 14px; padding: 14px 16px;
    background: var(--lc-surface); border: 1px solid var(--lc-lines); border-radius: var(--lc-radius);
    text-decoration: none; color: inherit; overflow: hidden;
    transition: box-shadow var(--lc-dur) var(--lc-ease), border-color var(--lc-dur) var(--lc-ease),
                transform var(--lc-dur) var(--lc-ease);
}
.learn-root .wf-card:hover { box-shadow: var(--lc-shadow-2); border-color: color-mix(in srgb, var(--pa) 50%, var(--lc-lines)); }
/* The workflow holding "up next" is lit, so the eye lands on where you are rather than scanning six
   identical rows — the same treatment .phase.is-current gets on the other paths. */
.learn-root .wf-card.is-current { border-color: var(--lc-info-border); box-shadow: 0 0 0 3px var(--lc-info-bg), var(--lc-shadow-2); }
.learn-root .wf-card > .grow { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.learn-root .wf-card-ic {
    width: 36px; height: 36px; border-radius: var(--lc-radius); flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--pa) 14%, transparent); color: var(--pa);
}
.learn-root .wf-card-ic .mud-icon-root { font-size: 20px; }
.learn-root .wf-card-t { font: 600 14.5px sans-serif; color: var(--lc-fg-1); line-height: 1.25; }
/* Two lines: the blurb orients, and a longer one would push six rows off the fold. */
.learn-root .wf-card-b {
    font-size: 12px; line-height: 1.4; color: var(--lc-fg-2);
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.learn-root .wf-card-m { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; font-size: 11.5px; color: var(--lc-fg-3); }
.learn-root .wf-card-auto,
.learn-root .wf-auto-note { display: inline-flex; align-items: center; gap: 3px; color: var(--lc-info-fg); font-weight: 600; }
.learn-root .wf-card-auto .mud-icon-root,
.learn-root .wf-auto-note .mud-icon-root { font-size: 14px; }
.learn-root .wf-card .phase-bar { margin-top: 5px; border-radius: 999px; overflow: hidden; }
.learn-root .wf-card.is-done .phase-bar > span { background: var(--lc-success); }
.learn-root .wf-card-go { flex-shrink: 0; color: var(--lc-fg-3); display: flex; }
.learn-root .wf-card:hover .wf-card-go { color: var(--pa); }

/* ---- the workflow screen ---- */
.learn-root .wf { display: flex; flex-direction: column; gap: 16px; }
.learn-root .wf-head {
    display: flex; align-items: flex-start; gap: 14px; padding: 16px 18px;
    background: var(--lc-surface); border: 1px solid var(--lc-lines); border-radius: var(--lc-radius);
}
.learn-root .wf-head-ic {
    width: 40px; height: 40px; border-radius: var(--lc-radius); flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--pa) 14%, transparent); color: var(--pa);
}
.learn-root .wf-head-t { font: 600 19px sans-serif; color: var(--lc-fg-1); line-height: 1.25; }
.learn-root .wf-head-b { margin: 6px 0 0; max-width: 76ch; font-size: 13px; line-height: 1.5; color: var(--lc-fg-2); text-wrap: pretty; }
.learn-root .wf-head-meta { flex-shrink: 0; display: flex; flex-direction: column; align-items: flex-end; gap: 6px; font-size: 12px; color: var(--lc-fg-3); }
/* The concept-talk shortcut in the header is a plain secondary MudButton (see WorkflowPage.razor),
   so it needs no accent-tinted pill styling of its own. */

/* Queried as a CONTAINER, not against the viewport. What decides whether the wheel and the rail
   can sit side by side is how much room this page actually got — which the nav rail, the gutter and
   the browser width all move independently. A viewport breakpoint gets that wrong in the ordinary
   case: at 1280px with the nav open the column is ~555px, wide enough by the window's reckoning and
   far too narrow to read a nine-step wheel in. */
.learn-root .wf { container-type: inline-size; container-name: wf; }
.learn-root .wf-body { display: grid; grid-template-columns: minmax(0, 1fr) 372px; gap: 16px; align-items: start; }
/* The stage takes Design D's CHROME panel — the same --defex-glass-* fill, rim, radius and shadow
   PageHeader carries (utilities.css → .page-header), so the wheel sits on the header's surface
   rather than on a grey slab of its own.
   No backdrop-filter: blur is reserved for D's three real chrome surfaces (app bar, nav, page
   header). It isn't missed here — the ground behind this is a smooth gradient, and blurring a
   smooth gradient returns very nearly the same gradient.
   These tokens are LIGHT-ONLY (utilities.css:17); the dark restatement is at the bottom of this
   file with the rest of the D overrides. */
.learn-root .wf-stage {
    display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 16px;
    background: var(--defex-glass-panel);
    border: 1px solid var(--defex-glass-edge);
    border-radius: var(--defex-radius-panel);
    box-shadow: var(--defex-panel-shadow);
}

.learn-root .wf-legend {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px 20px;
    padding: 9px 14px; background: var(--lc-surface);
    border: 1px solid var(--lc-lines); border-radius: var(--lc-radius);
}
.learn-root .wf-legend-i { display: inline-flex; align-items: center; gap: 6px; font: 600 12px sans-serif; color: var(--sa, var(--lc-fg-2)); }
.learn-root .wf-legend-i .mud-icon-root { font-size: 16px; }
.learn-root .wf-legend-bar { width: 22px; height: 4px; border-radius: 999px; background: var(--sa); }
.learn-root .wf-legend-sep { width: 1px; height: 18px; background: var(--lc-lines); }
.learn-root .wf-legend-i.is-auto { color: var(--lc-info-fg); }
/* Manual is the DEFAULT half of the pair, so it stays in body ink — colouring it would make two
   competing signals out of one distinction. */
.learn-root .wf-legend-i.is-manual { color: var(--lc-fg-2); }
.learn-root .wf-legend-chip { width: 14px; height: 14px; border-radius: var(--lc-radius-sm); background: var(--lc-info-bg); border: 1px solid var(--lc-info-border); }

/* One viewBox holds the whole composition — bands, spokes, arrows, hub and steps — so it scales as
   a unit at any container width instead of only lining up at the width it was drawn at. */
.learn-root .wf-wheel { display: block; width: 100%; max-width: 840px; height: auto; }
/* --wfk scales every line with the ring, so a one-step wheel and a nine-step one read with the
   same weight on screen even though their viewBoxes differ. See WorkflowWheel.Scale. */
.learn-root .wf-track { fill: none; stroke: var(--lc-lines); stroke-width: calc(1px * var(--wfk, 1)); }
.learn-root .wf-band { fill: none; stroke: var(--sa); stroke-width: calc(9px * var(--wfk, 1)); stroke-linecap: butt; opacity: .9; }
.learn-root .wf-spoke { fill: none; stroke: var(--lc-lines); stroke-width: calc(1px * var(--wfk, 1)); }
.learn-root .wf-turn { fill: none; stroke: var(--lc-border-strong); stroke-width: calc(1.5px * var(--wfk, 1)); }
.learn-root .wf-arrowhead { fill: var(--lc-border-strong); }

/* Hub and steps are <foreignObject> HTML: SVG <text> does not wrap, and these are sentences. It
   also makes each step a real <button> — focusable, and announced as one. */
.learn-root .wf-hub {
    box-sizing: border-box; width: 100%; height: 100%; border-radius: 999px;
    display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
    padding: 0 30px; background: var(--mud-palette-dark); color: var(--mud-palette-dark-text);
}
.learn-root .wf-hub > .mud-icon-root { font-size: 28px; opacity: .6; }
.learn-root .wf-hub-t { margin-top: 9px; font: 600 15px sans-serif; line-height: 1.3; }
.learn-root .wf-hub-s { margin-top: 8px; font-size: 11.5px; line-height: 1.45; opacity: .65; }
.learn-root .wf-hub-p { margin-top: 12px; padding-top: 10px; border-top: 1px solid rgba(255,255,255,.16); font-size: 11px; opacity: .8; }

.learn-root .wf-node {
    box-sizing: border-box; width: 100%; height: 100%; margin: 0;
    display: flex; align-items: center; gap: 9px; padding: 9px 11px; text-align: left;
    /* One colour for every card on the wheel. The band each step belongs to is already said twice
       over — by the coloured arc it sits on and by its own icon tile — so tinting the card as well
       turned the wheel into four competing colours and made the SELECTED card hard to find. Must
       stay OPAQUE: the card sits ON the ring, and a translucent surface lets the arc draw through. */
    background: var(--lc-surface);
    border: 1px solid var(--lc-lines);
    border-radius: var(--lc-radius); box-shadow: var(--lc-shadow-1); cursor: pointer;
    color: var(--lc-fg-1); font-family: inherit;
    transition: box-shadow var(--lc-dur) var(--lc-ease), border-color var(--lc-dur) var(--lc-ease);
}
.learn-root .wf-node:hover { box-shadow: var(--lc-shadow-2); border-color: color-mix(in srgb, var(--lc-fg-3) 45%, var(--lc-lines)); }
.learn-root .wf-node:focus-visible { outline: 2px solid var(--lc-info-fg); outline-offset: 2px; }
/* The selected step has to win against eight identical siblings, so it takes a ring rather than
   just a heavier border — the border alone is invisible at wheel scale — and that ring BREATHES: on a
   wheel of nine cards movement is the only thing the eye finds without being told where to look.
   Blue because that is the app's selection colour, so it says "you are here" rather than anything
   about the step itself.

   The ring is INSET. A <foreignObject> is sized to the card exactly and clips, so an outward
   box-shadow — the obvious way to draw a pulsing ring — renders nothing at all here. */
.learn-root .wf-node.is-sel {
    border-color: var(--lc-info);
    animation: wf-node-pulse 1.9s var(--lc-ease) infinite;
}
@keyframes wf-node-pulse {
    0%, 100% { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--lc-info) 35%, transparent), var(--lc-shadow-2); }
    50%      { box-shadow: inset 0 0 0 4px color-mix(in srgb, var(--lc-info) 30%, transparent), var(--lc-shadow-2); }
}
@media (prefers-reduced-motion: reduce) {
    .learn-root .wf-node.is-sel {
        animation: none;
        box-shadow: inset 0 0 0 3px color-mix(in srgb, var(--lc-info) 30%, transparent), var(--lc-shadow-2);
    }
}
.learn-root .wf-node-n {
    width: 25px; height: 25px; flex: none; border-radius: 999px;
    display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, var(--sa) 20%, transparent); color: var(--sa);
    font: 600 11.5px sans-serif; font-variant-numeric: tabular-nums;
}
.learn-root .wf-node-n .mud-icon-root { font-size: 16px; }
.learn-root .wf-node.is-sel .wf-node-n { background: var(--sa); color: #fff; }
.learn-root .wf-node.is-auto .wf-node-n { background: color-mix(in srgb, var(--lc-info) 20%, var(--lc-surface)); color: var(--lc-info-fg); }
.learn-root .wf-node.is-done .wf-node-n { background: var(--lc-success); color: #fff; }
.learn-root .wf-node-b { flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* A <foreignObject> CLIPS — there is no overflow to spill into — so the title is clamped rather
   than left to push the automation tag out of the bottom of the card. Three lines is what the
   longest authored title ("The technician performs the inspection") needs at this width. */
.learn-root .wf-node-t {
    font: 500 11.5px sans-serif; line-height: 1.25;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
/* One line, always: this sits below a clamped title inside a clipping foreignObject, so letting it
   wrap is what pushes it out of the bottom of the card. */
.learn-root .wf-node-a {
    margin-top: 4px; font: 600 9.5px sans-serif; letter-spacing: .05em; text-transform: uppercase;
    color: var(--lc-info-fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* The same steps as an ordered list, for widths where the wheel's cards are too small to read.
   One of the two is always hidden — see the breakpoints below. */
.learn-root .wf-steplist { display: none; width: 100%; background: var(--lc-surface); border: 1px solid var(--lc-lines); border-radius: var(--lc-radius); }

/* ---- detail rail ---- */
.learn-root .wf-rail {
    /* No min-height: the rail is as tall as its content now that nothing pushes the nav to the
       bottom. Stretching it to the wheel's height left a dead band between the lesson card and
       Prev/Next. */
    display: flex; flex-direction: column; padding: 18px;
    background: var(--lc-surface); border: 1px solid var(--lc-lines); border-radius: var(--lc-radius);
}
.learn-root .wf-rail-t { margin: 0; font: 600 18px sans-serif; line-height: 1.3; color: var(--lc-fg-1); text-wrap: pretty; }
.learn-root .wf-rail-d { margin: 9px 0 0; font-size: 13px; line-height: 1.55; color: var(--lc-fg-2); text-wrap: pretty; }

.learn-root .wf-autobox { margin-top: 14px; padding: 11px 12px; border-radius: var(--lc-radius); background: var(--lc-info-bg); border: 1px solid var(--lc-info-border); }
.learn-root .wf-autobox-h { display: flex; align-items: center; gap: 5px; font: 600 11px sans-serif; letter-spacing: .06em; text-transform: uppercase; color: var(--lc-info-fg); }
.learn-root .wf-autobox-h .mud-icon-root { font-size: 16px; }
.learn-root .wf-autobox-b { margin-top: 6px; font-size: 12.5px; line-height: 1.5; color: var(--lc-fg-1); }
.learn-root .wf-autobox-m { display: flex; gap: 7px; margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--lc-info-border); font-size: 12px; line-height: 1.45; color: var(--lc-fg-2); }
.learn-root .wf-autobox-m .mud-icon-root { font-size: 16px; flex-shrink: 0; }


/* Everything the step offers, as one list of equal-weight rows — the concept, the lesson, the
   article. No row is promoted: which one a reader needs first depends on the step, and the author
   settles that by ordering them. Hairline rows on the rail's own surface, so the list reads as a
   menu rather than competing calls to action. */
.learn-root .wf-more { margin-top: 16px; }
.learn-root .wf-more-row {
    display: flex; align-items: center; gap: 9px; width: 100%;
    margin-top: 6px; padding: 9px 10px; text-align: left;
    border: 1px solid var(--lc-lines); border-radius: var(--lc-radius);
    background: transparent; color: inherit; text-decoration: none; cursor: pointer;
    transition: background var(--lc-dur) var(--lc-ease), border-color var(--lc-dur) var(--lc-ease);
}
.learn-root .wf-more-row:hover { background: var(--lc-gray-light); border-color: var(--lc-fg-3); }
.learn-root .wf-more-row > .mud-icon-root { font-size: 19px; color: var(--lc-secondary); flex-shrink: 0; }
.learn-root .wf-more-row > .grow { display: flex; flex-direction: column; min-width: 0; }
.learn-root .wf-more-t { font: 500 12.5px sans-serif; line-height: 1.35; color: var(--lc-fg-1); text-wrap: pretty; }
.learn-root .wf-more-m { font-size: 11.5px; color: var(--lc-fg-3); }
.learn-root .wf-more-go { font-size: 16px !important; color: var(--lc-fg-3) !important; flex-shrink: 0; }
.learn-root .wf-more-row.is-watched > .mud-icon-root { color: var(--lc-success); }

/* The step's completion tick. Carries the step's own band accent while it is outstanding, so it
   reads as belonging to this step rather than as a generic save; goes green once ticked, matching
   the success mark the wheel node and the step list already use for the same state. Full width
   because it is the one thing on the rail that CHANGES something. */
.learn-root .wf-done {
    display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
    margin-top: 14px; padding: 10px 12px;
    font: 600 13px sans-serif; cursor: pointer;
    border: 1px solid color-mix(in srgb, var(--sa) 45%, transparent);
    border-radius: var(--lc-radius);
    color: var(--sa);
    background: color-mix(in srgb, var(--sa) 8%, transparent);
    transition: background var(--lc-dur) var(--lc-ease), border-color var(--lc-dur) var(--lc-ease);
}
.learn-root .wf-done:hover { background: color-mix(in srgb, var(--sa) 16%, transparent); border-color: var(--sa); }
.learn-root .wf-done > .mud-icon-root { font-size: 19px; }
.learn-root .wf-done.is-done {
    color: var(--lc-success);
    border-color: color-mix(in srgb, var(--lc-success) 40%, transparent);
    background: color-mix(in srgb, var(--lc-success) 10%, transparent);
}
.learn-root .wf-done.is-done:hover { background: color-mix(in srgb, var(--lc-success) 18%, transparent); border-color: var(--lc-success); }

.learn-root .wf-nav { display: flex; gap: 10px; margin-top: 16px; }
.learn-root .wf-nav .lc-btn { flex: 1; justify-content: center; }

/* ---- workflow: responds to its own column, not the window ---- */
/* Below this the wheel is squeezed under ~660px and its cards stop being readable, so the rail
   folds underneath and hands the whole width back to the diagram. */
@container wf (max-width: 1060px) {
    .learn-root .wf-body { grid-template-columns: minmax(0, 1fr); }
    .learn-root .wf-rail { min-height: 0; }
    .learn-root .wf-head { flex-wrap: wrap; }
    .learn-root .wf-head-meta { align-items: flex-start; flex-direction: row; flex-wrap: wrap; gap: 6px 14px; }
}
/* Narrower still and the header's title column is squeezed into a thin ribbon by the meta beside
   it, so the meta drops to its own line and gives the title the width back. */
@container wf (max-width: 820px) {
    .learn-root .wf-head > .grow,
    .learn-root .wf-head-meta { flex: 1 1 100%; }
}
/* And below THIS even the full width isn't enough — the cards render around 60px wide and their
   labels are gone. A diagram nobody can read is worse than no diagram, so the same steps are
   offered as the ordered list they also are, with the same selection state. */
@container wf (max-width: 700px) {
    .learn-root .wf-wheel,
    .learn-root .wf-legend { display: none; }
    .learn-root .wf-steplist { display: block; }
    .learn-root .wf-stage { padding: 0; background: transparent; border: 0; }
}

/* ---- library grid ----------------------------------------- */
.learn-root .card { background: var(--lc-surface); border-radius: var(--lc-radius); box-shadow: var(--lc-shadow-1); }
.learn-root .bar { height: 6px; border-radius: 999px; background: var(--lc-lines); overflow: hidden; }
.learn-root .bar > span { display: block; height: 100%; background: var(--lc-secondary); border-radius: 999px; }

.learn-root .filter-bar .field { position: relative; max-width: 320px; }
.learn-root .field-input { width: 100%; box-sizing: border-box; border: 1px solid var(--lc-border); background: var(--lc-surface); color: var(--lc-fg-1); border-radius: var(--lc-radius); padding: 9px 12px 9px 34px; font: 400 13.5px sans-serif; outline: none; }
.learn-root .field-input:focus { border-color: var(--lc-secondary); }
.learn-root .field .mud-icon-root { position: absolute; left: 10px; top: 9px; font-size: 18px; color: var(--lc-fg-3); }


/* ---- big player frame (in dock) --------------------------- */
.learn-root .player { position: relative; aspect-ratio: 16 / 9; width: 100%; max-height: 60vh; border-radius: var(--lc-radius); overflow: hidden; background: radial-gradient(110% 130% at 80% 10%, rgba(21,93,252,.28), transparent 55%), linear-gradient(150deg, #1d2a4a 0%, #0d1326 75%); display: flex; align-items: center; justify-content: center; }
.learn-root .player-watermark { position: absolute; right: -20px; bottom: -30px; font-size: 200px; color: rgba(255,255,255,.06); line-height: 1; }
/* Arcade interactive embed — preserves Arcade's recommended aspect wrapper */
.learn-root .arcade-embed { position: relative; padding-bottom: calc(56.25% + 41px); height: 0; width: 100%; border-radius: var(--lc-radius); overflow: hidden; }
.learn-root .arcade-embed iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; color-scheme: light; border: 0; }
/* Real video off blob (kind: video) — sits in the same slot as the mock player frame */
.learn-root .dock-video { width: 100%; aspect-ratio: 16 / 9; max-height: 60vh; object-fit: contain; border-radius: var(--lc-radius); background: #0d1326; display: block; }
/* Written material (kind: article) — the markdown body reads inside the lesson dialog */
.learn-root .dock-article { font-size: 14.5px; line-height: 1.65; color: var(--lc-fg-2); }
.learn-root .dock-article .markdig-markdown > *:first-child { margin-top: 0; }
.learn-root .dock-article h1, .learn-root .dock-article h2, .learn-root .dock-article h3 { font-weight: 600; color: var(--lc-fg-1); line-height: 1.3; margin: 22px 0 8px; }
.learn-root .dock-article h1 { font-size: 20px; }
.learn-root .dock-article h2 { font-size: 17px; }
.learn-root .dock-article h3 { font-size: 15px; }
.learn-root .dock-article p { margin: 0 0 12px; }
.learn-root .dock-article ul, .learn-root .dock-article ol { margin: 0 0 12px; padding-left: 20px; }
.learn-root .dock-article li { margin-bottom: 4px; }
.learn-root .dock-article img { max-width: 100%; height: auto; border-radius: var(--lc-radius); margin: 6px 0; }
.learn-root .dock-article a { color: var(--lc-secondary); }
.learn-root .dock-article code { font-size: 12px; background: var(--lc-gray-light); border-radius: 4px; padding: 1px 5px; }
.learn-root .dock-article pre { background: var(--lc-gray-light); border-radius: var(--lc-radius); padding: 10px 12px; overflow-x: auto; }
.learn-root .dock-article pre code { background: transparent; padding: 0; }
.learn-root .dock-article blockquote { margin: 0 0 10px; padding: 8px 12px; border-left: 3px solid var(--lc-secondary); background: var(--lc-gray-light); border-radius: 0 var(--lc-radius) var(--lc-radius) 0; }
.learn-root .dock-article table { width: 100%; border-collapse: collapse; margin: 0 0 10px; display: block; overflow-x: auto; }
.learn-root .dock-article th, .learn-root .dock-article td { border: 1px solid var(--lc-lines); padding: 5px 8px; text-align: left; }

.learn-root .player-play { width: 84px; height: 84px; border-radius: 50%; background: rgba(255,255,255,.95); display: flex; align-items: center; justify-content: center; box-shadow: 0 8px 28px rgba(0,0,0,.35); cursor: pointer; z-index: 1; transition: transform var(--lc-dur) var(--lc-ease); }
.learn-root .player-play:hover { transform: scale(1.05); }
.learn-root .player-play .mud-icon-root { font-size: 46px; color: var(--lc-secondary); }
.learn-root .player-ui { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; padding: 14px 16px 12px; background: linear-gradient(transparent, rgba(8,12,24,.72)); }
.learn-root .player-scrub { height: 4px; border-radius: 999px; background: rgba(255,255,255,.25); overflow: hidden; }
.learn-root .player-scrub > span { display: block; height: 100%; background: var(--lc-secondary); border-radius: 999px; }
.learn-root .player-row { display: flex; align-items: center; gap: 14px; margin-top: 10px; color: #fff; }
.learn-root .player-row .mud-icon-root { font-size: 20px; opacity: .92; cursor: pointer; color: #fff; }
.learn-root .player-time { font: 500 12px sans-serif; color: rgba(255,255,255,.85); letter-spacing: .02em; }
.learn-root .player-spacer { flex: 1; }

/* ---- lesson player (inside the lesson dialog) -------------- */
.learn-root .dock-head { display: flex; align-items: center; gap: 8px; padding: 14px 14px 14px 22px; border-bottom: 1px solid var(--lc-lines); }
.learn-root .dock-kicker { font: 500 10.5px sans-serif; letter-spacing: .06em; text-transform: uppercase; color: var(--lc-fg-3); display: flex; align-items: center; gap: 6px; }
.learn-root .dock-kicker .dot { width: 6px; height: 6px; border-radius: 50%; }
.learn-root .dock-title { font: 600 17px sans-serif; color: var(--lc-fg-1); line-height: 1.3; margin-top: 3px; }
.learn-root .icon-btn { width: 32px; height: 32px; border-radius: var(--lc-radius); border: 0; background: transparent; cursor: pointer; display: flex; align-items: center; justify-content: center; color: var(--lc-fg-3); transition: background var(--lc-dur); flex-shrink: 0; }
.learn-root .icon-btn:hover { background: var(--lc-gray-light); color: var(--lc-fg-1); }
/* Lesson body: media/prose in the main column, reference + "try it" on a side rail.
   .no-aside reins the prose back to a readable measure instead of letting it run the
   full width of the dialog. */
.learn-root .lesson-grid { display: grid; grid-template-columns: minmax(0,1fr) 320px; gap: 26px; align-items: start; padding: 22px 24px 26px; }
.learn-root .lesson-grid.no-aside { grid-template-columns: minmax(0,1fr); }
.learn-root .lesson-main { min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.learn-root .lesson-grid.no-aside .lesson-main { max-width: 880px; margin-inline: auto; width: 100%; }
/* align-self:start keeps the rail content-height inside the tall grid row, which is what
   lets sticky actually travel while a long article scrolls past it. */
.learn-root .lesson-aside { display: flex; flex-direction: column; gap: 14px; position: sticky; top: 22px; align-self: start; }
.learn-root .dock-desc { font-size: 14px; color: var(--lc-fg-2); line-height: 1.6; margin: 0; }
/* A talk lesson can carry prose as well as narration. The rule + label mark where the
   90-second version ends and the read-at-your-own-pace one begins. */
.learn-root .lesson-prose { border-top: 1px solid var(--lc-lines); padding-top: 18px; }
.learn-root .lesson-prose-head { display: flex; align-items: center; gap: 7px; margin-bottom: 12px;
    font: 500 11px sans-serif; letter-spacing: .07em; text-transform: uppercase; color: var(--lc-fg-3); }
.learn-root .lesson-prose-head .mud-icon-root { font-size: 16px; }
.learn-root .dock-foot { padding: 14px 24px; border-top: 1px solid var(--lc-lines); display: flex; align-items: center; gap: 16px; width: 100%; }
.learn-root .dock-foot .row { margin-left: auto; }
.learn-root .dock-foot .lc-btn-secondary { min-width: 190px; }
.learn-root .dock-pathnav { display: flex; align-items: center; gap: 10px; background: var(--lc-gray-light); border-radius: var(--lc-radius); padding: 10px 12px; }
.learn-root .dpn-t { font: 500 12px sans-serif; color: var(--lc-fg-1); }
.learn-root .dpn-m { font-size: 11px; color: var(--lc-fg-3); margin-top: 1px; }

/* "Read the full article" — the lesson's link out to the Help Center reference. */
.learn-root .help-link { display: flex; align-items: center; gap: 10px; padding: 11px 13px; border: 1px solid var(--lc-border); border-radius: var(--lc-radius); background: var(--lc-surface); color: var(--lc-fg-1); font: 500 13px sans-serif; text-decoration: none; transition: background var(--lc-dur), border-color var(--lc-dur); }
.learn-root .help-link:hover { background: var(--lc-gray-light); border-color: var(--lc-border-strong); }
.learn-root .help-link .mud-icon-root { font-size: 18px; color: var(--lc-secondary); }
.learn-root .help-link-go { font-size: 15px !important; opacity: .6; }

.learn-root .trybox { background: var(--lc-info-bg); border: 1px solid var(--lc-info-border); border-radius: var(--lc-radius); padding: 13px; }
.learn-root .trybox .kicker { color: var(--lc-secondary); }
.learn-root .trybox-hint { font: 500 13px sans-serif; color: var(--lc-fg-1); line-height: 1.4; margin: 6px 0 10px; }
/* A lesson can offer more than one "do it now" route (e.g. organisation settings AND Businesses),
   so the stacked buttons need their own gap. */
.learn-root .trybox .lc-btn-block + .lc-btn-block { margin-top: 8px; }

/* shared button styles for dock / hero (non-MudButton) */
/* Also used on <a> (the deck's previous-lesson step is a real link), hence text-decoration. */
.learn-root .lc-btn { border: 0; cursor: pointer; border-radius: var(--lc-radius); font: 600 13px sans-serif; text-transform: none; letter-spacing: .01em; padding: 9px 14px; display: inline-flex; align-items: center; justify-content: center; gap: 7px; text-decoration: none; transition: background var(--lc-dur), box-shadow var(--lc-dur); }
.learn-root .lc-btn .mud-icon-root { font-size: 18px; }
.learn-root .lc-btn-secondary { background: var(--lc-secondary); color: #fff; }
.learn-root .lc-btn-secondary:hover { box-shadow: var(--lc-shadow-2); }
.learn-root .lc-btn-outlined { background: transparent; border: 1px solid var(--lc-border-strong); color: var(--lc-fg-1); }
.learn-root .lc-btn-outlined:hover { background: var(--lc-gray-light); }
.learn-root .lc-btn-block { width: 100%; }

/* ---- minimized PiP pill ----------------------------------- */
.learn-root .pip { position: fixed; bottom: 18px; right: 18px; width: 300px; background: var(--lc-surface); border-radius: var(--lc-radius); box-shadow: var(--lc-shadow-3); border: 1px solid var(--lc-border); display: flex; align-items: center; gap: 10px; padding: 8px; z-index: 1000; cursor: pointer; }
.learn-root .pip .thumb { width: 76px; aspect-ratio: 16/9; border-radius: var(--lc-radius-sm); }
.learn-root .pip-t { font: 500 12.5px sans-serif; color: var(--lc-fg-1); line-height: 1.3; }
.learn-root .pip-m { font-size: 11px; color: var(--lc-fg-3); margin-top: 3px; }

/* ---- lesson dialog shell ---------------------------------- */
/* The lesson opens in a large MudDialog. Its own header / body / footer already carry the
   padding and rules the old docked panel had, so MudBlazor's slot chrome is zeroed out and
   the paper becomes a flex column: fixed head, scrolling body, fixed foot.
   Keyed off :has(.lesson-grid) — the same pattern dialogs.css uses — so it holds regardless
   of where MudDialog lands the Class. */
.mud-dialog.learn-lesson-dlg,
.mud-dialog:has(.lesson-grid) {
    width: min(1160px, 94vw);
    max-width: none;
    max-height: min(92vh, calc(100dvh - var(--mud-appbar-height, 64px)));
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
.mud-dialog:has(.lesson-grid) .mud-dialog-title { padding: 0; margin: 0; border-bottom: 0; flex: 0 0 auto; }
.mud-dialog:has(.lesson-grid) .mud-dialog-content { padding: 0; margin: 0; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.mud-dialog:has(.lesson-grid) .mud-dialog-actions { padding: 0; margin: 0; border-top: 0; flex: 0 0 auto; display: block; }

/* responsive: collapse multi-column grids on small screens */
@media (max-width: 1100px) {
    .learn-root .paths { grid-template-columns: repeat(2,1fr); }
    /* Two columns of lesson rows need the width to stay readable — below this they stack. */
    .learn-root .steps { column-count: 1; column-rule: 0; }
    .learn-root .phases { column-count: 1; padding: 14px 14px 0; }
    .learn-root .wf-cards { padding: 14px; }
}
@media (max-width: 900px) {
    /* Deck resources drop under the slides rather than stealing width from them. */
    .learn-root .ct-deck-row { flex-direction: column; }
    .learn-root .ct-deck-rail { width: 100%; height: 0; }
    .learn-root .ct-deck-row.rail-open > .ct-deck-rail { width: 100%; height: auto; margin-left: 0; margin-top: 14px; }
    .learn-root .ct-deck-rail-inner { width: 100%; }

    /* Side rail folds under the lesson, and the footer stacks so the primary action stays wide. */
    .learn-root .lesson-grid,
    .learn-root .lesson-grid.no-aside { grid-template-columns: minmax(0,1fr); gap: 18px; padding: 16px; }
    .learn-root .lesson-aside { position: static; }
    .learn-root .dock-head { padding: 12px 12px 12px 16px; }
    .learn-root .dock-foot { flex-direction: column; align-items: stretch; gap: 10px; padding: 12px 16px; }
    .learn-root .dock-foot .row { margin-left: 0; }
    .learn-root .dock-foot .lc-btn-secondary { min-width: 0; }
    .mud-dialog.learn-lesson-dlg,
    .mud-dialog:has(.lesson-grid) { width: 100vw; height: 100dvh; max-height: 100dvh; border-radius: 0; margin: 0; }
}
@media (max-width: 640px) {
    .learn-root .paths { grid-template-columns: 1fr; }
    .learn-root .wf-card { flex-wrap: wrap; }
}

/* ===================== concept-talk player ===================== */
.learn-root .ct { display: flex; flex-direction: column; gap: 14px; }
.learn-root .ct-stage {
    background: var(--lc-surface);
    border: 1px solid var(--lc-lines);
    border-radius: var(--lc-radius);
    padding: 14px;
    display: flex; align-items: center; justify-content: center;
    min-height: 220px;
}
.learn-root .ct-stage .dex-sketch { margin-top: 0; border: none; background: transparent; max-width: 460px; }

.learn-root .ct-side { display: flex; flex-direction: column; gap: 12px; }
.learn-root .ct-controls { display: flex; gap: 8px; }
.learn-root .ct-btn {
    display: inline-flex; align-items: center; gap: 6px;
    font: 500 13px sans-serif; cursor: pointer;
    padding: 7px 14px; border-radius: var(--lc-radius);
    /* Also worn by anchors (the deck's Cinema link), which arrive underlined and link-coloured. */
    text-decoration: none;
    border: 1px solid var(--lc-lines); background: var(--lc-surface); color: var(--lc-fg-1);
    transition: background var(--lc-dur), box-shadow var(--lc-dur);
}
.learn-root .ct-btn .mud-icon-root { font-size: 18px; }
.learn-root .ct-btn:hover:not([disabled]) { background: var(--lc-lines); }
.learn-root .ct-btn[disabled] { opacity: .45; cursor: default; }
.learn-root .ct-btn-primary { background: var(--lc-secondary); border-color: var(--lc-secondary); color: #fff; }
.learn-root .ct-btn-primary:hover:not([disabled]) { box-shadow: var(--lc-shadow-1); background: var(--lc-secondary); }

.learn-root .ct-script { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.learn-root .ct-beat {
    padding: 10px 12px; border-radius: var(--lc-radius);
    border-left: 3px solid transparent;
    background: var(--lc-surface);
    transition: background var(--lc-dur), border-color var(--lc-dur), opacity var(--lc-dur);
    opacity: .6;
}
.learn-root .ct-beat.is-done { opacity: .8; }
.learn-root .ct-beat.is-current {
    opacity: 1;
    border-left-color: var(--lc-secondary);
    background: color-mix(in srgb, var(--lc-secondary) 10%, var(--lc-surface));
}
.learn-root .ct-beat-label { display: block; font: 600 11px sans-serif; letter-spacing: .05em; text-transform: uppercase; color: var(--lc-fg-3); margin-bottom: 3px; }
.learn-root .ct-beat-text { font: 400 13.5px sans-serif; line-height: 1.5; color: var(--lc-fg-1); }

/* ---- Concept deck (reveal.js presentation of a concept talk) ---- */
.learn-root .ct-deck-controls { align-items: center; margin-bottom: 12px; }
.learn-root .ct-deck-count { margin-left: auto; font: 600 12px sans-serif; color: var(--lc-fg-3); }

/* The deck's chrome now rides in the PageHeader's actions slot, which is OUTSIDE .learn-root — the
   --lc-* token bridge doesn't reach it, so these rules spend --mud-palette-* and the :root-level
   --defex-* tokens directly. The count also loses its margin-left:auto: in the bar it was pushing
   itself to the far end, in the header the actions stack already places it. */
.page-header .ct-deck-count {
    margin-left: 0;
    font: 600 12px sans-serif;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}
.page-header .ct-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    font: 500 13px sans-serif;
    color: var(--mud-palette-text-primary);
    text-decoration: none;
    cursor: pointer;
    border: 1px solid var(--defex-card-edge);
    border-radius: var(--defex-radius-control);
    background: var(--defex-card-bg);
    white-space: nowrap;
}
.page-header .ct-btn:hover:not([disabled]) { background: var(--defex-inner-bg); }
.page-header .ct-btn.is-on {
    background: var(--defex-inner-bg);
    border-color: var(--defex-ghost-edge);
}

/* The embedded reveal.js stage. Fixed height so reveal has a viewport to lay out within. */
.learn-root .ct-deck {
    height: calc(100vh - 230px);
    min-height: 420px;
    border: 1px solid var(--lc-border);
    border-radius: var(--lc-radius);
    background: var(--lc-surface);
}
.learn-root .ct-deck:focus { outline: none; }

/* ---- chain strip (workflow stages, above a chain deck's slides) ----
   A chain deck crosses five screens; the strip is what stops a learner losing which stage they are
   watching. Ruled rather than boxed, per the register system: a 1px connector carries the sequence
   and the dots carry the state.

   Nothing here changes size between states — the label holds one weight throughout and only its
   colour moves. A weight change would re-measure the row on every slide advance and make the strip
   twitch as the deck plays, which is the same reason selection never thickens a border in this app. */
.learn-root .ct-spine {
    display: flex;
    align-items: flex-start;
    gap: 0;
    margin: 0 0 12px;
    padding: 0;
    list-style: none;
    /* The strip owns its overflow — a five-stage chain never pushes the page sideways. */
    overflow-x: auto;
    scrollbar-width: thin;
}

.learn-root .ct-spine-stage {
    position: relative;
    flex: 1 1 0;
    min-width: 96px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 0 8px;
    text-align: center;
}

/* The connector arrives from the left, so a stage owns the rule that leads INTO it and the first
   stage has none. Colouring it by this stage's own state is what makes the accent advance with the
   deck instead of being drawn twice. */
.learn-root .ct-spine-stage + .ct-spine-stage::before {
    content: "";
    position: absolute;
    top: 5px;
    right: 50%;
    left: -50%;
    height: 1px;
    background: var(--lc-lines);
    transition: background 220ms var(--lc-ease);
}

.learn-root .ct-spine-dot {
    position: relative;
    z-index: 1;
    width: 11px;
    height: 11px;
    border-radius: 50%;
    background: var(--lc-surface);
    box-shadow: inset 0 0 0 1px var(--lc-lines);
    transition: background 220ms var(--lc-ease), box-shadow 220ms var(--lc-ease);
}

.learn-root .ct-spine-label {
    font: 500 13px var(--mud-typography-default-family, sans-serif);
    line-height: 1.35;
    color: var(--lc-fg-3);
    transition: color 220ms var(--lc-ease);
}

/* Reached: the accent fills the dot and the rule behind it. */
.learn-root .ct-spine-stage.is-done::before,
.learn-root .ct-spine-stage.is-current::before { background: var(--sp-accent); }

.learn-root .ct-spine-stage.is-done .ct-spine-dot,
.learn-root .ct-spine-stage.is-current .ct-spine-dot {
    background: var(--sp-accent);
    box-shadow: inset 0 0 0 1px var(--sp-accent);
}

.learn-root .ct-spine-stage.is-done .ct-spine-label { color: var(--lc-fg-2); }

/* Current: the one stage the viewer is inside. A halo ring rather than a bigger dot, so the row
   never re-measures as the deck advances. */
.learn-root .ct-spine-stage.is-current .ct-spine-dot {
    box-shadow: inset 0 0 0 1px var(--sp-accent),
                0 0 0 4px color-mix(in srgb, var(--sp-accent) 26%, transparent);
}

.learn-root .ct-spine-stage.is-current .ct-spine-label { color: var(--lc-fg-1); }

@media (prefers-reduced-motion: reduce) {
    .learn-root .ct-spine-stage::before,
    .learn-root .ct-spine-dot,
    .learn-root .ct-spine-label { transition: none; }
}

/* Narrow: the dots and their ruling still say where you are, and the labels are on the slide
   itself — so drop the labels rather than crushing them to an unreadable width. */
@media (max-width: 700px) {
    .learn-root .ct-spine-stage { min-width: 0; padding: 0 4px; }
    .learn-root .ct-spine-label { display: none; }
}

/* ---- resources rail (slides in beside the slides) ----------------
   The deck genuinely narrows rather than being overlaid, so a centred diagram is never covered.
   ConceptDeck redraws the visible slide once the transition settles — rough.js measures its
   container as it draws, so without that the diagram keeps the pre-slide width. */
.learn-root .ct-deck-row { display: flex; align-items: stretch; }
/* The stage: the reveal container plus the transport floating over it. It exists only to give the
   transport something to be absolute against — the deck itself can't, because reveal.js owns the
   positioning of everything inside it. */
.learn-root .ct-deck-stagewrap { position: relative; flex: 1 1 auto; min-width: 0; display: flex; }
.learn-root .ct-deck-stagewrap > .ct-deck { flex: 1 1 auto; min-width: 0; }

/* THE TRANSPORT. Play/Pause/Replay sit on the slide rather than in the chrome above it, so the
   control that runs the talk is where the eye already is. It rides a translucent wash of the deck
   surface — the buttons keep their own fill, and the wash is what stops the pill reading as a
   tablet dropped on the drawing.

   It lives at the FOOT of the stage in every state. Centre is where the diagram builds, so a
   control parked there covers the thing the format exists to show; and holding one position means
   Play, Pause, Resume and Replay are always found in the same place rather than the pill moving
   under the cursor between states. */
.learn-root .ct-deck-transport {
    position: absolute;
    left: 50%;
    top: 100%;
    transform: translate(-50%, calc(-100% - 18px));
    z-index: 4;
    gap: 8px;
    padding: 8px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--lc-surface) 72%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid var(--defex-card-edge, var(--lc-border));
    box-shadow: var(--defex-panel-shadow, 0 6px 18px rgba(0, 0, 0, .10));
    transition: opacity 220ms var(--lc-ease);
}
.learn-root .ct-deck-transport .ct-btn {
    border-radius: var(--defex-radius-control);
    background: var(--defex-card-bg);
    border-color: var(--defex-card-edge);
}
.learn-root .ct-deck-transport .ct-btn:hover:not([disabled]) { background: var(--defex-inner-bg); }
.learn-root .ct-deck-transport .ct-btn-primary,
.learn-root .ct-deck-transport .ct-btn-primary:hover:not([disabled]) {
    background: var(--lc-secondary);
    border-color: var(--lc-secondary);
}
/* Underway (playing OR paused part-way): sat back a little so the diagram building above it stays
   the loudest thing on screen. Hover or keyboard focus brings it fully forward. Before the talk
   starts and after it ends the pill is at full strength — those are the moments it IS the thing to
   look at. Position never changes; only weight does. */
.learn-root .ct-deck-transport.is-parked { opacity: .82; }
.learn-root .ct-deck-stagewrap:hover .ct-deck-transport.is-parked,
.learn-root .ct-deck-transport.is-parked:focus-within { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
    .learn-root .ct-deck-transport { transition: none; }
}
.learn-root .ct-deck-rail {
    flex: 0 0 auto;
    width: 0;
    margin-left: 0;
    overflow: hidden;
    transition: width 220ms var(--lc-ease), margin-left 220ms var(--lc-ease);
}
.learn-root .ct-deck-row.rail-open > .ct-deck-rail { width: 320px; margin-left: 16px; }
.learn-root .ct-deck-rail-inner {
    width: 320px;
    height: 100%;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 14px;
}
/* The current slide's words. Takes the space under the reference cards and scrolls on its own
   when a beat runs long, so the cards above stay put. */
/* ---- the end card ----------------------------------------------------------------
   The slide a talk finishes on. It is quiet on purpose: no surface, no border, no illustration. Its
   whole job is to say the topic ended and offer the two or three things worth doing next, so it
   should read as the deck coming to rest rather than as one more slide of content. */
.learn-root .ct-end-slide { text-align: center; }
.learn-root .ct-end-kicker {
    margin: 0;
    font: 600 11px sans-serif;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--lc-fg-3);
}
.learn-root .ct-end-heading {
    margin: 10px 0 0;
    font: 600 26px/1.25 sans-serif;
    color: var(--lc-fg-1);
}
.learn-root .ct-end-sub {
    margin: 8px 0 0;
    font: 400 14.5px sans-serif;
    color: var(--lc-fg-2);
}
/* Wraps rather than scrolls: a talk with a help article AND two try-actions can carry four buttons,
   and on a narrow deck they belong on two rows, not off the edge. */
.learn-root .ct-end-actions {
    margin-top: 26px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 10px;
}
/* The primary sits last in the source (it is the onward step) but should read first among equals. */
.learn-root .ct-end-actions .lc-btn { min-width: 170px; }

.learn-root .ct-deck-script {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    background: var(--lc-surface);
    border: 1px solid var(--lc-border);
    border-radius: var(--lc-radius);
    padding: 14px 15px;
}
.learn-root .ct-deck-script-text {
    margin: 8px 0 0;
    font: 400 14.5px/1.65 sans-serif;
    color: var(--lc-fg-1);
}
/* The rail's own toggle, so the control reads as pressed while the panel is out. */
.learn-root .ct-btn.is-on { background: var(--lc-gray-light); border-color: var(--lc-border-strong); color: var(--lc-fg-1); }

@media (prefers-reduced-motion: reduce) {
    .learn-root .ct-deck-rail { transition: none; }
}

/* reveal.js runs with disableLayout:true (see revealInterop.js), so it does NOT scale/centre
   slides into its fixed 960x700 box — we own the layout. Force the slide group + the active
   section to fill our container, and undo reveal.css's absolute-centre transform. */
.learn-root .ct-deck .slides {
    width: 100%;
    height: 100%;
    inset: 0;
    transform: none;
    text-align: left;
}
.learn-root .ct-deck .slides > section {
    width: 100%;
    height: 100%;
    inset: 0;
}
/* Lay out only the currently-shown section; non-present sections stay hidden by reveal.css.
   Centre the stack vertically so short slides look balanced.
   !important because reveal.js writes an INLINE `display: block` onto whichever section it shows —
   no selector can outrank that. Without it the slide is a block box: align-items never applies (the
   heading hugs the left of its max-width box) and the image frame has no definite height, so a
   `max-height: 100%` child falls back to its intrinsic size and overflows the deck. */
.learn-root .ct-deck .slides > section.present {
    display: flex !important;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    box-sizing: border-box;
    padding: 16px 24px 104px;   /* reserve room at the bottom for the caption overlay */
}
.learn-root .ct-deck-label {
    flex: 0 0 auto;
    margin: 0;
    font: 700 22px sans-serif;
    letter-spacing: .01em;
    text-transform: none;
    color: var(--lc-fg-1);
}
.learn-root .ct-deck-stage {
    flex: 0 1 auto;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}
/* Give the sketch a DEFINITE box (vh height) so the interop's preserveAspectRatio "xMidYMid meet"
   can scale the drawing to fit inside (contain) it. We avoid percentage/flex heights here because
   a flex item's resolved height isn't reliably "definite" for a child's height:100% — that let the
   SVG fall back to auto height and overflow. */
.learn-root .ct-deck-stage .dex-sketch {
    margin: 0;
    border: none;
    background: transparent;
    width: 100%;
    max-width: 760px;
    height: 52vh;
}
.learn-root .ct-deck-stage .dex-sketch svg {
    display: block;
    width: 100% !important;
    height: 100% !important;
}
/* A per-beat image stands in for the diagram on slides that declare ImageUrl. Share the sketch's
   definite box so it scales to "contain" rather than stretching. */
.learn-root .ct-deck-stage .ct-deck-image {
    display: block;
    width: 100%;
    max-width: 760px;
    height: 52vh;
    object-fit: contain;
}
/* Fade (and gently scale) the per-beat image in each time its slide becomes active. reveal.js
   marks the current slide <section class="present">, so re-adding that class on navigation
   restarts the animation. */
.learn-root .ct-deck .slides section.present .ct-deck-image {
    animation: ct-deck-image-in 600ms ease-out both;
}
@keyframes ct-deck-image-in {
    from { opacity: 0; transform: scale(0.97); }
    to   { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .learn-root .ct-deck .slides section.present .ct-deck-image { animation: none; }
}

/* A LESSON deck (narrated illustrations) needs a wider box than a concept talk's diagram: its slides
   are landscape captures of real screens carrying callout copy, and at the sketch's 760px that text
   stops being legible. The image is the instruction here, so it gets the room.

   Sized by WIDTH with a vh cap rather than a fixed height: these frames are landscape, so a fixed
   height letterboxes them inside their own box and leaves a dead band under the slide. vh keeps the
   cap definite, which is what the sketch box above needs its fixed height for. */
.learn-root .ct-deck-lesson .ct-deck-stage .ct-deck-image {
    width: 100%;
    max-width: 1400px;
    height: auto;
    max-height: 66vh;
}
/* Same trap as the sketch box above: the shared title-slide image sizes itself with max-height:100%
   against a `flex:1 1 auto; min-height:0` frame, which is not a definite height — a landscape capture
   then collapses to a thumbnail. Give it a definite vh box and let object-fit do the containing. */
.learn-root .ct-deck-lesson .ct-title-imgframe {
    width: 100%;
    max-width: 1020px;
}
.learn-root .ct-deck-lesson .ct-title-image {
    width: 100%;
    height: 42vh;
    max-width: none;
    max-height: none;
    object-fit: contain;
}

/* An education illustration standing in for a slide's screenshot (see EduIllustrationRegistry).
   Unlike an image it is live HTML, so it is sized by giving it a wider token budget rather than by
   scaling a bitmap — the text inside stays real text at any size. The vh cap matches the image
   above so a deck does not change height when a slide is migrated off its screenshot; anything
   taller scrolls inside the stage rather than pushing the slide furniture off screen.

   Everything else about it is owned by edu-illustration.css. Nothing here reaches inside .edu. */
.learn-root .ct-deck-stage .ct-deck-illustration {
    width: 100%;
    max-height: 66vh;
    overflow: auto;
}
.learn-root .ct-deck-stage .ct-deck-illustration .edu {
    --edu-max-width: 940px;
    margin: 0 auto;
}
.learn-root .ct-title-slide .ct-deck-illustration .edu { --edu-max-width: 820px; margin: 0 auto; }

/* A deliberately text-only slide (authored ‹image none›): the narration IS the slide, so it is set
   large and centred rather than left in the notes rail where nothing would be on screen. */
.learn-root .ct-deck-textslide {
    margin: 0 auto;
    max-width: 760px;
    font: 400 24px/1.5 sans-serif;
    text-align: center;
    color: var(--lc-fg-1);
    text-wrap: balance;
}

/* ---- First slide rendered as an animated TITLE slide (PowerPoint-style opener) ------------- */
.learn-root .ct-deck .slides > section.ct-title-slide.present {
    justify-content: center;
    /* Without this the column children stretch-anchor to the left edge, so a max-width heading and a
       fit-content image frame both hug the left rather than sitting on the slide's centre line. */
    align-items: center;
    gap: 12px;
    padding: 20px 32px 96px;
    text-align: center;
    background:
        radial-gradient(1000px 460px at 50% -8%, rgba(99, 102, 241, 0.10), transparent 70%),
        var(--lc-surface);
}
/* Small-caps position line above the title. It carries the context so the heading itself does not
   have to be oversized to feel like a title card. */
.learn-root .ct-title-eyebrow {
    flex: 0 0 auto;
    margin: 0 0 6px;
    font: 600 11px/1.2 sans-serif;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--lc-fg-2, var(--mud-palette-text-secondary));
}
/* Was 800 weight at up to 46px with a 64x4 rule under it, which read as a poster rather than the
   opening of a lesson and pushed the illustration down the slide. The eyebrow above now does the
   "this is a title card" work, so the heading can sit at a normal heading size and the underline
   is redundant - it was decoration carrying no meaning. */
.learn-root .ct-title-heading {
    flex: 0 0 auto;
    margin: 2px 0 10px;
    max-width: 34ch;
    font: 700 clamp(20px, 2.4vw, 30px)/1.2 sans-serif;
    letter-spacing: -0.01em;
    color: var(--lc-fg-1);
}
/* The image is the slide. It takes every pixel the title and the controls don't need — flex: 1 so it
   absorbs the leftover height, min-height: 0 so it may shrink below its intrinsic size on short
   viewports instead of pushing the heading off the top. */
.learn-root .ct-title-imgframe {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
    max-width: 100%;
    margin-top: 4px;
    padding: 10px;
    border: 1px solid var(--lc-border);
    border-radius: 20px;
    background: var(--lc-surface);
    box-shadow: 0 24px 60px -24px rgba(0, 0, 0, 0.45);
}
.learn-root .ct-title-image {
    display: block;
    width: auto;
    height: auto;
    max-width: min(1180px, 88vw);
    max-height: 100%;
    object-fit: contain;
    border-radius: 12px;
}

/* Cascade entrance — replays whenever the slide becomes .present (reveal re-adds the class). */
.learn-root .ct-deck .slides section.ct-title-slide.present .ct-title-eyebrow { animation: ct-title-rise 720ms cubic-bezier(0.2, 0.7, 0.2, 1) both 120ms; }
.learn-root .ct-deck .slides section.ct-title-slide.present .ct-title-heading { animation: ct-title-rise 720ms cubic-bezier(0.2, 0.7, 0.2, 1) both 180ms; }
.learn-root .ct-deck .slides section.ct-title-slide.present .ct-title-imgframe { animation: ct-title-pop 860ms cubic-bezier(0.2, 0.8, 0.2, 1) both 340ms; }
.learn-root .ct-deck .slides section.ct-title-slide.present .ct-deck-narration { animation: ct-title-fade 700ms ease-out both 700ms; }

@keyframes ct-title-rise { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
@keyframes ct-title-pop  { from { opacity: 0; transform: translateY(26px) scale(0.93); } to { opacity: 1; transform: none; } }
@keyframes ct-title-fade { from { opacity: 0; }                                    to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
    .learn-root .ct-deck .slides section.ct-title-slide.present .ct-title-eyebrow,
    .learn-root .ct-deck .slides section.ct-title-slide.present .ct-title-heading,
    .learn-root .ct-deck .slides section.ct-title-slide.present .ct-title-imgframe,
    .learn-root .ct-deck .slides section.ct-title-slide.present .ct-deck-narration { animation: none; }
}

/* ---- Slide-to-slide transition. disableLayout neutralises reveal's built-in transforms, so the
   incoming (present) content slide fades + slides in here. The title slide is excluded — it keeps
   its own richer cascade above. ---------------------------------------------------------------- */
.learn-root .ct-deck .slides > section.present:not(.ct-title-slide) {
    animation: ct-slide-in 440ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}
@keyframes ct-slide-in {
    from { opacity: 0; transform: translateX(30px); }
    to   { opacity: 1; transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
    .learn-root .ct-deck .slides > section.present:not(.ct-title-slide) { animation: none; }
}
/* Narration pinned to the bottom-centre like video captions (section is position:absolute via
   reveal.css, so it's the containing block for this overlay). */
.learn-root .ct-deck-narration {
    position: absolute;
    left: 50%;
    bottom: 28px;
    transform: translateX(-50%);
    width: max-content;
    max-width: min(900px, calc(100% - 48px));
    margin: 0;
    padding: 10px 18px;
    border-radius: 8px;
    background: rgba(15, 23, 42, .85);
    color: #fff;
    font: 500 16px/1.5 sans-serif;
    text-align: center;
    box-sizing: border-box;
}

.learn-root .ct-deck-missing {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 48px 16px;
    color: var(--lc-fg-3);
}
.learn-root .ct-deck-missing .mud-icon-root { font-size: 40px; }

/* ============================================================
   Design D "Glass Cohesion" — the lesson / concept deck screen
   ============================================================
   Applies to /learn/lesson/{id} and its sibling
   /learn/deck/{talk}, which share every .ct-deck-* class.

   These decks predate Design D: learn.css was lifted whole from the
   tutorials design file and carries its own --lc-* system, so every
   surface here is an opaque --lc-surface rectangle with a grey hairline
   and a 5px radius. Dropped onto D's blue ground that reads as a set of
   hard white slabs sitting NEXT to the app's cards rather than among
   them — same failure the asset lifecycle wheel had (see
   asset-lifecycle-wheel.css:455).

   So this block moves the deck's page-level surfaces onto D's SOLID card
   tier: --defex-card-bg (alpha, so the gradient reads faintly through),
   a white rim, the 18px panel radius and the house card shadow. It is a
   surface change only — the --lc-* palette, typography and the deck's
   own layout are untouched.

   NOT converted to .custom-border: that class brings a nesting reset
   that would flip the rail's inner panels to the grey inner-panel
   treatment. The tokens give the same card without that behaviour.

   NO backdrop-filter anywhere below. Blur is reserved for D's three
   chrome surfaces (app bar, nav, page header) and the page header here
   already gets it from utilities.css with no per-page markup.

   This file is linked AFTER utilities.css (index.template.html:135) and
   these rules sit at the end of it, so each one out-orders the (0,2,0)
   original above at equal specificity. Dark mode is restated at the
   bottom: the --defex-* card tokens are LIGHT-ONLY (utilities.css:17).
   ------------------------------------------------------------ */

/* THE STAGE. The deck box itself — the largest surface on the screen and
   the one that most needs to read as a card rather than as a hole. */
.learn-root .ct-deck {
    background: var(--defex-card-bg);
    border: 1px solid var(--defex-card-edge);
    border-radius: var(--defex-radius-panel);
    box-shadow: var(--defex-card-shadow);
}

/* THE RAIL. Three stacked cards beside the stage — reference link, the
   do-it-now box, and the narration. All three are page-level surfaces
   (siblings in the rail column, not nested inside a card), so they take
   the full card treatment rather than the inner-panel one.

   .trybox keeps its brand-tinted fill: it is a callout, and the tint is
   what marks it as the action in a column of reading material. It takes
   the radius and the shadow so it still sits on the same plane. */
.learn-root .ct-deck-script {
    background: var(--defex-card-bg);
    border: 1px solid var(--defex-card-edge);
    border-radius: var(--defex-radius-panel);
    box-shadow: var(--defex-card-shadow);
    padding: 16px 18px;
}

.learn-root .ct-deck-rail .help-link {
    background: var(--defex-card-bg);
    border: 1px solid var(--defex-card-edge);
    border-radius: var(--defex-radius-panel);
    box-shadow: var(--defex-card-shadow);
    padding: 13px 15px;
}

.learn-root .ct-deck-rail .help-link:hover {
    background: var(--defex-inner-bg);
    border-color: var(--defex-card-edge);
}

.learn-root .ct-deck-rail .trybox {
    border-radius: var(--defex-radius-panel);
    box-shadow: var(--defex-card-shadow);
    padding: 15px;
}

/* THE CONTROLS. A bare row of buttons on the ground above the stage.
   They pick up D's control radius and the card fill so the row reads as
   part of the same material as the panel underneath it, rather than as
   five hard white tablets floating on the gradient. The primary button
   is untouched — it is a filled brand control and already correct. */
.learn-root .ct-deck-controls .ct-btn {
    border-radius: var(--defex-radius-control);
    background: var(--defex-card-bg);
    border-color: var(--defex-card-edge);
    box-shadow: var(--defex-panel-shadow);
}

.learn-root .ct-deck-controls .ct-btn:hover:not([disabled]) {
    background: var(--defex-inner-bg);
}

.learn-root .ct-deck-controls .ct-btn.is-on {
    background: var(--defex-inner-bg);
    border-color: var(--defex-ghost-edge);
}

.learn-root .ct-deck-controls .ct-btn-primary,
.learn-root .ct-deck-controls .ct-btn-primary:hover:not([disabled]) {
    background: var(--lc-secondary);
    border-color: var(--lc-secondary);
}

/* The empty state. Previously bare centred text directly on the page —
   on the gradient it read as a rendering failure rather than a message. */
.learn-root .ct-deck-missing {
    background: var(--defex-card-bg);
    border: 1px solid var(--defex-card-edge);
    border-radius: var(--defex-radius-panel);
    box-shadow: var(--defex-card-shadow);
}

/* Dark mode. Only the RADII survive from above — the --defex-* fills,
   rims and shadows are light-only, and inherited into dark they would
   paint pale translucent cards with bright white outlines on a navy
   page. Everything else goes back to this file's own theme-tracking
   --lc-* tokens, which is exactly how these surfaces looked before. */
.defex-theme-dark .learn-root .ct-deck,
.mud-theme-dark .learn-root .ct-deck,
.defex-theme-dark .learn-root .ct-deck-script,
.mud-theme-dark .learn-root .ct-deck-script,
.defex-theme-dark .learn-root .ct-deck-rail .help-link,
.mud-theme-dark .learn-root .ct-deck-rail .help-link {
    background: var(--lc-surface);
    border-color: var(--lc-border);
    box-shadow: none;
}

.defex-theme-dark .learn-root .ct-deck-rail .trybox,
.mud-theme-dark .learn-root .ct-deck-rail .trybox {
    box-shadow: none;
}

/* The workflow wheel's stage, for the same reason: it borrows PageHeader's glass panel, and those
   white-alpha fills inherited into dark would paint a pale translucent slab with a bright white
   outline on a navy page. Back to this file's own theme-tracking tokens; only the radius survives. */
.defex-theme-dark .learn-root .wf-stage,
.mud-theme-dark .learn-root .wf-stage {
    background: var(--lc-gray-light);
    border-color: var(--lc-lines);
    box-shadow: none;
}

.defex-theme-dark .learn-root .ct-deck-controls .ct-btn,
.mud-theme-dark .learn-root .ct-deck-controls .ct-btn,
.defex-theme-dark .learn-root .ct-deck-transport .ct-btn,
.mud-theme-dark .learn-root .ct-deck-transport .ct-btn {
    background: var(--lc-surface);
    border-color: var(--lc-lines);
    box-shadow: none;
}

.defex-theme-dark .learn-root .ct-deck-controls .ct-btn.is-on,
.mud-theme-dark .learn-root .ct-deck-controls .ct-btn.is-on {
    background: var(--lc-gray-light);
    border-color: var(--lc-border-strong);
}

/* The empty state was bare in dark before this pass and stays bare — a
   navy panel on a navy page would be a visible change, not a no-op. */
.defex-theme-dark .learn-root .ct-deck-missing,
.mud-theme-dark .learn-root .ct-deck-missing {
    background: none;
    border: 0;
    box-shadow: none;
}

/* ============================================================
   Design D "Glass Cohesion" — the workflow wheel screen
   ============================================================
   /learn/workflow/{slug}, every workflow. The page already
   uses the standard scaffold, so PageHeader's glass chrome and the
   blue ground arrive from utilities.css with no markup here; .wf-stage
   took the chrome panel earlier. What was left were the three surfaces
   that sit DIRECTLY on the ground beside it — the workflow's own
   header, the detail rail, and the narrow-width step list — each still
   an opaque --lc-surface rectangle with a grey hairline and a 5px
   radius, reading as hard white slabs next to an 18px glass panel.

   Tier assignment, per DESIGN.md → Glass Cohesion:
     .wf-head     GLASS  — it is this screen's own header strip, the
                           same role PageHeader plays above it, so it
                           takes the same --defex-glass-* panel.
     .wf-rail     SOLID  — a content card beside the stage.
     .wf-steplist SOLID  — the same content, in the layout where the
                           wheel is too small to read.

   Nothing NESTED changes: the legend inside the stage, the wheel's own
   node cards and the rail's autobox/open panels are all inner surfaces
   and keep the --lc-* treatment. The node cards in particular MUST stay
   opaque — they sit on the coloured ring inside a <foreignObject>, and
   any alpha lets the band draw through them.

   NO backdrop-filter, here or anywhere in this file — blur belongs to
   D's three real chrome surfaces only.

   The --defex-* fills, rims and shadows are LIGHT-ONLY
   (utilities.css:17), so each is restated for dark below. */
.learn-root .wf-head {
    background: var(--defex-glass-panel);
    border: 1px solid var(--defex-glass-edge);
    border-radius: var(--defex-radius-panel);
    box-shadow: var(--defex-panel-shadow);
}

.learn-root .wf-rail,
.learn-root .wf-steplist {
    background: var(--defex-card-bg);
    border: 1px solid var(--defex-card-edge);
    border-radius: var(--defex-radius-panel);
    box-shadow: var(--defex-card-shadow);
}

/* Dark keeps only the radii, for the reason given on the deck block
   above: white-alpha fills and bright white rims inherited onto a navy
   page look like a bug rather than a theme. */
.defex-theme-dark .learn-root .wf-head,
.mud-theme-dark .learn-root .wf-head,
.defex-theme-dark .learn-root .wf-rail,
.mud-theme-dark .learn-root .wf-rail,
.defex-theme-dark .learn-root .wf-steplist,
.mud-theme-dark .learn-root .wf-steplist {
    background: var(--lc-surface);
    border-color: var(--lc-lines);
    box-shadow: none;
}

/* --- Collapsible sections (Concepts) ------------------------------------------------------
   The Concepts path is a shelf of ~60 talks browsed by heading, so its section cards open on
   click and start closed. The heading is a div wearing role="button" (it can contain the
   "Watch the concept" button, and buttons can't nest), hence the hand cursor here rather than
   a button's own. */
.learn-root .phase.is-collapsible .phase-head { cursor: pointer; user-select: none; }
.learn-root .phase.is-collapsible .phase-head:hover { background: var(--lc-hover, rgba(127,127,127,.06)); }
.learn-root .phase.is-collapsible .phase-head:focus-visible { outline: 2px solid var(--pa); outline-offset: -2px; }
.learn-root .phase-chev {
    flex-shrink: 0; display: flex; align-items: center; color: var(--lc-fg-3);
    transition: transform var(--lc-dur) var(--lc-ease);
}
.learn-root .phase-chev .mud-icon-root { font-size: 20px; }
.learn-root .phase.is-open .phase-chev { transform: rotate(180deg); }

/* The workflow header IS this page's header (there is no PageHeader above it), so it carries the
   back nav on the left — the one way out, matching PageHeader’s arrow. It is pinned to the title’s
   line rather than to the top of the blurb, which can run to three lines. */
.learn-root .wf-head > .mud-tooltip-root { flex-shrink: 0; margin-top: 6px; }

/* ============================================================
   dexsketch palette (roughSketchInterop.js)
   ------------------------------------------------------------
   Specs author semantic names — "accent", "warn" — never a hex, so one diagram reads correctly on
   the light web host and the dark mobile host. The renderer reads these from the sketch container,
   which is why they sit on :root and not under .learn-root: the same component renders inside Ask
   Dex answers too.

   Ink and muted aren't here — the renderer takes them from the live text colour on the container
   (see _readPalette). The four hues are fixed mid-tones rather than Mud semantic colours: they have
   to hold their meaning against a white board AND a dark one, which the Mud semantics are not tuned
   for (they are chip fills). Each has a matching -fill, used as the rough.js hachure colour and kept
   light enough to sit under a label.
   ============================================================ */
:root {
    /* ink and muted are deliberately NOT declared here: aliasing them to --mud-palette-* would
       substitute at :root and hand every host the light-theme ink. The renderer reads the live text
       colours off the sketch container instead. Declare them here only to override that. */
    --ct-accent: #4C8DFF;  /* the spine: the thing the talk is about */
    --ct-support: #2BB3A3; /* what hangs off the spine */
    --ct-warn: #E9A13B;    /* the gotcha, the "trips people up" box */
    --ct-good: #46B26B;    /* the outcome / the payoff */

    --ct-ink-fill: rgba(120, 124, 132, 0.16);
    --ct-muted-fill: rgba(138, 143, 152, 0.14);
    --ct-accent-fill: rgba(76, 141, 255, 0.26);
    --ct-support-fill: rgba(43, 179, 163, 0.24);
    --ct-warn-fill: rgba(233, 161, 59, 0.28);
    --ct-good-fill: rgba(70, 178, 107, 0.24);
}
