﻿/* ==========================================================================
   Examin design system
   --------------------------------------------------------------------------
   Ported from Quizora on 2026-09-09. Two sources, and where they disagree the
   SHIPPED product wins, because that is the one the user actually likes:
     - C:\Users\gad_s\OneDrive\Documents\QUIZORA - the shipped Next.js app.
       app/globals.css is the authority for palette, buttons, inputs and nav.
     - C:\Projects\BODEK - the earlier UI/UX mock. Serve it with the BodekMock
       launch entry. Still the reference for layout ideas the shipped app has
       no equivalent of (stat tiles, the numbered-step settings flow).
   Three places the mock was wrong and the shipped app corrected it: buttons and
   the brand mark are FLAT green, not gradient; primary hover goes darker, not
   lighter; and top-level nav is an underline, not a segmented pill trough.

   Structure — read top to bottom, add to the right layer:
     1. FONT      — Heebo, self-hosted (Hebrew + Latin subsets).
     2. TOKENS    — the design system proper. Nothing outside this block may
                    invent a color, radius, shadow or font size; everything
                    references a token here. This is the layer that was
                    missing before, and its absence is why the app had 31
                    distinct hand-written font sizes.
     3. BOOTSTRAP — maps Bootstrap 5.3's --bs-* variables onto the tokens.
                    Bootstrap's compiled CSS reads these via var() at :root,
                    so utilities (bg-*, text-*, border-*, alerts, links) and
                    the body pick up the new language with no markup changes.
     4. COMPONENT — the handful of Bootstrap components that bake a literal
                    hex INSIDE their own --bs-btn-bg / --bs-table-bg at Sass
                    compile time, so a :root override never reaches them.
                    Buttons, tables, forms, pagination, list-group, dropdown.
     5. EXAMIN    — our own component classes (.ex-*). Prefer adding one of
                    these over writing an inline style on a page.
     6. CONTENT   — saved rich-text/question HTML rendered read-only.
   ========================================================================== */

/* ==========================================================================
   1. FONT — Heebo (self-hosted; matches the mock, and works offline / under
   SEB lockdown where a Google Fonts CDN request would simply fail).
   ========================================================================== */
@font-face {
  font-family: "Heebo";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("../fonts/heebo/heebo-latin.woff2") format("woff2-variations"), url("../fonts/heebo/heebo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+2000-206F, U+20AC, U+2122;
}
@font-face {
  font-family: "Heebo";
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url("../fonts/heebo/heebo-hebrew.woff2") format("woff2-variations"), url("../fonts/heebo/heebo-hebrew.woff2") format("woff2");
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}

/* ==========================================================================
   2. TOKENS
   ========================================================================== */
:root {
  /* ---- Brand: emerald & mint ---------------------------------------------
     A full 50→950 ramp, not three ad-hoc hexes. Pick a step by role:
       700/800  primary actions, active nav, headings on tint
       600      hover / focus rings
       500      "live" indicators
       100/50   subtle fills behind primary-toned text
     ---------------------------------------------------------------------- */
  --primary-950: #0C3527;
  --primary-900: #17533D;  /* Quizora --green-dark: primary hover, labels, headings on tint */
  --primary-800: #1D6449;
  --primary-700: #257A59;  /* Quizora --green: THE brand colour */
  --primary-600: #2E9169;
  --primary-500: #3FAB80;
  --primary-400: #63C69F;
  --primary-200: #B6E4CE;
  --primary-100: #E1F2E8;  /* Quizora --mint: icon tiles, count badges, soft fills */
  --primary-50:  #F0F8F4;

  /* ---- Surfaces & canvas -------------------------------------------------
     Warm paper, not blue-white. --canvas-bg is the page; --surface-card is
     anything raised above it. They must stay distinct or cards stop reading
     as cards. --surface-subtle is for inset areas: table headers, segmented
     control troughs, well backgrounds.
     ---------------------------------------------------------------------- */
  --canvas-bg: #F5F3EC;      /* Quizora --cream */
  --surface-card: #FFFEFA;   /* Quizora --paper */
  --surface-subtle: #EDF0EC;
  /* Quizora fills inputs with a faint off-white and only goes pure white on
     focus, which is why its forms read softer than a wall of white boxes. */
  --surface-input: #FBFCF9;
  --surface-glass: rgba(255, 254, 250, .94);
  --border-light: #DCE4DE;   /* Quizora --line */
  --border-medium: #CBD5CF;
  --border-strong: #9FBEAC;

  /* ---- Ink ---------------------------------------------------------------
     Four steps of text weight. Body copy is --ink-primary; a label above a
     field is --ink-secondary; helper text and metadata are --ink-muted;
     --ink-faint is for disabled or decorative text only.
     ---------------------------------------------------------------------- */
  --ink-primary: #18342A;    /* Quizora --ink */
  --ink-secondary: #3E5449;
  --ink-muted: #6D7D75;      /* Quizora --muted */
  --ink-faint: #A0ACA6;      /* Quizora's placeholder colour */
  --ink-inverse: #FFFFFF;

  /* ---- Semantic accents --------------------------------------------------
     Deliberately few. Green is the brand, so "good" is carried by the
     primary ramp; these three exist for states that must NOT be confused
     with the brand: warning (amber), destructive/alert (coral), neutral
     informational (blue).
     ---------------------------------------------------------------------- */
  --accent-amber: #8A6410;
  --accent-amber-bg: #FDF4DC;
  --accent-amber-border: #E4CD93;
  /* Coral is split in two on purpose. Quizora paints decorative surfaces (the
     student portal tile) in the light --coral and writes coral TEXT in a much
     darker tone; using the light one for text fails contrast on its own tint. */
  --accent-coral: #A5503A;
  --accent-coral-soft: #E98D72;  /* Quizora --coral */
  --accent-coral-bg: #FFF2EE;
  --accent-coral-border: #F0C4B8;
  --accent-blue: #0369A1;
  --accent-blue-bg: #E0F2FE;
  --accent-blue-border: #B9E1F8;
  --accent-green: #15803D;
  --accent-green-bg: #E7F5EC;
  --accent-green-border: #BFE3CC;

  /* ---- Radius ------------------------------------------------------------
     Five steps and a pill. Before this the app mixed rounded-2/3/4/pill on
     one screen with no rule; the rule now is: xs = chips and tiny squares,
     sm = controls (buttons, inputs), md = inner panels, lg = cards, xl =
     hero surfaces.
     ---------------------------------------------------------------------- */
  --radius-xs: 8px;
  --radius-sm: 12px;   /* Quizora's control radius: buttons, inputs */
  --radius-md: 15px;
  --radius-lg: 23px;   /* Quizora's panel radius */
  --radius-xl: 28px;
  --radius-pill: 9999px;

  /* ---- Elevation ---------------------------------------------------------
     Green-tinted shadows, so raised surfaces sit in the warm canvas instead
     of looking cut out of it. A surface takes a shadow OR a heavy border,
     not both: cards use --shadow-sm + --border-light.
     ---------------------------------------------------------------------- */
  --shadow-xs: 0 1px 3px rgba(35, 66, 51, .05);
  --shadow-sm: 0 8px 22px rgba(35, 66, 51, .06);
  --shadow-md: 0 14px 38px rgba(35, 66, 51, .09);
  --shadow-lg: 0 20px 50px rgba(35, 66, 51, .1);      /* Quizora --shadow */
  --shadow-float: 0 30px 90px rgba(7, 28, 19, .34);   /* Quizora's modal */
  --shadow-primary: 0 9px 20px rgba(37, 122, 89, .2); /* Quizora's primary button */

  /* ---- Type scale --------------------------------------------------------
     The scale that did not exist. Nine steps, and nothing between them.
     If a size you want is not here, use the nearest step — do not write a
     new rem value into a page.
       2xs  chips, table micro-metadata
       xs   badges, helper text under a field
       sm   secondary body, dense table cells
       base default body text
       md   emphasised body, card titles
       lg   section headings
       xl   card/panel headings
       2xl  page headings
       3xl  hero headings
     ---------------------------------------------------------------------- */
  --fs-2xs: .6875rem;
  --fs-xs: .75rem;
  --fs-sm: .8125rem;
  --fs-base: .9375rem;
  --fs-md: 1rem;
  --fs-lg: 1.125rem;
  --fs-xl: 1.375rem;
  --fs-2xl: 1.75rem;
  --fs-3xl: clamp(1.75rem, 4vw, 2.625rem);

  /* Weights — Heebo carries 300-900, so headings can go genuinely heavy. */
  --fw-normal: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-heavy: 800;
  --fw-black: 900;

  /* ---- Spacing -----------------------------------------------------------
     Bootstrap's own 0-5 spacers are remapped onto this in layer 3, so the
     existing p-3 / gap-2 / mb-4 utilities across the app land on the scale
     automatically.
     ---------------------------------------------------------------------- */
  --space-1: .25rem;
  --space-2: .5rem;
  --space-3: .875rem;
  --space-4: 1.375rem;
  --space-5: 2rem;
  --space-6: 3rem;

  /* ---- Layout ------------------------------------------------------------
     The app topbar is sticky, so anything else that sticks (the activity phase
     nav, its second bar) has to offset by its height rather than guessing. */
  --examin-topbar-h: 68px;

  /* ---- Motion ------------------------------------------------------------ */
  --transition-fast: .15s cubic-bezier(.4, 0, .2, 1);
  --transition-smooth: .25s cubic-bezier(.4, 0, .2, 1);
  --transition-bounce: .35s cubic-bezier(.34, 1.56, .64, 1);

  /* ---- Legacy aliases ----------------------------------------------------
     ~350 var() references across .razor.css files and inline styles still
     name these. Renaming them would mean re-touching every consumer, so the
     names stay and only the values move onto the ramp above — the same
     approach the previous re-skin used. New code should reference the
     tokens above directly, not these.
     ---------------------------------------------------------------------- */
  --examin-navy: var(--primary-700);
  --examin-navy-dark: var(--primary-900);
  --examin-seal: var(--accent-coral-soft);
  --examin-seal-strong: var(--accent-coral);
  --examin-surface: var(--surface-card);
  --examin-sidebar-bg: var(--primary-900);
  --examin-sidebar-fg: #EAF5EF;
  --examin-sidebar-fg-soft: #A8CDBB;
  --examin-sidebar-active: var(--primary-700);
  --examin-topbar-bg: var(--surface-card);
  --examin-topbar-fg: var(--ink-primary);
  --examin-topbar-fg-soft: var(--ink-muted);
  --examin-topbar-btn-color: var(--ink-secondary);
  --examin-header-bg: var(--surface-card);
  --examin-header-fg: var(--ink-primary);
  --examin-header-fg-soft: var(--ink-muted);
  --examin-header-btn-color: var(--ink-secondary);
}

/* ==========================================================================
   3. BOOTSTRAP VARIABLE MAPPING
   Every --bs-* below is read by Bootstrap's own compiled CSS at :root, so
   setting them here re-skins the utilities and components already used
   across ~8,000 lines of Razor without touching a single page.
   ========================================================================== */
:root {
  --bs-font-sans-serif: "Heebo", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --bs-body-font-size: var(--fs-base);
  --bs-body-font-weight: var(--fw-normal);
  --bs-body-line-height: 1.55;

  --bs-primary: #257A59;
  --bs-primary-rgb: 37, 122, 89;
  --bs-primary-text-emphasis: #17533D;
  --bs-primary-bg-subtle: #E1F2E8;
  --bs-primary-border-subtle: #B6E4CE;

  /* Coral — destructive-adjacent accent. Used for "needs attention" chips and
     the one or two brand actions that must not read as the primary CTA. */
  --bs-secondary: #A5503A;
  --bs-secondary-rgb: 165, 80, 58;
  --bs-secondary-text-emphasis: #843F2D;
  --bs-secondary-bg-subtle: #FFF2EE;
  --bs-secondary-border-subtle: #F0C4B8;

  /* Success is a purer, brighter green than the emerald brand tone so a
     "passed / correct" state still separates from ordinary primary chrome. */
  --bs-success: #15803D;
  --bs-success-rgb: 21, 128, 61;
  --bs-success-text-emphasis: #0D5828;
  --bs-success-bg-subtle: #E7F5EC;
  --bs-success-border-subtle: #BFE3CC;

  --bs-warning: #8A6410;
  --bs-warning-rgb: 138, 100, 16;
  --bs-warning-text-emphasis: #63480B;
  --bs-warning-bg-subtle: #FDF4DC;
  --bs-warning-border-subtle: #E4CD93;

  --bs-danger: #9A4331;
  --bs-danger-rgb: 154, 67, 49;
  --bs-danger-text-emphasis: #7A3426;
  --bs-danger-bg-subtle: #FFF2EE;
  --bs-danger-border-subtle: #F0C4B8;

  /* `info` was used 25 times across the pages but had no token at all, so it
     rendered as stock Bootstrap cyan (#0DCAF0) — the single most off-brand
     color in the app. It is now the calm blue from the mock's accent set. */
  --bs-info: #0369A1;
  --bs-info-rgb: 3, 105, 161;
  --bs-info-text-emphasis: #024A73;
  --bs-info-bg-subtle: #E0F2FE;
  --bs-info-border-subtle: #B9E1F8;

  /* Bootstrap's `light` and `dark` are stock greys (#F8F9FA and #212529) with no
     relation to any palette, and they are used ~70 times across the pages as
     bg-light / bg-dark / btn-dark. Mapping them here re-tones every one of those
     call sites at once: light becomes the neutral inset surface, dark becomes the
     deep brand tone. */
  --bs-light: #EDF0EC;
  --bs-light-rgb: 237, 240, 236;
  --bs-light-text-emphasis: #3E5449;
  --bs-light-bg-subtle: #F5F7F4;
  --bs-light-border-subtle: #DCE4DE;

  --bs-dark: #17533D;
  --bs-dark-rgb: 23, 83, 61;
  --bs-dark-text-emphasis: #17533D;
  --bs-dark-bg-subtle: #E1F2E8;
  --bs-dark-border-subtle: #B6E4CE;

  --bs-body-bg: #F5F3EC;
  --bs-body-bg-rgb: 245, 243, 236;
  --bs-body-color: #18342A;
  --bs-body-color-rgb: 24, 52, 42;
  --bs-emphasis-color: #0C3527;
  --bs-secondary-color: #6D7D75;
  --bs-secondary-bg: #EDF0EC;
  --bs-tertiary-bg: #FFFEFA;
  --bs-tertiary-bg-rgb: 255, 254, 250;

  --bs-border-color: #DCE4DE;

  /* <mark>, written by the editor's highlight button and read back on every surface that
     renders question content. Bootstrap's default is a raw yellow from outside the palette. */
  --bs-highlight-bg: var(--accent-amber-bg);
  --bs-highlight-color: var(--accent-amber);
  --bs-border-color-translucent: rgba(24, 52, 42, .1);

  --bs-link-color: #257A59;
  --bs-link-color-rgb: 37, 122, 89;
  --bs-link-hover-color: #17533D;
  --bs-link-hover-color-rgb: 23, 83, 61;

  --bs-border-radius-sm: var(--radius-xs);
  --bs-border-radius: var(--radius-sm);
  --bs-border-radius-lg: var(--radius-md);
  --bs-border-radius-xl: var(--radius-lg);
  --bs-border-radius-xxl: var(--radius-xl);

  --bs-box-shadow-sm: var(--shadow-xs);
  --bs-box-shadow: var(--shadow-sm);
  --bs-box-shadow-lg: var(--shadow-md);

  /* Note: Bootstrap compiles its spacing utilities (p-3, mb-4, gap-2 …) to
     literal rem values, so they cannot be remapped from here. The --space-*
     tokens above apply to our own .ex-* components and to any new CSS; the
     Bootstrap spacers stay on their 0.25rem multiples, which the scale was
     chosen to sit comfortably alongside. */

  --bs-heading-color: var(--ink-primary);
}

/* ---------- Base ---------- */
/* Pages short enough not to scroll used to omit the scrollbar gutter, so
   navigating to a page that DOES scroll shifted the layout ~16px sideways
   (user report, 2026-07-29). Reserving the gutter always keeps every page the
   same width. overflow-y is the fallback where scrollbar-gutter is missing. */
html {
  scrollbar-gutter: stable;
  overflow-y: scroll;
}

body {
  font-family: var(--bs-font-sans-serif);
  font-size: var(--fs-base);
  color: var(--ink-primary);
  /* Two very soft brand washes over the warm canvas, straight from the mock —
     they keep large empty regions from reading as flat gray. Fixed attachment
     so they stay put while content scrolls past. */
  background:
    radial-gradient(circle at 12% 10%, rgba(223, 242, 232, .85) 0%, transparent 32%),
    radial-gradient(circle at 88% 25%, rgba(245, 238, 226, .7) 0%, transparent 28%),
    var(--canvas-bg);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  color: var(--ink-primary);
  font-weight: var(--fw-heavy);
  letter-spacing: -.015em;
}

h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }
h5, h6 { font-size: var(--fs-base); }

/* ==========================================================================
   4. BOOTSTRAP COMPONENT OVERRIDES
   These components bake their default color as a literal hex inside their own
   --bs-btn-bg / --bs-table-bg / etc. at Sass-compile time, so the :root
   mapping above does not reach them. Each is re-declared against the tokens.
   Add to this list as new components turn up.
   ========================================================================== */

/* ---------- Buttons ----------
   The primary button is the one thing on a screen the eye should find first,
   so it gets the mock's gradient + brand shadow. Everything else is quieter
   by design: outline for secondary, ghost/link for tertiary. */
.btn {
  --bs-btn-font-size: var(--fs-sm);
  --bs-btn-font-weight: var(--fw-bold);
  --bs-btn-border-radius: var(--radius-sm);
  --bs-btn-padding-y: .5rem;
  --bs-btn-padding-x: 1rem;
  transition: var(--transition-fast);
}

.btn-sm {
  --bs-btn-font-size: var(--fs-xs);
  --bs-btn-padding-y: .35rem;
  --bs-btn-padding-x: .75rem;
  --bs-btn-border-radius: var(--radius-xs);
}

/* Bootstrap has no .btn-xs. Pages wanted one anyway and faked it with inline
   padding + font-size on every single button (and two components defined their
   own scoped copy), so it is a real size here now. min-height keeps icon-only
   buttons on the 32px touch grid the row actions are laid out to. */
.btn-xs {
  --bs-btn-font-size: var(--fs-2xs);
  --bs-btn-padding-y: .35rem;
  --bs-btn-padding-x: .55rem;
  --bs-btn-border-radius: var(--radius-xs);
  min-height: 32px;
  min-width: 32px;
}

.btn-lg {
  --bs-btn-font-size: var(--fs-md);
  --bs-btn-padding-y: .7rem;
  --bs-btn-padding-x: 1.5rem;
  --bs-btn-border-radius: var(--radius-sm);
}

.btn-primary {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--primary-700);
  --bs-btn-border-color: var(--primary-700);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--primary-900);
  --bs-btn-hover-border-color: var(--primary-900);
  --bs-btn-focus-shadow-rgb: 37, 122, 89;
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--primary-950);
  --bs-btn-active-border-color: var(--primary-950);
  --bs-btn-disabled-bg: var(--primary-700);
  --bs-btn-disabled-border-color: var(--primary-700);
  /* Flat, not a gradient. The mock used a gradient; the shipped app does not,
     and hovering goes DARKER rather than lighter. */
  box-shadow: var(--shadow-primary);
}

.btn-primary:hover:not(:disabled):not(.disabled) {
  transform: translateY(-1px);
}

.btn-primary:disabled,
.btn-primary.disabled {
  box-shadow: none;
}

.btn-outline-primary {
  /* The shipped "secondary action": paper fill, hairline border, green label. */
  --bs-btn-color: var(--primary-700);
  --bs-btn-bg: var(--surface-card);
  --bs-btn-border-color: var(--border-light);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--primary-700);
  --bs-btn-hover-border-color: var(--primary-700);
  --bs-btn-active-bg: var(--primary-900);
  --bs-btn-active-border-color: var(--primary-900);
  --bs-btn-focus-shadow-rgb: 37, 122, 89;
}

/* The neutral workhorse. Most toolbars should reach for this, not for an
   accent-colored outline — five coral buttons in a row is what removed all
   sense of hierarchy from the activity settings toolbar. */
.btn-outline-secondary {
  --bs-btn-color: var(--ink-secondary);
  --bs-btn-border-color: var(--border-medium);
  --bs-btn-bg: transparent;
  --bs-btn-hover-color: var(--ink-primary);
  --bs-btn-hover-bg: var(--surface-subtle);
  --bs-btn-hover-border-color: var(--border-strong);
  --bs-btn-active-color: var(--ink-primary);
  --bs-btn-active-bg: var(--surface-subtle);
  --bs-btn-active-border-color: var(--border-strong);
  --bs-btn-focus-shadow-rgb: 107, 127, 117;
}

.btn-secondary {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--accent-coral);
  --bs-btn-border-color: var(--accent-coral);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--examin-seal-strong);
  --bs-btn-hover-border-color: var(--examin-seal-strong);
  --bs-btn-active-bg: var(--examin-seal-strong);
  --bs-btn-active-border-color: var(--examin-seal-strong);
  --bs-btn-focus-shadow-rgb: 165, 80, 58;
}

/* "Add a course" — a deliberate second brand action, deeper than the primary
   CTA so the two never compete for the same glance. */
.btn-examin-course {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--primary-900);
  --bs-btn-border-color: var(--primary-900);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--primary-800);
  --bs-btn-hover-border-color: var(--primary-800);
  --bs-btn-active-bg: var(--primary-950);
  --bs-btn-active-border-color: var(--primary-950);
  --bs-btn-focus-shadow-rgb: 23, 83, 61;
  --bs-btn-disabled-bg: var(--primary-900);
  --bs-btn-disabled-border-color: var(--primary-900);
}

.btn-success {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--bs-success);
  --bs-btn-border-color: var(--bs-success);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-success-text-emphasis);
  --bs-btn-hover-border-color: var(--bs-success-text-emphasis);
  --bs-btn-focus-shadow-rgb: var(--bs-success-rgb);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-success-text-emphasis);
  --bs-btn-active-border-color: var(--bs-success-text-emphasis);
  --bs-btn-disabled-bg: var(--bs-success);
  --bs-btn-disabled-border-color: var(--bs-success);
}

.btn-outline-success {
  --bs-btn-color: var(--bs-success);
  --bs-btn-border-color: var(--bs-success-border-subtle);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-success);
  --bs-btn-hover-border-color: var(--bs-success);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-success);
  --bs-btn-active-border-color: var(--bs-success);
  --bs-btn-focus-shadow-rgb: var(--bs-success-rgb);
}

/* Amber is dark enough to carry white text, unlike Bootstrap's stock yellow —
   so warning buttons no longer need the black-on-yellow exception. */
.btn-warning {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--bs-warning);
  --bs-btn-border-color: var(--bs-warning);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-warning-text-emphasis);
  --bs-btn-hover-border-color: var(--bs-warning-text-emphasis);
  --bs-btn-focus-shadow-rgb: var(--bs-warning-rgb);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-warning-text-emphasis);
  --bs-btn-active-border-color: var(--bs-warning-text-emphasis);
  --bs-btn-disabled-bg: var(--bs-warning);
  --bs-btn-disabled-border-color: var(--bs-warning);
}

.btn-outline-warning {
  --bs-btn-color: var(--bs-warning);
  --bs-btn-border-color: var(--bs-warning-border-subtle);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-warning);
  --bs-btn-hover-border-color: var(--bs-warning);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-warning);
  --bs-btn-active-border-color: var(--bs-warning);
  --bs-btn-focus-shadow-rgb: var(--bs-warning-rgb);
}

.btn-danger {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--bs-danger);
  --bs-btn-border-color: var(--bs-danger);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-danger-text-emphasis);
  --bs-btn-hover-border-color: var(--bs-danger-text-emphasis);
  --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-danger-text-emphasis);
  --bs-btn-active-border-color: var(--bs-danger-text-emphasis);
  --bs-btn-disabled-bg: var(--bs-danger);
  --bs-btn-disabled-border-color: var(--bs-danger);
}

.btn-outline-danger {
  --bs-btn-color: var(--bs-danger);
  --bs-btn-border-color: var(--bs-danger-border-subtle);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-danger);
  --bs-btn-hover-border-color: var(--bs-danger);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-danger);
  --bs-btn-active-border-color: var(--bs-danger);
  --bs-btn-focus-shadow-rgb: var(--bs-danger-rgb);
}

.btn-info {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--bs-info);
  --bs-btn-border-color: var(--bs-info);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-info-text-emphasis);
  --bs-btn-hover-border-color: var(--bs-info-text-emphasis);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-info-text-emphasis);
  --bs-btn-active-border-color: var(--bs-info-text-emphasis);
  --bs-btn-focus-shadow-rgb: var(--bs-info-rgb);
}

.btn-outline-info {
  --bs-btn-color: var(--bs-info);
  --bs-btn-border-color: var(--bs-info-border-subtle);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--bs-info);
  --bs-btn-hover-border-color: var(--bs-info);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--bs-info);
  --bs-btn-active-border-color: var(--bs-info);
  --bs-btn-focus-shadow-rgb: var(--bs-info-rgb);
}

/* Bootstrap's .btn-link underlines on hover and uses link-blue; here it is the
   quietest tier of action — a text button that only darkens. */
/* Same bake-a-hex problem as the other button variants. .btn-dark is used for
   "serious but not destructive" actions (AI grading, publish confirmations); the
   deep brand tone reads that way without introducing a second neutral black. */
.btn-dark {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--primary-900);
  --bs-btn-border-color: var(--primary-900);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--primary-950);
  --bs-btn-hover-border-color: var(--primary-950);
  --bs-btn-active-bg: var(--primary-950);
  --bs-btn-active-border-color: var(--primary-950);
  --bs-btn-focus-shadow-rgb: 23, 83, 61;
  --bs-btn-disabled-bg: var(--primary-900);
  --bs-btn-disabled-border-color: var(--primary-900);
}

.btn-outline-dark {
  --bs-btn-color: var(--primary-900);
  --bs-btn-border-color: var(--border-medium);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--primary-900);
  --bs-btn-hover-border-color: var(--primary-900);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--primary-900);
  --bs-btn-active-border-color: var(--primary-900);
  --bs-btn-focus-shadow-rgb: 23, 83, 61;
}

.btn-light {
  --bs-btn-color: var(--ink-secondary);
  --bs-btn-bg: var(--surface-subtle);
  --bs-btn-border-color: var(--border-light);
  --bs-btn-hover-color: var(--ink-primary);
  --bs-btn-hover-bg: #fff;
  --bs-btn-hover-border-color: var(--border-strong);
  --bs-btn-active-bg: #fff;
  --bs-btn-active-border-color: var(--border-strong);
}

.btn-link {
  --bs-btn-color: var(--ink-secondary);
  --bs-btn-hover-color: var(--primary-700);
  --bs-btn-active-color: var(--primary-800);
  text-decoration: none;
}

/* ---------- Cards & modals ----------
   Both default to --bs-body-bg, which is now the warm canvas — a card would
   be invisible against the page and a modal indistinguishable from its own
   backdrop. Route both through the raised paper surface. */
.card {
  --bs-card-bg: var(--surface-card);
  --bs-card-border-color: var(--border-light);
  --bs-card-border-radius: var(--radius-lg);
  --bs-card-inner-border-radius: var(--radius-md);
  --bs-card-spacer-y: var(--space-4);
  --bs-card-spacer-x: var(--space-4);
}

.modal-content {
  --bs-modal-bg: var(--surface-card);
  --bs-modal-border-color: var(--border-light);
  --bs-modal-border-radius: var(--radius-lg);
  box-shadow: var(--shadow-float);
}

.modal-header,
.modal-footer {
  border-color: var(--border-light);
}

.offcanvas {
  --bs-offcanvas-bg: var(--surface-card);
  --bs-offcanvas-border-color: var(--border-light);
}

.dropdown-menu {
  --bs-dropdown-bg: var(--surface-card);
  --bs-dropdown-border-color: var(--border-light);
  --bs-dropdown-border-radius: var(--radius-md);
  --bs-dropdown-link-active-bg: var(--primary-700);
  --bs-dropdown-link-hover-bg: var(--primary-50);
  --bs-dropdown-font-size: var(--fs-sm);
  box-shadow: var(--shadow-md);
}

/* ---------- Tables ----------
   The row context classes bake a literal --bs-table-bg (e.g. #fff3cd for
   warning) with no relation to the theme — confirmed against the shipped
   Bootstrap 5 stylesheet. table-secondary/table-light map to a neutral tint
   rather than the coral --bs-secondary, so "done / unmatched" rows read as
   inactive rather than as something needing attention. */
.table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--ink-primary);
  --bs-table-border-color: var(--border-light);
  --bs-table-striped-bg: rgba(238, 236, 228, .5);
  --bs-table-hover-bg: var(--primary-50);
  font-size: var(--fs-sm);
}

.table > thead {
  background: var(--surface-subtle);
  color: var(--ink-secondary);
  font-weight: var(--fw-heavy);
}

.table > thead th {
  border-bottom-color: var(--border-medium);
  font-weight: var(--fw-heavy);
}

.table-success {
  --bs-table-color: var(--bs-success-text-emphasis);
  --bs-table-bg: var(--bs-success-bg-subtle);
  --bs-table-border-color: var(--bs-success-border-subtle);
}
.table-warning {
  --bs-table-color: var(--bs-warning-text-emphasis);
  --bs-table-bg: var(--bs-warning-bg-subtle);
  --bs-table-border-color: var(--bs-warning-border-subtle);
}
.table-danger {
  --bs-table-color: var(--bs-danger-text-emphasis);
  --bs-table-bg: var(--bs-danger-bg-subtle);
  --bs-table-border-color: var(--bs-danger-border-subtle);
}
.table-info {
  --bs-table-color: var(--bs-info-text-emphasis);
  --bs-table-bg: var(--bs-info-bg-subtle);
  --bs-table-border-color: var(--bs-info-border-subtle);
}
.table-secondary,
.table-light {
  --bs-table-color: var(--ink-muted);
  --bs-table-bg: var(--surface-subtle);
  --bs-table-border-color: var(--border-light);
}

/* ---------- Forms ---------- */
.form-label {
  color: var(--ink-secondary);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  margin-bottom: .3rem;
}

.form-control,
.form-select {
  background-color: var(--surface-input);
  border-color: var(--border-light);
  border-radius: var(--radius-sm);
  color: var(--ink-primary);
  font-size: var(--fs-sm);
  padding: .5rem .75rem;
  transition: var(--transition-fast);
}

/* Off-white at rest, pure white on focus — the shipped app's trick for making a
   dense form read as a surface rather than a grid of white boxes. */
.form-control:focus,
.form-select:focus {
  background-color: #fff;
  border-color: var(--primary-700);
  box-shadow: 0 0 0 3px rgba(37, 122, 89, .12);
}

.form-control-sm,
.form-select-sm {
  font-size: var(--fs-xs);
  padding: .35rem .6rem;
  border-radius: var(--radius-xs);
}

.input-group-text {
  background: var(--surface-subtle);
  border-color: var(--border-medium);
  color: var(--ink-muted);
  font-size: var(--fs-sm);
}

/* Placeholders stay faint so they never compete with real typed content —
   Bootstrap's default renders them at full secondary-color opacity. */
::placeholder {
  color: var(--ink-faint) !important;
  opacity: 1 !important;
}

.form-check-input:checked {
  background-color: var(--primary-700);
  border-color: var(--primary-700);
}

.form-check-input:focus {
  border-color: var(--primary-700);
  box-shadow: 0 0 0 3px rgba(37, 122, 89, .12);
}

.form-text {
  color: var(--ink-muted);
  font-size: var(--fs-xs);
}

/* ---------- Navigation, list groups, pagination, progress ---------- */
.nav-tabs {
  --bs-nav-tabs-border-color: var(--border-light);
  --bs-nav-tabs-link-active-color: var(--primary-800);
  --bs-nav-tabs-link-active-bg: var(--surface-card);
  --bs-nav-tabs-link-active-border-color: var(--border-light) var(--border-light) var(--surface-card);
  --bs-nav-link-color: var(--ink-muted);
  --bs-nav-link-hover-color: var(--ink-primary);
  --bs-nav-link-font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
}

.nav-pills {
  --bs-nav-pills-link-active-bg: var(--primary-700);
  --bs-nav-pills-border-radius: var(--radius-sm);
  --bs-nav-link-color: var(--ink-muted);
  --bs-nav-link-font-size: var(--fs-sm);
}

.list-group {
  --bs-list-group-bg: var(--surface-card);
  --bs-list-group-border-color: var(--border-light);
  --bs-list-group-border-radius: var(--radius-md);
  --bs-list-group-active-bg: var(--primary-700);
  --bs-list-group-active-border-color: var(--primary-700);
  --bs-list-group-action-hover-bg: var(--primary-50);
}

.pagination {
  --bs-pagination-color: var(--ink-secondary);
  --bs-pagination-bg: var(--surface-card);
  --bs-pagination-border-color: var(--border-light);
  --bs-pagination-hover-color: var(--primary-800);
  --bs-pagination-hover-bg: var(--primary-50);
  --bs-pagination-active-bg: var(--primary-700);
  --bs-pagination-active-border-color: var(--primary-700);
  --bs-pagination-border-radius: var(--radius-xs);
  --bs-pagination-font-size: var(--fs-sm);
}

.progress {
  --bs-progress-bg: var(--surface-subtle);
  --bs-progress-border-radius: var(--radius-pill);
  --bs-progress-height: .5rem;
}

.progress-bar {
  background-color: var(--primary-700);
}

.alert {
  --bs-alert-border-radius: var(--radius-md);
  font-size: var(--fs-sm);
}

.badge {
  font-weight: var(--fw-bold);
  font-size: var(--fs-2xs);
  border-radius: var(--radius-pill);
  padding: .35em .7em;
}

.spinner-border {
  color: var(--primary-600);
}

/* ==========================================================================
   5. EXAMIN COMPONENTS
   Prefer adding a class here over writing an inline style on a page. Each of
   these replaces a pattern that was previously hand-styled per page.
   ========================================================================== */

/* ---------- Surfaces ----------
   .ex-panel is the standard raised card: paper, hairline border, soft shadow,
   large radius. Use it instead of stacking `card border-0 shadow-sm` plus a
   background utility. */
.ex-panel {
  background: var(--surface-card);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: var(--transition-smooth);
}

.ex-panel-hover:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--border-medium);
}

.ex-panel-pad { padding: var(--space-4); }

/* Inset region inside a panel: table headers, toolbars, wells. */
.ex-inset {
  background: var(--surface-subtle);
  border-radius: var(--radius-md);
}

/* Kept for the ~180 existing references; now simply the paper surface. */
.examin-surface {
  background-color: var(--surface-card) !important;
}

/* ---------- Page title banner ----------
   The mock's page opening: a small uppercase kicker, a heavy headline, one
   line of supporting copy. Replaces the "icon + h2 + two stacked muted
   paragraphs inside a card" header the dashboard used. */
.ex-page-head {
  margin-bottom: var(--space-5);
}

.ex-page-head-center {
  text-align: center;
}

.ex-kicker {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-heavy);
  color: var(--primary-700);
  letter-spacing: .06em;
  margin-bottom: .25rem;
}

.ex-page-title {
  font-size: var(--fs-3xl);
  font-weight: var(--fw-black);
  color: var(--ink-primary);
  letter-spacing: -.04em;
  line-height: 1.1;
  margin-bottom: .35rem;
}

.ex-page-sub {
  color: var(--ink-muted);
  font-size: var(--fs-base);
  max-width: 62ch;
  margin: 0;
}

.ex-page-head-center .ex-page-sub {
  margin-inline: auto;
}

/* ---------- Stat tiles ----------
   The metric row from the mock's activities view: label above, one large
   number below. Colour the number only when it means something. */
.ex-stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-3);
}

.ex-stat {
  background: var(--surface-card);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--space-3) var(--space-4);
}

.ex-stat-label {
  display: block;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  color: var(--ink-muted);
}

.ex-stat-value {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-black);
  color: var(--ink-primary);
  line-height: 1.15;
  margin-top: .15rem;
}

.ex-stat-value-primary { color: var(--primary-700); }
.ex-stat-value-alert   { color: var(--accent-coral); }
.ex-stat-value-good    { color: var(--accent-green); }

/* ---------- Tile grid ----------
   Equal-width tiles that reflow into even rows. A flex-wrap row leaves the last
   tile stranded at whatever width is left over; a grid keeps every tile the same
   size at every breakpoint. */
.ex-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-3);
}

/* ---------- Segmented control ----------
   The mock's top nav and its source pickers are the same object: a trough
   holding buttons, the active one lifted onto white. */
.ex-segmented {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--surface-subtle);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-md);
  padding: 4px;
}

.ex-segmented-item {
  border: 0;
  background: transparent;
  color: var(--ink-muted);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-sm);
  padding: .5rem 1.1rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  white-space: nowrap;
  text-decoration: none;
  transition: var(--transition-fast);
}

.ex-segmented-item:hover { color: var(--ink-primary); }

.ex-segmented-item.active {
  background: #fff;
  color: var(--primary-900);
  font-weight: var(--fw-heavy);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .07);
}

/* ---------- Underline tabs ----------
   Top-level navigation in the shipped app is an underline, not a pill trough:
   a plain text button that gains a 3px brand rule when active. Use .ex-tabs for
   "which area of the app am I in"; keep .ex-segmented for choosing between
   options inside a panel (source pickers, view switches). */
.ex-tabs {
  display: flex;
  align-items: stretch;
  /* Tight enough that five entries fit beside the brand and the identity block,
     loose enough that the active underline reads as belonging to one of them. */
  gap: 1.15rem;
  align-self: stretch;
}

.ex-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  border: 0;
  background: transparent;
  color: var(--ink-muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: var(--transition-fast);
}

.ex-tab:hover { color: var(--ink-primary); }

.ex-tab.active { color: var(--primary-900); font-weight: var(--fw-heavy); }

.ex-tab.active::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 3px;
  border-radius: var(--radius-pill);
  background: var(--primary-700);
}

/* A count sitting next to a tab label, e.g. "Activities 15". */
.ex-tab-count {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 20px;
  padding-inline: .35rem;
  border-radius: var(--radius-pill);
  background: var(--primary-100);
  color: var(--primary-700);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-heavy);
}

/* ---------- Panel title ----------
   The shipped app's section header: a mint icon tile, a heading, and one line of
   supporting copy. Use it at the top of a panel; .ex-page-head is for the page. */
.ex-panel-title {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: var(--space-4);
}

.ex-panel-title-icon {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-sm);
  background: var(--primary-100);
  color: var(--primary-700);
  font-size: var(--fs-lg);
}

.ex-panel-title h2,
.ex-panel-title h3 {
  margin: 0;
  font-size: var(--fs-lg);
}

.ex-panel-title p {
  margin: 2px 0 0;
  color: var(--ink-muted);
  font-size: var(--fs-2xs);
}

/* ---------- Chips ----------
   One chip component with tone modifiers, replacing several hand-rolled
   badge styles. .pill below is the older name, kept for existing pages. */
.ex-chip {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  padding: .25rem .65rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-light);
  background: #FDFDFB;
  color: var(--ink-muted);
  white-space: nowrap;
}

.ex-chip-brand  { background: var(--primary-100); color: var(--primary-800); border-color: var(--primary-200); }
.ex-chip-good   { background: var(--accent-green-bg); color: var(--accent-green); border-color: var(--accent-green-border); }
.ex-chip-warn   { background: var(--accent-amber-bg); color: var(--accent-amber); border-color: var(--accent-amber-border); }
.ex-chip-alert  { background: var(--accent-coral-bg); color: var(--accent-coral); border-color: var(--accent-coral-border); }
.ex-chip-info   { background: var(--accent-blue-bg); color: var(--accent-blue); border-color: var(--accent-blue-border); }
.ex-chip-code   { font-family: "Cascadia Code", "Fira Code", Consolas, monospace; font-size: var(--fs-xs); font-weight: var(--fw-heavy); letter-spacing: .02em; }

/* Status pills — the pre-existing name, now built on the same tokens. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  padding: .3rem .7rem;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
}
.pill .dot { width: .4rem; height: .4rem; border-radius: 50%; background: currentColor; }
.pill-live      { background: var(--accent-green-bg); color: var(--accent-green); border-color: var(--accent-green-border); }
.pill-scheduled { background: var(--accent-amber-bg); color: var(--accent-amber); border-color: var(--accent-amber-border); }
.pill-draft     { background: var(--surface-subtle);  color: var(--ink-muted);    border-color: var(--border-light); }
.pill-graded    { background: var(--primary-100);     color: var(--primary-800);  border-color: var(--primary-200); }
.pill-alert     { background: var(--accent-coral-bg); color: var(--accent-coral); border-color: var(--accent-coral-border); }

/* ---------- Rows ----------
   List rows inside a panel. The last row drops its rule so it does not
   double up with the panel's own bottom border. */
.ex-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-light);
  transition: var(--transition-fast);
}

.ex-row:last-child { border-bottom: 0; }
.ex-row:hover { background: var(--primary-50); }

/* ---------- Choice tiles ----------
   Plain div[role=radio] elements with a manual tabindex, so they need their
   own focus ring; Bootstrap's .card gives none. Selected state is carried by
   the brand border and lift, not by a different hue per tile — tinting each
   tile a different semantic color is what made the dashboard read as
   decorative rather than functional. */
.choice-tile {
  background: var(--surface-card);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  transition: var(--transition-smooth);
}

.choice-tile:hover {
  border-color: var(--primary-200);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

.choice-tile.selected,
.choice-tile[aria-checked="true"] {
  border-color: var(--primary-700);
  box-shadow: 0 0 0 3px rgba(37, 122, 89, .12), var(--shadow-sm);
}

.choice-tile:focus-visible {
  outline: 2px solid var(--primary-700);
  outline-offset: 2px;
}

/* ---------- Type helpers ----------
   For the cases that genuinely need a size on the element. Use one of these
   instead of writing a new rem value inline. */
.ex-text-2xs { font-size: var(--fs-2xs); }
.ex-text-xs  { font-size: var(--fs-xs); }
.ex-text-sm  { font-size: var(--fs-sm); }
.ex-text-md  { font-size: var(--fs-md); }
.ex-text-lg  { font-size: var(--fs-lg); }
.ex-text-xl  { font-size: var(--fs-xl); }
.ex-muted    { color: var(--ink-muted); }
.ex-faint    { color: var(--ink-faint); }

/* ==========================================================================
   6. RENDERED RICH CONTENT (RichContentDisplay.razor)
   Question bodies saved via RichContentEditor can contain tables, images and
   LaTeX — this styles that saved HTML wherever it is shown read-only (student
   Run page, teacher Check / Review / Grading). RichContentEditor.razor.css is
   Blazor-scoped to the editor's own wrapper and cannot reach markup rendered
   outside it, so the rules live here.
   ========================================================================== */
/* dir="auto" on the wrapper resolves ONE direction for the whole block and
   inherits down — it does not let each paragraph detect its own direction.
   unicode-bidi: plaintext does, per element, matching what was typed line by
   line. Scoped to [dir="auto"] only: unicode-bidi: plaintext ignores the dir
   attribute per spec, so applying it universally would defeat an explicit
   dir="rtl"/"ltr" set by the HE/EN toolbar buttons. */
.rich-content-display :is(p, div, h1, h2, h3, li, blockquote)[dir="auto"] {
  unicode-bidi: plaintext;
}

.rich-content-display table {
  width: 100%;
  border-collapse: collapse;
  margin-block: .5rem;
}

.rich-content-display :is(td, th) {
  min-width: 3rem;
  padding: .4rem .5rem;
  border: 1px solid var(--border-light);
}

.rich-content-display img {
  max-width: 100%;
  height: auto;
}

.rich-content-display math-field {
  display: inline-block;
  min-width: 2.5rem;
  min-height: 2rem;
  line-height: 2rem;
  border: 1px solid var(--border-light);
  background: var(--surface-subtle);
  color: var(--ink-primary);
  border-radius: var(--radius-xs);
  padding-inline: .3rem;
  vertical-align: middle;
  --text-color: var(--ink-primary);
  --smart-fence-color: var(--ink-primary);
}

.rich-content-display .mermaid-diagram-block {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  margin-block: .6em;
  padding: .75rem;
  border: 1px solid var(--border-light);
  border-radius: var(--radius-sm);
  background: var(--surface-subtle);
}
.rich-content-display .mermaid-diagram-block svg { max-width: 100%; height: auto; }
.rich-content-display .mermaid-diagram-block.has-error { color: var(--bs-danger-text-emphasis); font-size: var(--fs-sm); direction: ltr; }
/* A diagram the model wrote that will not parse. The frame goes with it — an empty bordered
   box reads as broken layout, which is the impression the whole change is meant to avoid. */
.rich-content-display .mermaid-diagram-block.is-hidden { display: none; }

.rich-content-display pre {
  direction: ltr;
  background: #12181B;
  color: #E2E8F0;
  border-radius: var(--radius-sm);
  padding: .75rem;
  margin-block: .6em;
  overflow-x: auto;
  font-size: var(--fs-sm);
  line-height: 1.5;
}

.rich-content-display pre code {
  font-family: "Cascadia Code", "Fira Code", Consolas, "Courier New", monospace;
  white-space: pre;

  /* Both of those fonts ship programming ligatures, which draw => as a single arrow glyph.
     Pleasant in an editor, wrong here: this is exam material about code, and the same
     operator was being drawn one way in the question body and another in the answer
     options, which use a plain monospace face. Characters render literally. */
  font-variant-ligatures: none;
  font-feature-settings: "liga" 0, "calt" 0;
}
