/* ============================================================
   DEFEX Learn — education illustrations
   ------------------------------------------------------------
   The visual language for abstract UI illustrations used in help
   and training content.

   These illustrations DERIVE FROM THE LIVE THEME. Every colour,
   radius and shadow below resolves from --mud-palette-*,
   --defex-* or --status-*, so an illustration of a Defex screen
   looks like Defex — same ink-filled action button, same Rule
   Line, same 18px card, same AA-checked status tokens — and a
   change to the product palette reaches the whole education
   library for free. (This reverses the original decision to
   freeze a private indigo palette here; frozen literals didn't
   survive a redesign, they just stopped tracking it.)

   What stays quarantined is COMPOSITION, not colour: no
   MudBlazor components, no Material icons, no focusable
   controls, no real column sets. See
   Documentation/plans/edu-illustration-framework.md.

   Dark mode needs no marker class: MudThemeProvider swaps the
   palette variables on :root, so every derived token below flips
   with it. (Keying off .mud-theme-dark — as this file used to —
   is dead on the web host, which stamps .defex-theme-dark on
   .main-container instead. Same trap documented at
   utilities.css:410.)

   Everything is scoped under .edu so the generic names below
   (.title, .row, .note, …) cannot leak into the application.
   ============================================================ */

.edu {
    /* ---- tokens: the bridge onto the product theme ------------- */
    /* The illustration canvas, the ground the illustrated screen sits on.

       This has to RECONSTRUCT the product's page ground rather than name it. The obvious token,
       --mud-palette-background-gray (#F4F6FA), is redefined to `transparent` by utilities.css for
       everything inside .main-container - where illustrations render - so using it leaves the stage
       with no fill at all.

       The reconstruction is two mixes because one cannot get there. The old single mix pulled 7% of
       --mud-palette-text-primary (#252525, a NEUTRAL) into white, so the ground could only ever come
       out grey - measured at rgb(240,240,240), R=G=B, zero hue - while every production screen sits
       on a blue-tinted ground. Signal Blue alone overshoots the other way: blue is already near 255
       so mixing it moves red and green and leaves blue untouched, giving a lilac white.

       The target is NOT --mud-palette-background-gray (#F4F6FA). That token is what a page ground
       would be if anything painted it, but nothing does: utilities.css neutralises it inside
       .main-container, and measurement on a real screen confirms html, #app, .main-container and
       .mud-main-content are all transparent. The only ground production actually paints is on body,
       and it is two faint blue radials over the white canvas. So a learner comparing the two sees a
       near-white screen in the app and a grey card in the lesson.

       Hence blue only, and barely any of it: 3% Signal Blue over the surface lands on
       rgb(248,250,255). Adding neutral is what made this grey in the first place - #252525 has no
       hue, so any amount of it drags the ground toward flat grey however much blue goes in.

       Verify by eye against a real page, not against a token: the stage should read as the same
       almost-white the app sits on, with the frame's border doing the work of separating it. */
    --edu-background: color-mix(in srgb, var(--mud-palette-secondary) 3%, var(--mud-palette-surface));
    --edu-surface: var(--mud-palette-surface);
    /* Inert fills (inputs, skeletons, grid heads). Mixed rather than a literal so it stays
       one quiet step off the surface in light, dark and the tenant-operator red.

       Carries the same 1:1 blue-over-neutral construction as --edu-background above, one step
       deeper (lands on ~#EDF0F6). It has to: a neutral grey input sitting on a blue-tinted ground
       is the same mismatch the ground itself had, just smaller and harder to spot. */
    --edu-surface-sunken: color-mix(in srgb, var(--mud-palette-secondary) 7%, var(--mud-palette-surface));
    --edu-border: var(--mud-palette-lines-default);
    --edu-border-strong: var(--mud-palette-lines-inputs);
    --edu-text: var(--mud-palette-text-primary);
    --edu-muted: var(--mud-palette-text-secondary);

    /* THE ACTION. Matches a real filled primary button (Variant.Filled Color="Color.Primary"),
       and resolving from --mud-palette-primary rather than a frozen hex is what lets the
       tenant-operator red reach illustrations too — see DESIGN.md. */
    --edu-accent: var(--mud-palette-primary);
    --edu-accent-contrast: var(--mud-palette-primary-text);

    /* THE TEACHING ANNOTATION — arrows, notes, callouts, the glow ring. Signal Blue, the
       app's "this is actionable" colour, kept DISTINCT from the action fill so the pointer
       and the thing it points at never render as the same object. */
    --edu-attention: var(--mud-palette-secondary);
    --edu-attention-soft: color-mix(in srgb, var(--mud-palette-secondary) 10%, transparent);
    --edu-highlight: color-mix(in srgb, var(--mud-palette-secondary) 30%, transparent);
    /* Retained name: pre-existing rules and lesson components reference it. */
    --edu-accent-soft: var(--edu-attention-soft);

    /* States consume the shared status trio (12/30/66 mixes, AA-checked in both themes).
       Never hand-pick a red, amber or green here — DESIGN.md, the Two-Token Status Rule. */
    --edu-positive: var(--status-success-fg);
    --edu-positive-soft: var(--status-success-bg);
    --edu-positive-border: var(--status-success-border);
    /* A NOTICEABLE STATE (overdue, catch-up). Distinct from both the action and the
       annotation, so a state never competes with what the illustration is teaching. */
    --edu-flag: var(--status-warning-fg);
    --edu-flag-soft: var(--status-warning-bg);
    --edu-flag-border: var(--status-warning-border);

    --edu-radius: var(--defex-radius-panel);          /* cards, screens, modals   */
    --edu-radius-sm: var(--defex-radius-inner);       /* panels nested in a card  */
    --edu-radius-control: var(--defex-radius-control);/* buttons, inputs          */
    --edu-radius-pill: var(--defex-radius-pill);
    /* Design D SOLID: the lift is radius + a large soft shadow, and the rim nearly vanishes. */
    --edu-shadow: var(--defex-card-shadow);
    --edu-shadow-raised: var(--defex-menu-shadow);

    --edu-spacing: 16px;
    --edu-spacing-sm: 8px;
    --edu-spacing-lg: 28px;

    --edu-font: inherit;
    --edu-text-size: clamp(12.5px, 1.6vw, 14px);
    --edu-title-size: clamp(16px, 2.4vw, 20px);
    --edu-max-width: 720px;

    /* animation hooks — see "Animation" at the foot of this file */
    --edu-duration: 260ms;
    --edu-ease: cubic-bezier(.4, 0, .2, 1);
    --edu-delay: 0ms;

    display: block;
    margin: var(--edu-spacing-lg) auto;
    /* Explicit 100%, not just max-width: the deck drops the illustration into a shrink-to-fit
       slot, so without it the figure sizes to its content's max-content width and a four-across
       filter row lands at ~150px per field with every value truncated. */
    width: 100%;
    max-width: var(--edu-max-width);
    font-family: var(--edu-font);
    font-size: var(--edu-text-size);
    line-height: 1.45;
    color: var(--edu-text);
    -webkit-font-smoothing: antialiased;
}

/* The host page's typography is not welcome inside an illustration. */
.edu p, .edu ul, .edu ol, .edu figure { margin: 0; }
.edu * { box-sizing: border-box; }

.edu--component { --edu-max-width: 420px; }
.edu--workflow  { --edu-max-width: 460px; }

.edu__stage {
    background: var(--edu-background);
    border: 1px solid var(--edu-border);
    border-radius: calc(var(--edu-radius) + 4px);
    padding: var(--edu-spacing-lg);
    /* NO container-type here. The deck's illustration slot is a shrink-to-fit flex item, so size
       containment on the stage makes its intrinsic contribution zero and the whole illustration
       collapses to a ~180px column. The form grid wraps on flex-basis instead. */
    /* Real screens are left-aligned. The lesson deck centres its slide typography, and without
       this the host's text-align reaches every screen title, field label and card inside the
       illustration — which reads as a poster, not as the product. The caption and the callout
       note re-centre themselves. */
    text-align: left;
}

.edu--component .edu__stage { padding: var(--edu-spacing-lg) var(--edu-spacing); }

.edu__caption {
    margin: var(--edu-spacing-sm) 2px 0;
    font-size: .92em;
    color: var(--edu-muted);
    text-align: center;
}

/* Screen-reader-only description: the instruction must survive with
   images off, colour removed, or a screen reader in use. */
.edu__sr {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ---- screen: the abstract "page" -------------------------- */

.edu-screen {
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius);
    box-shadow: var(--edu-shadow);
    padding: var(--edu-spacing);
    display: flex;
    flex-direction: column;
    gap: var(--edu-spacing);
}

.edu-screen__head { display: flex; flex-direction: column; gap: 2px; }
.edu-screen__title { margin: 0; font-size: var(--edu-title-size); font-weight: 600; letter-spacing: -.01em; }
.edu-screen__subtitle { margin: 0; color: var(--edu-muted); font-size: .92em; }

/* A window chrome bar, only when the illustration is teaching
   "this is a separate window/screen". Three dots, nothing more. */
.edu-screen--chrome { padding-top: 0; }
.edu-screen__chrome {
    display: flex; align-items: center; gap: 6px;
    margin: 0 calc(var(--edu-spacing) * -1);
    padding: 10px var(--edu-spacing);
    border-bottom: 1px solid var(--edu-border);
}
.edu-screen__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--edu-border-strong); }

/* ---- page header ------------------------------------------
   The bar every Defex page scaffolds above its content: icon tile, eyebrow, title. */

.edu-page-header {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius);
    box-shadow: var(--edu-shadow);
}
.edu-page-header__tile {
    flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px;
    border-radius: var(--defex-radius-tile, 12px);
    background: var(--edu-attention-soft);
    border: 1px solid color-mix(in srgb, var(--edu-attention) 25%, transparent);
    color: var(--edu-attention);
    font-size: 1.15em;
}
.edu-page-header__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.edu-page-header__eyebrow { font-size: .8em; color: var(--edu-muted); }
.edu-page-header__actions { display: flex; align-items: center; gap: var(--edu-spacing-sm); margin-left: auto; flex-wrap: wrap; justify-content: flex-end; }
.edu-page-header__title { font-size: var(--edu-title-size); font-weight: 600; letter-spacing: -.01em; }

/* ---- app bar ----------------------------------------------- */

.edu-appbar {
    display: flex;
    align-items: center;
    gap: var(--edu-spacing-sm);
    padding: 8px 12px;
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius-pill);
    box-shadow: var(--edu-shadow);
}
.edu-appbar__tenant { font-weight: 600; white-space: nowrap; }
.edu-appbar__spacer { flex: 1 1 0; min-width: 0; }
.edu-appbar .edu-search { flex: 0 1 200px; }

/* ---- tabs --------------------------------------------------
   Top-rounded pills under a faint rule, the active one lifted on the surface with a blue inset
   underline — the Design D tab treatment from utilities.css. */

.edu-tabs {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    border-bottom: 1px solid var(--edu-border);
}
.edu-tabs__tab {
    padding: 8px 16px;
    color: var(--edu-muted);
    font-weight: 500;
    border-radius: var(--edu-radius-sm) var(--edu-radius-sm) 0 0;
    white-space: nowrap;
}
.edu-tabs__tab--active {
    color: var(--edu-text);
    background: var(--edu-surface);
    box-shadow: inset 0 -2px 0 var(--edu-attention);
}

/* ---- navigation menu --------------------------------------- */

.edu-nav {
    /* 218px, not the real drawer's 260: wide enough that "Clients & Properties" fits on one line,
       which is the longest group label the lessons point at. */
    width: 218px;
    flex: none;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--edu-spacing-sm);
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius);
    box-shadow: var(--edu-shadow);
}
.edu-nav__search { margin-bottom: 6px; min-height: 30px; }
.edu-nav__row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 7px 8px;
    border-radius: var(--defex-radius-nav, 9px);
}
.edu-nav__glyph { flex: none; color: var(--edu-muted); }
.edu-nav__text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.edu-nav__chevron { flex: none; color: var(--edu-muted); transform: rotate(90deg); }
.edu-nav__group--open > .edu-nav__row { background: var(--edu-surface-sunken); }
.edu-nav__group--open > .edu-nav__row .edu-nav__chevron { transform: rotate(-90deg); }
.edu-nav__children { display: flex; flex-direction: column; gap: 2px; padding: 2px 0 2px 26px; }
.edu-nav__child {
    padding: 6px 10px;
    border-radius: var(--defex-radius-nav, 9px);
    color: var(--edu-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.edu-nav__child--active {
    background: var(--edu-surface);
    box-shadow: var(--edu-shadow);
    color: var(--edu-text);
    font-weight: 500;
}

/* ---- dropdown menu ----------------------------------------- */

.edu-menu {
    width: 240px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--edu-spacing-sm);
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius);
    box-shadow: var(--edu-shadow-raised);
}
.edu-menu__search { margin-bottom: 6px; min-height: 30px; }
.edu-menu__section { display: flex; flex-direction: column; gap: 2px; padding-top: 6px; }
.edu-menu__section-label {
    padding: 2px 8px;
    font-size: .78em; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--edu-attention);
}
.edu-menu__item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 8px;
    border-radius: var(--defex-radius-nav, 9px);
}
.edu-menu__glyph { flex: none; color: var(--edu-muted); }
.edu-menu__text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edu-menu__chevron { flex: none; color: var(--edu-muted); }
.edu-menu__item--action { background: var(--edu-attention-soft); color: var(--edu-text); font-weight: 600; }

/* ---- step card --------------------------------------------
   A numbered section card. The real screens stack these on the page ground with no outer frame,
   so an illustration using them should NOT also wrap the lot in an EduScreen. */

.edu-step-card {
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius);
    box-shadow: var(--edu-shadow);
    padding: var(--edu-spacing);
    display: flex;
    flex-direction: column;
    gap: var(--edu-spacing);
}
.edu-step-card__head { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
/* Signal Blue, filled, white numeral — NumberCircle Color="Color.Secondary" Size="Size.Small". */
.edu-step-card__number {
    flex: none;
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--edu-attention);
    color: var(--mud-palette-secondary-text, #fff);
    font-size: .85em; font-weight: 700; line-height: 1;
}
.edu-step-card__heading { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.edu-step-card__title { font-size: var(--edu-title-size); font-weight: 600; letter-spacing: -.01em; }
.edu-step-card__subtitle { color: var(--edu-muted); font-size: .92em; }
/* Pushed right of the heading, as the preview card's toolbar cluster is. */
.edu-step-card__actions {
    display: flex; align-items: center; gap: var(--edu-spacing-sm);
    margin-left: auto;
    flex-wrap: wrap;
}
.edu-step-card__body { display: flex; flex-direction: column; gap: var(--edu-spacing); }
/* A lookup in the heading cluster is a fixed-width slot on the real screens (min-width: 300px on
   the diagnostic property picker), not a field that eats the row. */
.edu-step-card__actions .edu-search { flex: 0 1 200px; }

/* ---- form grid --------------------------------------------
   MudGrid with md="3": four fields across, collapsing rather than squeezing. */

/* Flex rather than grid, and sized off flex-basis rather than a container query: the deck's
   illustration slot is a shrink-to-fit flex item (see the note on .edu__stage), so anything that
   needs the stage's resolved width to lay out is unreliable here. Four across at full width; the
   row halves to two, then one, as the illustration narrows — the same collapse MudGrid md="3"
   performs, without depending on the viewport. */
.edu-form-grid {
    display: flex;
    flex-wrap: wrap;
    gap: var(--edu-spacing);
    align-items: flex-end;
}
/* `.edu-form-grid > .edu-field` and not `> *`: .edu-field carries `min-width: 0` (it has to, or a
   long value stretches its column), and being later in the file that rule wins a specificity tie —
   which let the columns squeeze to ~100px and truncate every value instead of wrapping. */
.edu-form-grid > *,
.edu-form-grid > .edu-field {
    flex: 1 1 calc((100% / var(--edu-form-columns, 4)) - var(--edu-spacing));
    /* Below this a field stops being readable, so the row wraps rather than shrinking further. */
    min-width: 150px;
}
.edu-form-grid--2 { --edu-form-columns: 2; }
.edu-form-grid--3 { --edu-form-columns: 3; }
.edu-form-grid--4 { --edu-form-columns: 4; }

/* ---- segmented switch --------------------------------------- */

.edu-segmented {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    border-radius: var(--edu-radius-pill);
    background: var(--edu-surface-sunken);
}
.edu-segmented__option {
    padding: 4px 12px;
    border-radius: var(--edu-radius-pill);
    color: var(--edu-muted);
    font-weight: 500;
    white-space: nowrap;
}
.edu-segmented__option--active {
    background: var(--edu-surface);
    color: var(--edu-text);
    box-shadow: 0 1px 2px rgba(15, 23, 43, .12);
}

/* ---- record card -------------------------------------------
   A backlog job, a kanban card: reference + state, a name, then attribute chips. */

.edu-record {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 12px;
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-left: 3px solid var(--edu-border-strong);
    border-radius: var(--edu-radius-sm);
}
.edu-record--selected { border-left-color: var(--edu-attention); background: var(--edu-attention-soft); }
/* The panel title above a stack of record cards ("Jobs not booked · 24"). */
.edu-record-heading { font-weight: 600; }
/* The bar that appears once rows or cards are selected. */
.edu-bulkbar {
    padding: 8px 12px;
    border-radius: var(--edu-radius-sm);
    background: var(--edu-attention-soft);
    border: 1px solid color-mix(in srgb, var(--edu-attention) 25%, transparent);
    align-items: center;
}
.edu-record__top { display: flex; align-items: center; gap: 8px; }
.edu-record__ref { color: var(--edu-attention); font-weight: 600; font-size: .9em; }
.edu-record__status { margin-left: auto; }
.edu-record__title { font-weight: 600; }
.edu-record__subtitle { color: var(--edu-muted); font-size: .9em; }
.edu-record__chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
.edu-record__chips .edu-chip { font-size: .78em; padding: 1px 8px; }

/* ---- schedule ----------------------------------------------- */

.edu-schedule {
    display: grid;
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius-sm);
    overflow: hidden;
    font-size: .9em;
    background: var(--edu-surface);
}
.edu-schedule__corner { background: var(--edu-surface-sunken); border-bottom: 1px solid var(--edu-border); }
.edu-schedule__head {
    padding: 8px 10px;
    background: var(--edu-surface-sunken);
    border-bottom: 1px solid var(--edu-border);
    border-left: 1px solid var(--edu-border);
    font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.edu-schedule__time {
    padding: 6px 8px;
    color: var(--edu-muted);
    font-size: .86em;
    border-top: 1px solid var(--edu-border);
    text-align: right;
}
.edu-schedule__cell { border-top: 1px solid var(--edu-border); border-left: 1px solid var(--edu-border); min-height: 34px; }
/* Blocks are grid items placed over the cells; a 1px inset keeps the cell rules visible around
   them, which is what makes the drop read as "into this slot". */
.edu-schedule__block {
    margin: 1px;
    padding: 5px 8px;
    border-radius: 6px;
    background: var(--edu-attention-soft);
    border: 1px solid var(--edu-attention);
    display: flex;
    flex-direction: column;
    gap: 1px;
    overflow: hidden;
    z-index: 1;
}
.edu-schedule__block-title { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edu-schedule__block-sub { color: var(--edu-muted); font-size: .86em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- split layout -------------------------------------------
   A side panel beside a main surface — the planner's backlog next to its grid. Stacks when the
   illustration is too narrow to carry both. */

/* The flex BASIS is what decides whether these wrap, not min-width: with flex-wrap on, an item is
   pushed to the next line when the hypothetical sizes overflow, and shrinking only happens once a
   line is settled. Bases of 210 + 300 + 16 gap = 526 therefore wrapped inside the deck's ~498px
   reveal slide, stacking the panes - which drew Job Bookings, a two-pane screen, as one column and
   took the single strongest cue for "you are on the planner" with it.

   Basis now equals min-width, so the pair wraps only when it genuinely cannot fit (466px, real
   phone width) rather than 60px early. Do not raise these without re-measuring in the deck. */
.edu-split { display: flex; gap: var(--edu-spacing); align-items: flex-start; flex-wrap: wrap; }
.edu-split__side { flex: 1 1 190px; min-width: 190px; display: flex; flex-direction: column; gap: var(--edu-spacing-sm); }
.edu-split__main { flex: 2 1 260px; min-width: 260px; display: flex; flex-direction: column; gap: var(--edu-spacing-sm); }

/* ---- empty state ------------------------------------------- */

.edu-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: var(--edu-spacing-lg) var(--edu-spacing);
    text-align: center;
}
.edu-empty__icon { font-size: 1.9em; color: var(--edu-muted); }
.edu-empty__title { font-weight: 600; }
.edu-empty__body { color: var(--edu-muted); font-size: .92em; }

/* ---- toolbar ---------------------------------------------- */

/* Top aligned, not centred: a toolbar control wrapped in an EduTarget grows downwards to make room
   for its note, and centring would then float every other control out of line with it. */
.edu-toolbar {
    display: flex;
    align-items: flex-start;
    gap: var(--edu-spacing-sm);
    flex-wrap: wrap;
}
/* Basis 0, not 24px: flexbox wraps before it shrinks, so a spacer with a real basis spends width
   it doesn't need and tips a full toolbar onto a second row at the deck's stage width. At 0 it
   takes only what is left over. */
.edu-toolbar__spacer { flex: 1 1 0; min-width: 0; }

/* ---- button ----------------------------------------------- */

/* Shaped like a real Defex button: the 24px control radius, no drop shadow (the app strips
   them globally), and sentence case — MudBlazor's uppercase is turned off app-wide by
   .no-uppercase, which every toolbar button carries. */
.edu-button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    /* 13px, not the app's 16: the pill radius already buys visual width, and a toolbar in an
       illustration has a much narrower budget than a real page — the accent button wrapped to
       its own row at the deck's stage width with 16. */
    padding: 6px 13px;
    border-radius: var(--edu-radius-control);
    border: 1px solid var(--edu-border-strong);
    background: var(--edu-surface);
    color: var(--edu-text);
    font: inherit;
    font-weight: 500;
    text-transform: none;
    box-shadow: none;
    white-space: nowrap;
}
/* Filled primary — the ONE control the learner must find. */
.edu-button--accent {
    background: var(--edu-accent);
    border-color: var(--edu-accent);
    color: var(--edu-accent-contrast);
}
/* Outlined primary — a secondary action sitting beside the accent one, as on the real
   toolbars (Import / Bulk Create next to Add Client). */
.edu-button--outline {
    background: transparent;
    border-color: var(--edu-accent);
    color: var(--edu-accent);
}
.edu-button--quiet {
    background: transparent;
    border-color: transparent;
    color: var(--edu-muted);
}
.edu-button--icon { padding: 8px; }

/* ---- input-ish primitives --------------------------------- */

/* The app's inputs are OUTLINED and share the button's 24px control radius (see
   .mud-input-control.mud-input-control-margin-dense in utilities.css), so an illustrated
   field is a rim on the surface — not a sunken grey slab. */
.edu-input {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 34px;
    padding: 0 12px;
    border: 1px solid var(--edu-border-strong);
    border-radius: var(--edu-radius-control);
    background: var(--edu-surface);
    color: var(--edu-muted);
}
.edu-input__text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edu-input--filled { color: var(--edu-text); }
.edu-search { flex: 1 1 180px; max-width: 320px; }

.edu-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
/* Matches .form-label: one step back in colour, 13px, not bold. */
.edu-field__label { font-size: .93em; font-weight: 400; color: var(--edu-muted); }
.edu-field__chevron { transform: rotate(90deg); flex: none; }
.edu-field__adornment { flex: none; opacity: .75; }

/* ---- toggle ------------------------------------------------ */

.edu-toggle { display: inline-flex; align-items: center; gap: 10px; min-height: 34px; }
.edu-toggle__track {
    position: relative;
    flex: none;
    width: 32px; height: 14px;
    border-radius: var(--edu-radius-pill);
    background: var(--edu-border-strong);
}
.edu-toggle__knob {
    position: absolute;
    top: -3px; left: -1px;
    width: 20px; height: 20px;
    border-radius: 50%;
    background: var(--edu-surface);
    border: 1px solid var(--edu-border-strong);
    box-shadow: 0 1px 3px rgba(15, 23, 43, .2);
}
.edu-toggle__track--on { background: color-mix(in srgb, var(--edu-accent) 40%, transparent); }
.edu-toggle__track--on .edu-toggle__knob { left: auto; right: -1px; background: var(--edu-accent); border-color: var(--edu-accent); }
.edu-toggle__label { color: var(--edu-text); }

/* ---- list / grid ------------------------------------------ */

.edu-list {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius-sm);
    overflow: hidden;
}
.edu-list__item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-top: 1px solid var(--edu-border);
}
.edu-list__item:first-child { border-top: 0; }
/* Header row, shaped like the real data grid's: bold ink on the surface under a rule —
   NOT an uppercase grey band. The app's grid heads don't shout. */
.edu-list__item--head { background: var(--edu-surface); color: var(--edu-text); font-size: .9em; font-weight: 600; border-bottom: 1px solid var(--edu-border); }
.edu-list__text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edu-list__meta { color: var(--edu-muted); font-size: .9em; white-space: nowrap; }

/* A "there are more rows" hint that needs no invented data. */
.edu-list__more { display: flex; gap: 4px; padding: 12px; justify-content: center; }
.edu-list__more span { width: 4px; height: 4px; border-radius: 50%; background: var(--edu-border-strong); }

/* ---- grid (only when the columns are being taught) --------- */

.edu-grid {
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius-sm);
    overflow: hidden;
    font-size: .92em;
}
.edu-grid__row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-top: 1px solid var(--edu-border); }
.edu-grid__row:first-child { border-top: 0; }
.edu-grid__row--head { background: var(--edu-surface); color: var(--edu-text); font-weight: 600; border-bottom: 1px solid var(--edu-border); }
.edu-grid__row--accent { background: var(--edu-attention-soft); }
.edu-grid__cell { flex: 1 1 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.edu-grid__cell--select { flex: 0 0 auto; display: inline-flex; align-items: center; }
/* Cells clip by default so long values ellipsis rather than shove the row about. A cell holding a
   chip or a callout has to opt out, or the attention ring is sliced off at the cell edge. */
.edu-grid__cell--rich { overflow: visible; }

.edu-checkbox {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 15px; height: 15px;
    flex: none;
    border: 1px solid var(--edu-border-strong);
    border-radius: 3px;
    background: var(--edu-surface);
    font-size: 11px;
}
.edu-checkbox--on { background: var(--edu-accent); border-color: var(--edu-accent); color: var(--edu-accent-contrast); }
.edu-checkbox__label { margin-left: 6px; }

/* Tinted-bg / tinted-border / tinted-fg, the same three-token shape as .status-pill. */
.edu-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: var(--edu-radius-pill);
    background: var(--edu-surface-sunken);
    border: 1px solid var(--edu-border);
    color: var(--edu-muted);
    font-size: .85em;
    font-weight: 500;
    white-space: nowrap;
}
.edu-chip--flag { background: var(--edu-flag-soft); border-color: var(--edu-flag-border); color: var(--edu-flag); }
.edu-chip--positive { background: var(--edu-positive-soft); border-color: var(--edu-positive-border); color: var(--edu-positive); }
/* Struck through as well as muted: the exclusion has to survive greyscale and colour blindness. */
.edu-chip--skipped { background: transparent; color: var(--edu-muted); text-decoration: line-through; }

/* ---- phone frame -------------------------------------------
   For a beat that happens in the field. Just enough bezel to say "this is the mobile app". */

.edu-phone {
    /* 264px: at 230 a check label and its verdict chip could not share a row without the label
       ellipsing, and the label is the half that carries the lesson. */
    width: 264px;
    margin: 0 auto;
    padding: 10px;
    border: 1px solid var(--edu-border-strong);
    border-radius: 22px;
    background: var(--edu-surface-sunken);
    box-shadow: var(--edu-shadow);
}
.edu-phone__screen {
    display: flex;
    flex-direction: column;
    gap: var(--edu-spacing-sm);
    padding: 12px 10px;
    border-radius: 14px;
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
}
.edu-phone__title { font-weight: 600; }

/* ---- card / modal ----------------------------------------- */

.edu-card {
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius);
    padding: var(--edu-spacing);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.edu-card__title { font-weight: 600; }

/* A card INSIDE a card is an inner surface, not a second card: filled, tighter radius, hairline,
   no lift. Mirrors `.custom-border .custom-border` in utilities.css. */
.edu-step-card .edu-card,
.edu-screen .edu-card {
    background: var(--edu-surface-sunken);
    border-radius: var(--edu-radius-sm);
    box-shadow: none;
}

.edu-modal {
    background: var(--edu-surface);
    border: 1px solid var(--edu-border);
    border-radius: var(--edu-radius);
    box-shadow: var(--edu-shadow-raised);
    overflow: hidden;
}
.edu-modal__head {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 12px var(--edu-spacing);
    border-bottom: 1px solid var(--edu-border);
    font-weight: 600;
}
.edu-modal__body { padding: var(--edu-spacing); display: flex; flex-direction: column; gap: 12px; }
.edu-modal__foot { padding: 12px var(--edu-spacing); border-top: 1px solid var(--edu-border); display: flex; align-items: flex-start; justify-content: flex-end; gap: 8px; }

/* ---- attention: highlight, arrow, note, cursor ------------- */

/* Every illustration should have ONE of these. The ring is drawn
   outside the subject so it never changes the subject's metrics. */
.edu-target { display: inline-flex; gap: 10px; align-items: center; }
.edu-target--up, .edu-target--down { flex-direction: column; }
.edu-target--down { flex-direction: column-reverse; }
/* Point.Right means the arrow travels rightwards, so the words start on the left. */
.edu-target--right { flex-direction: row-reverse; }

.edu-target__subject { position: relative; display: inline-flex; }
.edu-target--block { display: flex; width: 100%; }
.edu-target--block .edu-target__subject { width: 100%; }
.edu-target--block .edu-target__subject > * { width: 100%; }
.edu-target--glow .edu-target__subject::after {
    content: "";
    position: absolute;
    inset: -6px;
    border-radius: calc(var(--edu-radius-sm) + 6px);
    box-shadow: 0 0 0 3px var(--edu-highlight);
    pointer-events: none;
    animation: edu-pulse 2.4s var(--edu-ease) infinite;
}

.edu-target__note {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--edu-attention);
    font-weight: 500;
    font-size: .95em;
    text-align: center;
}
/* A side-pointing note must not be squeezed into a one-word-per-line column by the row it sits in. */
.edu-target--right .edu-target__note,
.edu-target--left .edu-target__note { flex: none; max-width: 170px; }
/* The arrow always sits on the edge of the note nearest its subject. */
.edu-target--up .edu-target__note { flex-direction: column; gap: 4px; }
.edu-target--down .edu-target__note { flex-direction: column-reverse; gap: 4px; }
.edu-target--right .edu-target__note { flex-direction: row-reverse; }

.edu-arrow { display: block; color: var(--edu-attention); flex: none; }
.edu-arrow--up { width: 12px; height: 26px; }
.edu-arrow--down { width: 12px; height: 26px; transform: rotate(180deg); }
.edu-arrow--right { width: 26px; height: 12px; transform: rotate(90deg); }
.edu-arrow--left { width: 26px; height: 12px; transform: rotate(-90deg); }

.edu-cursor {
    position: absolute;
    right: -14px;
    bottom: -16px;
    width: 20px;
    height: 20px;
    color: var(--edu-text);
    filter: drop-shadow(0 1px 2px rgba(16, 24, 40, .3));
    pointer-events: none;
}

/* A standalone instruction that is not attached to a control. */
.edu-callout {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 12px;
    border-radius: var(--edu-radius-sm);
    background: var(--edu-attention-soft);
    color: var(--edu-text);
}
.edu-callout__marker { color: var(--edu-attention); flex: none; margin-top: 1px; }

/* ---- workflow --------------------------------------------- */

/* Connectors are drawn by CSS on every node but the first, so a
   step never needs to know its own index. */
.edu-flow {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    list-style: none;
    margin: 0;
    padding: 0;
    counter-reset: edu-step;
}
.edu-flow__node { position: relative; counter-increment: edu-step; }
.edu-flow__node + .edu-flow__node { margin-top: 42px; }
.edu-flow__node + .edu-flow__node::before {
    content: "";
    position: absolute;
    left: 50%;
    top: -32px;
    width: 2px;
    height: 20px;
    background: var(--edu-border-strong);
    transform: translateX(-50%);
}
.edu-flow__node + .edu-flow__node::after {
    content: "";
    position: absolute;
    left: 50%;
    top: -17px;
    width: 7px;
    height: 7px;
    border-right: 2px solid var(--edu-border-strong);
    border-bottom: 2px solid var(--edu-border-strong);
    transform: translateX(-50%) rotate(45deg);
}

/* Left-to-right variant. The connectors move from "above each node" to "left of each node", and
   the arrowhead turns a quarter turn — nothing else changes, because a step still doesn't know its
   own index. */
.edu-flow--row { flex-direction: row; align-items: stretch; }
.edu-flow--row .edu-flow__node { flex: 1 1 0; min-width: 0; }
.edu-flow--row .edu-flow__node + .edu-flow__node { margin-top: 0; margin-left: 30px; }
.edu-flow--row .edu-flow__node + .edu-flow__node::before {
    left: -22px; top: 50%;
    width: 14px; height: 2px;
    transform: translateY(-50%);
}
.edu-flow--row .edu-flow__node + .edu-flow__node::after {
    left: -12px; top: 50%;
    transform: translateY(-50%) rotate(-45deg);
}
.edu-flow--row .edu-step { height: 100%; }
.edu-flow--row .edu-card { height: 100%; }

.edu-step { display: flex; flex-direction: column; gap: 6px; }
.edu-step__label {
    display: flex; align-items: center; gap: 8px;
    font-size: .86em; font-weight: 600; letter-spacing: .04em;
    text-transform: uppercase; color: var(--edu-muted);
}
.edu-step__index {
    display: inline-flex; align-items: center; justify-content: center;
    width: 20px; height: 20px; border-radius: 50%;
    background: var(--edu-surface-sunken); color: var(--edu-muted);
    font-size: 11px; letter-spacing: 0;
}
.edu-step__index::before { content: counter(edu-step); }
.edu-step--current .edu-step__label { color: var(--edu-attention); }
.edu-step--current .edu-step__index { background: var(--edu-attention); color: var(--mud-palette-secondary-text); }

/* The success pill, on the shared success trio. */
.edu-success {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    align-self: center;
    padding: 10px 16px;
    border-radius: var(--edu-radius-pill);
    border: 1px solid var(--edu-positive-border);
    background: var(--edu-positive-soft);
    color: var(--edu-positive);
    font-weight: 600;
}

/* ---- small helpers ----------------------------------------- */

.edu-muted-note { color: var(--edu-muted); font-size: .92em; }
/* The page ground: cards stacked with the gap the real .mud-stack Spacing="2" leaves. */
.edu-page { display: flex; flex-direction: column; gap: var(--edu-spacing); }
/* An inline hint on a toolbar ("Can't find your property?"). */
.edu-hint { display: inline-flex; align-items: center; gap: 6px; color: var(--edu-muted); font-size: .92em; }
.edu-fill { width: 100%; }
.edu-stack { display: flex; flex-direction: column; gap: var(--edu-spacing-sm); }
.edu-row { display: flex; align-items: center; gap: var(--edu-spacing-sm); flex-wrap: wrap; }
.edu-row--center { justify-content: center; }
.edu-row--end { justify-content: flex-end; }

@media (max-width: 480px) {
    .edu__stage { padding: var(--edu-spacing); }
    .edu-search { max-width: none; flex-basis: 100%; }
    .edu-toolbar__spacer { display: none; }
}

/* ---- dark mode --------------------------------------------
   Nothing to do. Every token above derives from :root palette
   variables, which MudThemeProvider swaps for the dark and the
   tenant-operator-red palettes, so the whole language follows
   without a marker class — which also fixes the previous block:
   it was keyed off `.mud-theme-dark`, a class the web host never
   stamps (MainLayout stamps `.defex-theme-dark`), so dark-mode
   illustrations were rendering with the light tokens.

   The two exceptions are the SHADOW tokens, which resolve from
   --defex-card-shadow / --defex-menu-shadow. Those are light-only
   rgba(15,23,43,…) literals, so a dark illustration leans on its
   radius and rim for separation — exactly as the app's own cards
   do in dark. Don't reach for --defex-glass-* or --defex-card-bg
   here: they are white-alpha and have no dark counterpart. */

/* ---- animation --------------------------------------------
   No engine yet, deliberately. What is here is the contract a
   future one will use: illustrations opt in with .edu--animate,
   each animatable element reads --edu-delay for sequencing, and
   every motion sits behind the reduced-motion guard below, so
   adding a step later cannot reintroduce the accessibility bug. */

@keyframes edu-pulse {
    0%, 100% { box-shadow: 0 0 0 3px var(--edu-highlight); }
    50%      { box-shadow: 0 0 0 7px transparent; }
}

@keyframes edu-enter {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

.edu--animate .edu-flow__node,
.edu--animate .edu-target__note {
    animation: edu-enter var(--edu-duration) var(--edu-ease) both;
    animation-delay: var(--edu-delay);
}

@media (prefers-reduced-motion: reduce) {
    .edu *,
    .edu *::before,
    .edu *::after {
        animation: none !important;
        transition: none !important;
    }
}
