/* ==========================================================================
   iLearn LMS styles — "Lantern" design system.
   Every colour, size, radius and timing comes from assets/css/tokens.css,
   which is loaded first. This file only draws with tokens.

   PRINCIPLES
   1. One brand light: amber marks the brand and the ONE solid primary action
      per view; repeated row/panel actions are tonal or outline. Text on amber
      is ink (--on-accent), never white, in both themes.
   2. Violet (--live) means "live right now" only (Join, Meet now, LIVE).
   3. Navy-ink neutrals; in dark mode cards are flat (surface + 1px border +
      inset highlight) and hover by turning surface-2 — no gradients, no lift.
      Light mode cards rest on shadow-1 and rise to shadow-2.
   4. States never borrow the brand: success/warning/danger/info, each with a
      text, soft and fill token. Warning (yellow) always comes with an icon.
   5. Class identity comes from the 8 category colours (--cat-N).
   6. Calm, short motion from --dur-1/2/3 + --ease-out; reduced motion honoured.

   GUARDRAILS (do not add without a design review)
   - One --glass token (blur 8px), only on the top bar, the phone tab bar and
     floating Meet chrome on desktop.
   - No neumorphism, aurora/mesh backgrounds, grain, 3D or Lottie, no
     AI-sparkle gradients, no parallax or auto-playing motion.
   - No infinite scroll in admin tables (50 rows per page).
   - No pure #000. No new hue token without updating tokens.css and the app
     constants together.
   - No icon-only buttons without labels in children's navigation.
   - Radii only from 6 / 8 / 12 / 16 / 24 / pill (--r-xs..--r-pill).
   - One accent per view plus semantic states. Text/links use --accent-text,
     shapes use --accent-fill; never put white text on gold.
   ========================================================================== */

/* ---------- Legacy aliases ----------
 * The old token names stay valid so the modules that inject their own styles
 * (chat, mail, calendar, rewards, assignments…) keep drawing correctly while
 * they migrate. New code uses the tokens.css names directly. */
:root {
  color-scheme: dark;
  accent-color: var(--accent-fill);
  --accent: var(--accent-fill);          /* fills only — text uses --accent-text */
  --accent-2: var(--accent-text);
  --accent-deep: var(--accent-fill-deep);
  --muted-2: var(--muted);               /* one muted tier (the second failed AA) */
  --border-2: var(--border-strong);
  --bg-2: var(--bg);                      /* old "inset well" colour */
  --danger-text: var(--danger);
  --success-text: var(--success);
  --warning-text: var(--warning);
  --warning-line: color-mix(in srgb, var(--warning) 40%, transparent);
  --danger-soft-2: color-mix(in srgb, var(--danger) 22%, transparent);
  --danger-line: color-mix(in srgb, var(--danger) 30%, transparent);
  --mine-border: var(--accent-line);
  --accent-tint-1: color-mix(in srgb, var(--accent-fill) 8%, transparent);
  --accent-tint-2: color-mix(in srgb, var(--accent-fill) 3%, transparent);
  --accent-tint-strong: var(--accent-soft);
  --accent-line-strong: color-mix(in srgb, var(--accent-fill) 55%, transparent);
  --tint: rgba(255, 255, 255, 0.015);    /* panel headers, table row hover */
  --topbar-bg: var(--glass);
  --overlay: rgba(4, 7, 15, 0.7);        /* behind a modal */
  --radius: var(--r-lg);
  --radius-sm: var(--r-md);
  --shadow: var(--shadow-overlay);
  --shadow-sm: var(--elev);
  /* Two-tone focus ring: a gap in the page colour, then the ring colour, so
     it reads on any surface in either theme. */
  --ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--focus-ring);
}
:root[data-theme="light"] {
  color-scheme: light;
  --bg-2: var(--surface);
  --tint: rgba(15, 23, 42, 0.025);
  --overlay: rgba(15, 23, 42, 0.40);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
/* Safety net so nothing can push the page wider than the screen on a phone.
   `clip` (not `hidden`) avoids turning <html> into a scroll container, which
   would break the sticky top bar. Wide content (tables) still scrolls inside
   its own .table-wrap. */
html { overflow-x: clip; }
body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  line-height: 1.5;
}
/* The one lantern glow, painted once on a fixed layer (a body background
   tiled with a visible seam on long pages) and only where it belongs: Home
   and the sign-in screen. Not background-attachment:fixed — janky on Android. */
body.page-home::before, body.page-login::before {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(1100px 560px at 85% -12%, var(--glow-1), transparent 60%);
}
a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font-family: inherit; cursor: pointer; }
input, textarea, select { font-family: inherit; }
/* Native controls follow the theme through color-scheme + accent-color on
   :root; one comfortable size for every checkbox and radio. */
/* :where() keeps this at zero specificity so visually-hidden inputs (.switch,
   .frm-vh) and any component's own size still win. */
:where(input[type="checkbox"], input[type="radio"]) { width: 18px; height: 18px; }
.modal audio { width: 100%; border-radius: var(--r-md); }
.table-wrap, .chat, .cls-rail, .sidebar { scrollbar-color: var(--border-strong) transparent; }

/* One visible focus ring for everything keyboard-reachable. */
:where(a, button, [role="button"], [tabindex], summary, .card, input[type="checkbox"], input[type="radio"]):focus-visible {
  outline: 2px solid var(--focus-ring); outline-offset: 2px;
}

/* Display face (Space Grotesk) for big headings and figures only — 20px+. */
.page-head h1, .section-head h2, .stat b, .card-figure b, .help-stats b, .auth-card .logo h1, .train-hero h1, .greeting {
  font-family: var(--font-display); letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}

/* ---------- Arabic and mixed-direction text ----------
 * User content is tagged dir="auto" (and lang="ar" when it starts in Arabic)
 * by the ui.js helpers. Arabic gets no tracking, no fake italics and more
 * open leading; reading blocks resolve their own direction per paragraph. */
[dir="auto"] { text-align: start; }
/* ...except inside the centred notices and empty states, which keep their
   centring (the start rule is for buttons and rows, which centre by default). */
:where(.empty:not(.inline), .help-soon, .frm-done, .fp-notice, .td-empty, .td-rw, .boot-off, .ov-empty, .auth-card .logo, .reauth-ic, .load-cap, .drop) [dir="auto"] { text-align: inherit; }
.ann-body, .card .desc, .chat .txt, .frm-desc, .asg-desc, .sub-body, .fb-body { unicode-bidi: plaintext; }
[lang="ar"] { letter-spacing: 0 !important; font-style: normal !important; }
[lang="ar"]:is(p, div, li, .ann-body, .desc, .txt, .ch-text, .rw-card-note) { line-height: 1.8; }
[lang="ar"]:is(h1, h2, h3, b) { line-height: 1.45; }

/* ---------- Layout ----------
   The app shell (sidebar / rail / phone tab bar) is drawn at the end of this
   file, in the "App shell" section. */
/* Interim logo fix (until the currentColor SVG wordmark exists): the PNG's
   wordmark is dark ink, unreadable on navy, so in dark mode it sits on a small
   white plate like the admin console's. */
:root:not([data-theme="light"]) :is(.auth-card .logo img, .fp-brand img) {
  background: #fff; border: 1px solid var(--border); border-radius: var(--r-sm); padding: 5px 9px; box-sizing: content-box;
}

/* ---------- Get help pages (Protocols / Requests / Resources / Training) ---------- */
.help-nav { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 18px; }
.help-nav a { display: inline-flex; align-items: center; gap: 7px; padding: 7px 14px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface); color: var(--text-2); font-weight: 600; font-size: 14px; text-decoration: none; }
.help-nav a:hover { color: var(--text); border-color: var(--accent-line); }
.help-nav a.active { background: var(--accent-soft); color: var(--accent-text); border-color: var(--accent-line); }
.help-nav .hn-ic { font-size: 15px; }
.help-head { align-items: flex-end; }
.help-stats { display: flex; gap: 10px; }
.help-stats div { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 16px; text-align: center; min-width: 88px; }
.help-stats b { display: block; font-size: 22px; color: var(--accent-text); line-height: 1.1; }
.help-stats small { color: var(--muted); font-size: 12px; }
.help-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 16px; }
.help-search { flex: 1; min-width: 220px; display: flex; align-items: center; gap: 8px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 0 10px; color: var(--muted); }
.help-search:focus-within { border-color: var(--focus-ring); box-shadow: var(--ring); }
.help-search input { flex: 1; border: 0; background: none; color: var(--text); padding: 10px 0; outline: 2px solid transparent; font: inherit; } /* the box around it draws the ring */
.help-search .hs-x { border: 0; background: none; color: var(--muted); cursor: pointer; display: flex; padding: 4px; }
.help-found { color: var(--muted); font-size: 13.5px; margin: 0 0 14px; }
.help-found a { color: var(--accent-text); }
.help-h2 { font-size: var(--fs-lg); margin: 26px 0 12px; }

.proto-list, .res-list { display: flex; flex-direction: column; gap: 12px; }
.proto, .res-cat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; position: relative; box-shadow: var(--elev); }
.proto::before, .res-cat::before { content: ''; position: absolute; inset-inline-start: 0; top: 0; bottom: 0; width: 4px; background: var(--c); }
.proto-head, .res-head { display: flex; align-items: center; gap: 14px; width: 100%; padding-block: 16px; padding-inline: 22px 18px; border: 0; background: none; color: var(--text); text-align: start; cursor: pointer; font: inherit; }
.proto-head:hover, .res-head:hover { background: var(--tint); }
.proto-ic, .res-ic { width: 42px; height: 42px; flex: none; border-radius: var(--r-md); display: flex; align-items: center; justify-content: center; font-size: 21px; background: color-mix(in srgb, var(--c) 18%, transparent); }
.proto-title, .res-title { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.proto-title b, .res-title b { font-size: var(--fs-lg); font-weight: 600; }
.proto-title small, .res-title small { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.proto-chev { display: flex; color: var(--muted); transform: rotate(-90deg); transition: transform var(--dur-2) var(--ease-out); }
.proto.open .proto-chev, .res-cat.open .proto-chev { transform: rotate(90deg); }
.proto-body { padding: 4px 22px 20px 22px; }
.proto-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.proto-steps > li { display: flex; gap: 14px; align-items: flex-start; }
.ps-n { width: 32px; height: 32px; flex: none; border-radius: 50%; background: var(--c); color: #fff; font-weight: 700; display: flex; align-items: center; justify-content: center; font-size: 14px; }
.proto-steps p { margin: 5px 0 0; font-size: var(--fs-md); line-height: var(--lh-read); }
.proto-steps ul { margin: 8px 0 0; padding-inline-start: 18px; color: var(--text-2); font-size: var(--fs-md); line-height: var(--lh-read); }
.proto-steps ul li::marker { color: var(--c); }
.proto-items { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 10px; }
.pi { display: flex; gap: 10px; align-items: flex-start; background: var(--tint); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px; }
.pi span { font-size: 18px; }
.pi p { margin: 0; line-height: 1.55; font-size: var(--fs-md); }
.proto-note { margin-top: 16px; display: flex; gap: 10px; background: var(--warning-soft); border: 1px solid var(--warning-line); color: var(--text); border-radius: var(--radius-sm); padding: 12px 14px; line-height: 1.5; font-size: 14px; }

.res-grid { display: none; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 10px; padding: 0 18px 18px 22px; }
.res-cat.open .res-grid { display: grid; }
.res-link { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--tint); color: var(--text); text-decoration: none; transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out); }
.res-link:hover { background: var(--surface-2); border-color: var(--c); }
.res-link[hidden] { display: none; }
.rl-ic { font-size: 18px; }
.rl-t { flex: 1; font-weight: 500; font-size: 14px; }
.rl-go { display: flex; color: var(--muted); opacity: 0; transition: opacity var(--dur-1) var(--ease-out); }
.res-link:hover .rl-go { opacity: 1; color: var(--c); }

.help-soon { text-align: center; background: var(--surface); border: 1px dashed var(--border); border-radius: var(--radius); padding: 56px 24px; max-width: 640px; margin: 10px auto; }
.help-soon .hs-ic { font-size: 44px; margin-bottom: 8px; }
.help-soon h2 { font-size: var(--fs-xl); font-family: var(--font-display); margin: 0 0 8px; }
.help-soon p { color: var(--muted); margin: 0; line-height: 1.6; }

.train-hero { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; padding: 24px; border-radius: var(--radius); border: 1px solid var(--accent-line); background: linear-gradient(135deg, var(--accent-soft), transparent 70%), var(--surface); margin-bottom: 18px; }
.train-hero h1 { margin: 0 0 4px; font-size: var(--fs-2xl); }
.train-hero p { margin: 0; color: var(--muted); }
.train-video { position: relative; aspect-ratio: 16 / 9; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--border); background: var(--bg-sunken); max-width: 1100px; }
.train-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.train-topics { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 12px; }
.tt { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; }
.tt span { font-size: 24px; }
.tt b { display: block; margin: 8px 0 4px; }
.tt p { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.5; }
/* Emoji icon in a menu row: a fixed 18px slot like the SVG icons (the generic
   `.tb-item > span` rule would otherwise stretch it to half the row). */
.tb-item > .tb-emoji { flex: 0 0 18px; width: 18px; display: inline-flex; justify-content: center; font-size: 16px; line-height: 1; }
@media (max-width: 560px) {
  .proto-head, .res-head { padding: 14px 14px 14px 18px; gap: 10px; }
  .proto-body { padding: 4px 14px 16px 18px; }
  .res-grid { padding: 0 14px 14px 18px; grid-template-columns: 1fr; }
  .proto-items { grid-template-columns: 1fr; }
  .help-stats { display: none; }
}

/* Menu rows (the Learning sites and Get the app dialogs, shell.js). */
.tb-item { display: flex; align-items: center; gap: 11px; width: 100%; padding: 9px 10px; border: 0; border-radius: var(--radius-sm); background: none; color: var(--text); text-align: start; text-decoration: none; font: inherit; cursor: pointer; }
.tb-item:hover { background: var(--surface-2); text-decoration: none; }
.tb-item:focus-visible { background: var(--accent-soft); outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.tb-item > svg { flex: none; color: var(--accent-text); }
.tb-item > span { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.tb-item b { font-size: 14px; font-weight: 600; }
.tb-item small { color: var(--muted); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tb-rec { display: inline-block; margin-inline-start: 6px; padding: 1px 7px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-text); font-size: 11px; font-style: normal; font-weight: 600; vertical-align: 1px; }
.install-steps { margin: 4px 0 0; padding-inline-start: 22px; line-height: 1.6; }
.install-steps li { margin: 6px 0; }

/* The app uses the whole window rather than a 1100px column. Nothing inside
 * stretches badly for it: the card grid adds columns, the class page splits
 * into two, and the tables were always the things starved of width. The padding
 * opens up with the viewport so content never runs into the window edge on a
 * large monitor. */
.container { width: 100%; margin: 0 auto; padding: 28px clamp(20px, 3vw, 56px) 64px; }

.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 22px; flex-wrap: wrap; }
.page-head h1 { font-size: var(--fs-2xl); line-height: var(--lh-tight); font-weight: 700; }
.page-head p { color: var(--muted); font-size: 14px; margin-top: 3px; }

/* ---------- Tabs ---------- */
.tabs { display: flex; gap: 6px; margin-bottom: 22px; border-bottom: 1px solid var(--border); }
.tabs button {
  background: none; border: none; color: var(--muted);
  padding: 12px 16px; font-size: 14px; font-weight: 600;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.tabs button { transition: color var(--dur-1) var(--ease-out), border-color var(--dur-2) var(--ease-out); }
.tabs button:hover { color: var(--text); }
.tabs button.active { color: var(--text); border-bottom-color: var(--accent-fill); }
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.page-head h1:focus, h1[tabindex="-1"]:focus, h1[tabindex="-1"]:focus-visible { outline: none; box-shadow: none; }

/* ---------- Cards / grid ---------- */
/* The class grid fills whatever width the window gives it. auto-fill with a
 * floor rather than a fixed column count: a class card is legible from about
 * 300px, so the row simply takes as many as fit instead of stretching three of
 * them across a wide monitor. */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 18px; }
.card {
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px; box-shadow: var(--elev);
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.card.clickable { cursor: pointer; }
.card.clickable:hover { background: var(--surface-2); border-color: var(--border-strong); box-shadow: var(--elev-hover); }
/* Light mode: the card stays white and lifts by shadow alone. */
:root[data-theme="light"] .card.clickable:hover { background: var(--surface); }
.card h3 { font-size: var(--fs-lg); font-weight: 600; line-height: var(--lh-title); margin-bottom: 6px; }
.card .desc { color: var(--text-2); font-size: var(--fs-sm); min-height: 20px; }
.card .meta { display: flex; gap: 14px; margin-top: 14px; color: var(--muted); font-size: var(--fs-xs); flex-wrap: wrap; }

/* Class colour: a card or tile carrying style="--c:var(--cat-N);--c-soft:var(--cat-N-soft)"
   (ui.js catStyle) shows its class identity as a top edge / initials tile. */
.card.class { border-top: 3px solid var(--c, var(--border)); }
.cls-tile {
  display: inline-grid; place-items: center; flex: none; width: 40px; height: 40px; border-radius: var(--r-md);
  background: var(--c-soft, var(--surface-3)); color: var(--c, var(--text-2));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c, var(--border)) 22%, transparent);
  font: 700 15px/1 var(--font-display); letter-spacing: -0.01em;
}
.cls-tile[lang="ar"] { font-family: var(--font-ar); font-size: 17px; }
.cls-tile.sm { width: 28px; height: 28px; border-radius: var(--r-sm); font-size: 12px; }
.cls-tile.lg { width: 56px; height: 56px; border-radius: var(--r-lg); font-size: 20px; }
.card .meta .m { display: inline-flex; align-items: center; gap: 5px; }
/* Navigation cards are real links (R-A11Y-1): look like cards, not like links. */
a.card { display: block; color: inherit; text-decoration: none; }
a.card:hover { text-decoration: none; }
.card .cls-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 6px; }
.card .cls-head h3 { margin: 0; padding-top: 2px; min-width: 0; flex: 1; overflow-wrap: anywhere; }
.card .cls-head + .desc { margin-top: 4px; }
/* Stretched link: a card holding its own buttons puts the link on its title and
   stretches it over the card; the buttons sit above it. */
.card:has(.card-link) { position: relative; }
.card-link { color: inherit; }
.card-link:hover { text-decoration: none; }
.card-link::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.card:has(.card-link) .btn, .card:has(.card-link) button { position: relative; z-index: 1; }
.card:has(.card-link:focus-visible) { box-shadow: var(--ring); }
.card-link:focus-visible { outline: none; }

/* Person avatars: initials on the deep (light-theme) category hex in BOTH
   themes, so white initials keep 4.99-7.58:1. Keyed by user id (catIndex). */
:root {
  --av-1: #1d4ed8; --av-2: #0f766e; --av-3: #15803d; --av-4: #0369a1;
  --av-5: #4d7c0f; --av-6: #be185d; --av-7: #7c4a2d; --av-8: #475569;
}
.av {
  display: inline-grid; place-items: center; flex: none; width: 30px; height: 30px; border-radius: 50%;
  background: var(--av, var(--av-8)); color: #fff; font: 600 12px/1 var(--font); letter-spacing: 0;
  vertical-align: middle; margin-inline-end: 10px;
}
.av.sm { width: 24px; height: 24px; font-size: 11px; margin-inline-end: 8px; }
/* Agenda class tags wear the class colour (beats the injected agenda CSS). */
.ag-main .ag-cls[style] { background: var(--c-soft); color: var(--text); box-shadow: inset 3px 0 0 var(--c); padding-inline-start: 9px; }
.ins-card h3 { display: flex; align-items: center; }
.ins-card h3 > bdi { flex: 0 1 auto; min-width: 0; }
.ins-card h3 .dot-badge { flex: none; white-space: nowrap; }
@media (max-width: 560px) {
  .ann.collapsed .ann-tag.neutral { display: none; }
  .ann.collapsed .ann-top { flex-wrap: nowrap; }
  .ann.collapsed .ann-top h3 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* ---------- Freeze switch (instructor / student access) ----------
 * A real checkbox, visually hidden behind the track, so it keeps its keyboard
 * behaviour and its focus ring without any of that being rebuilt by hand. */
.switch { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; user-select: none; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track {
  position: relative; flex: none; width: 38px; height: 21px; border-radius: 999px;
  background: var(--surface-3); border: 1px solid var(--field-border);
  transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.switch .knob {
  position: absolute; top: 2px; left: 2px; width: 15px; height: 15px; border-radius: 50%;
  background: var(--muted); transition: transform var(--dur-1) var(--ease-out), background var(--dur-1) var(--ease-out);
}
.switch input:checked + .track { background: var(--danger-soft); border-color: var(--danger); }
.switch input:checked + .track .knob { transform: translateX(17px); background: var(--danger); }
.switch input:focus-visible + .track { box-shadow: var(--ring); }
.switch input:disabled + .track { opacity: .5; }
.switch-label { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.switch input:checked ~ .switch-label { color: var(--danger-text); font-weight: 600; }
/* A frozen person stays in the list, dimmed — they are still on the platform,
   they just cannot get in. The controls are named rather than counted from the
   end of the row: the two tables have different column counts, and a
   positional rule brightened whichever cell happened to sit there. */
.tbl tr.row-frozen td { opacity: .55; }
.tbl tr.row-frozen td.cell-access, .tbl tr.row-frozen td.cell-actions { opacity: 1; }

/* ---------- Instructor directory (the office's Classes tab) ----------
 * One card per instructor, with the headline number the office is actually
 * scanning for — how many classes this person is carrying. */
.card-figure { display: flex; align-items: baseline; gap: 8px; margin-top: 12px; }
.card-figure b { font-size: var(--fs-3xl); font-weight: 700; line-height: 1; }
.card-figure span { color: var(--muted); font-size: 13px; }
/* The filtered instructor cards live in their own element so a search can
   redraw them without touching the "view all" card; display:contents keeps
   that wrapper out of the grid's own layout. */
.cards-slot { display: contents; }
/* The way past the grouping: an amber outline and icon (no peach wash — Lantern
   cards are flat), so it reads as the odd one out in a row of people rather
   than as another instructor. */
.card.all-card { border-color: var(--accent-line); }
.card.all-card h3 { display: flex; align-items: center; gap: 8px; }
.card.all-card h3 svg { width: 17px; height: 17px; flex: none; color: var(--accent-text); }

.panel {
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--elev); overflow: hidden; margin-bottom: 20px;
}
.panel > header {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 18px; border-bottom: 1px solid var(--border); background: var(--tint);
}
.panel > header h2 { font-size: var(--fs-lg); font-weight: 600; line-height: var(--lh-title); display: flex; align-items: center; gap: 9px; }
.panel > header h2 > svg { color: var(--muted); flex: none; }
.panel .body { padding: 18px; }
.panel .body.pad0 { padding: 0; }

/* ---------- Badges ---------- */
/* Badge = a status label (not clickable). Neutral by default; tones carry
   meaning. Sentence case, no tracking: uppercase made short words shout and
   breaks Arabic. Role badges are neutral on purpose: the word carries the
   meaning, not a hue (no indigo/teal/sky role colours). */
.badge {
  display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 8px;
  border-radius: var(--r-pill); font-size: var(--fs-2xs); font-weight: 600; line-height: 1;
  letter-spacing: 0; text-transform: none; white-space: nowrap;
  background: var(--surface-3); color: var(--text-2);
}
.badge svg { width: 12px; height: 12px; flex: none; }
.badge.admin, .badge.hr, .badge.instructor, .badge.student, .badge.viewer, .badge.neutral { background: var(--surface-3); color: var(--text-2); }
.badge.t-accent { background: var(--accent-soft); color: var(--accent-text); }
.badge.t-success, .badge.printable { background: var(--success-soft); color: var(--success); }
.badge.t-warning, .badge.proc { background: var(--warning-soft); color: var(--warning); }
.badge.t-danger { background: var(--danger-soft); color: var(--danger); }
.badge.t-info { background: var(--info-soft); color: var(--info); }
.badge.t-live { background: var(--live-soft); color: var(--live); }
/* Processing: a small spinner in front of the word. */
.badge.proc::before {
  content: ''; width: 9px; height: 9px; flex: none; border-radius: 50%; box-sizing: border-box;
  border: 2px solid currentColor; border-right-color: transparent; animation: spin 1s linear infinite;
}
/* Count = a number (tabs, panel headers, nav). */
.count {
  display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: var(--r-pill); background: var(--surface-2); color: var(--text-2);
  font: 600 12px/20px var(--font); font-variant-numeric: tabular-nums; letter-spacing: 0;
}
.count.t-accent { background: var(--accent-soft); color: var(--accent-text); }
.count.alert { background: var(--danger-fill); color: #fff; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 16px; border-radius: var(--radius-sm); font-size: var(--fs-base); font-weight: 600;
  border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--text);
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out), opacity var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out); white-space: nowrap;
}
/* :where() keeps the light base at .btn specificity, so every .btn.variant
   (here or in a module) still wins without repeating the theme selector. */
:where(:root[data-theme="light"]) .btn { background: var(--surface); }
.btn:hover { background: var(--surface-3); }
.btn:active:not(:disabled) { transform: scale(.98); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
/* Primary = the one solid amber action per view. Ink label on gold in BOTH
   themes (white on gold is ~2:1); the gradient runs fill -> fill-deep. */
.btn.primary {
  background: linear-gradient(180deg, var(--accent-fill), var(--accent-fill-deep)); border-color: transparent; color: var(--on-accent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28), 0 6px 16px -8px var(--accent-fill-deep);
}
.btn.primary:hover { background: linear-gradient(180deg, var(--accent-fill), var(--accent-fill-deep) 70%); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28), 0 8px 20px -8px var(--accent-fill-deep); }
/* Tonal = repeated or secondary accent actions (Add task, Give a reward...). */
.btn.tonal { background: var(--accent-soft); color: var(--accent-text); border-color: transparent; }
.btn.tonal:hover { background: color-mix(in srgb, var(--accent-fill) 24%, transparent); }
/* Live = meetings happening now (violet means "live", nothing else). */
.btn.live { background: var(--live-soft); color: var(--live); border-color: transparent; }
.btn.live:hover { background: color-mix(in srgb, var(--live-fill) 24%, transparent); }
.btn.live-solid { background: var(--live-fill); color: var(--on-live); border-color: transparent; box-shadow: 0 8px 22px -10px var(--live-fill); }
.btn.live-solid:hover { background: color-mix(in srgb, var(--live-fill) 88%, black); }
.btn.danger { background: var(--danger-soft); border-color: transparent; color: var(--danger); }
.btn.danger:hover { background: var(--danger-soft-2); }
.btn.danger-solid { background: var(--danger-fill); border-color: transparent; color: #fff; }
.btn.danger-solid:hover { background: color-mix(in srgb, var(--danger-fill) 88%, black); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn.ghost:hover { background: var(--surface-2); color: var(--text); }
a.btn, a.btn:hover { text-decoration: none; }
.btn.sm { padding: 7px 12px; font-size: var(--fs-sm); border-radius: var(--r-sm); }
.btn.icon { padding: 8px; }
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- Announcements ---------- */
.ann-feed { display: flex; flex-direction: column; gap: 12px; margin-bottom: 24px; }

.ann {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 16px 18px; border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--border);
  border-inline-start: 4px solid var(--accent-fill);
  box-shadow: var(--elev);
  animation: annIn var(--dur-3) var(--ease-out);
}
/* Pinned notices say so with their "Pinned" tag, not with a stronger wash. */
.ann.permanent { border-color: var(--border); border-inline-start-color: var(--accent-fill); }
.ann.ann-leaving { opacity: 0; transform: translateY(-6px); transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out); }
@keyframes annIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

.ann-ico {
  flex: none; width: 38px; height: 38px; border-radius: var(--r-md);
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent-text);
}
.ann-main { flex: 1; min-width: 0; }
.ann-top { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 5px; }
.ann-top h3 { font-size: var(--fs-lg); font-weight: 600; line-height: var(--lh-title); color: var(--text); }
/* An Arabic title should start at the right edge, with its tags flowing to
   its left, the way an Arabic reader expects (R-AR-1). dir=auto alone only
   aligns text inside the h3, which shrink-wraps in this flex row. Browsers
   without :has() keep the old left-aligned row, which still reads fine. */
.ann-top:has(> h3[lang="ar"]) { flex-direction: row-reverse; }
.ann-top:has(> h3[lang="ar"]) .ann-toggle { margin-inline-start: 0; margin-inline-end: auto; }
/* .ann-tag is the Badge (accent tone) under its old name. */
.ann-tag {
  display: inline-flex; align-items: center; gap: 4px; height: 20px;
  padding: 0 8px; border-radius: var(--r-pill); font-size: var(--fs-2xs); font-weight: 600; line-height: 1;
  text-transform: none; letter-spacing: 0; white-space: nowrap;
  background: var(--accent-soft); color: var(--accent-text);
}
.ann-tag.neutral { background: var(--surface-3); color: var(--text-2); }
/* Prose does not get wider just because the window did — a line of body text
 * running the full width of a large monitor is unreadable. The panel spans the
 * page; the sentence inside it stops at a comfortable measure. */
.ann-body { color: var(--text); font-size: var(--fs-md); line-height: var(--lh-read); white-space: pre-wrap; overflow-wrap: anywhere; max-width: 72ch; }
/* The 72ch measure box sits at the left of the (LTR) card; an Arabic body
   right-aligned inside it landed mid-card. Push the box to the right edge. */
.ann-body[lang="ar"] { margin-left: auto; }
.ann-meta { color: var(--muted); font-size: var(--fs-xs); margin-top: 9px; }
/* Unread bodies are clamped (4 lines, 2 on Home) with "Read more"; a read
   notice collapses to its title line with a Show/Hide toggle (aria-expanded). */
.ann-body.clamp { display: -webkit-box; -webkit-line-clamp: var(--lines, 4); -webkit-box-orient: vertical; overflow: hidden; }
.ann-more { background: none; border: 0; padding: 2px 0; margin-top: 4px; color: var(--accent-text); font: inherit; font-size: var(--fs-sm); font-weight: 600; cursor: pointer; }
.ann-more:hover { text-decoration: underline; }
.ann.collapsed { align-items: center; padding-block: 8px; min-height: 44px; }
.ann.collapsed .ann-fold { display: none; }
.ann.collapsed .ann-top { margin-bottom: 0; }
.ann.collapsed .ann-ico { width: 28px; height: 28px; }
.ann.collapsed .ann-ico svg { width: 15px; height: 15px; }
.ann.collapsed .ann-top h3 { font-size: var(--fs-md); }
.ann-toggle { margin-inline-start: auto; padding-block: 4px; }
.ann-actions { flex: none; display: flex; align-items: center; gap: 6px; align-self: center; }
/* Already-read notices stay in class history; their state shows through
   structure (neutral stripe, quieter title and icon), not 72% opacity, which
   pushed the body text below AA. */
.ann-done { border-inline-start-color: var(--border-strong); }
.ann-done .ann-ico { opacity: .6; background: var(--surface-3); color: var(--text-2); }
.ann-done h3 { color: var(--text-2); }
.ann-sent { background: var(--surface); border-color: var(--border); border-inline-start-color: var(--accent-fill); }

.ann-audience {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; margin-bottom: 16px;
  border-radius: var(--radius-sm); background: var(--accent-soft);
  color: var(--accent-text); font-size: var(--fs-sm);
}
.ann-kind { display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; margin-bottom: 8px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--bg-2); cursor: pointer; }
.ann-kind:hover { border-color: var(--accent-line); background: var(--surface-2); }
.ann-kind input { margin-top: 1px; flex: none; }
.ann-kind span { display: block; }
.ann-kind b { display: block; font-size: 14px; }
.ann-kind small { color: var(--muted); font-size: 12.5px; }

@media (max-width: 560px) {
  .ann { flex-wrap: wrap; position: relative; gap: 10px; padding: 14px; }
  /* Phone: the megaphone shrinks to 28px and sits inline with the title. */
  .ann .ann-ico { width: 28px; height: 28px; position: absolute; top: 14px; inset-inline-start: 14px; }
  .ann .ann-ico svg { width: 15px; height: 15px; }
  .ann .ann-top { padding-inline-start: 38px; min-height: 28px; }
  .ann.collapsed .ann-ico { top: 50%; transform: translateY(-50%); }
  .ann-actions { width: 100%; justify-content: flex-end; }
  /* A folded one-line notice keeps its delete icon on the same line
     instead of growing a second row for it. */
  .ann.collapsed { flex-wrap: nowrap; }
  .ann.collapsed .ann-actions { width: auto; }
  .ann.collapsed .ann-actions:empty { display: none; }
}

/* ---------- Phone layout pass ----------------------------------------------
   Applies to tablets-and-down. The class page has many tabs (Files, Links,
   Attendance, Grades, Chat…) that overflow a phone; without this they were
   clipped by the overflow-x guard with no way to reach them. */
@media (max-width: 720px) {
  /* Tabs become a horizontal swipe strip instead of overflowing off-screen. */
  .tabs { overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .tabs::-webkit-scrollbar { display: none; }
  .tabs button { flex: none; white-space: nowrap; padding: 12px 13px; }
  /* One card per row so a 300px min-track can never spill past a 320px screen. */
  .grid { grid-template-columns: 1fr; gap: 14px; }
  /* Give modals the whole width of a small screen. */
  .modal-backdrop { padding: 12px; }
  .modal > header, .modal > footer { padding-inline: 16px; }
  .modal .body { padding: 16px; }
  /* Wrap panel headers whose title + actions don't fit one phone line. */
  .panel > header { flex-wrap: wrap; }
  /* Tighten the page gutter so content gets a little more room. */
  .container { padding-inline: 16px; }
}

/* ---------- Forms ---------- */
.field { margin-bottom: 16px; }
.field label { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); margin-bottom: 7px; }
.field .hint { font-size: var(--fs-xs); color: var(--muted); margin-top: 6px; }
.input, textarea.input, select.input {
  width: 100%; padding: 11px 13px; border-radius: var(--radius-sm);
  background: var(--bg-2); border: 1px solid var(--field-border); color: var(--text); font-size: var(--fs-base);
  transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
/* transparent (not none) outline: invisible normally, drawn in Windows high-contrast mode */
.input:focus, textarea.input:focus, select.input:focus { outline: 2px solid transparent; border-color: var(--focus-ring); box-shadow: var(--ring); }
textarea.input { resize: vertical; min-height: 84px; }
.input::placeholder { color: var(--muted); }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 560px) { .form-row { grid-template-columns: 1fr; } }

.checklist { max-height: 260px; overflow-y: auto; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--bg-2); }
.checklist label { display: flex; align-items: center; gap: 10px; padding: 10px 13px; font-size: 14px; border-bottom: 1px solid var(--border); cursor: pointer; }
.checklist label:last-child { border-bottom: none; }
.checklist label:hover { background: var(--surface-2); }
.checklist input { flex: none; }
.checklist .em { color: var(--muted); font-size: 12px; }

/* ---------- Search ---------- */
.list-toolbar { margin-bottom: 16px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.search-field { position: relative; display: block; width: 100%; max-width: 360px; }
.panel > header .search-field { max-width: 300px; }
.search-field > svg { position: absolute; inset-inline-start: 12px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.search-field input { padding-inline: 38px 36px; }
.search-field input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
/* Our own clear button (the native one is hidden above, and absent outside
   WebKit): only there while the box holds something. */
.search-clear {
  position: absolute; inset-inline-end: 6px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; display: grid; place-items: center;
  border: none; border-radius: 999px; background: transparent; color: var(--muted); cursor: pointer;
}
.search-clear:hover, .search-clear:focus-visible { background: var(--surface-2); color: var(--text); }
.search-field input:placeholder-shown ~ .search-clear { display: none; }
.search-count { color: var(--muted); font-size: 13px; white-space: nowrap; }
.search-count:empty { display: none; }
/* Classes found straight from the instructor directory, under the cards. */
.search-section-head { display: flex; align-items: center; gap: 9px; font-size: var(--fs-lg); font-weight: 600; margin: 26px 0 14px; }
@media (max-width: 560px) { .panel > header .search-field { max-width: 100%; } }

/* ---------- Tables ---------- */
.table-wrap { overflow-x: auto; }
table.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-base); font-variant-numeric: tabular-nums; }
table.tbl th { text-align: start; color: var(--muted); font-weight: 600; font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .03em; padding: 12px 16px; border-bottom: 1px solid var(--border); white-space: nowrap; }
/* Dates, times, IDs and numbers never wrap, at any width. */
table.tbl td.mono, table.tbl td.c, table.tbl td.right, table.tbl td.r, table.tbl td.date { white-space: nowrap; }
table.tbl td { padding: 12px 16px; border-bottom: 1px solid var(--border); vertical-align: middle; }
table.tbl tr:last-child td { border-bottom: none; }
table.tbl tr:hover td { background: var(--tint); }
.mono { font-variant-numeric: tabular-nums; }
/* Free-text notes in a table stop at a readable measure instead of widening it. */
table.tbl td.att-note { max-width: 36ch; overflow-wrap: anywhere; }

/* ---------- List items (files / links) ---------- */
.item { display: flex; align-items: center; gap: 14px; padding: 13px 16px; border-bottom: 1px solid var(--border); }
.item:last-child { border-bottom: none; }
.item .ico { flex: none; width: 40px; height: 40px; border-radius: var(--r-md); display: grid; place-items: center; background: var(--accent-soft); color: var(--accent-text); }
.item .ico.link { background: var(--success-soft); color: var(--success-text); }
.item .info { flex: 1; min-width: 0; }
.item .info b { display: block; font-size: var(--fs-base); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.item .info small { color: var(--muted); font-size: var(--fs-xs); }
/* File/meta line: badges and text sit on one centred row. */
.meta-line { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; }
.item .actions { display: flex; gap: 8px; flex: none; }

/* ---------- Empty ---------- */
.empty { text-align: center; padding: 40px 20px; color: var(--muted); }
.empty .ico { width: 54px; height: 54px; border-radius: var(--r-lg); background: var(--surface-2); display: grid; place-items: center; margin: 0 auto 14px; color: var(--muted); }
.empty p { font-size: 14px; }
.empty .sub { font-size: var(--fs-sm); color: var(--muted); margin-top: 4px; }

/* ---------- Login ---------- */
.auth-wrap { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.auth-card { width: 100%; max-width: 400px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-xl); box-shadow: var(--elev), var(--shadow-2); padding: 34px 30px; }
.auth-card .logo { display: flex; flex-direction: column; align-items: center; text-align: center; margin-bottom: 26px; }
.auth-card .logo img { height: 52px; margin-bottom: 14px; }
.auth-card .logo h1 { font-size: var(--fs-xl); font-weight: 700; }
.auth-card .logo p { color: var(--muted); font-size: 13px; margin-top: 4px; }
.auth-card .btn.primary { width: 100%; padding: 12px; margin-top: 4px; }
.auth-error { background: var(--danger-soft); color: var(--danger-text); border: 1px solid var(--danger-line); padding: 10px 13px; border-radius: var(--radius-sm); font-size: 13px; margin-bottom: 18px; }

/* ---------- Modal ---------- */
.modal-backdrop { position: fixed; inset: 0; background: var(--overlay); z-index: 60; display: grid; grid-template-columns: minmax(0, 1fr); place-items: center; padding: 24px; animation: fade var(--dur-1) var(--ease-out); }
.modal { width: 100%; min-width: 0; max-width: 520px; background: var(--surface-overlay); border: 1px solid var(--border-strong); border-radius: var(--r-xl); box-shadow: var(--shadow-overlay); max-height: 90vh; display: flex; flex-direction: column; animation: pop var(--dur-2) var(--ease-out); }
.modal.wide { max-width: 760px; }
.modal > header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 22px; border-bottom: 1px solid var(--border); }
.modal > header h2 { font-size: var(--fs-lg); font-weight: 600; line-height: var(--lh-title); min-width: 0; overflow-wrap: anywhere; }
.modal > header .btn { flex: none; }
.modal .body { padding: 22px; overflow-y: auto; }
.modal > footer { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; padding: 16px 22px; border-top: 1px solid var(--border); }
.viewer-frame { width: 100%; height: 70vh; border: none; border-radius: var(--r-md); background: #fff; } /* documents render on paper */
.viewer-img { max-width: 100%; max-height: 70vh; display: block; margin: 0 auto; border-radius: var(--r-md); }
@keyframes fade { from { opacity: 0; } }
@keyframes pop { from { opacity: 0; transform: translateY(8px) scale(.98); } }

/* ---------- Toast ---------- */
#toasts { position: fixed; inset-inline-end: 20px; bottom: 20px; z-index: 80; display: flex; flex-direction: column; gap: 10px; }
/* Toast v2: [icon][text][action][×]. The tone colours the stripe and icon. */
.toast {
  --tone: var(--accent-fill);
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--surface-overlay); color: var(--text);
  border: 1px solid var(--border-strong); border-inline-start: 3px solid var(--tone);
  padding: 10px 8px 10px 12px; border-radius: var(--r-md); box-shadow: var(--shadow-2);
  font-size: var(--fs-base); line-height: 1.45; min-width: 260px; max-width: 380px;
  animation: slide var(--dur-2) var(--ease-out);
}
.toast.success { --tone: var(--success); }
.toast.error { --tone: var(--danger); }
.toast.info { --tone: var(--info); }
.toast-ico { flex: none; color: var(--tone); display: grid; place-items: center; padding-top: 1px; }
.toast-txt { flex: 1; min-width: 0; padding-top: 1px; overflow-wrap: anywhere; }
.toast-act { flex: none; margin-top: -4px; color: var(--accent-text); font-weight: 600; }
.toast-x { flex: none; margin: -4px 0 -4px -2px; padding: 5px; color: var(--muted); }
.toast.leaving { animation: toastOut var(--dur-2) var(--ease-out) forwards; }
@keyframes slide { from { opacity: 0; transform: translateX(20px); } }
@keyframes toastOut { to { opacity: 0; transform: translateX(16px); } }

/* ---------- Row "⋯" menu (ui.js rowMenu) ---------- */
.row-menu { position: relative; display: inline-block; }
.rm-pop {
  position: absolute; inset-inline-end: 0; top: calc(100% + 4px); z-index: 40; min-width: 200px;
  background: var(--surface-overlay); border: 1px solid var(--border-strong); border-radius: var(--r-md);
  box-shadow: var(--shadow-2); padding: 6px; display: flex; flex-direction: column;
}
.rm-pop[hidden] { display: none; }
.rm-item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: start;
  background: none; border: 0; color: var(--text); font: inherit; font-size: var(--fs-sm);
  padding: 8px 10px; border-radius: var(--r-sm); cursor: pointer; white-space: nowrap;
}
.rm-item:hover, .rm-item:focus-visible { background: var(--surface-2); }
.rm-item.danger { color: var(--danger); }
.rm-div { height: 1px; background: var(--border); margin: 5px 4px; }
/* Phones: the row menu is a bottom sheet (R-CMP-4), over a scrim (ui.js). */
.rm-scrim { position: fixed; inset: 0; z-index: 69; background: var(--overlay); animation: fade var(--dur-1) var(--ease-out); }
@media (max-width: 560px) {
  .rm-pop:not([hidden]) {
    position: fixed; inset: auto 0 0 0; z-index: 70; min-width: 0; max-height: 80vh; max-height: 80dvh; overflow-y: auto;
    padding: 22px 8px calc(8px + env(safe-area-inset-bottom, 0px)); border-radius: 24px 24px 0 0; border-bottom: 0;
    box-shadow: var(--shadow-overlay); animation: sheetUp var(--dur-3) var(--ease-out);
  }
  .rm-pop:not([hidden])::before { content: ''; position: absolute; top: 8px; left: 50%; width: 36px; height: 4px; margin-left: -18px; border-radius: 2px; background: var(--border-strong); }
  .rm-item { min-height: 48px; font-size: var(--fs-base); white-space: normal; }
}

/* ---------- Misc ---------- */
.back-link { display: inline-flex; align-items: center; gap: 6px; color: var(--text-2); font-size: var(--fs-sm); font-weight: 500; margin-bottom: 16px; }
.back-link:hover { color: var(--text); text-decoration: none; }
.spinner { width: 34px; height: 34px; border: 3px solid var(--border-strong); border-top-color: var(--accent-fill); border-radius: 50%; animation: spin .7s linear infinite; margin: 60px auto; }
@keyframes spin { to { transform: rotate(360deg); } }
.center-load { display: grid; place-items: center; min-height: 40vh; }
.chip { display: inline-flex; align-items: center; gap: 6px; background: var(--surface-2); border: 1px solid var(--border-strong); padding: 5px 11px; border-radius: 999px; font-size: var(--fs-sm); }
.chip button { background: none; border: none; color: var(--muted); display: grid; place-items: center; padding: 0; }
.chip button:hover { color: var(--danger); }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.divider { height: 1px; background: var(--border); margin: 18px 0; }
.stat-row { display: flex; gap: 22px; flex-wrap: wrap; }
.stat { background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px 18px; min-width: 120px; }
:root[data-theme="light"] .stat { background: var(--surface); box-shadow: var(--shadow-1); }
.stat b { display: block; font-size: 26px; font-weight: 700; line-height: 1.15; }
.stat small { color: var(--muted); font-size: var(--fs-xs); }
.stat.warn b { color: var(--warning); }
/* Yellow warning never travels alone: an alert-triangle (CSS mask, so it takes
   the text colour) marks every .warn surface so it cannot read as brand. */
.stat.warn small::before, .tbl td.warn::before {
  content: ''; display: inline-block; width: 14px; height: 14px; margin-inline-end: 5px; vertical-align: -2px;
  background: var(--warning); -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27none%27 stroke=%27black%27 stroke-width=%272%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3E%3Cpath d=%27M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z%27/%3E%3Cpath d=%27M12 9v4M12 17h.01%27/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27none%27 stroke=%27black%27 stroke-width=%272%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3E%3Cpath d=%27M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0z%27/%3E%3Cpath d=%27M12 9v4M12 17h.01%27/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ---------- Grades panel ----------
   Grade entry for instructors. The components and maximums come from the
   grading system at gradebook.ilearncenters.com; this screen only records the
   marks against them. Styles are kept in step with that application so the two
   gradebooks look like one product. */
.qtabs { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 3px; margin-bottom: 14px; }
.qtabs button { background: none; border: none; color: var(--text-2); padding: 8px 15px; font-size: var(--fs-sm); font-weight: 600; border-radius: var(--r-sm); transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.qtabs button:hover { color: var(--text); }
/* Segmented control: the selected quarter is tonal, not a second solid primary. */
.qtabs button.active { background: var(--accent-soft); color: var(--accent-text); box-shadow: inset 0 0 0 1px var(--accent-line); }

.grade-editing { padding: 9px 13px; border-radius: var(--radius-sm); background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--text-2); font-size: var(--fs-sm); margin-bottom: 14px; }
.grade-editing b { color: var(--accent-text); }
.grade-hint { color: var(--muted); font-size: 12.5px; line-height: 1.6; margin-top: 12px; }
.grade-hint b { color: var(--text); }

table.tbl th.c, table.tbl td.c { text-align: center; }
table.tbl td small.sub { display: block; color: var(--muted); font-size: 11px; font-weight: 500; margin-top: 2px; }
table.gradebook th .subj { display: block; text-transform: none; font-size: 12.5px; letter-spacing: 0; color: var(--text); }
table.gradebook th small { display: block; color: var(--muted); font-size: 11px; font-weight: 600; margin-top: 2px; }
table.gradebook th, table.gradebook td { padding: 8px 12px; }
/* The student column stays put while the marks scroll, at every width. */
table.gradebook thead tr:first-child th:first-child, table.gradebook tbody td:first-child {
  position: sticky; inset-inline-start: 0; z-index: 1; min-width: 180px; max-width: 220px;
  background: var(--surface); box-shadow: 1px 0 0 var(--border);
}
table.gradebook tbody td:first-child > b, table.gradebook tbody td:first-child > span:first-child {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere;
}
table.gradebook tbody tr:hover td:first-child { background: linear-gradient(var(--tint), var(--tint)), var(--surface); }
table.gradebook td.res, table.gradebook th.res { border-inline-start: 1px solid var(--border); }

.cell {
  width: 66px; padding: 7px 8px; text-align: center;
  background: var(--bg-2); border: 1px solid var(--field-border);
  border-radius: var(--r-sm); color: var(--text); font-size: 14px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cell:focus { outline: 2px solid transparent; border-color: var(--focus-ring); box-shadow: var(--ring); }
.cell[readonly] { background: transparent; border-color: transparent; }
.cell.changed { border-color: var(--accent); background: var(--accent-soft); }
.cell.invalid { border-color: var(--danger); background: var(--danger-soft); color: var(--danger-text); }
.cell::placeholder { color: var(--muted); font-weight: 400; }
.cell-pct { display: block; margin-top: 3px; font-size: var(--fs-2xs); color: var(--muted); font-variant-numeric: tabular-nums; min-height: 13px; }

.pill { display: inline-block; padding: 3px 9px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-text); font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
/* "Not graded" is drawn as an outline so an empty result never reads as a score. */
.pill.none { background: transparent; color: var(--muted); border: 1px dashed var(--border-strong); font-weight: 500; }

/* Grade grid: a component marked by sub-components expands into a column per
   sub-component + a read-only Total (two-row colspan header). */
.colexp { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 12px; padding: 0 3px 0 0; }
.colexp.on { color: var(--accent-text); }
/* Each sub-component group is boxed with an accent frame and its own tint, ending
   in a clearly emphasised Total column. */
table.gradebook th.grouphead { text-align: center; background: var(--accent-soft); color: var(--accent-text); font-weight: 700; font-size: 12.5px; border-inline: 2px solid var(--accent); }
table.gradebook th.subcol { background: var(--tint); }
table.gradebook th.subcol .subj, table.gradebook th.subtotal .subj { font-size: 11.5px; }
table.gradebook th.grp-start, table.gradebook td.grp-start { border-inline-start: 2px solid var(--accent); }
table.gradebook th.grp-end, table.gradebook td.grp-end { border-inline-end: 2px solid var(--accent); }
table.gradebook td.grp-cell { background: var(--tint); }
table.gradebook th.subtotal, table.gradebook td.subtotal-cell { text-align: center; white-space: nowrap; background: var(--accent-soft); }
.subtotal-cell .tot-val { display: block; font-weight: 700; font-size: 15px; color: var(--accent-text); font-variant-numeric: tabular-nums; }

/* Student's own read-only grades: components with sub-components listed beneath. */
.sg-table td, .sg-table th { padding: 9px 12px; }
.sg-table .c { text-align: center; font-variant-numeric: tabular-nums; }
.sg-comprow td { border-top: 1px solid var(--border); }
.sg-tag { font-size: var(--fs-2xs); font-weight: 600; color: var(--text-2); background: var(--surface-3); border-radius: var(--r-xs); padding: 1px 5px; margin-inline-start: 4px; }
.sg-subrow td { border: none; padding-top: 3px; padding-bottom: 3px; color: var(--muted); font-size: 13px; }
.sg-subname { padding-inline-start: 26px !important; position: relative; }
.sg-subname::before { content: "›"; position: absolute; inset-inline-start: 12px; color: var(--muted); }
.sg-result td { border-top: 2px solid var(--border-strong); }
/* Letter grade badge shown beside the percentage. */
.sg-letter { display: inline-block; min-width: 26px; padding: 2px 7px; border-radius: 6px;
  font-weight: 700; font-size: 13px; line-height: 1.3; text-align: center;
  color: var(--accent-text); background: var(--accent-soft); border: 1px solid var(--accent-line); }
.sg-letter.big { min-width: 32px; font-size: 16px; padding: 3px 9px; }

/* ---------- Class notes (office <-> instructor) ---------- */
.panel.notes > header { padding: 14px 16px; }
.panel.notes .btn-row { display: flex; gap: 4px; }
.notes-priv {
  padding: 9px 16px; margin: 0; font-size: var(--fs-xs); line-height: 1.5;
  color: var(--muted); background: var(--tint);
  border-bottom: 1px solid var(--border);
}
/* The scrolling message list of a conversation.
 *
 * Left at one class deliberately: `.cls-rail .panel > .chat` (class page) overrides its
 * height for the full-height rails, and adding a second class here would win
 * the cascade back on equal specificity and undo that. The badge that used to
 * collide with this rule was renamed instead (.dot-badge.room). */
.chat {
  display: flex; flex-direction: column; gap: 12px; background: var(--bg-sunken);
  padding: 14px 16px; max-height: 46vh; min-height: 150px; overflow-y: auto;
}
.chat .empty { padding: 22px 6px; }
.chat .msg { display: flex; }
.chat .msg.mine { justify-content: flex-end; }
.chat .bub {
  max-width: 92%; padding: 9px 12px; border-radius: var(--r-lg) var(--r-lg) var(--r-lg) var(--r-xs);
  background: var(--bubble-in); border: 1px solid var(--border);
}
.chat .msg.mine .bub {
  border-radius: var(--r-lg) var(--r-lg) var(--r-xs) var(--r-lg);
  background: var(--bubble-out); color: var(--bubble-out-text); border-color: var(--accent-line);
}
.chat .who { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.chat .who b { font-size: var(--fs-sm); font-weight: 600; }
.chat .who .badge, .seat { text-transform: none; letter-spacing: 0; }
.chat .who .badge { height: 18px; padding: 0 6px; font-size: var(--fs-2xs); }
.chat .txt { font-size: var(--fs-md); line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
.chat .foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 6px; font-size: var(--fs-2xs); color: var(--muted);
}
.chat .foot .x {
  background: none; border: none; color: var(--muted); padding: 0;
  display: grid; place-items: center; opacity: 0; transition: opacity var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.chat .bub:hover .foot .x, .chat .foot .x:focus-visible { opacity: 1; }
.chat .foot .x:hover { color: var(--danger); }
.chat-compose { display: flex; align-items: flex-end; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--border); }
.chat-compose textarea.input { min-height: 40px; font-size: var(--fs-base); padding: 9px 11px; }
.chat-compose .btn { flex: none; }

/* Unread-note marker on a class card. */
.card h3 .dot-badge {
  float: inline-end; display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px; font-size: var(--fs-2xs); font-weight: 600;
  background: var(--accent-soft); color: var(--accent-text);
}
.card h3 .dot-badge svg { width: 13px; height: 13px; }
/* A card can carry both markers. The class chat is green — the same colour the
 * student badge uses — so "the class is talking" never reads at a glance like
 * "the office is waiting for an answer", which is what the accent one means.
 *
 * The modifier is `room`, not `chat`: `.chat` is the message-list component
 * below, and a badge wearing that class picked up its flex-column layout and
 * 150px min-height, which drew the badge as a tall vertical pill. */
.card h3 .dot-badge.room { margin-inline-end: 6px; background: var(--success-soft); color: var(--success-text); }

/* ---------- Class chat (everyone on the class) ----------
 * Same furniture as the notes thread, one room instead of two sides: bubbles
 * are only ever "mine" or "someone else's", so there is no peer styling here.
 * It is taller than the notes panel because it is the busier of the two. */
/* Height is set once for the whole rail (.cls-rail .panel > .chat) so the chat and the
 * notes match when they sit side by side — this rule would out-specify it. */
.panel.chat-room .chat .bub { max-width: 96%; }
.panel.chat-room .chat .who { flex-wrap: wrap; gap: 5px; }

/* ---- Transition instructor ------------------------------------------------
 * A class can have a second instructor during a handover. Wherever that shows
 * up it is tinted amber — the same colour the office (HR) badge already uses
 * for "temporary arrangement" — so a second name never reads as a second class.
 */
.card .meta .m.seat-transition { color: var(--warning-text); }
.seat {
  display: inline-flex; align-items: center; padding: 1px 7px;
  border-radius: 999px; font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: 0; text-transform: none; white-space: nowrap;
  background: var(--surface-2); color: var(--muted);
}
.seat.transition { background: var(--warning-soft); color: var(--warning-text); }
.seat.main       { background: var(--accent-soft); color: var(--accent-text); }
.seat.former     { background: var(--surface-2); color: var(--muted); }

/* The other instructor's messages: same side of the conversation as the reader,
 * but not the reader's own words, so they are set apart from both the office
 * bubbles opposite and the reader's own. */
.chat .msg.peer .bub { border-style: dashed; border-color: var(--warning-line); }

/* Standing state at the top of a modal (who currently holds the second seat). */
.notice-line {
  padding: 10px 12px; margin-bottom: 14px; border-radius: 10px;
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 13px; line-height: 1.5; color: var(--muted);
}
.notice-line b { color: var(--text); }
.field label .opt { color: var(--muted); font-weight: 400; }

/* Transitions page: a couple of table utilities the other tables never needed. */
.tbl small.muted, small.muted { color: var(--muted); }
.tbl td.right { text-align: end; }
.tbl td.warn { color: var(--warning-text); }
.tbl td.warn small.muted { color: var(--warning-text); opacity: .8; }
.tbl .seat { vertical-align: middle; }


/* ---------- iLearn Forms (shared renderer: LMS Requests + public /form/ page) ----------
 * Everything is scoped under .frm-* so the renderer can be dropped into the SPA
 * or the standalone page without touching anything else. */
.frm, .frm-done { max-width: 760px; margin: 0 auto; }
.frm [hidden], .frm-done [hidden], .frm-page [hidden] { display: none !important; }
.frm-head { background: var(--surface); border: 1px solid var(--border); border-top: 4px solid var(--accent-fill); border-radius: var(--radius); padding: 22px 24px; margin-bottom: 14px; box-shadow: var(--shadow-sm); }
.frm-title { font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; overflow-wrap: anywhere; }
.frm-desc { color: var(--muted); font-size: 14.5px; margin-top: 8px; white-space: pre-line; line-height: 1.6; overflow-wrap: anywhere; }
.frm-reqnote { color: var(--danger-text); font-size: 12.5px; margin-top: 12px; }
.frm-req { color: var(--danger-text); margin-inline-start: 3px; font-weight: 700; }
.frm-as { display: flex; align-items: center; gap: 9px; background: var(--accent-soft); border: 1px solid var(--accent-line); color: var(--text); border-radius: var(--radius-sm); padding: 10px 14px; margin-bottom: 14px; font-size: 14px; }
.frm-as > svg { color: var(--accent-text); flex: none; }
.frm-as small { color: var(--muted); margin-inline-start: 4px; }
.frm-q { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px 20px; margin-bottom: 12px; transition: border-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out); }
.frm-q:focus-within { border-color: var(--accent-line); }
.frm-q.frm-invalid { border-color: var(--danger-line); box-shadow: 0 0 0 1px var(--danger-line); }
.frm-label { display: block; font-size: 15px; font-weight: 600; color: var(--text); margin-bottom: 10px; line-height: 1.4; overflow-wrap: anywhere; }
.frm-help { color: var(--muted); font-size: 13px; margin: -4px 0 10px; line-height: 1.5; white-space: pre-line; }
.frm-opt-tag { color: var(--muted); font-weight: 400; font-size: 12px; margin-inline-start: 4px; }
.frm-err { color: var(--danger-text); font-size: 13px; margin-top: 8px; display: flex; gap: 6px; align-items: flex-start; }
.frm-err::before { content: "!"; flex: none; width: 16px; height: 16px; border-radius: 50%; background: var(--danger-fill); color: #fff; display: inline-grid; place-items: center; font-size: 11px; font-weight: 700; margin-top: 1px; }
.frm .input { font-size: 15px; }
.frm .frm-short { max-width: 280px; }
.frm .frm-select { max-width: 420px; }
.frm-count { text-align: end; font-size: 12px; color: var(--muted); margin-top: 4px; }
.frm-count:empty { display: none; }
.frm-ident-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.frm-ident .frm-label { font-size: 14px; margin-bottom: 7px; }
.frm-ident .frm-help { margin: 10px 0 0; }

/* Choice lists */
.frm-opts { display: flex; flex-direction: column; gap: 4px; }
.frm-opt { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--radius-sm); cursor: pointer; font-size: 14.5px; }
.frm-opt:hover { background: var(--surface-2); }
.frm-opt input[type=radio], .frm-opt input[type=checkbox] { flex: none; margin: 0; cursor: pointer; }
.frm-opt > span { overflow-wrap: anywhere; }
.frm-opt-other { flex-wrap: wrap; cursor: default; }
.frm-opt-other > label { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.frm-opt-other .frm-other-text { flex: 1; min-width: 160px; padding: 8px 11px; }
.frm-clear { border: 0; background: none; color: var(--muted); font: inherit; font-size: 12.5px; margin-top: 8px; padding: 2px 0; text-decoration: underline; cursor: pointer; }
.frm-clear:hover { color: var(--text); }

/* Pills: yes/no and the linear scale. Real radios, visually hidden. */
.frm-vh { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; opacity: 0; }
.frm-pills { display: flex; gap: 10px; flex-wrap: wrap; }
.frm-pill { position: relative; cursor: pointer; }
.frm-pill > span { display: inline-flex; align-items: center; justify-content: center; min-width: 88px; padding: 10px 18px; border-radius: 999px; border: 1px solid var(--field-border); background: var(--bg-2); color: var(--text); font-weight: 600; font-size: 14px; transition: background var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); user-select: none; }
.frm-pill:hover > span { border-color: var(--accent-line-strong); }
.frm-pill input:checked + span { background: linear-gradient(180deg, var(--accent-fill), var(--accent-fill-deep)); border-color: transparent; color: var(--on-accent); }
.frm-pill input:focus-visible + span, .frm-star input:focus-visible ~ svg { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.frm-scale-row { display: grid; grid-template-columns: repeat(var(--n), minmax(0, 1fr)); gap: 6px; max-width: 560px; }
.frm-num > span { min-width: 0; width: 100%; padding: 10px 0; border-radius: var(--radius-sm); }
.frm-scale-labels { display: flex; justify-content: space-between; gap: 12px; max-width: 560px; margin-top: 7px; color: var(--muted); font-size: 12.5px; }
.frm-scale-labels span:last-child { text-align: end; }

/* Star rating */
.frm-stars { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.frm-star { position: relative; cursor: pointer; padding: 2px; line-height: 0; }
.frm-star svg { width: 32px; height: 32px; fill: transparent; stroke: var(--muted); stroke-width: 1.5; stroke-linejoin: round; transition: fill var(--dur-1) var(--ease-out), stroke var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out); }
.frm-star.on svg { fill: var(--star); stroke: var(--star); }
.frm-star.hover svg { transform: scale(1.08); }
.frm-stars-val { color: var(--muted); font-size: 13px; margin-inline-start: 8px; }

/* File picker */
.frm-file { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.frm-file-btn { position: relative; cursor: pointer; }
.frm-file-btn:focus-within { box-shadow: var(--ring); border-color: var(--focus-ring); }
.frm-file-btn.disabled { opacity: .5; cursor: not-allowed; }
.frm-file-hint { color: var(--muted); font-size: 12.5px; }
.frm-files { list-style: none; width: 100%; display: flex; flex-direction: column; gap: 6px; }
.frm-files:empty { display: none; }
.frm-files li { display: flex; align-items: center; gap: 9px; padding: 8px 10px; background: var(--bg-2); border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 14px; min-width: 0; }
.frm-files li > svg { color: var(--accent-text); flex: none; }
.frm-files li.bad { border-color: var(--danger-line); }
.frm-files .frm-fn { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.frm-files small { color: var(--muted); flex: none; }
.frm-rm { border: 0; background: none; color: var(--muted); padding: 5px; border-radius: 8px; display: flex; cursor: pointer; }
.frm-rm:hover { background: var(--danger-soft); color: var(--danger-text); }

/* Section headings */
.frm-section { padding: 18px 4px 8px; margin-bottom: 4px; }
.frm-section h2 { font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 600; letter-spacing: -0.01em; color: var(--text); overflow-wrap: anywhere; }
.frm-section p { color: var(--muted); font-size: 14px; margin-top: 4px; white-space: pre-line; line-height: 1.55; }

/* Honeypot: off-screen, never seen by people */
.frm-hp { position: absolute !important; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

.frm-formerr { background: var(--danger-soft); color: var(--danger-text); border: 1px solid var(--danger-line); padding: 11px 14px; border-radius: var(--radius-sm); font-size: 14px; margin: 4px 0 12px; }
.frm-actions { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 6px; }
.frm-submit { min-width: 140px; padding: 12px 22px; }
.frm-progress { flex: 1; min-width: 180px; display: flex; flex-direction: column; gap: 4px; }
.frm-bar { height: 6px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.frm-bar span { display: block; height: 100%; width: 0; background: var(--accent); transition: width var(--dur-2) var(--ease-out); }
.frm-progress small { color: var(--muted); font-size: 12px; }

/* Confirmation */
.frm-done { text-align: center; background: var(--surface); border: 1px solid var(--border); border-top: 4px solid var(--success); border-radius: var(--radius); padding: 40px 24px; box-shadow: var(--elev); outline: 2px solid transparent; } /* focused by script for screen readers, not by the keyboard */
.frm-done-ic { width: 60px; height: 60px; border-radius: 50%; margin: 0 auto 14px; display: grid; place-items: center; background: var(--success-soft); color: var(--success-text); }
.frm-done h2 { font-family: var(--font-display); font-size: var(--fs-xl); letter-spacing: -0.01em; overflow-wrap: anywhere; }
.frm-done-msg { color: var(--muted); margin: 8px auto 22px; max-width: 520px; white-space: pre-line; line-height: 1.6; }
.frm-done-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

/* LMS Requests list */
.frm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.frm-card { display: flex; flex-direction: column; color: inherit; }
.frm-card:hover { text-decoration: none; }
.frm-card .frm-card-ic { width: 40px; height: 40px; border-radius: 12px; background: var(--accent-soft); display: grid; place-items: center; font-size: 20px; margin-bottom: 12px; }
.frm-card h3 { overflow-wrap: anywhere; color: var(--text); }
.frm-card .desc { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.5; flex: 1; }
.frm-card .frm-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 16px; }
.frm-card .frm-card-foot small { color: var(--muted); font-size: 12.5px; }
.frm-wrap { padding-bottom: 24px; }

@media (max-width: 560px) {
  .frm-head { padding: 18px 16px; }
  .frm-q { padding: 16px 14px; }
  .frm-ident-row { grid-template-columns: 1fr; }
  .frm-scale-row { gap: 4px; }
  .frm-num > span { padding: 9px 0; font-size: 13px; }
  .frm-star svg { width: 28px; height: 28px; }
  .frm-submit { width: 100%; }
  .frm .frm-short, .frm .frm-select { max-width: none; }
}

/* ==========================================================================
   Responsive pass (2026-09-28)
   Every screen from a 320px phone to a 1920px monitor: nothing may push the
   page sideways, overlap its neighbour or shrink below a comfortable tap size.
   Wide tables still scroll, but only inside their own .table-wrap. Several
   rules here target classes whose base styles are injected by app.js at run
   time (those <style> tags come after this file), so they carry one extra
   class to win on specificity rather than on order.
   ========================================================================== */

/* Long unbroken text (a URL, an e-mail, a run-on word) wraps inside its box
   instead of widening it. */
.card, .page-head > div:first-child { min-width: 0; }
.card h3, .card .desc, .page-head h1, .page-head p, .ann-top h3, .panel > header h2,
.notice-line, .checklist label span, .stat b, .sub-body, .asg-desc, .fb-body, .ag-rp-lead { overflow-wrap: anywhere; }

/* The chat's queued-image strip is display:flex, which beat its own [hidden]
   attribute and left an empty bordered box above every composer. */
.chat-attach-pending[hidden] { display: none; }

/* List rows (enrolled students, files, links, books): the second line is one
   line with an ellipsis rather than running underneath the buttons. */
.item .info small { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* A chat image's download line, and a file chip, never exceed their box. */
.chat .chat-dl { max-width: 100%; }
.asg-files .asg-file { min-width: 0; }
.asg-files .asg-file > a { flex: 0 1 auto; }
.reward-stat .rw-note-sm { max-width: 100%; }
/* Your own chat image sits in a right-aligned column that shrinks to its
   content, and a width:100% image has no content width — it collapsed to a
   2px dot. Give it the same 260px the other side of the chat gets. */
.chat .msg.mine .chat-att .chat-img { width: 260px; max-width: 100%; }

/* PDF viewer: a page wider than the screen was centred with its left part
   pushed past the edge, where no scrolling reaches it. Auto margins centre
   the pages when they fit and fall back to the start edge when they do not. */
.pdfv .pdfv-scroll { align-items: flex-start; }
.pdfv .pdfv-pages { margin-left: auto; margin-right: auto; }
.chat-compose textarea.input::placeholder { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* The class chat composer lives in a rail 300–400px wide on a desktop and in
   a full-width panel on a phone. Wherever it is narrow, the Send button drops
   its word (icon + tooltip stay) so the message box keeps a usable width. */
.chat-room .chat-compose { container-type: inline-size; }
@container (max-width: 380px) {
  .chat-compose #cSend .tb-lbl { display: none; }
}

/* The freeze switch hides its real checkbox with position:absolute; with no
   positioned ancestor that 0×0 box escaped the table's scroll container and
   widened the whole page once the table was wider than a phone. */
.switch, .table-wrap { position: relative; }

/* Search boxes on the Get help pages: the field shrinks with its box. */
.help-search input { min-width: 0; width: 100%; }

/* Emoji picker: eight columns that share the popover's width. */
.emoji-pop .emoji-grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
.emoji-pop .emoji-grid .emoji { padding: 5px 0; }

/* Selects sitting in a panel header (the grades year) keep their own width. */
.panel > header select.input { width: auto; max-width: 100%; padding: 7px 30px 7px 11px; }
.qtabs { max-width: 100%; }

/* Touch screens have no hover: the per-message actions (react, edit, delete)
   were invisible until hovered, i.e. never shown on a phone. */
@media (hover: none) {
  .chat .foot .x { opacity: .75; }
  .rl-go { opacity: .6; }
}

/* ---- Tablets and phones (≤720px) ---------------------------------------- */
@media (max-width: 720px) {
  /* One card per row — minmax(0, …) so a card can never be wider than it. */
  .grid { grid-template-columns: minmax(0, 1fr); }

  /* No iOS zoom-on-focus: every text field is at least 16px on a phone. */
  .input, textarea.input, select.input, .cell, .frm .input, .help-search input,
  .chat-compose textarea.input, .panel .att-filter .input, .ag-bar .ag-filter { font-size: 16px; }
  .panel .att-filter .input { padding: 8px 10px; }

  /* Comfortable tap targets (~38px) for the small buttons. */
  .btn.sm { min-height: 38px; }
  .btn.icon { min-width: 38px; min-height: 38px; }
  .back-link { min-height: 36px; margin-bottom: 10px; }
  .help-nav a { padding: 9px 14px; }
  .search-clear { width: 34px; height: 34px; inset-inline-end: 4px; }
  .switch { min-height: 36px; }
  .chat .foot .x { padding: 9px; margin: -7px 0; }
  .chat .rx { padding: 9px 11px; }
  .chat .chat-dl { padding: 6px 0; }
  .chat .who .badge, .fb-meta .badge, .seat { font-size: var(--fs-2xs); }
  .item .proc-pie span { font-size: var(--fs-2xs); }
  .item .asg-more, .ag-task .ag-more { padding: 10px 0 6px; }
  .rw-edit .rw-stk { padding: 8px 9px; }
  table.tbl input[type="checkbox"] { width: 20px; height: 20px; }
  .pdfv-bar .pdfv-tool, .pdfv-bar .pdfv-btn { padding: 9px 11px; }
  .pdfv-bar .pdfv-color { height: 37px; }
  .fb-item .fb-acts .btn.icon, .ag-task .ag-acts .btn.icon, .ag-dhead .ag-add { padding: 8px; }
  .ag-task .ag-prog { min-height: 36px; padding: 6px 12px; }
  .ag-task .ag-side { flex-wrap: wrap; row-gap: 6px; }
  .ag-task .ag-acts { margin-inline-start: auto; }
  .ag-task .ag-tick { width: 30px; height: 30px; margin-top: -2px; }
  .asg-files .asg-file { padding: 1px 6px 1px 9px; }
  .asg-files .asg-file > a, .asg-files .asg-file > .fb-pname { padding: 8px 0; }
  .asg-files .asg-file .dl, .asg-files .asg-file .x, .asg-files .asg-file .mf-play { padding: 8px 6px; display: inline-flex; }
  .mf-list .mf-row .x { padding: 8px; }
  .frm-opt { padding-top: 10px; padding-bottom: 10px; }
  .frm-rm { padding: 9px; }
  .colexp { padding: 6px; }
  .rw-edit .rw-star { padding: 4px 3px; }

  /* List rows: when the buttons do not fit beside the name they drop to their
     own line, right-aligned, instead of squeezing the name to one word. */
  .item { flex-wrap: wrap; row-gap: 10px; padding: 12px 14px; gap: 12px; }
  .item .info { flex: 1 1 140px; }
  .item .actions { margin-inline-start: auto; flex-wrap: wrap; justify-content: flex-end; }
  .item .info b { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow-wrap: anywhere; }

  /* Tables scroll inside .table-wrap; give their columns a readable minimum
     instead of folding a date or a name into a column one word wide. */
  table.tbl th, table.tbl td { padding: 10px 12px; }
  table.tbl td.cell-access, table.tbl td.cell-actions, table.tbl td.att-actions { white-space: nowrap; }
  table.tbl td:has(> b), #abody table.tbl td:first-child { min-width: 150px; }
  #abody table.tbl td:nth-child(5) { min-width: 190px; }
  #stbody table.tbl td:nth-child(3), #insbody table.tbl td:nth-child(2) { white-space: nowrap; }
  #trashBody table.tbl td small.sub { min-width: 180px; }
  #transBody table.tbl td { min-width: 130px; }
  #transBody table.tbl td:last-child { min-width: 0; }
  #transHistory table.tbl td:first-child { min-width: 0; white-space: nowrap; }

  /* Phones: the sticky student column (set for every width above) gets narrower. */
  table.gradebook thead tr:first-child th:first-child, table.gradebook tbody td:first-child { min-width: 140px; max-width: 190px; }

  /* Chat composer: the Send label steps back on a phone so the text box keeps
     its width (the icon and tooltip stay). */
  .chat-compose { padding: 10px 12px; }
  .panel .chat-compose #cSend .tb-lbl { display: none; }
  .chat { padding: 12px; }

  /* Panels and modals on a small screen. */
  .panel > header { padding: 14px; }
  .panel .body { padding: 14px; }
  .panel .body.pad0 { padding: 0; }
}

/* PDF viewer on screens narrower than a page: zoom from the top-left corner,
   so zooming never grows the page past the left edge (which cannot be
   scrolled to) — it grows to the right and down instead. */
@media (max-width: 940px) {
  .pdfv .pdfv-pages { transform-origin: top left; }
}

/* ---- Phones (≤560px) ------------------------------------------------------ */
@media (max-width: 560px) {
  /* Header stats pair up in two tidy columns instead of ragged rows. */
  .stat-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .stat-row .stat, .stat-row .reward-stat { min-width: 0; padding: 12px 14px; }
  .stat-row .reward-stat.has-reward { grid-column: 1 / -1; }
  .stat b { font-size: 22px; }

  /* Quarter tabs share the width evenly. */
  .qtabs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); width: 100%; }
  .qtabs button { padding: 10px 4px; white-space: nowrap; }

  /* (The page title scales itself through --fs-2xl's clamp.) */
  .page-head { margin-bottom: 18px; gap: 12px; }

  /* Modals use the whole small screen and keep their footer reachable. */
  .modal-backdrop { padding: 10px; }
  .modal { max-height: calc(100vh - 20px); border-radius: var(--r-lg); }
  .modal > header { padding: 14px 16px; }
  .modal > footer { padding: 12px 16px; }
  .modal > footer .btn { flex: 1 1 auto; }

  /* Toasts span the bottom of the screen instead of hanging off the right. */
  #toasts { inset-inline: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .toast { min-width: 0; max-width: none; }

}
@supports (height: 100dvh) {
  @media (max-width: 560px) { .modal { max-height: calc(100dvh - 20px); } }
}

/* The reaction picker (8 emoji) is narrower than the smallest phone. */
@media (max-width: 400px) {
  body .rx-picker { gap: 0; padding: 4px; }
  body .rx-picker button { font-size: 19px; padding: 6px 3px; }
}

/* ---- Smallest phones (<360px) ------------------------------------------- */
@media (max-width: 359px) {
  .qtabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .container { padding-inline: 12px; }
}

/* ---- Chat toasts, full-height Chat page (2026-10-01) ---- */
.toast .chat-toast { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; text-align: start; cursor: pointer; color: var(--text); font: inherit; font-size: 14px; background: none; border: 0; padding: 2px 0; }
.toast .chat-toast b { font-size: var(--fs-sm); font-weight: 600; }
.toast .chat-toast span { color: var(--muted); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
body.page-chat #view { max-width: none; padding: 0; }
.chat-mount { height: calc(100vh - var(--topbar-h, 64px)); height: calc(100dvh - var(--topbar-h, 64px)); min-height: 420px; }

/* ---- Show / hide password (login form; the Mail page's unlock form has its own copy) ---- */
.pw-wrap { position: relative; }
.pw-wrap .input { padding-inline-end: 46px; }
.pw-toggle { position: absolute; inset-inline-end: 6px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px; padding: 0; border: 0; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer; }
.pw-toggle:hover { color: var(--text); background: var(--surface-2); }
.pw-toggle:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); color: var(--text); }
.pw-toggle svg { width: 18px; height: 18px; }
.pw-wrap .input::-ms-reveal, .pw-wrap .input::-ms-clear { display: none; } /* Edge's own eye would double up */

/* ---- Link chips (ui.js linkify) ------------------------------------------
   A pasted URL shows as a short chip (host/first-path, max 42 chars + ↗)
   instead of a 200-character line; the full address is in its title. */
.link-chip {
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%; vertical-align: baseline;
  padding: 1px 8px; border-radius: var(--r-sm); background: var(--surface-2); border: 1px solid var(--border);
  color: var(--accent-text); font-size: .92em; font-weight: 500; line-height: 1.5;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; unicode-bidi: isolate; direction: ltr;
  transition: border-color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.link-chip:hover { text-decoration: none; border-color: var(--accent-line); background: var(--accent-soft); }
.chat .msg.mine .bub .link-chip { background: color-mix(in srgb, var(--surface) 55%, transparent); }

/* ---- Reduced motion ------------------------------------------------------
   Everything settles instantly; spinners keep turning (slowly) so "busy"
   is still visible; nothing lifts on hover. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
  .spinner, .mf-spin, .ch-spin, .badge.proc::before { animation-duration: 1.6s !important; animation-iteration-count: infinite !important; }
  .card.clickable:hover, .btn:active:not(:disabled) { transform: none; }
}

/* ===== Agent D: class page, grades, touch targets ========================= */
/* R-TCH-4: unsaved grades — a solid sticky bar (no blur) at the panel's foot. */
.save-bar {
  position: sticky; bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 20;
  display: flex; gap: 10px; align-items: center; margin: 10px 0 0; padding: 10px 14px;
  background: var(--surface); border: 1px solid var(--accent-line, var(--border)); border-radius: 16px;
  box-shadow: var(--shadow-2); font-size: var(--fs-sm); font-weight: 600;
}
.save-bar[hidden] { display: none; }
.save-bar .sb-sp { flex: 1; }

/* R-MOB-1: 44px targets wherever the pointer is a finger, tablets included. */
@media (pointer: coarse) {
  .btn.sm { min-height: 44px; }
  .btn.icon, .btn.sm.icon { min-width: 44px; min-height: 44px; }
  .back-link { min-height: 44px; }
  .qtabs button { min-height: 44px; }
  .ag-task .ag-tick { width: 28px; height: 28px; position: relative; }
  .ag-task .ag-tick::after { content: ''; position: absolute; inset: -8px; }
  .item .asg-more, .ag-task .ag-more, .asg-more, .ag-more, .ann-more { display: inline-flex; align-items: center; min-height: 44px; }
  .chat .foot .x { min-width: 28px; min-height: 28px; border-radius: 8px; position: relative; }
  .chat .foot .x::after { content: ''; position: absolute; inset: -8px; }
}

/* ==========================================================================
   App shell (Lantern phase 2, step 1 — R-NAV-1 / R-NAV-2), drawn by shell.js.
     >= 1280px   248px sidebar
     720-1279px  76px icon rail (same markup, labels clipped)
     < 720px     slim top bar + floating bottom tab bar + More sheet
   --shell-top / --shell-bottom are what full-height pages (Chat, Mail)
   subtract from the viewport; --shell-bottom is the tab bar's footprint.
   ========================================================================== */
:root { --sidebar-w: 248px; --shell-top: 64px; --shell-bottom: 0px; }
@media (max-width: 1279px) { :root { --sidebar-w: 76px; } }
@media (max-width: 719px) {
  :root { --sidebar-w: 0px; --shell-top: 56px; --shell-bottom: calc(84px + env(safe-area-inset-bottom, 0px)); }
  body.kb-open { --shell-bottom: 0px; }
}

.app-shell { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); min-height: 100vh; min-height: 100dvh; }
.app-main { min-width: 0; display: flex; flex-direction: column; }
#view:focus { outline: none; }
.sh-ic { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: var(--icon-stroke); stroke-linecap: round; stroke-linejoin: round; }

.skip-link {
  position: fixed; inset-inline-start: 16px; top: -64px; z-index: 100; padding: 10px 14px; border-radius: var(--r-md);
  background: var(--surface-overlay); color: var(--text); border: 1px solid var(--border-strong); font: 600 var(--fs-base)/1 var(--font);
  cursor: pointer; transition: top var(--dur-2) var(--ease-out);
}
.skip-link:focus { top: 12px; }

/* ---- Sidebar ---- */
/* Brand on top and the profile block at the foot stay put; only the nav
   between them scrolls when a long nav meets a short window. */
.sidebar {
  position: sticky; top: 0; z-index: 30; height: 100vh; height: 100dvh;
  display: flex; flex-direction: column; padding: 16px 12px;
  background: var(--sidebar); border-inline-end: 1px solid var(--border); overflow: hidden;
}
.sb-brand { display: flex; align-items: center; gap: 10px; flex: none; height: 48px; padding: 0 8px; margin-bottom: 10px; border-radius: var(--r-md); color: var(--text); }
.sb-brand:hover { text-decoration: none; }
.sb-mark {
  display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: var(--r-md);
  background: linear-gradient(145deg, var(--amber-300), var(--amber-500) 45%, var(--amber-600)); color: var(--on-accent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 6px 14px -6px var(--amber-600);
}
.sb-mark svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.sb-mark.sm { width: 32px; height: 32px; }
.sb-mark.sm svg { width: 19px; height: 19px; }
.sb-word { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sb-word b { font: 700 19px/1 var(--font-display); letter-spacing: -.02em; }
.sb-word small { font: 500 var(--fs-xs)/1 var(--font); color: var(--muted); }

.sb-nav {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
  margin: 0 -12px; padding: 0 12px 8px; overflow-y: auto; overflow-x: hidden; scrollbar-width: thin;
}
.nav-sec { display: flex; flex-direction: column; }
.nav-sec[hidden] { display: none; }
.nav-label { margin: 0; padding: 16px 12px 6px; font: 600 var(--fs-xs)/1 var(--font); color: var(--muted); }
.nav-group { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.nav-item {
  position: relative; display: flex; align-items: center; gap: 12px; width: 100%; height: 40px; padding: 0 12px;
  border: 0; border-radius: var(--r-md); background: none; color: var(--text-2);
  font: 500 var(--fs-base)/1 var(--font); text-align: start; text-decoration: none; cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.nav-item:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav-item .sh-ic { color: var(--muted); transition: color var(--dur-1) var(--ease-out); }
.nav-item:hover .sh-ic { color: var(--text-2); }
.nav-item .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1.3; text-align: start; }
.nav-item .ext { width: 14px; height: 14px; color: var(--muted); }
.nav-item[aria-current="page"] { background: var(--accent-soft); color: var(--text); font-weight: 600; }
.nav-item[aria-current="page"] .sh-ic { color: var(--accent-text); }
.nav-item[aria-current="page"]::before {
  content: ""; position: absolute; inset-inline-start: -12px; top: 10px; bottom: 10px; width: 3px;
  border-radius: 0 3px 3px 0; background: var(--accent-fill);
}
/* Unread counts: chat is a strong neutral, student mail is red, per-class chat
   is quiet, office notes are amber (R-NAV-10). */
.nav-count {
  display: inline-grid; place-items: center; flex: none; min-width: 20px; height: 20px; padding: 0 6px;
  border-radius: var(--r-pill); background: var(--text); color: var(--bg);
  font: 600 var(--fs-2xs)/1 var(--font); font-variant-numeric: tabular-nums;
}
.nav-count[hidden] { display: none; }
.nav-count.alert { background: var(--danger-fill); color: #fff; }
.nav-count.soft { background: var(--surface-3); color: var(--text-2); }
.soft-count { flex: none; color: var(--muted); font: 500 var(--fs-xs)/1 var(--font); font-variant-numeric: tabular-nums; }
.soft-count[hidden] { display: none; }
.nav-note { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent-fill); }
/* The user's classes: colour initials tile + title. */
.nav-item.cls { gap: 10px; padding: 0 10px 0 6px; }
.nav-item.cls .cls-tile.sm { width: 28px; height: 28px; font-size: 11px; }
.nav-item.cls .cls-tile[lang="ar"] { font-size: 13px; }
.nav-item.cls[aria-current="true"] { background: var(--surface-2); color: var(--text); box-shadow: inset 3px 0 0 var(--c), inset 0 0 0 1px var(--border); }
.nav-item.nav-more { color: var(--muted); font-size: var(--fs-sm); }
.nav-item.nav-more .sh-ic { width: 16px; height: 16px; margin-inline: 2px; }

.side-foot { flex: none; display: flex; flex-direction: column; gap: 12px; padding-top: 12px; }
.nav-group.util .nav-item { height: 36px; font-size: var(--fs-sm); }
.nav-group.util .nav-item .sh-ic { width: 18px; height: 18px; }

/* Theme: Auto / Light / Dark (real radios inside their labels). */
.theme-seg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 2px; margin: 0; padding: 3px; min-width: 0; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); }
.theme-seg[hidden] { display: none; }
.theme-seg label {
  position: relative; display: flex; align-items: center; justify-content: center; gap: 6px; height: 30px; min-width: 0;
  border-radius: var(--r-sm); color: var(--muted); font: 500 var(--fs-xs)/1 var(--font); cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.theme-seg label:hover { color: var(--text); }
.theme-seg label:has(input:checked) { background: var(--surface); color: var(--text); box-shadow: var(--elev), 0 0 0 1px var(--border); }
.theme-seg label:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.theme-seg input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.theme-seg .sh-ic { width: 15px; height: 15px; }

/* Profile block + its menu. */
.me-btn {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 8px; border-radius: var(--r-md);
  border: 1px solid var(--border); background: var(--surface); color: var(--text); font: inherit; text-align: start; cursor: pointer;
  box-shadow: var(--elev); transition: background-color var(--dur-1) var(--ease-out);
}
.me-btn:hover { background: var(--surface-2); }
.me-av {
  position: relative; display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: 50%; overflow: hidden;
  background: linear-gradient(145deg, var(--amber-300), var(--amber-600)); color: var(--on-accent); font: 700 13px/1 var(--font-display);
}
.me-av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.me-av.sm { width: 32px; height: 32px; font-size: 12px; }
.me-txt { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.me-txt b { font-size: var(--fs-sm); font-weight: 600; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me-txt > span { font-size: var(--fs-xs); color: var(--muted); }
.me-btn .chev { width: 16px; height: 16px; color: var(--muted); transition: transform var(--dur-2) var(--ease-out); }
.me-btn[aria-expanded="true"] .chev { transform: rotate(180deg); }
.me-menu {
  position: fixed; z-index: 55; padding: 6px; background: var(--surface-overlay); border: 1px solid var(--border-strong);
  border-radius: var(--r-lg); box-shadow: var(--shadow-overlay); animation: pop var(--dur-2) var(--ease-out);
}
.me-menu[hidden] { display: none; }
.mm-id { display: flex; align-items: center; gap: 10px; padding: 8px 8px 12px; margin-bottom: 6px; border-bottom: 1px solid var(--border); min-width: 0; }
.mm-id > div { min-width: 0; }
.mm-id b { display: block; font-size: var(--fs-sm); line-height: 1.3; overflow-wrap: anywhere; }
.mm-id span { display: block; font-size: var(--fs-xs); color: var(--muted); margin-top: 2px; }
.mm-item {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; padding: 0 10px; border: 0; border-radius: var(--r-md);
  background: none; color: var(--text); font: 500 var(--fs-base)/1 var(--font); text-align: start; cursor: pointer;
}
.mm-item:hover, .mm-item:focus-visible { background: var(--surface-2); }
.mm-item:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -2px; }
.mm-item .sh-ic { width: 18px; height: 18px; color: var(--muted); }

/* Lists inside the Learning sites / Get the app dialogs. */
.sh-lead { margin: 0 0 12px; font-size: var(--fs-sm); line-height: 1.5; }
.sh-list { display: flex; flex-direction: column; gap: 2px; margin: 0 -8px; }

/* ---- Top bar: glass, breadcrumb on the left, Meet now on the right ---- */
.topbar {
  position: sticky; top: 0; z-index: 40; display: flex; align-items: center; gap: 12px;
  height: var(--shell-top); padding: 0 clamp(20px, 3vw, 56px);
  background: var(--glass); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
}
@supports not ((backdrop-filter: blur(8px)) or (-webkit-backdrop-filter: blur(8px))) { .topbar { background: var(--glass-solid); } }
.tb-home, .tb-title, .tb-avatar { display: none; }
.crumbs { min-width: 0; }
.crumbs ol { display: flex; align-items: center; gap: 8px; min-width: 0; margin: 0; padding: 0; list-style: none; font-size: var(--fs-sm); color: var(--muted); white-space: nowrap; }
.crumbs li { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.crumbs li:first-child:not(:last-child) { flex: none; max-width: 22ch; }
.crumbs a { color: var(--muted); }
.crumbs a:hover { color: var(--text); }
.crumbs .sep { display: flex; flex: none; color: var(--disabled); }
.crumbs .sep .sh-ic { width: 14px; height: 14px; }
.crumbs [aria-current] { color: var(--text); font-weight: 600; font-size: var(--fs-md); }
.tb-sp { flex: 1; }
.tb-meet { flex: none; }
.tb-meet .sh-ic { width: 16px; height: 16px; stroke-width: 2; }
.btn.live.tb-meet { background: var(--live-fill); color: var(--on-live); box-shadow: 0 8px 20px -10px var(--live-fill); }
.btn.live.tb-meet:hover { background: color-mix(in srgb, var(--live-fill) 88%, black); }

/* Hidden until the phone layout. */
.tabbar, .more-sheet { display: none; }

/* The office's in-page section row duplicates the nav once the sidebar/rail is there. */
@media (min-width: 720px) { .tabs.admin-tabs { display: none; } }

/* ---- Icon rail: 720-1279px ---- */
@media (min-width: 720px) and (max-width: 1279px) {
  .sidebar { padding: 16px 10px; align-items: center; }
  .sb-brand { justify-content: center; padding: 0; width: 100%; }
  .sb-word, .nav-label, .nav-item .lbl, .nav-item .ext, .nav-item .soft-count, .me-txt, .me-btn .chev, .theme-seg label span {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
  .sb-nav { margin: 0 -10px; padding: 0 10px 8px; width: calc(100% + 20px); }
  .side-foot { width: 100%; }
  .side-foot { align-items: center; }
  .nav-sec + .nav-sec { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
  .nav-item, .nav-item.cls { justify-content: center; padding: 0; height: 44px; }
  .nav-item[aria-current="page"]::before { inset-inline-start: -10px; }
  .nav-item .nav-count { position: absolute; top: 2px; inset-inline-end: 2px; min-width: 18px; height: 18px; padding: 0 5px; box-shadow: 0 0 0 2px var(--sidebar); }
  /* A class tile is too small to carry a number: its counts become dots. */
  .nav-item.cls .nav-count { width: 10px; min-width: 10px; height: 10px; padding: 0; top: 6px; inset-inline-end: 6px; font-size: 0; background: var(--text); }
  .nav-item.cls .nav-note { position: absolute; top: 6px; inset-inline-start: 6px; box-shadow: 0 0 0 2px var(--sidebar); }
  .nav-item.cls[aria-current="true"] { background: transparent; box-shadow: none; }
  .nav-item.cls[aria-current="true"] .cls-tile { box-shadow: 0 0 0 2px var(--sidebar), 0 0 0 4px var(--c); }
  .nav-item.nav-more { height: 36px; }
  .theme-seg { grid-template-columns: 1fr; width: 44px; }
  .theme-seg label { height: 32px; }
  .me-btn { width: auto; padding: 4px; border-color: transparent; background: transparent; box-shadow: none; justify-content: center; }
  .me-btn:hover { background: var(--surface-2); }
  .topbar { padding: 0 24px; }
}

/* ---- Phones: < 720px ---- */
@media (max-width: 719px) {
  .app-shell { display: block; }
  .sidebar { display: none; }
  .topbar { padding: 0 6px; gap: 6px; }
  .crumbs { display: none; }
  .tb-home { display: grid; place-items: center; flex: none; width: 44px; height: 44px; border-radius: var(--r-md); }
  .tb-title { display: block; min-width: 0; margin: 0; font: 700 var(--fs-lg)/1.2 var(--font-display); letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .tb-meet { width: 44px; height: 44px; padding: 0; border-radius: var(--r-md); }
  .tb-meet .tb-lbl { display: none; }
  .tb-meet .sh-ic { width: 20px; height: 20px; }
  .tb-avatar { position: relative; display: grid; place-items: center; flex: none; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; background: none; cursor: pointer; }
  .tb-avatar .nav-count { position: absolute; top: 0; inset-inline-end: 0; min-width: 18px; height: 18px; padding: 0 5px; box-shadow: 0 0 0 2px var(--bg); }
  .container { padding-bottom: calc(var(--shell-bottom) + 28px); }

  .tabbar {
    position: fixed; z-index: 45; inset-inline: 12px; bottom: calc(10px + env(safe-area-inset-bottom, 0px));
    display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 2px; height: 64px; padding: 6px;
    border-radius: var(--r-xl); background: var(--glass); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    border: 1px solid var(--border); box-shadow: var(--shadow-2);
  }
  body.kb-open .tabbar { display: none; }
  .tab {
    position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; min-width: 0;
    padding: 0; border: 0; border-radius: var(--r-lg); background: none; color: var(--muted);
    font: 600 var(--fs-2xs)/1 var(--font); text-decoration: none; cursor: pointer;
  }
  .tab:hover { text-decoration: none; color: var(--text); }
  .tab .pip { display: grid; place-items: center; width: 52px; height: 30px; border-radius: var(--r-pill); transition: background-color var(--dur-2) var(--ease-out); }
  .tab .sh-ic { width: 22px; height: 22px; }
  .tab .tl { max-width: 100%; padding: 0 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .tab[aria-current="page"], .tab.is-active { color: var(--text); }
  .tab[aria-current="page"] .pip, .tab.is-active .pip { background: var(--accent-soft); color: var(--accent-text); }
  .tab .nav-count { position: absolute; top: 2px; inset-inline-start: calc(50% + 6px); min-width: 18px; height: 18px; padding: 0 5px; box-shadow: 0 0 0 2px var(--surface); }

  /* More sheet (a modal dialog). */
  .more-sheet { display: block; position: fixed; inset: 0; z-index: 58; }
  .more-sheet[hidden] { display: none; }
  .ms-scrim { position: absolute; inset: 0; background: var(--overlay); animation: fade var(--dur-2) var(--ease-out); }
  .ms-panel {
    position: absolute; inset-inline: 0; bottom: 0; max-height: 88vh; max-height: 88dvh; overflow-y: auto; overscroll-behavior: contain;
    padding: 8px 16px calc(20px + env(safe-area-inset-bottom, 0px));
    border-radius: var(--r-xl) var(--r-xl) 0 0; background: var(--surface-overlay);
    border: 1px solid var(--border-strong); border-bottom: 0; box-shadow: var(--shadow-overlay);
    animation: sheet-up var(--dur-3) var(--ease-out);
  }
  .ms-panel:focus { outline: none; }
  .ms-grab { width: 40px; height: 4px; margin: 4px auto 12px; border-radius: 2px; background: var(--border-strong); }
  .ms-me { display: flex; align-items: center; gap: 10px; padding: 8px 4px 8px 8px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }
  .ms-me .ms-x { flex: none; }
  .ms-h { margin: 18px 4px 4px; font: 600 var(--fs-lg)/1.3 var(--font); }
  .ms-label { margin: 14px 4px 8px; font: 600 var(--fs-xs)/1 var(--font); color: var(--muted); }
  .ms-h + nav > .ms-grid:first-child { margin-top: 10px; }
  .ms-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
  .ms-item {
    position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 84px;
    padding: 10px 6px; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border);
    color: var(--text-2); font: 500 var(--fs-xs)/1.3 var(--font); text-align: center; text-decoration: none; cursor: pointer;
    overflow-wrap: anywhere;
  }
  .ms-item:hover { text-decoration: none; color: var(--text); border-color: var(--border-strong); }
  .ms-item .sh-ic { width: 22px; height: 22px; color: var(--text); }
  .ms-item[aria-current="page"] { background: var(--accent-soft); border-color: var(--accent-line); color: var(--text); }
  .ms-item[aria-current="page"] .sh-ic { color: var(--accent-text); }
  .ms-item .nav-count { position: absolute; top: 6px; inset-inline-end: 6px; }
  .more-sheet .theme-seg { margin-top: 18px; }
  .more-sheet .theme-seg label { height: 44px; font-size: var(--fs-sm); }
  .ms-foot { display: flex; gap: 8px; margin-top: 14px; }
  .ms-foot .btn { flex: 1; min-height: 44px; }

  /* Things that float at the bottom sit above the tab bar. */
  #toasts { bottom: calc(var(--shell-bottom) + 12px); }
  .save-bar { bottom: calc(var(--shell-bottom) + 12px); }
}
@media (max-width: 719px) and (pointer: coarse) {
  /* Blur stays off on touch / low-end devices. */
  .topbar, .tabbar { -webkit-backdrop-filter: none; backdrop-filter: none; background: var(--glass-solid); }
}
@keyframes sheet-up { from { transform: translateY(24px); opacity: 0; } }

/* Full-height pages fill exactly the space beside the sidebar and between the
   top bar and the tab bar (overrides the injected chat / mail heights). */
body.page-chat .chat-mount, body.page-mail .mail-mount {
  height: calc(100vh - var(--shell-top) - var(--shell-bottom));
  height: calc(100dvh - var(--shell-top) - var(--shell-bottom));
}

@media (forced-colors: active) {
  .nav-item[aria-current="page"], .tab[aria-current="page"], .ms-item[aria-current="page"] { outline: 2px solid CanvasText; }
}

/* ==========================================================================
   Student "Today" home (Lantern phase 2, step 2 — R-HOME-1), drawn by today.js.
   Everything is prefixed td- and sized from the page's own width (a container
   query on .td), so the sidebar / rail / phone shell can change around it.
     >= 1000px  Next class · To do · Agenda in one row; classes + a 360px side
     640-999px  Next class across the top, To do + Agenda below; side in 2 columns
     < 640px    one column in priority order: Next, To do, Agenda, Classes,
                Stars, Announcements (the DOM order), above the tab bar
   ========================================================================== */
.td { container: td / inline-size; max-width: 1200px; margin-inline: auto; display: flex; flex-direction: column; gap: 32px; }
.td-ic { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: var(--icon-stroke); stroke-linecap: round; stroke-linejoin: round; }

/* ---- Hero: greeting, date, the day in one line, stars tile ---- */
.td-hero {
  position: relative; overflow: hidden; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 24px; align-items: center;
  padding: 28px 32px; border-radius: var(--r-xl); border: 1px solid var(--accent-line); box-shadow: var(--elev);
  background:
    radial-gradient(420px 240px at 96% -10%, color-mix(in srgb, var(--accent-fill) 20%, transparent), transparent 70%),
    linear-gradient(135deg, var(--accent-soft), var(--surface) 62%);
}
.td-eyebrow { display: flex; align-items: center; gap: 8px; margin: 0; font: 600 var(--fs-xs)/1.45 var(--font); color: var(--accent-text); letter-spacing: .06em; text-transform: uppercase; }
.td-eyebrow .td-ic { width: 14px; height: 14px; }
.td-h1 { margin: 8px 0 0; font: 700 var(--fs-3xl)/1.15 var(--font-display); letter-spacing: -.02em; overflow-wrap: anywhere; }
.td-sub { margin: 10px 0 0; max-width: 66ch; font-size: var(--fs-md); line-height: 1.6; color: var(--text-2); }
.td-sub b { color: var(--text); font-weight: 600; }
.td-live-txt { color: var(--live); font-weight: 600; }
.td-stars {
  display: grid; grid-template-columns: auto auto; align-items: center; gap: 6px 14px; min-width: 232px; padding: 16px 18px;
  border-radius: var(--r-lg); background: var(--surface); border: 1px solid var(--border); box-shadow: var(--elev);
  color: var(--text); font: inherit; text-align: start; cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
}
.td-stars:hover { background: var(--surface-2); box-shadow: var(--elev-hover); }
.td-stars[hidden] { display: none; }
.td-stars > .td-skel { grid-column: 1 / -1; margin: 0; }
.td-stars-num { display: flex; align-items: center; gap: 8px; font: 700 var(--fs-3xl)/1 var(--font-display); font-variant-numeric: tabular-nums; }
.td-stars-num .td-star { width: 28px; height: 28px; }
.td-stars-lbl { font-size: var(--fs-sm); color: var(--text-2); line-height: 1.35; }
.td-stars-lbl b { display: block; color: var(--text); font-weight: 600; }
.td-stars-stk { grid-column: 1 / -1; display: flex; align-items: center; gap: 6px; padding-top: 10px; border-top: 1px solid var(--border); font-size: var(--fs-xs); color: var(--muted); }
.td-stars-stk > span[aria-hidden] { font-size: 20px; line-height: 1; letter-spacing: 2px; }
.td-star { width: 16px; height: 16px; flex: none; fill: var(--star); stroke: var(--star); stroke-width: 1.2; stroke-linejoin: round; }
.td-star.off { fill: none; stroke: var(--muted); stroke-width: 1.5; }

/* ---- Loading skeletons ---- */
.td-skel {
  display: block; max-width: 100%; border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--surface-2) 0, var(--surface-3) 50%, var(--surface-2) 100%); background-size: 200% 100%;
  animation: td-shimmer 1.4s linear infinite;
}
.td-skel + .td-skel { margin-top: 8px; }
.td-skel.blk { border-radius: var(--r-md); }
.td-skel-row { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px; align-items: center; padding: 8px 0; }
@keyframes td-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ---- Cards, chips, shared bits ---- */
.td-card { min-width: 0; display: flex; flex-direction: column; padding: 20px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--elev); }
.td-card-head { display: flex; align-items: center; gap: 10px; min-height: 28px; margin-bottom: 14px; }
.td-card-head h2 { margin: 0; font: 600 var(--fs-lg)/1.3 var(--font); }
.td-push { margin-inline-start: auto; display: inline-flex; }
.td > :empty { display: none; }
.td [hidden] { display: none !important; }
.td-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 24px; padding: 0 10px; border-radius: var(--r-pill);
  background: var(--surface-3); color: var(--text-2); font: 600 var(--fs-xs)/1 var(--font); white-space: nowrap;
}
.td-chip .td-ic { width: 14px; height: 14px; }
.td-chip.live { background: var(--live-soft); color: var(--live); }
.td-chip.warn { background: var(--warning-soft); color: var(--warning); }
.td-chip.danger { background: var(--danger-soft); color: var(--danger); }
.td-chip.info { background: var(--info-soft); color: var(--info); }
.td-chip.accent { background: var(--accent-soft); color: var(--accent-text); }
.td-chip.cls { background: var(--c-soft, var(--surface-3)); color: var(--text); }
.td-chip.cls::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 3px; background: var(--c, var(--muted)); }
.td-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: currentColor; box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 22%, transparent); }
.td-more { margin-inline-start: auto; display: inline-flex; align-items: center; gap: 4px; min-height: 36px; color: var(--accent-text); font-weight: 600; font-size: var(--fs-sm); border-radius: var(--r-sm); }
.td-more .td-ic { width: 16px; height: 16px; }
.td-more[hidden] { display: none; }
.td-muted { color: var(--muted); font-size: var(--fs-sm); }
.td-note { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 10px 0 0; font-size: var(--fs-xs); color: var(--muted); }
.td-note .td-ic { width: 14px; height: 14px; color: var(--warning); }
.td-link { min-height: 28px; padding: 0; border: 0; background: none; color: var(--accent-text); font: inherit; font-weight: 600; cursor: pointer; }
.td-empty { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 12px 8px; text-align: center; }
.td-empty-ic { display: grid; place-items: center; width: 44px; height: 44px; margin-bottom: 6px; border-radius: var(--r-md); background: var(--surface-2); color: var(--muted); }
.td-empty-ic .td-ic { width: 22px; height: 22px; }
.td-empty-t { margin: 0; font-weight: 600; color: var(--text); }
.td-empty-s { margin: 0; max-width: 40ch; font-size: var(--fs-sm); color: var(--muted); }
.td-empty > .btn, .td-empty-acts { margin-top: 10px; }
.td-empty-acts { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.td-todo.is-clear .td-empty-ic, .td-agenda .td-empty-ic { background: var(--success-soft); color: var(--success); }
.td-err { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; padding: 12px 14px; border-radius: var(--r-md); background: var(--danger-soft); color: var(--text); font-size: var(--fs-sm); }
.td-err > .td-ic { color: var(--danger); }
.td-err .btn { margin-inline-start: auto; }
.td-err .btn .td-ic { width: 15px; height: 15px; }
.td-mini-h { margin: 0 0 2px; font: 600 var(--fs-xs)/1 var(--font); color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }

/* ---- Today row ---- */
.td-today { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; align-items: stretch; }
@container td (min-width: 640px) {
  .td-today { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
  .td-today > .td-next { grid-column: 1 / -1; }
}
@container td (min-width: 1000px) {
  .td-today { grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr) minmax(0, 1fr); }
  .td-today > .td-next { grid-column: auto; }
}

/* Next class: violet only while it is joinable (violet = live). */
.td-next { container: tdnext / inline-size; position: relative; overflow: hidden; }
.td-next.is-live { border-color: color-mix(in srgb, var(--live) 38%, var(--border)); background: linear-gradient(165deg, var(--live-soft), transparent 58%), var(--surface); }
.td-next-body { flex: 1; display: flex; flex-direction: column; gap: 16px; }
.td-next-class { display: flex; align-items: center; gap: 14px; min-width: 0; }
.td-next-txt { min-width: 0; }
.td-next-txt h3 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin: 0; font: 600 var(--fs-lg)/1.3 var(--font); overflow-wrap: anywhere; }
.td-next-txt h3[lang="ar"] { line-height: 1.5; }
.td-next-sub { margin: 2px 0 0; font-size: var(--fs-sm); color: var(--text-2); overflow-wrap: anywhere; }
.td-next-meta { display: flex; flex-wrap: wrap; gap: 4px 12px; margin: 6px 0 0; font-size: var(--fs-sm); color: var(--text-2); }
.td-next-meta > span { display: inline-flex; align-items: center; gap: 5px; min-width: 0; }
.td-next-meta .td-ic { width: 14px; height: 14px; color: var(--muted); }
.td-join { width: 100%; min-height: 48px; font-size: var(--fs-md); border-radius: var(--r-md); }
.td-join .td-ic { width: 18px; height: 18px; }
.td-join-wait {
  display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 48px; margin: 0; padding: 6px 16px;
  border: 1px dashed var(--border-strong); border-radius: var(--r-md); background: var(--surface-2); color: var(--text-2); font-weight: 600; text-align: center;
}
.td-hint { margin: -6px 0 0; font-size: var(--fs-xs); color: var(--muted); }
.td-later { display: flex; flex-direction: column; gap: 6px; margin-top: auto; padding-top: 14px; border-top: 1px dashed var(--border-strong); }
/* Rows whose hover wash bleeds 8px past the text edge: the wash is a pseudo-element,
   so the row box itself stays inside its card. */
.td-later-row, .td-ag-item label { position: relative; isolation: isolate; }
.td-later-row::before, .td-ag-item label::before { content: ""; position: absolute; z-index: -1; inset: 0 -8px; border-radius: var(--r-md); background: transparent; transition: background-color var(--dur-1) var(--ease-out); }
.td-later-row:hover::before, .td-ag-item label:hover::before { background: var(--surface-2); }
.td-later-row { display: grid; grid-template-columns: 28px minmax(0, 1fr) auto; gap: 10px; align-items: center; min-height: 44px; padding: 4px 0; color: var(--text); }
.td-later-row:hover { text-decoration: none; }
.td-later-txt { min-width: 0; }
.td-later-txt b { display: block; overflow: hidden; font-size: var(--fs-sm); font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.td-later-txt small { font-size: var(--fs-xs); color: var(--muted); }
.td-later-row time { font-size: var(--fs-sm); color: var(--text-2); font-variant-numeric: tabular-nums; }
@container tdnext (min-width: 560px) {
  .td-next-body:not(:has(> .td-skel)) { display: grid; grid-template-columns: minmax(0, 1fr) 240px; column-gap: 24px; row-gap: 12px; align-items: center; }
  .td-next-body > .td-join, .td-next-body > .td-join-wait { grid-column: 2; grid-row: 1; }
  .td-next-body > .td-hint { grid-column: 1 / -1; margin: 0; }
  .td-next-body > .td-later, .td-next-body > .td-empty, .td-next-body > .td-err { grid-column: 1 / -1; }
}

/* To do */
.td-todo-list { margin: 0; padding: 0; list-style: none; }
.td-todo-row { display: grid; grid-template-columns: 36px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 12px 0; }
.td-todo-row:first-child { padding-top: 2px; }
.td-todo-row + .td-todo-row { border-top: 1px solid var(--border); }
.td-todo-ic { display: grid; place-items: center; width: 36px; height: 36px; border-radius: var(--r-md); background: var(--c-soft, var(--surface-2)); color: var(--c, var(--muted)); }
.td-todo-ic .td-ic { width: 18px; height: 18px; }
.td-todo-txt { min-width: 0; }
.td-todo-title { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin: 0; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.td-todo-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 5px 0 0; font-size: var(--fs-xs); color: var(--muted); }
.td-todo-cls { min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Agenda: real checkboxes, drawn as the Lantern tick box */
.td-ag-wrap { flex: 1; display: flex; flex-direction: column; }
.td-ag-list { margin: 0; padding: 0; list-style: none; }
.td-ag-item label {
  display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 12px; align-items: start; min-height: 44px;
  padding: 9px 0; cursor: pointer;
}
.td-box { display: grid; place-items: center; width: 22px; height: 22px; margin-top: 1px; border: 1.75px solid var(--field-border); border-radius: var(--r-xs); background: var(--surface); transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out); }
.td-box::after { content: ''; width: 6px; height: 11px; margin-top: -3px; border: solid #fff; border-width: 0 2.5px 2.5px 0; transform: rotate(45deg) scale(0); transition: transform var(--dur-2) var(--ease-spring); }
.td-ag-item input:checked + .td-box { background: var(--success-fill); border-color: var(--success-fill); }
.td-ag-item input:checked + .td-box::after { transform: rotate(45deg) scale(1); }
.td-ag-item input:focus-visible + .td-box { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.td-ag-item input:disabled + .td-box { opacity: .6; }
.td-ag-txt { min-width: 0; }
.td-ag-t { display: block; font-weight: 500; line-height: 1.4; overflow-wrap: anywhere; }
.td-ag-c { display: block; margin-top: 3px; overflow: hidden; font-size: var(--fs-xs); color: var(--muted); text-overflow: ellipsis; white-space: nowrap; }
.td-ag-c::before { content: ''; display: inline-block; width: 8px; height: 8px; margin-inline-end: 6px; border-radius: 3px; background: var(--c, var(--muted)); vertical-align: 0; }
.td-ag-item:has(input:checked) .td-ag-t { color: var(--muted); text-decoration: line-through; text-decoration-thickness: 1px; }
.td-ag-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--border); font-size: var(--fs-sm); color: var(--text-2); }
.td-ag-complete { display: inline-flex; align-items: center; gap: 6px; color: var(--success); font-weight: 600; }
.td-agenda.is-done { border-color: color-mix(in srgb, var(--success) 45%, var(--border)); }
.td-ring { display: block; width: 40px; height: 40px; }
.td-ring circle { fill: none; stroke-width: 5; }
.td-ring .trk { stroke: var(--surface-3); }
.td-ring .val { stroke: var(--success); stroke-linecap: round; transition: stroke-dasharray var(--dur-3) var(--ease-out); }
.td-ring text { font: 700 10px/1 var(--font); fill: var(--text-2); }

/* ---- Classes + side column ---- */
.td-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: 28px; align-items: start; }
.td-side { display: flex; flex-direction: column; gap: 28px; min-width: 0; }
@container td (min-width: 640px) { .td-side { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; align-items: start; } }
@container td (min-width: 1040px) {
  .td-split { grid-template-columns: minmax(0, 1fr) 360px; gap: 24px; }
  .td-side { display: flex; gap: 32px; align-items: stretch; }
}
.td-sec { min-width: 0; }
.td-sec:focus { outline: none; }
.td-sec-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 14px; }
.td-sec-head h2 { margin: 0; font: 600 var(--fs-xl)/1.3 var(--font-display); letter-spacing: -.01em; }
.td-sec-head .count { align-self: center; }

/* Class cards (R-HOME-5): class-colour stripe, initials tile, title, teacher,
   then only what needs attention. */
.td-classes { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 16px; margin: 0; padding: 0; list-style: none; }
.td-cls {
  position: relative; isolation: isolate; overflow: hidden; height: 100%; min-height: 168px;
  display: grid; grid-template-rows: auto 1fr auto; gap: 12px; padding: 18px;
  border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--elev); color: var(--text);
  background: linear-gradient(180deg, var(--c-soft, var(--surface-2)), transparent 62%), var(--surface);
  transition: background-color var(--dur-1) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.td-cls::before { content: ''; position: absolute; inset: 0 0 auto; height: 4px; background: var(--c, var(--border-strong)); }
.td-cls::after { content: ''; position: absolute; z-index: -1; top: -52px; inset-inline-end: -46px; width: 132px; height: 132px; border-radius: 50%; background: var(--c-soft, transparent); }
.td-cls:hover { text-decoration: none; border-color: color-mix(in srgb, var(--c, var(--border)) 40%, var(--border)); box-shadow: var(--elev-hover); background: linear-gradient(180deg, var(--c-soft, var(--surface-2)), transparent 72%), var(--surface-2); }
:root[data-theme="light"] .td-cls:hover { background: linear-gradient(180deg, var(--c-soft), transparent 72%), var(--surface); }
.td-cls:focus-visible { outline-offset: 3px; }
.td-cls-skel { display: block; min-height: 168px; }
.td-cls-skel .td-skel:first-child { margin-bottom: 18px; }
.td-cls-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.td-cls-go { display: grid; place-items: center; width: 28px; height: 28px; border: 1px solid var(--border); border-radius: 50%; background: var(--surface); color: var(--muted); transition: transform var(--dur-2) var(--ease-out), color var(--dur-1) var(--ease-out); }
.td-cls:hover .td-cls-go { color: var(--text); transform: translateX(2px); }
.td-cls-go .td-ic { width: 15px; height: 15px; }
.td-cls-mid { display: flex; flex-direction: column; min-width: 0; }
.td-cls-title { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin: 0; font: 600 var(--fs-md)/1.35 var(--font); overflow-wrap: anywhere; }
.td-cls-title[lang="ar"] { font-family: var(--font-ar); line-height: 1.6; }
.td-cls-teacher { display: flex; align-items: center; gap: 6px; min-width: 0; margin-top: 6px; font-size: var(--fs-sm); color: var(--muted); }
.td-cls-teacher .td-ic { width: 14px; height: 14px; }
.td-cls-teacher bdi { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.td-cls-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 24px; }
.td-calm { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-xs); color: var(--muted); }
.td-calm .td-ic { width: 14px; height: 14px; color: var(--success); }

/* ---- My stars (R-STU-5) ---- */
.td-rw-strip { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.td-rw {
  position: relative; overflow: hidden; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 18px 14px 16px;
  border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--elev); text-align: center;
  background: radial-gradient(140px 90px at 50% 0, var(--accent-soft), transparent 72%), var(--surface);
}
.td-rw.feature {
  grid-column: 1 / -1; padding: 26px 22px 20px; border-color: var(--accent-line);
  background: radial-gradient(260px 150px at 50% 0, color-mix(in srgb, var(--accent-fill) 20%, transparent), transparent 72%), radial-gradient(160px 110px at 50% 22%, var(--accent-soft), transparent 72%), var(--surface);
}
.td-rw [dir="auto"] { text-align: center; }
.td-rw-new { position: absolute; top: 12px; inset-inline-start: 12px; }
.td-rw-cls { max-width: 100%; }
.td-rw.feature .td-rw-cls { max-width: calc(100% - 120px); }
.td-rw-clsname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.td-sticker { display: grid; place-items: center; width: 56px; height: 56px; border-radius: 50%; font-size: 30px; line-height: 1; background: radial-gradient(circle, var(--accent-soft) 0, transparent 70%); }
.td-rw.feature .td-sticker { width: 84px; height: 84px; font-size: 46px; }
.td-stars-row { display: flex; gap: 3px; }
.td-rw.feature .td-star { width: 20px; height: 20px; }
.td-rw-note { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; margin: 0; font-size: var(--fs-sm); line-height: 1.55; color: var(--text); overflow-wrap: anywhere; }
.td-rw.feature .td-rw-note { max-width: 34ch; font-size: var(--fs-md); line-height: 1.6; }
.td-rw-note[lang="ar"] { line-height: 1.8; }
.td-rw-from { margin: 0; font-size: var(--fs-xs); color: var(--muted); }
.td-rw-from bdi { color: var(--text-2); font-weight: 600; }
.td-rw-teaser { display: flex; align-items: center; gap: 14px; padding: 18px; border: 1.5px dashed var(--border-strong); border-radius: var(--r-lg); color: var(--text-2); }
.td-rw-teaser-ic { display: grid; place-items: center; flex: none; width: 48px; height: 48px; border-radius: 50%; background: var(--accent-soft); }
.td-rw-teaser-ic .td-star { width: 24px; height: 24px; }
.td-rw-teaser p { margin: 0; font-size: var(--fs-sm); }
.td-rw-teaser b { display: block; margin-bottom: 2px; color: var(--text); font-weight: 600; }
.td-confetti { position: absolute; top: 96px; left: 50%; width: 0; height: 0; pointer-events: none; }
.td-confetti i { position: absolute; width: 6px; height: 10px; border-radius: 2px; background: var(--pc); opacity: 0; }

/* ---- Announcements on Home: compact, in the side column ---- */
.td .ann-feed { gap: 10px; margin-bottom: 0; }
.td .ann { padding: 14px 16px; }
.td .ann-top h3 { font-size: var(--fs-base); }
.td .ann-body { font-size: var(--fs-sm); }

/* ---- First-run welcome (R-STU-9) ---- */
.td-welcome { padding: 20px; border: 1px solid var(--accent-line); border-radius: var(--r-xl); background: linear-gradient(135deg, var(--accent-soft), transparent 60%), var(--surface); box-shadow: var(--elev); }
.td-welcome h2 { margin: 0 0 14px; font: 600 var(--fs-lg)/1.3 var(--font); }
.td-wel-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); gap: 10px; margin: 0; padding: 0; list-style: none; }
.td-wel-grid li { display: flex; align-items: flex-start; gap: 12px; min-width: 0; padding: 12px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }
.td-wel-grid li > span:last-child { min-width: 0; }
.td-wel-grid b { display: block; font-size: var(--fs-sm); font-weight: 600; }
.td-wel-grid small { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--muted); overflow-wrap: anywhere; }
.td-wel-ic { display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: var(--r-md); background: var(--accent-soft); color: var(--accent-text); }
.td-wel-ic.live { background: var(--live-soft); color: var(--live); }
.td-wel-ic .td-ic { width: 18px; height: 18px; }
.td-ltr { unicode-bidi: isolate; color: var(--text-2); font-weight: 600; }
.td-wel-acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin-top: 14px; }

/* ---- Phones / narrow pages ---- */
@container td (max-width: 639px) {
  .td-hero { grid-template-columns: minmax(0, 1fr); gap: 18px; padding: 22px 20px; }
  .td-stars { min-width: 0; grid-template-columns: auto minmax(0, 1fr); padding: 12px 14px; }
  .td-stars-num { font-size: 28px; }
  .td-card { padding: 16px; }
  .td-todo-row { grid-template-columns: 36px minmax(0, 1fr); }
  .td-todo-row .btn { grid-column: 2; justify-self: start; }
  .td-classes { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .td-cls { min-height: 156px; gap: 10px; padding: 14px; }
  .td-cls-go { display: none; }
  .td-cls-title { font-size: var(--fs-base); }
  .td-cls-teacher { font-size: var(--fs-xs); }
  /* Rewards scroll sideways, one card at a time. */
  .td-rw-strip { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 78%; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; padding-bottom: 8px; scrollbar-width: none; }
  .td-rw-strip::-webkit-scrollbar { display: none; }
  .td-rw-strip:has(> .td-rw:only-child) { grid-auto-columns: 100%; }
  /* The strip clips; the cards themselves need not (keeps nested clipping out of a scroller). */
  .td-rw, .td-rw.feature { grid-column: auto; scroll-snap-align: start; padding: 24px 16px 18px; overflow: visible; }
  .td-rw.feature .td-sticker { width: 72px; height: 72px; font-size: 40px; }
  .td-wel-acts .btn { flex: 1; }
  /* 44px targets by width on phones too, not only when the pointer reports
     coarse: the page is then the same height whatever the browser says about
     its pointer (a full-page capture drops touch emulation mid-shot). */
  .td .btn.sm, .td .btn.icon, .td .ann-more, .td-more, .td-link { min-height: 44px; }
  .td .btn.icon { min-width: 44px; }
}
@container td (max-width: 340px) { .td-classes { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 719px) { .td { gap: 24px; } }
@media (pointer: coarse) { .td-more, .td-link { min-height: 44px; } }

/* ---- Motion: a gentle rise on arrival, one confetti burst, a live pulse ---- */
@keyframes td-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes td-burst { 0% { transform: translate(0, 0) rotate(0) scale(.4); opacity: 0; } 12% { opacity: 1; } 100% { transform: translate(var(--x), var(--y)) rotate(var(--r)) scale(1); opacity: 0; } }
@keyframes td-pop { 0% { transform: scale(.55); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
@keyframes td-pulse { 50% { box-shadow: 0 0 0 6px color-mix(in srgb, currentColor 0%, transparent); } }
@media (prefers-reduced-motion: no-preference) {
  .td-hero, .td-today > *, .td-split { animation: td-rise var(--dur-3) var(--ease-out) both; }
  .td-today > :nth-child(2) { animation-delay: 40ms; }
  .td-today > :nth-child(3) { animation-delay: 80ms; }
  .td-split { animation-delay: 120ms; }
  .td-confetti i { animation: td-burst 900ms var(--ease-out) 420ms both; }
  .td-rw.feature:has(.td-confetti) .td-sticker { animation: td-pop var(--dur-3) var(--ease-spring) 200ms both; }
  .td-chip.live .td-dot { animation: td-pulse 1.6s ease-in-out infinite; }
}
@media (prefers-reduced-motion: reduce) { .td-confetti { display: none; } .td-skel { animation: none; } }

/* ==========================================================================
   Class page (Lantern phase 2, step 3 — R-CLS-1/2/4/5/6, R-TCH-1, rail
   parts of R-CHAT-*), drawn by classDetail() in app.js.
     header  .cls-hero   tile, title, description, meta line, ⋯ menu, and the
                         four daily actions (managers) or the teacher card
                         and reward (students)
     tabs    .cls-tabs   sticky under the top bar; a chip strip on phones
     body    .cls-body   panels (.ctp, one per tab, mounted on first view) and
                         ONE rail (.cls-rail) with Class chat | Office notes.
   data-layout="wide" (the page is >= 920px wide, measured by a
   ResizeObserver) puts the rail beside the content; "narrow" turns Chat and
   Office notes into two more tabs (data-rail-open while one is shown).
   ========================================================================== */
.cls-page {
  --cpad: clamp(20px, 3vw, 56px); --ctabs-h: 52px;
  display: flex; flex-direction: column; min-width: 0;
}
.cls-page [hidden] { display: none !important; }
@media (max-width: 720px) { .cls-page { --cpad: 16px; } }
@media (max-width: 359px) { .cls-page { --cpad: 12px; } }
/* The breadcrumb already says where you are; the back link stays for phones. */
@media (min-width: 720px) { .cls-page .cls-back { display: none; } }

/* ---- Header ---- */
.cls-hero {
  position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "tile main more" "foot foot foot"; gap: 0 20px; padding: 24px;
  border-radius: var(--r-xl); border: 1px solid var(--border);
  background:
    radial-gradient(90% 160% at 0% 0%, var(--c-soft), transparent 60%),
    radial-gradient(60% 120% at 100% 0%, color-mix(in srgb, var(--accent-fill) 7%, transparent), transparent 70%),
    var(--surface);
  box-shadow: var(--elev);
}
.cls-hero::before { content: ""; position: absolute; inset-inline: 24px; top: -1px; height: 3px; border-radius: 0 0 3px 3px; background: var(--c); }
.cls-hero > .cls-tile { grid-area: tile; }
.cls-tile.xl { width: 64px; height: 64px; border-radius: 18px; font-size: 24px; }
.cls-tile.xl[lang="ar"] { font-size: 24px; }
.cls-hero-main { grid-area: main; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.cls-hero h1 { margin: 0; font: 700 var(--fs-2xl)/1.15 var(--font-display); letter-spacing: -.02em; text-wrap: balance; overflow-wrap: anywhere; }
.cls-hero h1 .sub { color: var(--muted); font-weight: 600; }
.cls-hero h1:lang(ar) { font-family: var(--font-ar); line-height: 1.45; letter-spacing: 0; }
.cls-desc { margin: 0; color: var(--text-2); font-size: var(--fs-md); line-height: 1.6; max-width: 68ch; overflow-wrap: anywhere; }
.cls-desc:lang(ar) { line-height: 1.8; }
.cls-desc.muted-note { color: var(--muted); font-size: var(--fs-sm); }
.cls-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px; margin: 0; padding: 0; list-style: none; font-size: var(--fs-sm); color: var(--muted); }
.cls-meta li { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.cls-meta b { color: var(--text); font-weight: 600; }
.cls-meta .av { margin: 0; }
.av.xs { width: 22px; height: 22px; font-size: 9.5px; margin-inline-end: 0; }
.cls-meta .cls-cover { padding: 3px 10px 3px 4px; border-radius: var(--r-md); background: var(--warning-soft); color: var(--text-2); }
.cls-meta .cls-rw svg { color: var(--star); }
.cls-more { grid-area: more; align-self: start; margin: -6px -8px 0 0; }
.cls-more .rm-btn { width: 40px; height: 40px; border: 1px solid var(--border); background: var(--surface); border-radius: var(--r-md); }
.cls-more .rm-btn:hover, .cls-more .rm-btn[aria-expanded="true"] { background: var(--surface-2); }

/* The four daily actions + the roll-call status. */
.cls-qa { grid-area: foot; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); }
.cls-qa .qa svg { flex: none; }
.cls-hint { margin-inline-start: auto; display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--muted); }
.cls-hint.done { color: var(--success); }
/* Students: their teacher and their reward. */
.cls-stu { grid-area: foot; display: flex; flex-wrap: wrap; gap: 12px; margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border); }
.cls-teacher, .cls-myrw { flex: 1 1 260px; min-width: 0; display: flex; align-items: center; gap: 12px; padding: 12px 14px; border-radius: var(--r-md); background: color-mix(in srgb, var(--surface-2) 70%, transparent); border: 1px solid var(--border); }
.cls-teacher .av { width: 44px; height: 44px; font-size: 15px; margin: 0; }
.cls-teacher small, .cls-myrw small { display: block; color: var(--muted); font-size: var(--fs-xs); }
.cls-teacher b { display: block; font-size: var(--fs-md); margin-top: 2px; overflow-wrap: anywhere; }
.cls-teacher .tc-help { display: block; color: var(--muted); font-size: var(--fs-xs); margin-top: 2px; }
.cls-myrw { flex-direction: column; align-items: flex-start; justify-content: center; gap: 4px; }
.cls-myrw:empty { display: none; }
.cls-myrw.has-reward { background: linear-gradient(180deg, var(--accent-soft), transparent), var(--surface); border-color: var(--accent-line); }
.cls-myrw .rw-badge-lg { margin-top: 0; }
.cls-myrw .rw-note-sm { max-width: 100%; white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }
.cls-myrw .rw-none { color: var(--muted); font-size: var(--fs-sm); }

/* ---- Section tabs (sticky) ---- */
.cls-tabs {
  position: sticky; top: var(--shell-top); z-index: 30; display: flex; align-items: stretch; gap: 2px;
  height: var(--ctabs-h); margin: 20px calc(var(--cpad) * -1) 20px; padding: 0 var(--cpad);
  background: var(--glass-solid); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border); overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
}
.cls-tabs::-webkit-scrollbar { display: none; }
.ctab {
  position: relative; flex: none; display: inline-flex; align-items: center; gap: 8px; padding: 0 14px;
  border: 0; background: none; color: var(--muted); font: 600 var(--fs-base)/1 var(--font); white-space: nowrap;
  border-radius: var(--r-sm) var(--r-sm) 0 0; cursor: pointer; transition: color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.ctab:hover { color: var(--text); }
.ctab[aria-selected="true"] { color: var(--text); }
.ctab[aria-selected="true"]::after { content: ""; position: absolute; inset-inline: 10px; bottom: 0; height: 2px; border-radius: 2px 2px 0 0; background: var(--accent-fill); }
.ctab:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: -4px; }
.ctab.rail-tab { display: none; }
.cls-page[data-layout="narrow"] .ctab.rail-tab { display: inline-flex; }
.count.t-live { background: var(--live-fill); color: var(--on-live); }

/* ---- Body: content + rail ---- */
.cls-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
.cls-page[data-layout="wide"] .cls-body { grid-template-columns: minmax(0, 1fr) clamp(320px, 30%, 380px); }
.cls-page[data-layout="narrow"]:not([data-rail-open]) .cls-rail { display: none; }
.cls-page[data-layout="narrow"][data-rail-open] .cls-main { display: none; }
.cls-main { min-width: 0; container: clsmain / inline-size; }
.ctp { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.ctp .panel { margin-bottom: 0; }
.ctp-pair { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; }
@container clsmain (min-width: 980px) { .ctp-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ---- Overview ---- */
.ov { display: flex; flex-direction: column; gap: 20px; }
.ov .ann-feed { margin-bottom: 0; }
#classAnnFeed:empty { display: none; }
.cstats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
@container clsmain (min-width: 640px) { .cstats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.cstat {
  display: grid; gap: 2px; align-content: start; padding: 16px 16px 14px; border-radius: var(--r-lg); min-width: 0;
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--elev);
  color: inherit; font: inherit; text-align: start; cursor: pointer; transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out);
}
.cstat:hover { background: var(--surface-2); }
.cstat:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.cstat-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--muted); font-size: var(--fs-xs); font-weight: 600; }
.cstat-ic { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 9px; background: var(--surface-2); color: var(--text-2); }
.cstat-fig { margin-top: 6px; font: 700 var(--fs-3xl)/1.15 var(--font-display); letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.cstat-fig small { font-size: .5em; font-weight: 600; color: var(--muted); letter-spacing: 0; }
.cstat-foot { font-size: var(--fs-xs); color: var(--muted); overflow-wrap: anywhere; }
.cstat.review { border-color: var(--accent-line); }
.cstat.review .cstat-ic { background: var(--accent-soft); color: var(--accent-text); }
.cstat.warn .cstat-ic { background: var(--warning-soft); color: var(--warning); }
.cstat.miss .cstat-ic { background: var(--danger-soft); color: var(--danger); }
.cstat.good .cstat-ic { background: var(--success-soft); color: var(--success); }
.cstat.info .cstat-ic { background: var(--info-soft); color: var(--info); }
.ov-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
@container clsmain (min-width: 760px) { .ov-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .ov-grid > :only-child { grid-column: 1 / -1; } }
.ov-card .ov-sub { color: var(--muted); font: 500 var(--fs-xs)/1 var(--font); }
.ov-list { list-style: none; margin: 0; padding: 0; }
.ov-row { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-top: 1px solid var(--border); min-width: 0; }
.ov-row:first-child { border-top: 0; }
.ov-row.live { background: var(--live-soft); box-shadow: inset 3px 0 0 var(--live); }
.ov-date { flex: 0 0 44px; text-align: center; padding: 5px 0; border-radius: var(--r-sm); background: var(--c-soft); color: var(--c); line-height: 1.1; }
.ov-date small { display: block; font-size: var(--fs-2xs); font-weight: 700; text-transform: uppercase; }
.ov-date b { display: block; font-size: var(--fs-lg); color: var(--text); }
.ov-ic { flex: 0 0 40px; height: 40px; display: grid; place-items: center; border-radius: var(--r-md); background: var(--accent-soft); color: var(--accent-text); }
.ov-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ov-info > b { font-weight: 600; overflow-wrap: anywhere; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.ov-info > b:lang(ar) { line-height: 1.6; }
.ov-info small { color: var(--muted); font-size: var(--fs-xs); }
.ov-live { color: var(--live); font-weight: 700; }
.ov-row > .btn { flex: none; }
.ov-empty { margin: 0; padding: 22px 16px; color: var(--muted); font-size: var(--fs-sm); text-align: center; }
.ov-empty.ok { display: flex; align-items: center; justify-content: center; gap: 6px; color: var(--success); }
.prog { display: block; height: 8px; border-radius: var(--r-pill); background: var(--surface-3); overflow: hidden; }
.prog > i { display: block; height: 100%; border-radius: inherit; background: var(--success); }
.ov-row.prog-row .prog { margin: 4px 0 2px; }
.asg-prog { display: flex; align-items: center; gap: 10px; max-width: 360px; margin-top: 8px; }
.asg-prog .prog { flex: 1; min-width: 60px; }
.item .info .asg-prog small { flex: none; }

/* ---- Rail: Class chat | Office notes ---- */
.cls-rail {
  display: flex; flex-direction: column; min-width: 0; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); box-shadow: var(--elev);
}
/* Sticky under the tabs. Its height leaves room for the page's bottom gutter,
   so even at the very end of the page (where a sticky box is pushed up by the
   end of its row) the switch never slides under the tab row. */
.cls-page[data-layout="wide"] { margin-bottom: -36px; }
.cls-page[data-layout="wide"] .cls-rail {
  position: sticky; top: calc(var(--shell-top) + var(--ctabs-h) + 16px);
  height: calc(100vh - var(--shell-top) - var(--ctabs-h) - 52px);
  height: calc(100dvh - var(--shell-top) - var(--ctabs-h) - 52px); min-height: 420px;
}
/* Narrow: the body is at least a screen tall, so choosing a tab can always
   bring the tab row to the top. */
.cls-page[data-layout="narrow"] .cls-body { min-height: calc(100vh - var(--shell-top) - var(--ctabs-h) - var(--shell-bottom) - 24px); }
.cls-page[data-layout="narrow"] .cls-rail {
  height: calc(100vh - var(--shell-top) - var(--ctabs-h) - var(--shell-bottom) - 40px);
  height: calc(100dvh - var(--shell-top) - var(--ctabs-h) - var(--shell-bottom) - 40px); min-height: 380px;
}
.rail-head { flex: none; padding: 10px; border-bottom: 1px solid var(--border); }
.cls-page[data-layout="narrow"] .rail-head { display: none; }
.rail-seg { display: grid; grid-template-columns: 1fr 1fr; padding: 3px; border-radius: var(--r-pill); background: var(--surface-2); border: 1px solid var(--border); }
.rail-seg [role="tab"] {
  display: flex; align-items: center; justify-content: center; gap: 7px; min-width: 0; height: 34px; padding: 0 8px;
  border: 0; border-radius: var(--r-pill); background: none; color: var(--muted); font: 600 var(--fs-sm)/1 var(--font); cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.rail-seg [role="tab"]:hover { color: var(--text); }
.rail-seg [role="tab"][aria-selected="true"] { background: var(--surface); color: var(--text); box-shadow: var(--elev), 0 0 0 1px var(--border); }
.rail-seg [role="tab"]:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.rail-seg .count { height: 18px; min-width: 18px; font-size: 11px; line-height: 18px; padding: 0 5px; }
.rail-pane { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.rail-pane > div { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* The panels inside lose their own card chrome: the rail is the card. */
.cls-rail .panel {
  flex: 1; min-height: 0; margin: 0; border: 0; border-radius: 0; box-shadow: none;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto minmax(0, 1fr) auto;
}
.cls-rail .panel > header { grid-column: 1 / -1; grid-row: 1; padding: 10px 12px 10px 16px; }
.cls-rail .panel > .notes-priv { grid-column: 1 / -1; grid-row: 2; }
.cls-rail .panel > .chat { grid-column: 1 / -1; grid-row: 3; max-height: none; min-height: 0; }
.cls-rail .panel > .chat-compose { grid-column: 1 / -1; grid-row: 4; }
/* Wide: the switch names the pane, so the panel's own title row folds into
   the "who can see this" line, with Refresh / Clear at its end. */
.cls-page[data-layout="wide"] .cls-rail:not(.solo) .panel { grid-template-rows: auto minmax(0, 1fr) auto; }
.cls-page[data-layout="wide"] .cls-rail:not(.solo) .panel > header { grid-column: 2; grid-row: 1; padding: 4px 6px; border-bottom: 1px solid var(--border); }
.cls-page[data-layout="wide"] .cls-rail:not(.solo) .panel > header h2 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.cls-page[data-layout="wide"] .cls-rail:not(.solo) .panel > .notes-priv { grid-column: 1; grid-row: 1; padding: 8px 4px 8px 14px; }
.cls-page[data-layout="wide"] .cls-rail:not(.solo) .panel > .chat { grid-row: 2; }
.cls-page[data-layout="wide"] .cls-rail:not(.solo) .panel > .chat-compose { grid-row: 3; }
.cls-rail .chat { background: radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--border) 70%, transparent) 1px, transparent 0) 0 0 / 18px 18px, var(--bg-sunken); }
.cls-rail .chat-compose { background: var(--surface); }

/* Rail messages: day chips, runs of one author, pending / failed sends. */
.chat .day-chip { align-self: center; display: flex; }
.chat .day-chip span { padding: 3px 10px; border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--border); font: 600 var(--fs-2xs)/1.4 var(--font); color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
.chat .msg.grouped { margin-top: -8px; }
.chat .msg.mine.grouped .bub { border-start-end-radius: var(--r-xs); }
.chat .msg:not(.mine).grouped .bub { border-start-start-radius: var(--r-xs); }
.chat .msg.is-pending .bub { opacity: .72; }
.chat .msg .pend { display: inline-flex; align-items: center; gap: 4px; }
.chat .msg .pend svg { width: 12px; height: 12px; }
.chat .msg.is-failed .bub { border-color: var(--danger); }
.ch-fail { display: inline-flex; align-items: center; gap: 6px; padding: 2px 0; border: 0; background: none; color: var(--danger); font: 600 var(--fs-xs)/1.3 var(--font); cursor: pointer; }
.ch-fail svg { width: 13px; height: 13px; }

/* ---- Attendance: summaries + the student's own list (R-CLS-6) ---- */
.att-sum { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--border); }
.att-sum[hidden], .att-filter[hidden] { display: none; }
.att-sum-h { margin-inline-end: 4px; font-size: var(--fs-xs); font-weight: 600; color: var(--muted); }
.att-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px; border-radius: var(--r-pill); background: var(--surface-2); border: 1px solid var(--border); font-size: var(--fs-xs); color: var(--text-2); }
.att-chip b { color: var(--text); font-weight: 600; }
.att-chip svg { width: 14px; height: 14px; }
.att-chip.ok { background: var(--success-soft); border-color: transparent; color: var(--success); font-size: var(--fs-sm); }
.att-chip.ok b { color: inherit; }
.att-chip.today { background: var(--accent-soft); border-color: var(--accent-line); }
.att-more { padding: 10px 16px; border-top: 1px solid var(--border); text-align: center; }
/* Beside the rail the table is narrower: the note keeps a readable width and
   the table scrolls inside its own frame instead of folding the note. */
#abody td.att-note { min-width: 200px; }
#abody table:not(.att-mine) td:first-child { min-width: 150px; }
/* Status column: Present / Late / Absent badge; an absence has no times. */
#abody td.att-st { white-space: nowrap; }
#abody tr.att-absent td[data-label^="Time"] { color: var(--muted); }
/* Edit attendance: the times hide while Absent is picked. */
.ea-times[hidden] { display: none; }

/* ---- Roll call (R-TCH-1) ---- */
.rc-top { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.rc-top .field { margin-bottom: 0; }
.rc-dup { display: flex; align-items: flex-start; gap: 8px; margin: 12px 0 0; padding: 10px 12px; border-radius: var(--r-md); background: var(--warning-soft); color: var(--text); font-size: var(--fs-sm); line-height: 1.45; }
.rc-dup[hidden], .rc-tin[hidden] { display: none; }
.rc-dup svg { flex: none; margin-top: 2px; color: var(--warning); }
.rc-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; margin: 16px 0 8px; }
.rc-help { font-size: var(--fs-xs); color: var(--muted); }
.rc-help b { color: var(--text-2); }
.rc-list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; }
.rc-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; min-height: 52px; padding: 6px 8px 6px 12px; border-top: 1px solid var(--border); transition: background-color var(--dur-1) var(--ease-out); }
.rc-row:first-child { border-top: 0; }
.rc-row[data-st="l"] { background: color-mix(in srgb, var(--warning-soft) 70%, transparent); }
.rc-row[data-st="a"] { background: color-mix(in srgb, var(--danger-soft) 70%, transparent); }
.rc-row.saved { opacity: .55; }
.rc-name { flex: 1 1 160px; min-width: 0; display: flex; align-items: center; font-size: var(--fs-sm); font-weight: 600; }
.rc-name bdi { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rc-name .av { margin-inline-end: 10px; }
.rc-seg { display: inline-flex; gap: 2px; padding: 3px; border-radius: var(--r-pill); background: var(--surface-2); border: 1px solid var(--border); }
.rc-opt { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 36px; padding: 0 12px; border: 0; border-radius: var(--r-pill); background: none; color: var(--muted); font: 600 var(--fs-sm)/1 var(--font); cursor: pointer; }
.rc-opt:hover { color: var(--text); }
.rc-opt:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; }
.rc-opt.rc-p[aria-checked="true"] { background: var(--success-soft); color: var(--success); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--success) 35%, transparent); }
.rc-opt.rc-l[aria-checked="true"] { background: var(--warning-soft); color: var(--warning); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--warning) 35%, transparent); }
.rc-opt.rc-a[aria-checked="true"] { background: var(--danger-soft); color: var(--danger); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--danger) 35%, transparent); }
.rc-tin.input { width: auto; max-width: 140px; padding: 6px 8px; }
.rc-sum { margin-inline-end: auto; align-self: center; font-size: var(--fs-sm); color: var(--muted); }
.rc-sum b { color: var(--text); font-variant-numeric: tabular-nums; }
.rc-foot-note { margin: 10px 0 0; font-size: var(--fs-xs); color: var(--muted); line-height: 1.5; }

/* ---- Agenda inside a class (R-CLS-5): a narrower day column, one column
   whenever the panel itself is narrow. ---- */
.ag-panel { container-type: inline-size; }
.ag-panel .ag-day { grid-template-columns: 112px minmax(0, 1fr); gap: 16px; padding: 12px 16px; }
.ag-panel .ag-dhead { flex-wrap: wrap; align-items: baseline; gap: 2px 6px; }
.ag-panel .ag-dhead b { flex-basis: 100%; }
@container (max-width: 640px) {
  .ag-panel .ag-day { grid-template-columns: minmax(0, 1fr); gap: 6px; padding: 10px 12px; }
  .ag-panel .ag-dhead { flex-wrap: nowrap; align-items: center; }
  .ag-panel .ag-dhead b { flex-basis: auto; }
}

/* ---- Tablets: a little tighter ---- */
@media (max-width: 1100px) {
  .cls-hero { padding: 20px; }
}

/* ---- Phones (< 720px) ---- */
@media (max-width: 719px) {
  .cls-page { --ctabs-h: 56px; }
  /* Tile and ⋯ share the first row; the title and its lines get the full width. */
  .cls-hero { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "tile more" "main main" "foot foot"; gap: 12px 14px; padding: 18px 16px 16px; border-radius: var(--r-lg); }
  .cls-more { justify-self: end; }
  .cls-qa, .cls-stu { margin-top: 2px; }
  .cls-hero::before { inset-inline: 16px; }
  .cls-tile.xl { width: 48px; height: 48px; border-radius: 14px; font-size: 18px; }
  .cls-hero h1 { font-size: var(--fs-xl); }
  .cls-hero h1 .sub { font-size: .8em; }
  .cls-desc { font-size: var(--fs-base); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
  .cls-meta { gap: 6px 12px; }
  .cls-meta .cls-lead { display: none; }
  .cls-more { margin: -6px -6px 0 0; }
  .cls-more .rm-btn { width: 44px; height: 44px; }
  .cls-qa { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; padding-top: 14px; }
  .cls-qa .qa { flex-direction: column; gap: 6px; min-height: 66px; padding: 10px 4px; border-radius: var(--r-md); font-size: var(--fs-xs); line-height: 1.2; white-space: normal; text-align: center; }
  .cls-qa .qa svg { width: 22px; height: 22px; }
  .cls-hint { grid-column: 1 / -1; margin: 2px 0 0; justify-content: center; }
  .cls-stu { padding-top: 14px; }
  .cls-tabs { gap: 6px; align-items: center; margin-top: 16px; margin-bottom: 16px; padding: 8px var(--cpad); }
  .ctab { height: 40px; padding: 0 14px; border-radius: var(--r-pill); font-size: var(--fs-sm); }
  .ctab[aria-selected="true"] { background: var(--accent-soft); color: var(--accent-text); }
  .ctab[aria-selected="true"]::after { display: none; }
  .cls-body { gap: 16px; }
  .ctp, .ov { gap: 16px; }
  .cstat { padding: 14px; }
  .cstat-fig { font-size: var(--fs-2xl); }
  .ov-row { flex-wrap: wrap; padding: 12px 14px; }
  .ov-row > .btn { margin-inline-start: 56px; }
  .ov-row.prog-row > .btn, .ov-row:has(.ov-ic) > .btn { margin-inline-start: auto; }
  .rc-top { grid-template-columns: 1fr 1fr; }
  .rc-top .field:first-child { grid-column: 1 / -1; }
  .rc-row { padding: 8px 10px; }
  .rc-name { flex-basis: 100%; }
  .rc-seg { flex: 1; }
  .rc-opt { flex: 1; min-height: 40px; padding: 0 8px; }
  .rc-sum { flex-basis: 100%; text-align: center; }
  #abody table.att-mine td:first-child { min-width: 0; }
  #abody table.att-mine td.att-note { min-width: 180px; }
}
@media (pointer: coarse) {
  .ctab { min-height: 44px; }
  .rail-seg [role="tab"] { height: 40px; }
  .rc-opt { min-height: 44px; }
}

/* ==========================================================================
   Top bar "Download app" beside Meet Now (every role, every width).
     >= 1280px   outline small button: download icon + "Download app"
     720-1279px  the same, labelled "App"
     < 720px     a 44px icon button beside the Meet Now icon
   ========================================================================== */
.tb-app { flex: none; background: transparent; border-color: var(--border-strong); color: var(--text); }
:where(:root[data-theme="light"]) .tb-app { background: transparent; }
.tb-app:hover { background: var(--surface-2); border-color: var(--field-border); }
.tb-app .sh-ic { width: 16px; height: 16px; stroke-width: 2; }
.tb-app .tb-lbl-s { display: none; }
@media (min-width: 720px) and (max-width: 1279px) {
  .tb-app .tb-lbl-l { display: none; }
  .tb-app .tb-lbl-s { display: inline; }
}
@media (max-width: 719px) {
  .tb-app { width: 44px; height: 44px; padding: 0; border-radius: var(--r-md); border-color: transparent; color: var(--text-2); }
  .tb-app:hover { border-color: transparent; color: var(--text); }
  .tb-app .tb-lbl { display: none; }
  .tb-app .sh-ic { width: 20px; height: 20px; stroke-width: var(--icon-stroke); }
  .topbar { gap: 2px; }
}

/* ==========================================================================
   Instructor "Today" home (Lantern phase 2, step 4 — R-HOME-2), drawn by
   today-staff.js on the student page's td- parts (cards, chips, skeletons,
   empty / error states, class cards). Mockup: app-shell.html.
     >= 1000px  greeting + timeline | Next lesson; three tiles; lessons | side
     640-999px  hero and side stack; tiles in a row as space allows
     < 640px    one column: greeting, Next lesson, To review, Attendance due,
                Unread, Today's lessons, Classes, then Notices / Quick actions
   ========================================================================== */
.td-staff { max-width: 1320px; gap: 20px; }
.tt-hero-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; }
@container td (min-width: 1000px) { .tt-hero-row { grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); } }

/* Greeting + the day strip */
.tt-greet {
  position: relative; overflow: hidden; display: flex; flex-direction: column; min-width: 0; padding: 28px 28px 24px;
  border: 1px solid var(--border); border-radius: var(--r-xl); box-shadow: var(--elev);
  background: radial-gradient(520px 260px at 100% 0%, color-mix(in srgb, var(--accent-fill) 16%, transparent), transparent 70%), var(--surface);
}
.tt-greet .td-eyebrow { color: var(--muted); letter-spacing: 0; text-transform: none; }
.tt-greet .td-h1 { margin-top: 10px; }
.tt-greet .td-sub { margin-top: 8px; max-width: 58ch; }
.tt-day { margin-top: auto; padding-top: 22px; }
.tt-day:empty { display: none; }
.tt-day-h { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: var(--fs-xs); color: var(--muted); }
.tt-day-h b { color: var(--text-2); font-weight: 600; }
.tt-daybar { position: relative; height: 40px; margin-top: 8px; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); }
.tt-daybar::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: repeating-linear-gradient(90deg, transparent 0 calc(16.666% - 1px), var(--border) calc(16.666% - 1px) 16.666%); }
.tt-slot {
  position: absolute; top: 6px; bottom: 6px; inset-inline-start: var(--s); width: var(--w); min-width: 30px; max-width: calc(100% - var(--s));
  display: block; padding: 0 5px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-align: center; line-height: 24px;
  border-radius: var(--r-xs); background: color-mix(in srgb, var(--c) 22%, var(--surface)); border: 1px solid color-mix(in srgb, var(--c) 55%, transparent);
  color: var(--text); font: 600 var(--fs-2xs)/24px var(--font);
}
.tt-slot[lang="ar"] { font: 600 12px/24px var(--font-ar); }
.tt-slot.done { opacity: .5; }
.tt-slot.upcoming { box-shadow: 0 0 0 2px var(--live-soft); }
.tt-slot.live { box-shadow: 0 0 0 2px var(--live); }
.tt-now { position: absolute; top: -5px; bottom: -5px; inset-inline-start: var(--s); width: 2px; margin-inline-start: -1px; border-radius: 2px; background: var(--live); }
.tt-now::before { content: ""; position: absolute; top: -4px; inset-inline-start: -3px; width: 8px; height: 8px; border-radius: 50%; background: var(--live); }
.tt-ticks { display: flex; justify-content: space-between; margin-top: 6px; font: 500 var(--fs-2xs)/1.45 var(--font); color: var(--muted); font-variant-numeric: tabular-nums; }
.tt-day-none { display: flex; align-items: center; gap: 8px; margin: 0; padding: 10px 12px; border-radius: var(--r-md); background: var(--surface-2); font-size: var(--fs-sm); color: var(--text-2); }
.tt-day-none .td-ic { color: var(--muted); }

/* Next lesson (violet = live: the border always hints it, Start turns solid in the window) */
.tt-next {
  gap: 16px; padding: 24px; border-radius: var(--r-xl);
  background: radial-gradient(420px 220px at 0% 0%, var(--live-soft), transparent 70%), var(--surface);
  border-color: color-mix(in srgb, var(--live) 30%, var(--border));
}
.tt-next.is-live { border-color: color-mix(in srgb, var(--live) 55%, var(--border)); }
.tt-next-top { display: flex; align-items: center; gap: 12px; min-height: 26px; }
.tt-next-top .td-mini-h { margin: 0; }
.tt-next-body { flex: 1; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.tt-next-body > .td-skel { margin: 0; }
.tt-next-title { display: flex; align-items: center; gap: 14px; min-width: 0; }
.tt-next-txt { min-width: 0; }
.tt-next-txt h3 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin: 0; font: 600 var(--fs-xl)/1.3 var(--font-display); letter-spacing: -.01em; overflow-wrap: anywhere; }
.tt-next-txt h3[lang="ar"] { font-family: var(--font-ar); line-height: 1.5; }
.tt-next-sub { margin: 2px 0 0; color: var(--text-2); font-size: var(--fs-base); overflow-wrap: anywhere; }
.tt-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 1px; margin: 0; border-radius: var(--r-md); overflow: hidden; background: var(--border); border: 1px solid var(--border); }
.tt-facts div { min-width: 0; padding: 10px 12px; background: var(--surface); }
.tt-facts dt { font-size: var(--fs-xs); color: var(--muted); }
.tt-facts dd { margin: 2px 0 0; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The time is the fact people need: let "Tomorrow, 6:30 PM" wrap instead of ending in "…". */
.tt-facts dd:has(> time) { white-space: normal; overflow-wrap: anywhere; }
.tt-mono { font-family: var(--font-mono, ui-monospace, Consolas, monospace); font-size: 13px; }
.tt-who { display: flex; align-items: center; gap: 10px; min-width: 0; font-size: var(--fs-sm); color: var(--muted); }
.tt-who > span:last-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-stack { display: flex; flex: none; }
.tt-stack .av { width: 28px; height: 28px; margin: 0; font-size: 10.5px; box-shadow: 0 0 0 2px var(--surface); }
.tt-stack .av + .av { margin-inline-start: -8px; }
.tt-next-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: auto; }
.tt-next-acts .tt-start { flex: 1 1 160px; min-height: 44px; }
.tt-next-acts .btn .td-ic { width: 16px; height: 16px; }

/* Action tiles */
.tt-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: 20px; }
.tt-tile { gap: 14px; }
.tt-tile-h { display: flex; align-items: center; gap: 12px; min-width: 0; }
.tt-tile-h > div { min-width: 0; }
.tt-tile-h h2 { margin: 0; font: 600 var(--fs-md)/1.3 var(--font); }
.tt-tile-h p { margin: 0; font-size: var(--fs-xs); color: var(--muted); }
.tt-itile { display: grid; place-items: center; flex: none; width: 40px; height: 40px; border-radius: var(--r-md); }
.tt-itile .td-ic { width: 20px; height: 20px; }
.tt-itile.accent { background: var(--accent-soft); color: var(--accent-text); }
.tt-itile.warn { background: var(--warning-soft); color: var(--warning); }
.tt-itile.neutral { background: var(--surface-3); color: var(--text-2); }
.tt-tile.is-clear .tt-itile { background: var(--success-soft); color: var(--success); }
.tt-tile.is-clear .td-empty-ic { background: var(--success-soft); color: var(--success); }
.tt-tile-body { flex: 1; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.tt-tile-body > .td-skel, .tt-tile-body > .td-note { margin: 0; }
.tt-figure { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 10px; margin: 0; }
.tt-num { font: 700 var(--fs-3xl)/1 var(--font-display); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.tt-figure > span:last-child { color: var(--text-2); font-size: var(--fs-sm); }
.tt-breakdown { display: flex; gap: 2px; height: 8px; border-radius: var(--r-pill); overflow: hidden; background: var(--surface-2); }
.tt-breakdown i { display: block; flex: var(--n); background: var(--c); }
.tt-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 0; padding: 0; list-style: none; font-size: var(--fs-xs); color: var(--text-2); }
.tt-legend li { min-width: 0; max-width: 100%; }
.tt-legend a { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; min-height: 28px; color: var(--text-2); }
.tt-legend a::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 3px; background: var(--c); }
.tt-legend a:hover { color: var(--text); }
.tt-legend a > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-legend b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.tt-legend-more { display: inline-flex; align-items: center; min-height: 28px; color: var(--muted); }
.tt-tile-foot { display: flex; gap: 8px; margin-top: auto; }
.tt-tile-foot .btn { flex: 1; }
.tt-tile-foot .btn .td-ic { width: 16px; height: 16px; }
.tt-mini { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.tt-mini li { display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 6px 0; font-size: var(--fs-sm); }
.tt-mini li + li { border-top: 1px dashed var(--border); }
.tt-mini .cls-tile.sm { width: 32px; height: 32px; border-radius: 9px; font-size: 11px; }
.tt-grow { flex: 1; min-width: 0; }
.tt-grow b { display: block; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.tt-grow small { display: block; font-size: var(--fs-xs); color: var(--muted); }
.tt-row-link { color: var(--text); }
.tt-row-link:hover { text-decoration: none; }
.tt-row-link:hover b { text-decoration: underline; text-underline-offset: 3px; }
.tt-warn-txt { display: inline-flex; align-items: center; gap: 4px; color: var(--warning); font-weight: 600; }
.tt-warn-txt .td-ic { width: 13px; height: 13px; }
.tt-pills { display: inline-flex; align-items: center; gap: 6px; flex: none; }
.tt-pills .td-chip { text-decoration: none; }

/* Panels: Today's lessons, Quick actions */
.tt-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; }
.tt-main { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.tt-side { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; min-width: 0; align-items: start; }
@container td (min-width: 640px) { .tt-side { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container td (min-width: 1100px) {
  .tt-split { grid-template-columns: minmax(0, 1fr) 380px; }
  .tt-side { display: flex; flex-direction: column; align-items: stretch; }
}
.tt-panel { padding: 0; overflow: hidden; }
.tt-panel-h { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; padding: 14px 20px; border-bottom: 1px solid var(--border); }
.tt-panel-h h2 { margin: 0; font: 600 var(--fs-lg)/1.3 var(--font); }
.tt-panel-h .btn .td-ic { width: 15px; height: 15px; }
.tt-pad { padding: 16px 20px; }
.tt-tl { margin: 0; padding: 0; list-style: none; }
.tt-tl li { position: relative; display: grid; grid-template-columns: 76px 40px minmax(0, 1fr) auto; align-items: center; gap: 14px; min-height: 72px; padding: 14px 20px; }
.tt-tl li + li { border-top: 1px solid var(--border); }
.tt-time { font: 500 13px/1.35 var(--font-mono, ui-monospace, Consolas, monospace); color: var(--text-2); font-variant-numeric: tabular-nums; }
.tt-what { display: block; min-width: 0; color: var(--text); }
a.tt-what:hover { text-decoration: none; }
a.tt-what:hover b { text-decoration: underline; text-underline-offset: 3px; }
.tt-what b { display: block; overflow: hidden; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
.tt-what > span { display: block; overflow: hidden; font-size: var(--fs-sm); color: var(--muted); text-overflow: ellipsis; white-space: nowrap; }
.tt-what [lang="ar"] { line-height: 1.6; }
.tt-act { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 8px; }
.tt-act .btn .td-ic { width: 15px; height: 15px; }
.tt-tl li.is-next { background: linear-gradient(90deg, var(--live-soft), transparent 60%); }
.tt-tl li.is-next::before { content: ""; position: absolute; inset-inline-start: 0; top: 12px; bottom: 12px; width: 3px; border-radius: 0 3px 3px 0; background: var(--live); }
.tt-tl li.is-done .tt-what b { color: var(--text-2); }
.tt-tl li.is-done .cls-tile { filter: saturate(.5); opacity: .75; }
.td-staff .btn.warn { background: var(--warning-soft); color: var(--warning); border-color: color-mix(in srgb, var(--warning) 30%, transparent); }
.td-staff .btn.warn:hover { background: color-mix(in srgb, var(--warning) 22%, transparent); }
.tt-quick { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; padding: 12px; }
.tt-quick > a, .tt-quick > button {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; min-height: 88px; padding: 12px 6px;
  border: 1px solid transparent; border-radius: var(--r-md); background: none; color: var(--text-2);
  font: 500 var(--fs-xs)/1.3 var(--font); text-align: center; cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-out), border-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out);
}
.tt-quick > a:hover, .tt-quick > button:hover { background: var(--surface-2); border-color: var(--border); color: var(--text); text-decoration: none; }
.tt-qi { display: grid; place-items: center; width: 40px; height: 40px; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); color: var(--text-2); }
.tt-qi .td-ic { width: 20px; height: 20px; }
.tt-quick > :hover .tt-qi { background: var(--accent-soft); border-color: transparent; color: var(--accent-text); }

/* My classes (staff card, R-HOME-5 / R-TCH-8) */
.tt-sec-head { align-items: flex-end; flex-wrap: wrap; margin-top: 4px; }
.tt-sec-head p { margin: 2px 0 0; }
.tt-sec-acts { display: flex; gap: 8px; }
.tt-sec-acts .btn .td-ic { width: 15px; height: 15px; }
.tt-cls-grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 20px; }
.tt-cls { grid-template-rows: auto 1fr auto; min-height: 150px; }
.tt-cls::after { display: none; }
.tt-cls-h { display: flex; align-items: flex-start; gap: 12px; min-width: 0; }
.tt-cls-h .cls-tile { width: 44px; height: 44px; }
.tt-cls-txt { display: flex; flex-direction: column; min-width: 0; }
.tt-cls-meta { margin-top: 4px; font-size: var(--fs-xs); color: var(--muted); }
.tt-cls-meta b { font-weight: 600; color: var(--text-2); }
.tt-cls .td-cls-foot { grid-row: 3; }
.tt-all { display: flex; justify-content: flex-end; margin: 10px 0 0; }
.tt-all[hidden] { display: none; }

/* First run (R-TCH-7) */
.tt-setup { padding: 20px; border: 1px solid var(--accent-line); border-radius: var(--r-xl); background: linear-gradient(135deg, var(--accent-soft), transparent 60%), var(--surface); box-shadow: var(--elev); }
.tt-setup h3 { margin: 0 0 12px; font: 600 var(--fs-lg)/1.3 var(--font); }
.tt-steps { display: flex; flex-direction: column; gap: 8px; margin: 0 0 8px; padding: 0; list-style: none; }
.tt-steps li { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 12px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface); }
.tt-steps li > span:nth-child(2) { flex: 1 1 200px; min-width: 0; }
.tt-steps b { display: block; font-weight: 600; }
.tt-steps small { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--muted); }
.tt-step-n { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 50%; background: var(--surface-3); color: var(--text-2); font: 700 13px/1 var(--font-display); }
.tt-steps li.is-next .tt-step-n { background: var(--accent-fill); color: var(--on-accent); }

/* Phones / narrow pages: one column in priority order, above the tab bar. */
@container td (max-width: 639px) {
  .tt-hero-row, .tt-tiles, .tt-split, .tt-main { display: contents; }
  .tt-greet { order: 0; padding: 20px 18px 18px; border-radius: 20px; }
  .tt-next { order: 1; padding: 18px; border-radius: 20px; gap: 14px; }
  .tt-review { order: 2; }
  .tt-att { order: 3; }
  .tt-unread { order: 4; }
  .tt-lessons { order: 5; }
  .tt-classes { order: 6; }
  .tt-side { order: 7; }
  .tt-greet .td-sub { font-size: var(--fs-base); }
  .tt-day { padding-top: 18px; }
  .tt-slot { font-size: 10px; }
  .tt-facts { grid-template-columns: 1fr 1fr; }
  .tt-facts div:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .tt-next-acts > .btn { flex: 1 1 auto; }
  .tt-tile { padding: 16px; }
  .tt-panel-h { padding: 14px 16px; }
  .tt-pad { padding: 14px 16px; }
  .tt-tl li { grid-template-columns: 40px minmax(0, 1fr); grid-template-areas: "tile what" "tile time" "act act"; gap: 4px 12px; padding: 14px 16px; }
  .tt-tl li > .cls-tile { grid-area: tile; align-self: start; }
  .tt-tl .tt-what { grid-area: what; }
  .tt-tl .tt-time { grid-area: time; font-size: 12px; }
  .tt-tl .tt-act { grid-area: act; justify-content: flex-start; margin-top: 8px; }
  .tt-tl .tt-act .btn { flex: 1 1 auto; }
  .tt-hide-phone { display: none; }
  .tt-legend { flex-direction: column; }
  .tt-legend a, .tt-legend-more { min-height: 44px; }
  .tt-cls-grid { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .tt-cls { min-height: 0; grid-template-rows: auto auto; padding: 16px; }
  .tt-cls .td-cls-foot { grid-row: auto; }
  .tt-cls .td-cls-foot:empty { display: none; }
  .tt-sec-head { margin-top: 4px; }
}
@container td (max-width: 380px) { .tt-quick { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (prefers-reduced-motion: no-preference) {
  .tt-hero-row, .tt-tiles, .tt-split { animation: td-rise var(--dur-3) var(--ease-out) both; }
  .tt-tiles { animation-delay: 40ms; }
  .tt-split { animation-delay: 80ms; }
}
@media (forced-colors: active) { .tt-slot { border: 1px solid CanvasText; } }

/* ==========================================================================
   Phase 3, batch 1 — resilience, errors and shared components.
   The STATE KIT (ui.js): buttons, inputs, tabs, modals v2 + bottom sheets,
   skeletons, busy buttons, empty/error states + spot art, alerts, dropzone,
   multi-select pickers, the connection banner, the sign-in sheet, print.
   Meet and offline.html copy these class names and tokens.
   ========================================================================== */

/* ---- Icons (R-CMP-11): one stroke weight, set here, not in the SVGs ---- */
svg.ic { flex: none; stroke-width: var(--icon-stroke, 1.75); }
svg.ic.ic-fill { stroke: none; }
.btn.sm svg.ic { stroke-width: 2; }

/* ---- Buttons (R-CMP-1): sm 32 / md 40 / lg 48; 44 on a finger ---- */
.btn { min-height: var(--h-md); padding: 8px 16px; border-radius: var(--r-md); font: 600 var(--fs-base)/1.2 var(--font); }
.btn.sm { min-height: var(--h-sm); padding: 6px 12px; font-size: var(--fs-sm); border-radius: var(--r-sm); }
.btn.lg { min-height: var(--h-lg); padding: 12px 20px; font-size: var(--fs-md); }
.btn.icon { min-width: var(--h-md); padding: 0 8px; }
.btn.sm.icon { min-width: var(--h-sm); padding: 0 6px; }
.btn.outline { background: transparent; border-color: var(--border-strong); color: var(--text); }
.btn.outline:hover { background: var(--surface-2); }
.btn:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
.btn:active:not(:disabled) { transform: scale(.97); }
.btn:disabled:not([aria-busy="true"]), .btn[aria-disabled="true"] {
  background: var(--surface-2); border-color: var(--border); color: var(--disabled); opacity: 1; cursor: not-allowed; box-shadow: none;
}
.btn[aria-busy="true"] { cursor: progress; opacity: .9; }
.btn-spin { width: 14px; height: 14px; flex: none; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .6s linear infinite; }
.toast-x.btn { min-width: 28px; min-height: 28px; padding: 5px; }
.toast-act.btn { min-height: 28px; padding: 4px 10px; }
@media (pointer: coarse) {
  /* .btn.sm too: the .btn.sm rule above out-ranks a plain .btn, which left small buttons 32px on phones. */
  .btn, .btn.sm { min-height: var(--h-touch); }
  .btn.icon, .btn.sm.icon { min-width: var(--h-touch); }
  .toast-x.btn, .toast-act.btn { min-height: 40px; min-width: 40px; }
}

/* ---- Inputs line up with buttons; invalid differs from focus (R-CMP-13) ---- */
.input:not(textarea), select.input { min-height: var(--h-md); padding: 8px 12px; border-radius: var(--r-md); }
textarea.input { padding: 9px 12px; border-radius: var(--r-md); }
.input[aria-invalid="true"] { border-color: var(--danger); }
.input[aria-invalid="true"]:focus { border-color: var(--danger); box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--danger); }
.field-err { display: flex; align-items: center; gap: 6px; margin-top: 6px; color: var(--danger); font-size: var(--fs-xs); font-weight: 500; }
.field-err[hidden] { display: none; }
@media (pointer: coarse) { .input:not(textarea), select.input { min-height: var(--h-touch); } }

/* ---- Tabs (R-CMP-12): underline for sections, raised thumb for values ---- */
.qtabs button.active, .qtabs button[aria-selected="true"], .qtabs button[aria-pressed="true"] {
  background: var(--surface-3); color: var(--text); box-shadow: var(--shadow-1), inset 0 0 0 1px var(--border-strong);
}
:root[data-theme="light"] .qtabs button.active, :root[data-theme="light"] .qtabs button[aria-selected="true"], :root[data-theme="light"] .qtabs button[aria-pressed="true"] {
  background: var(--surface); box-shadow: var(--shadow-1), inset 0 0 0 1px var(--border);
}
.tabs a:focus-visible, .tabs button:focus-visible, .qtabs button:focus-visible, .ctab:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); border-radius: var(--r-sm); }
table.tbl th { text-transform: none; letter-spacing: 0; font-size: var(--fs-xs); }

/* ---- Alerts (R-CMP-16): one anatomy for every inline error ----
   (.nav-count.alert / .count.alert are the red unread pills, not alerts.) */
.alert:not(.nav-count):not(.count), .auth-error {
  display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; margin-bottom: 16px;
  border-radius: var(--r-md); border: 1px solid var(--danger-line); background: var(--danger-soft); color: var(--danger);
  font-size: var(--fs-sm); line-height: 1.45;
}
.alert:not(.nav-count):not(.count) > svg { margin-top: 1px; }
.alert:not(.nav-count):not(.count) > span { flex: 1; min-width: 0; }
.alert:not(.nav-count):not(.count) .btn { margin-inline-start: auto; margin-block: -4px; color: inherit; }
.alert.warn { border-color: color-mix(in srgb, var(--warning) 30%, transparent); background: var(--warning-soft); color: var(--warning); }

/* ---- Spinner + captions (R-CMP-16) ---- */
.spinner { width: 36px; height: 36px; margin: 0 auto; border: 3px solid var(--border-strong); border-top-color: var(--accent-fill); border-radius: 50%; animation: spin .8s linear infinite; }
.center-load { display: grid; place-items: center; align-content: center; gap: 12px; min-height: 40vh; }
.load-cap { display: grid; margin: 0; min-height: 18px; color: var(--muted); font-size: var(--fs-sm); text-align: center; }
.load-cap span { grid-area: 1 / 1; opacity: 0; }
.load-cap .c1 { animation: capIn 0s 1.5s forwards, capOut 0s 8s forwards; }
.load-cap .c2 { animation: capIn 0s 8s forwards; }
@keyframes capIn { to { opacity: 1; } }
@keyframes capOut { to { opacity: 0; } }

/* ---- Skeletons (R-CMP-5) ---- */
.sk {
  display: block; border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--surface-2) 0, var(--surface-3) 50%, var(--surface-2) 100%); background-size: 200% 100%;
  animation: sk 1.2s linear infinite;
}
@keyframes sk { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.sk-wrap { display: block; }
.sk-line { height: 12px; margin: 8px 0; }
.sk-col { flex: 1; min-width: 0; }
.sk-col > .sk-line:first-child { margin-top: 0; }
.sk-col > .sk-line:last-child { margin-bottom: 0; }
.sk-av { width: 36px; height: 36px; border-radius: 50%; flex: none; }
.sk-tile { width: 48px; height: 48px; border-radius: 14px; flex: none; }
.sk-rowbox { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border-bottom: 1px solid var(--border); }
.sk-rowbox:last-child { border-bottom: 0; }
.sk-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: 16px; }
.sk-cardbox { display: flex; align-items: center; gap: 14px; min-height: 96px; padding: 18px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); }
.sk-annbox { padding: 16px 18px; margin-bottom: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); }
.sk-chat { display: flex; flex-direction: column; gap: 14px; padding: 16px; }
.sk-bub { display: flex; align-items: flex-end; gap: 10px; }
.sk-bub .sk-col { display: flex; }
.sk-bub.me .sk-col { justify-content: flex-end; }
.sk-table { padding: 12px 16px; }
.sk-trow { display: flex; gap: 18px; padding: 6px 0; border-bottom: 1px solid var(--border); }
.sk-page { padding-top: 4px; }

/* ---- Empty / error states + spot art (R-CMP-10) ---- */
.empty .ico { width: 48px; height: 48px; border-radius: var(--r-lg); background: var(--accent-soft); color: var(--accent-text); }
.empty .ico svg { width: 22px; height: 22px; opacity: 1; }
.empty .illus .illus-svg { width: 100%; height: 100%; opacity: 1; }
.rw-gift { display: inline-grid; place-items: center; color: var(--accent-text); }
.mf-over { outline: 2px dashed var(--accent-fill); outline-offset: 4px; border-radius: var(--r-md); background: var(--accent-soft); }
.empty.error .ico { background: var(--danger-soft); color: var(--danger); }
.empty .illus { width: 112px; height: 112px; margin: 0 auto 12px; }
.empty .empty-t { color: var(--text); font-size: var(--fs-md); font-weight: 600; }
.empty .sub { max-width: 48ch; margin-inline: auto; }
.empty-act { display: flex; justify-content: center; margin-top: 16px; }
.empty.inline { display: flex; align-items: center; gap: 12px; padding: 14px 16px; text-align: start; }
.empty.inline .ico { width: 32px; height: 32px; margin: 0; border-radius: 10px; flex: none; }
.empty.inline .ico svg { width: 16px; height: 16px; }
.empty.inline p { flex: 1; min-width: 0; margin: 0; color: var(--text-2); }
.empty.inline .sub { color: var(--muted); }
.illus-svg { display: block; width: 100%; height: 100%; overflow: visible; }
.illus-svg .il-s { fill: none; stroke: var(--text); stroke-opacity: .85; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.illus-svg .il-bg { fill: var(--accent-soft); }
.illus-svg .il-paper { fill: var(--surface); }
.illus-svg .il-acc { fill: var(--accent-fill); }
.illus-svg .il-acc-soft { fill: var(--accent-soft); }
.illus-svg .il-ok { fill: var(--success-fill); }
.illus-svg .il-live { fill: var(--live-soft); }
.illus-svg .il-w { stroke: #fff; stroke-opacity: 1; }
.illus-svg .il-spark { stroke: var(--accent-fill); stroke-opacity: 1; }
.illus-svg .il-bad { stroke: var(--danger); stroke-opacity: 1; stroke-width: 3; }
.illus-svg .il-dash { stroke-dasharray: 3 6; }

/* ---- Modal v2 (R-CMP-4): close animation, draft guard, bottom sheets ---- */
.modal:focus { outline: none; }
.modal > header { position: relative; }
.cd-msg { margin: 0; color: var(--text-2); font-size: var(--fs-base); line-height: var(--lh-ui); }
.modal-backdrop.closing { animation: fadeOut var(--dur-2) var(--ease-out) forwards; pointer-events: none; }
.modal-backdrop.closing .modal { animation: popOut var(--dur-2) var(--ease-out) forwards; }
.modal.shake { animation: shake .34s var(--ease-out); }
@keyframes fadeOut { to { opacity: 0; } }
@keyframes popOut { to { opacity: 0; transform: translateY(6px) scale(.98); } }
@keyframes shake { 20% { transform: translateX(-7px); } 40% { transform: translateX(6px); } 60% { transform: translateX(-4px); } 80% { transform: translateX(2px); } }
@keyframes sheetUp { from { transform: translateY(100%); } }
@keyframes sheetDown { to { transform: translateY(100%); } }
@media (max-width: 560px) {
  .modal-backdrop { place-items: end stretch; padding: 0; }
  .modal, .modal.wide {
    width: 100%; max-width: none; max-height: 92vh; max-height: 92dvh;
    border-radius: 24px 24px 0 0; border-bottom: 0; animation: sheetUp var(--dur-3) var(--ease-out);
  }
  .modal > header { padding-top: 22px; }
  .modal > header::before { content: ''; position: absolute; top: 8px; left: 50%; width: 36px; height: 4px; margin-left: -18px; border-radius: 2px; background: var(--border-strong); }
  .modal > footer { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .modal-backdrop.closing .modal { animation: sheetDown var(--dur-2) var(--ease-out) forwards; }
  .modal.shake { animation: shakeY .34s var(--ease-out); }
}
@keyframes shakeY { 30% { transform: translateY(-8px); } 60% { transform: translateY(3px); } }

/* ---- Toast: a repeated error pulses instead of stacking ---- */
.toast.pulse { animation: toastPulse .36s var(--ease-out); }
@keyframes toastPulse { 40% { transform: scale(1.03); } }
@media (max-width: 719px) { body.has-shell #toasts { bottom: calc(var(--shell-bottom, 0px) + 12px); } body.has-shell.kb-open #toasts { bottom: 12px; } }

/* ---- Upload dropzone + file chip (R-CMP-9) ---- */
.drop {
  position: relative; display: grid; place-items: center; gap: 6px; min-height: 120px; padding: 20px; text-align: center;
  border: 1.5px dashed var(--border-strong); border-radius: var(--r-lg); background: var(--bg-sunken); color: var(--muted);
  cursor: pointer; transition: border-color var(--dur-1) var(--ease-out), background-color var(--dur-1) var(--ease-out);
}
.drop b { color: var(--text); font-weight: 600; font-size: var(--fs-base); }
.drop u { color: var(--accent-text); text-underline-offset: 2px; }
.drop small { font-size: var(--fs-xs); }
.drop-ic { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: var(--accent-soft); color: var(--accent-text); }
.drop:hover, .drop.over { border-color: var(--accent-fill); background: var(--accent-soft); }
.drop:focus-within { box-shadow: var(--ring); }
.drop-input { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; clip: rect(0 0 0 0); }
.drop-wrap.has-file .drop { min-height: 72px; padding: 12px; }
.drop-wrap.has-file .drop small { display: none; }
.drop-chips:empty { display: none; }
.drop-chips { display: grid; gap: 8px; margin-top: 10px; }
.file-chip { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 6px 6px 6px 12px; border: 1px solid var(--border-strong); border-radius: var(--r-md); background: var(--surface-2); }
.file-chip .fc-ic { display: grid; place-items: center; color: var(--accent-text); }
.file-chip .fc-name { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: var(--fs-sm); font-weight: 600; }
.file-chip small { flex: none; color: var(--muted); font-size: var(--fs-xs); }
.fc-x { display: grid; place-items: center; flex: none; width: 32px; height: 32px; border: 0; border-radius: var(--r-sm); background: none; color: var(--muted); cursor: pointer; }
.fc-x:hover { background: var(--surface-3); color: var(--danger); }
.fc-x:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
@media (pointer: coarse) { .fc-x { width: 44px; height: 44px; } }
.up-prog { height: 6px; margin-top: 12px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.up-prog > i { display: block; height: 100%; width: 0; border-radius: inherit; background: var(--accent-fill); transition: width var(--dur-2) var(--ease-out); }

/* ---- Multi-select pickers (R-CMP-14) ---- */
.checklist { position: relative; }
.mp-head {
  position: sticky; top: 0; z-index: 2; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 6px 13px; background: var(--surface-overlay); border-bottom: 1px solid var(--border-strong); font-size: var(--fs-sm);
}
.checklist label.mp-all { padding: 6px 0; border-bottom: 0; font-weight: 600; background: none; }
.checklist label.mp-all:hover { background: none; }
.mp-count { color: var(--muted); font-weight: 600; white-space: nowrap; }
.checklist label:not(.mp-all):has(input:checked:not(:disabled)), .att-pick:has(input:checked:not(:disabled)) { background: var(--accent-soft); }
.checklist label .badge { margin-inline-start: auto; flex: none; white-space: nowrap; }
.checklist label > span { min-width: 0; overflow-wrap: anywhere; }

/* ---- Connection banner (R-SYS-1) ---- */
.net-banner {
  position: sticky; top: calc(var(--shell-top, 64px) + env(safe-area-inset-top, 0px)); z-index: 39;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 12px; padding: 8px 16px;
  background: color-mix(in srgb, var(--warning) 14%, var(--bg)); color: var(--warning);
  border-bottom: 1px solid color-mix(in srgb, var(--warning) 30%, transparent);
  font: 500 13.5px/1.35 var(--font); text-align: center;
}
.net-banner[hidden] { display: none; }
.net-banner svg { flex: none; }
.net-banner .btn { min-height: 28px; padding: 3px 10px; background: transparent; border-color: currentColor; color: inherit; }
.net-banner.ok { background: color-mix(in srgb, var(--success) 14%, var(--bg)); color: var(--success); border-bottom-color: color-mix(in srgb, var(--success) 30%, transparent); }
.net-banner.floating { position: fixed; top: 0; left: 0; right: 0; z-index: 95; }
.net-stale { display: flex; align-items: center; gap: 6px; margin: 0; padding: 6px 16px; color: var(--muted); font-size: var(--fs-xs); border-bottom: 1px solid var(--border); background: var(--surface-2); }
.net-stale[hidden] { display: none; }

/* ---- Sign-in sheet (R-SYS-2): above modals (60) and toasts (80) ---- */
.reauth-backdrop { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; padding: 24px; background: var(--overlay); animation: fade var(--dur-2) var(--ease-out); }
.reauth {
  width: 100%; max-width: 420px; padding: 26px 24px 22px; max-height: 100%; overflow-y: auto;
  background: var(--surface-overlay); border: 1px solid var(--border-strong); border-radius: var(--r-xl); box-shadow: var(--shadow-overlay);
  animation: pop var(--dur-3) var(--ease-out);
}
.reauth:focus { outline: none; }
.reauth-ic { display: grid; place-items: center; width: 44px; height: 44px; margin-bottom: 12px; border-radius: 14px; background: var(--accent-soft); color: var(--accent-text); }
.reauth h2 { margin: 0 0 6px; font: 700 var(--fs-xl)/1.25 var(--font-display); }
.reauth .lead { margin: 0 0 18px; color: var(--text-2); font-size: var(--fs-base); line-height: var(--lh-ui); }
.reauth .input[readonly] { background: var(--surface-2); color: var(--text-2); }
.reauth .btn.primary { width: 100%; margin-top: 4px; }
.reauth .ra-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px; margin-top: 14px; color: var(--muted); font-size: var(--fs-sm); }
.reauth .ra-foot .btn { min-height: 32px; padding: 4px 8px; color: var(--accent-text); }
@media (max-width: 560px) {
  .reauth-backdrop { place-items: end stretch; padding: 0; }
  .reauth { max-width: none; border-radius: 24px 24px 0 0; border-bottom: 0; padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px)); animation: sheetUp var(--dur-3) var(--ease-out); }
}

/* ---- Boot offline (R-SYS-1) ---- */
.boot-off { max-width: 420px; text-align: center; }
.boot-off .illus { width: 128px; height: 128px; margin: 0 auto 8px; }
.boot-off h1 { margin: 0 0 8px; font: 700 var(--fs-2xl)/1.2 var(--font-display); }
.boot-off p { margin: 0 0 20px; color: var(--text-2); }

/* ---- PWA polish (R-MOB-4) ---- */
.topbar { padding-top: env(safe-area-inset-top, 0px); height: calc(var(--shell-top) + env(safe-area-inset-top, 0px)); }
@media (display-mode: standalone) {
  .tb-app, [data-action="getapp"] { display: none !important; }
  body { overscroll-behavior-y: contain; }
}

/* ---- Revalidating: a 2px bar at the very top instead of a spinner (R-PERF-1) ---- */
.top-progress { position: fixed; top: 0; left: 0; z-index: 100; height: 2px; width: 30%; background: var(--accent-fill); animation: topProg 1.1s var(--ease-out) infinite; pointer-events: none; }
@keyframes topProg { from { transform: translateX(-100%); } to { transform: translateX(340%); } }

/* ---- Print (R-SYS-6) ---- */
.print-head { display: none; }
.modal > footer .print-btn { margin-inline-end: auto; }
@media (max-width: 479px) { .print-btn { display: none; } }
@media print {
  :root, :root[data-theme] {
    --bg: #fff; --bg-sunken: #fff; --bg-2: #fff; --surface: #fff; --surface-2: #f4f6f9; --surface-3: #e8ecf2; --surface-overlay: #fff;
    --text: #111827; --text-2: #374151; --muted: #4b5563; --border: #d1d5db; --border-strong: #9ca3af; --field-border: #9ca3af;
    --accent-text: #a35400; --accent-soft: #fdf1df; --success: #15803d; --warning: #a16207; --danger: #c81e1e; --info: #1d63d8;
    color-scheme: light;
  }
  html, body { background: #fff !important; color: #111827 !important; }
  body::before, body::after { display: none !important; }
  .sidebar, .topbar, .tabbar, .more-sheet, .me-menu, #toasts, .net-banner, .cls-rail, .class-side, .skip-link,
  .btn, .print-btn, .row-menu, .cls-tabs, .back-link, .search-field, .save-bar, .top-progress, [data-noprint] { display: none !important; }
  .app-shell { display: block; }
  .container { padding: 0 !important; max-width: none !important; }
  .panel, .card, .ann, .td-card, .modal { box-shadow: none !important; }
  .panel, .card, .ann, .td-card, tr, li, .ag-day { break-inside: avoid; }
  thead { display: table-header-group; }
  .table-wrap { overflow: visible !important; }
  a { color: inherit !important; text-decoration: none; }
  @page { margin: 14mm 12mm; }
  /* Print one panel: everything that is not the target, inside it, or on the
     way to it is dropped, so the panel starts at the top of the first page. */
  body.printing-scope *:not(.print-path):not(.print-target):not(.print-target *) { display: none !important; }
  body.printing-scope .print-path {
    display: block !important; position: static !important; inset: auto !important; transform: none !important;
    margin: 0 !important; padding: 0 !important; border: 0 !important; background: none !important; box-shadow: none !important;
    max-height: none !important; min-height: 0 !important; overflow: visible !important; animation: none !important;
  }
  body.printing-scope .print-target { display: block !important; position: static !important; max-height: none !important; overflow: visible !important; border: 0 !important; }
  .print-target .print-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; padding-bottom: 10px; border-bottom: 2px solid #111827; }
  .print-head img { height: 32px; }
  .print-head b { display: block; font-size: 16px; }
  .print-head span { display: block; color: #4b5563; font-size: 12px; }
  .print-head small { margin-inline-start: auto; color: #4b5563; font-size: 11px; white-space: nowrap; }
  select, .ag-more, .ag-filter, .td-link, .rx-add, [data-agmore] { display: none !important; }
  /* The printed panel itself may run over pages; its rows and cards stay whole. */
  .print-target, .print-target > .panel, .print-target .cal-wrap > .panel, .print-target .cal-wrap > div { break-inside: auto !important; }
  .print-target .cal-wrap { display: block !important; }
  .print-target .cal-wrap > * + * { margin-top: 14px; }
  .print-target .cal-day { min-height: 74px !important; box-shadow: none !important; }
  .print-target.modal .body, .print-target .body { max-height: none !important; overflow: visible !important; padding: 0 !important; }
  .print-target.modal > header, .print-target.modal > footer, .print-target .fb-compose, .print-target textarea:placeholder-shown,
  .print-target .field:has(#subPick), .print-target [data-rmfile] { display: none !important; }
  .clamp { -webkit-line-clamp: unset !important; display: block !important; overflow: visible !important; }
}
@media (prefers-reduced-motion: reduce) {
  .sk, .top-progress { animation: none !important; }
  .btn-spin { animation-duration: 1.6s !important; animation-iteration-count: infinite !important; }
}

/* ==========================================================================
   Phase 3, batch 2: office screens, replies, navigation, phones, a11y.
   ========================================================================== */

/* ---- Replies in class chat + office notes (meeting-protocol-v2 §1) ---- */
.chat .foot .acts { display: inline-flex; align-items: center; gap: 10px; margin-inline-start: auto; }
.chat .foot .x[data-replymsg]:hover { color: var(--accent-text); }
.chat .quote {
  display: flex; flex-direction: column; gap: 1px; width: 100%; min-width: 0; margin: 0 0 6px; padding: 5px 9px;
  border: 0; border-inline-start: 3px solid var(--accent-fill); border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--text) 6%, transparent); color: var(--text-2);
  font: 400 var(--fs-xs)/1.4 var(--font); text-align: start; cursor: pointer;
}
.chat .quote:hover { background: color-mix(in srgb, var(--text) 10%, transparent); }
.chat .quote:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
.chat .quote b { color: var(--accent-text); font-size: var(--fs-xs); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat .quote .q-txt { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
.chat .msg.mine .quote { background: color-mix(in srgb, var(--bubble-out-text) 9%, transparent); color: inherit; }
.chat .msg.mine .quote b { color: inherit; }
.chat .quote.deleted { flex-direction: row; align-items: center; gap: 6px; border-inline-start-color: var(--border-strong); color: var(--muted); font-style: italic; cursor: default; }
.chat .quote.deleted:hover { background: color-mix(in srgb, var(--text) 6%, transparent); }
.q-photo { display: inline-flex; align-items: center; gap: 4px; margin-inline-end: 4px; vertical-align: -2px; }
.chat .msg.flash .bub { animation: msgFlash 1.6s var(--ease-out); }
.chat .msg:focus { outline: none; }
@keyframes msgFlash { 0%, 35% { box-shadow: 0 0 0 3px var(--accent-fill); } 100% { box-shadow: 0 0 0 3px transparent; } }
.reply-strip {
  display: flex; align-items: center; gap: 10px; min-width: 0; padding: 6px 6px 6px 10px;
  border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); border-inline-start: 3px solid var(--accent-fill);
}
.reply-strip[hidden] { display: none; }
.chat-compose > .reply-strip, .chat-compose > .compose-row { align-self: stretch; }
.reply-strip .rs-ic { display: grid; place-items: center; color: var(--accent-text); flex: none; }
.reply-strip .rs-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.reply-strip .rs-main b { font-size: var(--fs-xs); font-weight: 600; color: var(--accent-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.reply-strip .rs-txt { font-size: var(--fs-sm); color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.reply-strip .rs-x { flex: none; }
#nForm { flex-direction: column; align-items: stretch; }
#nForm .compose-row textarea { flex: 1; min-width: 0; }
.chat .bub.pressed { box-shadow: 0 0 0 2px var(--accent-line); }
.msg-menu {
  position: fixed; z-index: 4000; min-width: 200px; padding: 6px; display: flex; flex-direction: column; gap: 2px;
  background: var(--surface-overlay); border: 1px solid var(--border-strong); border-radius: var(--r-lg); box-shadow: var(--shadow-overlay);
  animation: pop var(--dur-2) var(--ease-out);
}
.msg-menu .mm-act {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 44px; padding: 0 12px; border: 0; border-radius: var(--r-md);
  background: none; color: var(--text); font: 500 var(--fs-base)/1 var(--font); text-align: start; cursor: pointer;
}
.msg-menu .mm-act:hover, .msg-menu .mm-act:focus-visible { background: var(--surface-2); outline: none; }
.msg-menu .mm-act svg { color: var(--muted); }
.msg-menu .mm-act.danger, .msg-menu .mm-act.danger svg { color: var(--danger); }
@media (pointer: coarse) {
  .chat .bub { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
}

/* ---- WhatsApp-style formatting (textfmt.js FORMAT_CSS + the quiet hint) ---- */
.fmt-code { font-family: var(--font-mono); font-size: .92em; padding: .05em .35em; border-radius: var(--r-xs); background: var(--surface-3); }
.fmt-pre { font-family: var(--font-mono); font-size: .92em; margin: .35em 0; padding: .5em .65em; border-radius: var(--r-sm); background: var(--surface-3); white-space: pre-wrap; overflow-wrap: anywhere; }
.chat .msg.mine .fmt-code, .chat .msg.mine .fmt-pre { background: color-mix(in srgb, var(--bubble-out-text) 10%, transparent); }
.fmt-hint { margin: 6px 0 0; color: var(--muted); font-size: var(--fs-xs); }
.fmt-hint span { font-family: var(--font-mono); font-size: 11.5px; }
.btn.fmt-tip { font: 700 12px/1 var(--font); letter-spacing: -.02em; color: var(--muted); }

/* ---- Breadcrumbs that follow the path (R-NAV-3) ---- */
.crumbs li:not(:last-child):not(.sep) { flex: 0 1 auto; max-width: 22ch; }
.crumbs li:not(.sep) a { display: block; overflow: hidden; text-overflow: ellipsis; }
.back-link.crumb-up span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 720px) { .back-link.crumb-up { display: none; } }
@media (max-width: 719px) { .back-link.crumb-up { min-height: 44px; margin: -6px 0 6px; } }
:dir(rtl) .crumbs .sep svg, :dir(rtl) .back-link > svg { transform: scaleX(-1); }

/* ---- Office section row: real links, fade at the scrolling edge (R-NAV-7) ---- */
.tabs a { flex: none; padding: 12px 14px; margin-bottom: -1px; border-bottom: 2px solid transparent; color: var(--muted); font-size: 14px; font-weight: 600; white-space: nowrap; text-decoration: none; }
.tabs a:hover { color: var(--text); text-decoration: none; }
.tabs a[aria-current="page"] { color: var(--text); border-bottom-color: var(--accent-fill); }
.tabs.admin-tabs { overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 32px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 32px), transparent); }
.tabs.admin-tabs::-webkit-scrollbar { display: none; }

/* ---- Chips, counts, a segmented view switch (R-NAV-6, R-OFF-2) ---- */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 0 12px; border-radius: var(--r-pill);
  border: 1px solid var(--border-strong); background: transparent; color: var(--text-2); font: 600 var(--fs-sm)/1 var(--font); cursor: pointer;
}
.chip:hover { background: var(--surface-2); color: var(--text); }
.chip[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent-line); color: var(--text); }
.chip:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
.chip-n { min-width: 18px; padding: 0 5px; border-radius: var(--r-pill); background: var(--surface-3); color: var(--text-2); font-size: var(--fs-2xs); line-height: 18px; text-align: center; font-variant-numeric: tabular-nums; }
.chip[aria-pressed="true"] .chip-n { background: var(--accent-fill); color: var(--on-accent); }
@media (pointer: coarse) { .chip { min-height: 44px; } }
.seg { display: inline-flex; flex: none; gap: 2px; padding: 3px; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); }
.seg > a, .seg > button {
  display: inline-flex; align-items: center; gap: 6px; min-height: 32px; padding: 0 12px; border: 0; border-radius: var(--r-sm);
  background: none; color: var(--muted); font: 600 var(--fs-sm)/1 var(--font); white-space: nowrap; cursor: pointer; text-decoration: none;
}
.seg > a:hover, .seg > button:hover { color: var(--text); text-decoration: none; }
.seg > a[aria-current="page"], .seg > button[aria-pressed="true"] { background: var(--surface); color: var(--text); box-shadow: var(--elev), 0 0 0 1px var(--border-strong); }
:root[data-theme="light"] .seg > a[aria-current="page"], :root[data-theme="light"] .seg > button[aria-pressed="true"] { box-shadow: var(--shadow-1), 0 0 0 1px var(--border); }
.seg > a:focus-visible, .seg > button:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring); }
.seg-n { color: var(--muted); font-weight: 500; font-variant-numeric: tabular-nums; }
@media (pointer: coarse) { .seg > a, .seg > button { min-height: 40px; } }
.filter-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: -4px 0 16px; }
.filter-row select.input { width: auto; max-width: 260px; }
.fr-sp { flex: 1; }
.tbl-filters { padding: 10px 16px; border-bottom: 1px solid var(--border); }
.tbl-filters:empty { display: none; }

/* ---- Compact person rows (R-HOME-6, R-OFF-4) ---- */
.grid.people { grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 12px; }
.grid.people[hidden] { display: none; }
.card.person {
  display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; align-items: center; gap: 12px;
  min-height: 64px; padding: 12px 16px; color: inherit; text-decoration: none;
}
.card.person:hover { background: var(--surface-2); border-color: var(--border-strong); text-decoration: none; }
:root[data-theme="light"] .card.person:hover { background: var(--surface); box-shadow: var(--elev-hover); }
.card.person.cls-row { border-inline-start: 3px solid var(--c, var(--border)); }
.av.md { width: 40px; height: 40px; font-size: 14px; margin: 0; }
.av.lg { width: 56px; height: 56px; font-size: 19px; margin: 0; }
.p-main { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.p-main b { font-size: var(--fs-base); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-main small { color: var(--muted); font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-end { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.card.person.is-frozen .av { filter: grayscale(.8); opacity: .7; }
.pill { display: inline-flex; align-items: center; gap: 5px; height: 22px; padding: 0 8px; border-radius: var(--r-pill); font: 600 var(--fs-2xs)/1 var(--font); white-space: nowrap; }
.pill svg { flex: none; }
.pill.notes { background: var(--accent-soft); color: var(--accent-text); }
.pill.chatn { background: var(--surface-3); color: var(--text); }
.pill.frozen { background: var(--danger-soft); color: var(--danger); }
.pill.cover { background: var(--surface-2); color: var(--text-2); }
.pill.cover .dot, .person-cover .dot, .m.seat-transition .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--warning); flex: none; }
.person-cover { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; }
.card .meta .m.seat-transition { color: var(--text-2); }
.cls-pills { display: inline-flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; flex: none; margin-inline-start: auto; }
.match-line { margin-top: 4px; font-size: var(--fs-xs); color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.match-line > span { font-weight: 600; color: var(--text-2); }
mark { background: var(--accent-soft); color: inherit; border-radius: 3px; padding: 0 2px; }
@media (max-width: 560px) {
  .grid.people { gap: 0; border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; background: var(--surface); }
  .grid.people > .card.person { border: 0; border-radius: 0; border-bottom: 1px solid var(--border); min-height: 56px; box-shadow: none; }
  .grid.people > .card.person:last-child { border-bottom: 0; }
  .grid.people > .card.person.cls-row { border-inline-start: 3px solid var(--c, var(--border)); }
  .p-end { max-width: 42%; }
  .list-toolbar .seg { width: 100%; }
  .list-toolbar .seg > a, .list-toolbar .seg > button { flex: 1; justify-content: center; }
}

/* ---- Dense roster (R-OFF-3) and the student profile head ---- */
.roster { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(520px, 100%), 1fr)); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; background: var(--surface); box-shadow: var(--elev); }
.roster[hidden] { display: none; }
.roster-row {
  display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; align-items: center; gap: 12px; min-height: 56px; padding: 8px 16px;
  border-bottom: 1px solid var(--border); color: inherit; text-decoration: none;
}
.roster-row:hover { background: var(--surface-2); text-decoration: none; }
.roster-row:focus-visible { outline: 2px solid transparent; box-shadow: inset 0 0 0 2px var(--focus-ring); }
@media (min-width: 1100px) { .roster-row:nth-child(odd) { border-inline-end: 1px solid var(--border); } }
.roster-row .av { margin: 0; width: 32px; height: 32px; }
.roster-row.is-frozen .av { filter: grayscale(.8); opacity: .7; }
.r-main { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.r-main b { font-size: var(--fs-base); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.r-sub { display: flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; }
.r-id { font: 500 13px/1 var(--font-mono); color: var(--muted); flex: none; }
.cls-chip { display: inline-flex; align-items: center; gap: 5px; min-width: 0; max-width: 22ch; height: 20px; padding: 0 7px; border-radius: var(--r-pill); background: var(--c-soft, var(--surface-2)); color: var(--text-2); font-size: var(--fs-2xs); font-weight: 600; }
.cls-chip i { width: 6px; height: 6px; border-radius: 50%; background: var(--c, var(--muted)); flex: none; }
.cls-chip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cls-chip.more { background: var(--surface-2); color: var(--muted); }
.profile-head { display: flex; align-items: center; gap: 16px; margin-bottom: 22px; }
.ph-main { min-width: 0; flex: 1; }
.ph-main h1 { margin: 0; font: 700 var(--fs-2xl)/var(--lh-tight) var(--font-display); overflow-wrap: anywhere; }
.ph-facts { display: flex; flex-wrap: wrap; gap: 4px 8px; margin: 6px 0 0; color: var(--muted); font-size: var(--fs-sm); }
.ph-facts .r-id { font-size: var(--fs-sm); color: var(--text-2); }

/* ---- Office tables: identity cell, status, sticky header (R-OFF-2) ---- */
.ident { display: flex; align-items: center; gap: 12px; min-width: 0; }
.ident-txt { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ident-txt b { font-weight: 600; overflow-wrap: anywhere; }
.ident-txt small { color: var(--muted); font-size: var(--fs-xs); overflow-wrap: anywhere; }
.id-cell { font: 500 13px var(--font-mono); color: var(--text-2); }
.tbl td.date { white-space: nowrap; }
.tbl td .sub, .tbl td small.sub { display: block; color: var(--muted); font-size: var(--fs-xs); margin-top: 2px; white-space: normal; }
.status { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-sm); font-weight: 600; white-space: nowrap; }
.status i { width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
.status.active { color: var(--success); }
.status.frozen { color: var(--danger); }
.status.frozen i { background: var(--danger); }
.acc { display: inline-flex; align-items: center; gap: 12px; }
.acc .status { min-width: 64px; }
@media (min-width: 900px) {
  .panel.has-sticky { overflow: clip; }
  .panel.has-sticky .table-wrap { overflow: visible; }
  .panel.has-sticky thead th { position: sticky; top: calc(var(--shell-top) + env(safe-area-inset-top, 0px)); z-index: 2; background: var(--surface); box-shadow: inset 0 -1px 0 var(--border); }
}
.table-wrap.fade-end { -webkit-mask-image: linear-gradient(to right, #000 85%, transparent); mask-image: linear-gradient(to right, #000 85%, transparent); }
.badge.t-neutral { background: var(--surface-3); color: var(--text-2); }
.stat.good b { color: var(--success); }
tr.row-link { position: relative; }
tr.row-link .row-a { color: inherit; text-decoration: none; }
tr.row-link .row-a::after { content: ""; position: absolute; inset: 0; }
tr.row-link:hover td { background: var(--surface-2); }
tr.row-link .row-a:focus-visible { outline: none; }
tr.row-link:has(.row-a:focus-visible) td { box-shadow: inset 0 2px 0 var(--focus-ring), inset 0 -2px 0 var(--focus-ring); }

/* ---- Trash: restore first (R-OFF-8) ---- */
.trash-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; margin-bottom: 14px; }
.trash-bar p { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--fs-sm); }
.trash-bar #delAll { margin-inline-start: auto; }
.bulk-bar { position: sticky; top: calc(var(--shell-top) + 8px); z-index: 5; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 12px; padding: 10px 14px; border-radius: var(--r-md); background: var(--surface-overlay); border: 1px solid var(--border-strong); box-shadow: var(--shadow-2); font-weight: 600; }
.bulk-bar[hidden] { display: none; }
.bulk-bar .sb-sp { flex: 1; }
.btn.ghost.danger { background: transparent; color: var(--danger); }
.btn.ghost.danger:hover { background: var(--danger-soft); }
.tbl td.cell-actions { white-space: nowrap; text-align: end; }
.tbl td.cell-actions .btn + .btn { margin-inline-start: 4px; }

/* ---- Announcements console (R-OFF-10) ---- */
.ann.has-fail { box-shadow: inset 3px 0 0 var(--warning); }
.ann-fail { flex: none; }
.ann-meta b { color: var(--text-2); font-weight: 600; }
.ann-sent .ann-actions { align-self: flex-start; }

/* ---- Consequential actions in their own zone; a quieter hint (R-OFF-7) ---- */
.hint, .field .hint { font-size: 12.5px; line-height: 1.5; color: var(--muted); margin-top: 6px; }
.zone { margin-top: 20px; border: 1px solid var(--danger-line); border-radius: var(--r-md); overflow: hidden; }
.zone h4 { margin: 0; padding: 10px 16px; font: 600 var(--fs-sm)/1.3 var(--font); color: var(--danger); background: var(--danger-soft); }
.zone-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px 16px; }
.zone-row + .zone-row { border-top: 1px solid var(--border); }
.zone-row > div { min-width: 0; }
.zone-row b { display: block; font-size: var(--fs-sm); font-weight: 600; }
.zone-row small { display: block; color: var(--muted); font-size: var(--fs-xs); line-height: 1.45; margin-top: 2px; }
.zone-row .btn { flex: none; }
.zone-row.col { flex-direction: column; align-items: stretch; }
@media (max-width: 480px) { .zone-row { flex-direction: column; align-items: stretch; } }

/* ---- Add student: generate, live rules, credentials card (R-OFF-11) ---- */
.input-group { display: flex; gap: 8px; }
.input-group .input { flex: 1; min-width: 0; }
.input-group .btn { flex: none; }
.pw-rules { list-style: none; margin: 8px 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 4px 12px; font-size: var(--fs-xs); color: var(--muted); }
.pw-rules li { display: flex; align-items: center; gap: 6px; }
.pw-rules li svg { opacity: .35; }
.pw-rules li[data-ok="1"] { color: var(--success); }
.pw-rules li[data-ok="1"] svg { opacity: 1; }
.cred-ok { display: flex; align-items: center; gap: 10px; margin: 0 0 14px; color: var(--success); font-weight: 600; }
.cred-ok span { color: var(--text); font-weight: 500; }
.cred-card { border: 1px solid var(--border-strong); border-radius: var(--r-md); background: var(--surface-2); padding: 6px 16px; }
.cred-card dl { margin: 0; }
.cred-card dl > div { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 12px; padding: 9px 0; border-bottom: 1px dashed var(--border); }
.cred-card dl > div:last-child { border-bottom: 0; }
.cred-card dt { color: var(--muted); font-size: var(--fs-sm); }
.cred-card dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; }
.cred-card dd.mono { font-family: var(--font-mono); }
.cred-card dd.pw { font-size: var(--fs-md); letter-spacing: .02em; }
.cred-warn { display: flex; align-items: flex-start; gap: 8px; margin: 14px 0 0; color: var(--warning); font-size: var(--fs-sm); }

/* ---- Viewer: read-only, said in words (R-OFF-5, R-OFF-13) ---- */
.badge.ro { background: var(--surface-3); color: var(--text-2); }
.ro-note { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; padding: 8px 12px; border-radius: var(--r-md); background: var(--surface-2); color: var(--text-2); font-size: var(--fs-sm); }
.grade-editing.ro { color: var(--muted); }
.cell.ro { display: inline-block; min-width: 40px; padding: 6px 4px; font-variant-numeric: tabular-nums; font-weight: 600; }
.role-banner { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 8px 16px; font-size: 13px; background: var(--surface-2); border-bottom: 1px solid var(--border); color: var(--muted); text-align: center; }
.role-banner svg { flex: none; }

/* ---- Thumb-reach primary action on phones (R-MOB-5) ---- */
.fab { display: none; }
@media (max-width: 720px) {
  .fab:not([hidden]) {
    position: fixed; inset-inline-end: 16px; bottom: calc(88px + env(safe-area-inset-bottom, 0px)); z-index: 44;
    display: grid; place-items: center; width: 56px; height: 56px; border: 0; border-radius: var(--r-lg);
    background: linear-gradient(180deg, var(--accent-fill), var(--accent-fill-deep)); color: var(--on-accent); box-shadow: var(--shadow-2); cursor: pointer;
  }
  .fab:focus-visible { outline: 2px solid transparent; box-shadow: var(--ring), var(--shadow-2); }
  body.kb-open .fab { display: none; }
  .cls-page:has(.fab) .cls-qa { display: none; }
}
.act-sheet { display: flex; flex-direction: column; gap: 8px; }
.act-row { display: flex; align-items: center; gap: 14px; width: 100%; min-height: 56px; padding: 10px 14px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); color: var(--text); font: inherit; text-align: start; cursor: pointer; text-decoration: none; }
.act-row:hover { border-color: var(--border-strong); text-decoration: none; }
.act-row svg { color: var(--accent-text); flex: none; }
.act-row.live svg { color: var(--live); }
.act-row span { display: flex; flex-direction: column; gap: 2px; }
.act-row small { color: var(--muted); font-size: var(--fs-xs); }

/* ---- Tables become stacked rows on phones (R-MOB-2) ---- */
@media (max-width: 640px) {
  table.tbl.stack thead { display: none; }
  table.tbl.stack, .tbl.stack tbody { display: block; }
  .tbl.stack tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; padding: 12px 16px; border-bottom: 1px solid var(--border); }
  .tbl.stack tr:last-child { border-bottom: 0; }
  .tbl.stack td { display: block; padding: 0; border: 0; min-width: 0 !important; white-space: normal; text-align: start; grid-column: 1; }
  .tbl.stack td[data-label]:not(.cell-primary)::before { content: attr(data-label); display: block; font-size: 11px; color: var(--muted); font-weight: 500; }
  .tbl.stack td.cell-primary { grid-column: 1; grid-row: 1; }
  .tbl.stack td.cell-access, .tbl.stack td.cell-actions { grid-column: 2; grid-row: 1; justify-self: end; align-self: start; }
  .tbl.stack td.cell-access::before { display: none !important; }
  .tbl.stack td.cell-access + td.cell-actions { grid-row: 2; }
  .tbl.stack td.cell-check { grid-column: 2; grid-row: 1; justify-self: end; }
  .tbl.stack:has(td.cell-check) td.cell-actions { grid-row: 2; }
  .tbl.stack td.c { text-align: start; }
  .tbl.stack tr:hover td { background: none; }
  .tbl.stack tr.row-frozen td { opacity: 1; }
  .tbl.stack tr.row-frozen .ident { opacity: .6; }
  .tbl.stack .acc { flex-direction: column; align-items: flex-end; gap: 6px; }
  .tbl.stack .acc .status { min-width: 0; }
  .tbl.stack .ident .av { width: 32px; height: 32px; font-size: 12px; }
  /* Two short values share a line: ID + classes, created + status. */
  .people-tbl.stack td.id-cell, .people-tbl.stack td.c, .people-tbl.stack td.date { display: inline-block; grid-column: 1; }
  .tbl.stack td.att-note { max-width: none; }
}

/* ---- On-screen keyboard (R-MOB-3, kb.js sets --kb and body.kb-up) ---- */
body.kb-up .modal-backdrop { bottom: var(--kb, 0px); }
body.kb-up .modal, body.kb-up .modal.wide { max-height: calc(100dvh - 12px - var(--kb, 0px)); }
body.kb-up .ml-cmp { bottom: var(--kb, 0px); max-height: calc(100dvh - var(--kb, 0px) - 60px); }
body.kb-up .tabbar, body.kb-up .fab { display: none; }

/* ---- Quick switcher (R-NAV-4) ---- */
.tb-find { flex: none; gap: 8px; color: var(--muted); border: 1px solid var(--border) !important; }
.tb-find:hover { color: var(--text); }
.tb-kbd, .pal kbd { display: inline-grid; place-items: center; min-width: 22px; height: 20px; padding: 0 5px; border-radius: 5px; border: 1px solid var(--border-strong); background: var(--surface-2); color: var(--muted); font: 600 11px/1 var(--font); }
@media (max-width: 1100px) { .tb-find .tb-kbd { display: none; } }
@media (max-width: 719px) { .tb-find { display: none; } }
.pal-backdrop { position: fixed; inset: 0; z-index: 70; display: flex; justify-content: center; align-items: flex-start; padding: 0 16px; background: var(--overlay); animation: fade var(--dur-1) var(--ease-out); }
.pal {
  width: min(640px, calc(100vw - 32px)); margin-top: 12vh; max-height: 72vh; display: flex; flex-direction: column; overflow: hidden;
  background: var(--surface-overlay); border: 1px solid var(--border-strong); border-radius: var(--r-lg); box-shadow: var(--shadow-overlay); animation: pop var(--dur-2) var(--ease-out);
}
.pal-in { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border); color: var(--muted); }
.pal-in input { flex: 1; min-width: 0; border: 0; background: none; color: var(--text); font: 500 var(--fs-md)/1.4 var(--font); outline: none; }
.pal-list { list-style: none; margin: 0; padding: 6px; overflow-y: auto; }
.pal-h { padding: 10px 10px 4px; color: var(--muted); font: 600 var(--fs-xs)/1 var(--font); }
.pal-row { display: flex; align-items: center; gap: 12px; min-height: 44px; padding: 6px 10px; border-radius: var(--r-md); cursor: pointer; }
.pal-row[aria-selected="true"] { background: var(--accent-soft); }
.pal-tile { display: grid; place-items: center; flex: none; width: 30px; height: 30px; border-radius: var(--r-sm); background: var(--c-soft, var(--surface-3)); color: var(--c, var(--text-2)); }
.pal-txt { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 2px; }
.pal-txt b { font-weight: 600; font-size: var(--fs-base); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pal-txt small { color: var(--muted); font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pal-go { color: var(--accent-text); display: grid; }
.pal-empty { padding: 22px 12px; color: var(--muted); text-align: center; }
.pal-foot { display: flex; gap: 16px; margin: 0; padding: 8px 14px; border-top: 1px solid var(--border); color: var(--muted); font-size: var(--fs-xs); }
.pal-foot span { display: inline-flex; align-items: center; gap: 4px; }
@media (max-width: 560px) { .pal { margin-top: 8px; max-height: calc(100dvh - 16px - var(--kb, 0px)); } .pal-foot { display: none; } }

/* ---- Profile menu: office apps (R-NAV-13) ---- */
.mm-label { margin: 6px 10px 4px; color: var(--muted); font: 600 var(--fs-xs)/1 var(--font); }
.mm-div { height: 1px; margin: 6px 4px; background: var(--border); }
a.mm-item { text-decoration: none; }
a.mm-item:hover { text-decoration: none; }
.mm-item .ext { width: 14px; height: 14px; margin-inline-start: auto; color: var(--muted); }

/* ---- Login: the pay page is not here (R-NAV-13) ---- */
.auth-aside { margin: 18px 0 0; color: var(--muted); font-size: var(--fs-xs); text-align: center; line-height: 1.5; }
.field .field-lbl { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--text-2); margin-bottom: 7px; }
.field .field-lbl .opt, .field label .opt { color: var(--muted); font-weight: 400; }
.ph-facts > span { min-width: 0; overflow-wrap: anywhere; }
.tbl td .sub, .tbl td small.sub { overflow-wrap: anywhere; max-width: 100%; }
.search-field input.input { padding-inline: 38px 36px; }
.card.person .p-main b { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow-wrap: anywhere; }
.grid.people { grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr)); }
@media (max-width: 640px) {
  /* People tables: name + switch on line 1, the short values side by side on line 2. */
  .people-tbl.stack tr { grid-template-columns: repeat(3, minmax(0, 1fr)) auto; }
  .people-tbl.stack td.cell-primary { grid-column: 1 / 4; grid-row: 1; }
  .people-tbl.stack td.cell-access { grid-column: 4; grid-row: 1; }
  .people-tbl.stack td.cell-actions { grid-column: 4; grid-row: 2; align-self: end; }
  .people-tbl.stack td:not(.cell-primary):not(.cell-access):not(.cell-actions) { grid-column: auto; grid-row: 2; padding-inline-start: 0; font-size: var(--fs-sm); }
  .people-tbl.stack td.cell-primary .ident { padding-inline-end: 4px; }
}
@media (max-width: 560px) {
  .grid.people > .card.person { grid-template-columns: 40px minmax(0, 1fr); row-gap: 6px; }
  .grid.people > .card.person .p-end { grid-column: 2; justify-content: flex-start; max-width: none; }
  .grid.people > .card.person .p-end:empty { display: none; }
}
.tbl .cell.ro, .cell.ro { border: 0 !important; background: none !important; box-shadow: none !important; width: auto !important; min-height: 0 !important; height: auto !important; padding: 4px 2px !important; color: var(--text); }
.grade-editing.ro { background: var(--surface-2) !important; border-color: var(--border) !important; color: var(--text-2) !important; }
.grade-editing.ro b { color: var(--text) !important; }
@media (max-width: 640px) { .tbl.stack .seat { white-space: normal; } .tbl.stack td > small, .tbl.stack td > .sub { max-width: 100%; box-sizing: border-box; } }

/* ==========================================================================
   Phase 3, batch 3 (LMS core): grader, rewards, PDF viewer, bell, Join chip,
   mail for children, type/space tokens, brand mark.
   ========================================================================== */

/* ---- Split-pane grader (R-TCH-2) ---- */
.modal.grader-modal { max-width: min(1240px, 100%); height: min(92dvh, 920px); }
.modal.grader-modal > .body { padding: 0; overflow: hidden; flex: 1 1 auto; min-height: 0; display: flex; }
.modal > header.gr-headrow { justify-content: flex-start; flex-wrap: wrap; row-gap: 2px; }
.gr-headrow h2 { flex: 0 1 auto; }
.gr-headrow .gr-sub { margin-inline-end: auto; color: var(--muted); font-size: var(--fs-xs); white-space: nowrap; }
.grader { display: grid; grid-template-columns: 300px minmax(0, 1fr); width: 100%; min-height: 0; }
.gr-side { display: flex; flex-direction: column; min-height: 0; border-inline-end: 1px solid var(--border); background: var(--surface-2); }
.gr-filters { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding: var(--sp-3); border-bottom: 1px solid var(--border); }
.gr-f { display: inline-flex; align-items: center; gap: 6px; min-height: var(--h-sm); padding: 4px 12px; border: 1px solid var(--border-strong); border-radius: var(--r-pill); background: transparent; color: var(--text-2); font: 600 var(--fs-sm)/1.2 var(--font); cursor: pointer; }
.gr-f:hover { color: var(--text); }
.gr-f[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent-text); border-color: var(--accent-line); }
.gr-f .count { min-width: 20px; height: 18px; padding: 0 6px; font-size: var(--fs-2xs); line-height: 18px; }
.gr-f:focus-visible, .gr-row:focus-visible { outline: none; box-shadow: var(--ring); }
.gr-list { list-style: none; margin: 0; padding: 6px; overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.gr-row { display: flex; align-items: center; gap: var(--sp-3); width: 100%; min-height: 52px; padding: 10px 14px; border: 0; border-radius: var(--r-md); background: none; color: var(--text); font: inherit; text-align: start; cursor: pointer; }
.gr-row:hover { background: var(--surface-3); }
.gr-row[aria-current="true"] { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent-fill); }
[dir="rtl"] .gr-row[aria-current="true"] { box-shadow: inset -3px 0 0 var(--accent-fill); }
.gr-row .av { width: 32px; height: 32px; font-size: 12px; margin: 0; flex: none; }
.gr-row-txt { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1 1 auto; }
.gr-row-txt b { font-weight: 600; font-size: var(--fs-base); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gr-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.gr-chip { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 8px; border-radius: var(--r-pill); font: 600 var(--fs-2xs)/1 var(--font); white-space: nowrap; }
.gr-chip svg { width: 12px; height: 12px; flex: none; }
.gr-chip.in { background: var(--info-soft); color: var(--info); }
.gr-chip.sent { background: var(--success-soft); color: var(--success); }
.gr-chip.late { background: var(--warning-soft); color: var(--warning); }
.gr-chip.miss { background: var(--danger-soft); color: var(--danger); }
.gr-chip.none { background: var(--surface-3); color: var(--muted); }
.gr-none { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 28px 12px; color: var(--muted); font-size: var(--fs-sm); text-align: center; }
.gr-none svg { color: var(--success); }
.gr-main { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.gr-main > .gr-brief, .gr-main > .gr-empty { margin: var(--sp-5); }
.gr-pane { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.gr-head { display: flex; align-items: center; gap: var(--sp-3); padding: 14px var(--sp-5); border-bottom: 1px solid var(--border); }
.gr-head .av { flex: none; }
.gr-back { display: none; }
.gr-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.gr-who b { font-size: var(--fs-md); font-weight: 600; overflow-wrap: anywhere; }
.gr-who small { color: var(--muted); font-size: var(--fs-xs); }
.gr-late { color: var(--warning); font-weight: 600; }
.gr-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: var(--sp-4) var(--sp-5) var(--sp-5); }
.gr-brief { margin-bottom: var(--sp-4); padding: 6px 12px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-2); }
.gr-brief summary { display: flex; align-items: center; min-height: 32px; cursor: pointer; color: var(--text-2); font-weight: 600; font-size: var(--fs-sm); }
.gr-brief .asg-desc { max-width: var(--measure, 68ch); }
.gr-body { margin: 0 0 var(--sp-2); font-size: var(--fs-md); line-height: var(--lh-read); max-width: var(--measure, 68ch); }
.gr-thread { margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid var(--border); }
.gr-thread .fb-compose textarea { min-height: 88px; }
.gr-nav { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding: 10px var(--sp-5); border-top: 1px solid var(--border); }
.gr-pos { color: var(--muted); font-size: var(--fs-xs); }
.gr-empty .empty.inline { justify-content: flex-start; }
.gr-keys { display: inline-flex; align-items: center; gap: 4px; margin-inline-end: auto; color: var(--muted); font-size: var(--fs-xs); }
.gr-keys kbd { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px; border-radius: 5px; border: 1px solid var(--border-strong); background: var(--surface-2); font: 600 var(--fs-2xs)/1 var(--font); }
.fb-sendnext span[aria-hidden] { font-size: 1.1em; line-height: 1; }
@media (max-width: 900px) { .gr-keys { display: none; } .grader { grid-template-columns: 240px minmax(0, 1fr); } }
@media (max-width: 720px) {
  .modal.grader-modal { height: 92dvh; }
  .grader { grid-template-columns: minmax(0, 1fr); }
  .grader[data-view="list"] .gr-main, .grader[data-view="item"] .gr-side { display: none; }
  .gr-side { border-inline-end: 0; background: none; }
  .gr-back { display: inline-flex; grid-column: 1 / -1; justify-self: start; padding-inline: 6px 10px; }
  .gr-head { display: grid; grid-template-columns: 32px minmax(0, 1fr); padding: 8px 12px 10px; gap: 6px 10px; }
  .gr-head > .gr-chips { grid-column: 2; }
  .gr-who b { font-size: var(--fs-base); }
  .grader-modal > header h2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .grader-modal:has(.grader[data-view="item"]) > footer { display: none; }
  .gr-head .av.md { width: 32px; height: 32px; font-size: 12px; }
  .gr-scroll { padding: 12px; }
  .gr-nav { padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0px)); }
  .gr-nav .btn { min-width: 96px; }
  .gr-row { min-height: 56px; }
}
@media (pointer: coarse) { .gr-f { min-height: var(--h-touch); } }

/* ---- Activity bell (R-SYS-5) ---- */
.tb-bell { position: relative; display: grid; place-items: center; flex: none; width: 40px; height: 40px; padding: 0; border: 1px solid transparent; border-radius: var(--r-md); background: none; color: var(--text-2); cursor: pointer; }
.tb-bell:hover, .tb-bell[aria-expanded="true"] { background: var(--surface-2); color: var(--text); }
.tb-bell:focus-visible { outline: none; box-shadow: var(--ring); }
.tb-bell .sh-ic { width: 20px; height: 20px; }
.tb-bell .nav-count { position: absolute; top: 2px; inset-inline-end: 0; min-width: 18px; height: 18px; padding: 0 5px; font-size: var(--fs-2xs); line-height: 18px; box-shadow: 0 0 0 2px var(--bg); }
.bell-pop[hidden] { display: none; }
.bell-scrim { display: none; }
.bell-panel {
  position: fixed; z-index: 62; top: calc(var(--shell-top) + env(safe-area-inset-top, 0px) - 4px); inset-inline-end: clamp(12px, 2vw, 40px);
  width: min(380px, calc(100vw - 24px)); max-height: min(560px, calc(100dvh - var(--shell-top) - 24px)); display: flex; flex-direction: column;
  background: var(--surface-overlay); border: 1px solid var(--border-strong); border-radius: var(--r-lg); box-shadow: var(--shadow-overlay);
  animation: pop var(--dur-2) var(--ease-out); outline: none;
}
.bell-top { display: flex; align-items: center; gap: var(--sp-2); padding: 12px 12px 10px 16px; border-bottom: 1px solid var(--border); }
.bell-top h2 { margin: 0; font: 600 var(--fs-lg)/1.3 var(--font); }
.bell-n { color: var(--muted); font-size: var(--fs-xs); margin-inline-end: auto; }
.bell-body { overflow-y: auto; padding: 6px 8px 10px; }
.bell-sec + .bell-sec { margin-top: 4px; }
.bell-h { margin: 10px 8px 4px; color: var(--muted); font: 600 var(--fs-xs)/1.2 var(--font); }
.bell-list { list-style: none; margin: 0; padding: 0; }
.bell-row { position: relative; display: flex; align-items: center; gap: var(--sp-3); min-height: 52px; padding: 8px 10px 8px 12px; border-radius: var(--r-md); color: var(--text); text-decoration: none; }
.bell-row::before { content: ''; position: absolute; inset-block: 10px; inset-inline-start: 2px; width: 3px; border-radius: 2px; background: var(--accent-fill); }
.bell-row.t-live::before { background: var(--live-fill); }
.bell-row:hover { background: var(--surface-2); text-decoration: none; }
.bell-row:focus-visible { outline: none; box-shadow: var(--ring); }
.bell-ic { display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: var(--r-md); background: var(--surface-3); color: var(--text-2); }
.bell-row.t-accent .bell-ic { background: var(--accent-soft); color: var(--accent-text); }
.bell-row.t-live .bell-ic { background: var(--live-soft); color: var(--live); }
.bell-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.bell-txt b { font-weight: 600; font-size: var(--fs-base); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bell-txt small { color: var(--muted); font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bell-row .count { flex: none; }
.bell-more { padding: 6px 12px; color: var(--muted); font-size: var(--fs-xs); }
.bell-empty { padding: 24px 16px 28px; text-align: center; }
.bell-empty .illus-svg { width: 96px; height: 96px; }
.bell-empty .empty-t { margin: 8px 0 4px; font-weight: 600; }
.bell-empty .sub { margin: 0; color: var(--muted); font-size: var(--fs-sm); }
@media (max-width: 719px) {
  .tb-bell { width: 44px; height: 44px; }
  .bell-scrim { display: block; position: fixed; inset: 0; z-index: 61; background: var(--overlay); animation: fade var(--dur-1) var(--ease-out); }
  .bell-panel { top: auto; bottom: 0; inset-inline: 0; width: 100%; max-height: 80dvh; border-radius: var(--r-xl) var(--r-xl) 0 0; padding-bottom: env(safe-area-inset-bottom, 0px); animation: sheetUp var(--dur-3) var(--ease-out); }
}

/* ---- Contextual Join chip (R-NAV-8) ---- */
.tb-join { display: inline-flex; align-items: center; gap: 2px; flex: 0 1 auto; min-width: 0; }
.tb-join[hidden], .join-band[hidden] { display: none; }
.join-chip { display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; height: 36px; padding: 0 5px 0 14px; border-radius: var(--r-pill); background: var(--live-soft); color: var(--live); font-weight: 700; font-size: var(--fs-sm); text-decoration: none; }
.join-chip:hover { text-decoration: none; background: color-mix(in srgb, var(--live-fill) 22%, transparent); }
.join-chip:focus-visible, .join-x:focus-visible { outline: none; box-shadow: var(--ring); }
.join-chip .dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--live); animation: livepulse 1.6s ease-in-out infinite; }
.jc-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jc-txt b { font-weight: 700; }
.jc-title { font-weight: 600; }
.jc-go { flex: none; display: inline-flex; align-items: center; height: 26px; padding: 0 12px; border-radius: var(--r-pill); background: var(--live-fill); color: var(--on-live); font-weight: 700; }
.join-x { display: grid; place-items: center; flex: none; width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--muted); cursor: pointer; }
.join-x:hover { background: var(--surface-2); color: var(--text); }
.join-x .sh-ic { width: 14px; height: 14px; }
@keyframes livepulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--live) 55%, transparent); } 50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--live) 0%, transparent); } }
@media (prefers-reduced-motion: reduce) { .join-chip .dot { animation: none; } }
.btn.live.tb-meet.is-secondary { background: transparent; color: var(--live); box-shadow: none; border-color: var(--border-strong); }
.join-band { display: none; }
@media (max-width: 1100px) and (min-width: 720px) { .jc-title, .jc-sep { display: none; } }
@media (max-width: 719px) {
  .tb-join { display: none !important; }
  .join-band:not([hidden]) {
    position: sticky; top: calc(var(--shell-top) + env(safe-area-inset-top, 0px)); z-index: 39; display: flex; align-items: center; gap: 4px;
    height: 48px; padding: 4px 8px 4px 12px; background: var(--surface); border-bottom: 1px solid var(--border);
  }
  .join-band .join-chip { flex: 1 1 auto; height: 40px; justify-content: space-between; }
  .join-band .join-x { width: 40px; height: 40px; }
}

/* ---- Covering a class (R-TCH-8) ---- */
.card.class .cover-chip { align-self: flex-start; display: inline-flex; align-items: center; gap: 4px; margin-bottom: var(--sp-2); }
.card.class .cover-chip svg { flex: none; }
.cover-banner { display: flex; align-items: flex-start; gap: var(--sp-4); margin-bottom: var(--sp-4); padding: 14px 16px; border-radius: var(--r-md); border-inline-start: 4px solid var(--warning); background: var(--warning-soft); }
.cover-banner .cb-main { flex: 1 1 auto; min-width: 0; }
.cover-banner h2 { margin: 0; font: 600 var(--fs-md)/1.4 var(--font); color: var(--text); }
.cover-banner .cb-left { margin: 2px 0 8px; color: var(--text-2); font-size: var(--fs-sm); }
.cb-can, .tr-rights { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-sm); color: var(--text-2); }
.cb-can li, .tr-rights li { display: flex; align-items: flex-start; gap: 6px; }
.cb-can svg, .tr-rights svg { flex: none; margin-top: 3px; }
.cb-can .ok svg, .tr-rights .ok svg { color: var(--success); }
.cb-can .no svg, .tr-rights .no svg { color: var(--danger); }
.tr-rights { margin-top: 6px; color: var(--muted); }
@media (max-width: 560px) { .cover-banner { flex-direction: column; } }
.tr-seg { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.tr-opt { position: relative; display: flex; padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: var(--r-md); cursor: pointer; }
.tr-opt input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.tr-opt span { display: flex; flex-direction: column; gap: 2px; }
.tr-opt b { font-size: var(--fs-base); }
.tr-opt small { color: var(--muted); font-size: var(--fs-xs); line-height: 1.4; }
.tr-opt.on, .tr-opt:has(input:checked) { border-color: var(--accent-fill); background: var(--accent-soft); }
.tr-opt:has(input:focus-visible) { box-shadow: var(--ring); }
@media (max-width: 480px) { .tr-seg { grid-template-columns: 1fr; } }
.btn.danger-ghost { color: var(--danger); background: transparent; border-color: transparent; }
.btn.danger-ghost:hover { background: var(--danger-soft); }

/* ---- Class readiness (R-TCH-7) ---- */
.ready-card { margin-bottom: var(--sp-4); padding: var(--sp-4) var(--sp-5); border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface); box-shadow: var(--elev); }
.ready-top { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.ready-top h2 { flex: 1; margin: 0; display: flex; align-items: center; gap: var(--sp-2); font: 600 var(--fs-lg)/1.3 var(--font); }
.ready-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.ready-steps li { display: flex; align-items: center; gap: var(--sp-3); min-height: 48px; padding: 6px 0; border-top: 1px solid var(--border); }
.ready-steps li:first-child { border-top: 0; }
.rs-n { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 50%; background: var(--surface-3); color: var(--text-2); font: 700 var(--fs-sm)/1 var(--font); }
.ready-steps .is-next .rs-n { background: var(--accent-fill); color: var(--on-accent); }
.ready-steps .is-done .rs-n { background: var(--success-soft); color: var(--success); }
.rs-t { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; font-size: var(--fs-base); }
.ready-steps .is-done .rs-t { color: var(--muted); text-decoration: line-through; text-decoration-thickness: 1px; }
.rs-t small { color: var(--muted); font-size: var(--fs-xs); }

/* ---- Student reward on the class page (R-STU-5) ---- */
.cls-rw-row { display: flex; align-items: center; gap: 12px; }
.cls-rw-stk { display: grid; place-items: center; flex: none; width: 56px; height: 56px; border-radius: 50%; font-size: 30px; line-height: 1; color: var(--accent-text); background: radial-gradient(closest-side, var(--accent-soft), transparent); }
.cls-rw-stars { display: inline-flex; gap: 2px; color: var(--muted); }
.cls-rw-stars .ic { width: 20px; height: 20px; }
.cls-rw-stars .ic.on { color: var(--star); }
.cls-myrw .rw-note-sm { -webkit-line-clamp: 3; font-size: var(--fs-md); line-height: 1.5; color: var(--text); }

/* ---- R-TYP-3: spacing and radius tokens on the named components ---- */
.card, .panel, .ann { border-radius: var(--r-lg); }
.card { padding: var(--sp-5); }
.panel > header { padding: var(--sp-4) var(--sp-5); }
.panel .body { padding: var(--sp-5); }
.ann { padding: var(--sp-4) var(--sp-5); }
.grid { gap: var(--sp-5); }
.modal, .auth-card { border-radius: var(--r-xl); }
.btn, .input { border-radius: var(--r-md); }
.btn.sm { border-radius: var(--r-sm); }
@media (max-width: 560px) {
  .card, .panel .body { padding: var(--sp-4); }
  .panel > header { padding: var(--sp-3) var(--sp-4); }
  .ann { padding: var(--sp-3) var(--sp-4); }
  .grid { gap: var(--sp-4); }
}

/* ---- R-TYP-4: a reading measure and a container ceiling ---- */
:root { --measure: 68ch; }
.container { --gutter: clamp(16px, 3vw, 48px); max-width: calc(1440px + 2 * var(--gutter)); padding-inline: var(--gutter); }
body.page-class .container, body.page-mail .container, body.page-chat .container { max-width: none; }
.ann-body, .proto-steps p, .proto-note, .frm-desc, .install-steps { max-width: var(--measure); }
.ann-actions { align-self: flex-start; }

/* ---- R-TYP-5: one card anatomy in grids (header row, 2-line title/desc, pinned footer) ---- */
.grid > .card { display: flex; flex-direction: column; min-width: 0; }
.grid > .card .cls-head h3, .grid > .card > h3 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.grid > .card > .desc { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-size: var(--fs-sm); margin-bottom: var(--sp-3); }
.grid > .card > .meta { margin-top: auto; padding-top: var(--sp-3); border-top: 1px solid var(--border); }
.card h3 .dot-badge { float: none; flex: none; }

/* ---- R-TYP-6: one section-head component ---- */
.section-head { display: flex; align-items: center; gap: var(--sp-3); margin: var(--sp-8) 0 var(--sp-4); }
.section-head:first-child { margin-top: 0; }
.section-head h2 { display: flex; align-items: center; gap: var(--sp-2); margin: 0; font: 600 var(--fs-xl)/1.3 var(--font-display); letter-spacing: -.01em; }
.section-head h2 > svg { width: 20px; height: 20px; color: var(--muted); flex: none; }
.section-head .actions { margin-inline-start: auto; display: flex; gap: var(--sp-2); }

/* ---- Brand mark + wordmark (R-COL-8) ---- */
.sb-mark.is-brand { width: 36px; height: 40px; background: none; box-shadow: none; color: var(--text); border-radius: 0; }
.sb-mark.is-brand svg.brand-mark { width: auto; height: 40px; fill: none; stroke: none; }
.sb-mark.sm.is-brand { width: 30px; height: 36px; }
.sb-mark.sm.is-brand svg.brand-mark { height: 34px; }
.sb-word .bw-l { color: var(--brand-orange); }
.brand-word { display: block; height: 64px; width: auto; color: var(--text); overflow: visible; }
.auth-card .logo .brand-word { height: 72px; margin-bottom: 14px; }
.card .meta .m.seat-transition { display: inline; } .card .meta .m.seat-transition .dot { display: inline-block; vertical-align: middle; margin-inline-end: 5px; }

/* ---- Toasts never cover a composer (phone fix, phase 3 batch 3) ----
   While typing on a phone (a text field has focus: shell.js sets body.kb-open)
   or while a bottom sheet / dialog is open, the composer, the keyboard and the
   sheet's own buttons own the bottom of the screen, so toasts drop in from the
   top instead (under the visible top edge, which kb.js tracks as --vv-top). */
@media (max-width: 719px) {
  body.kb-open #toasts, body.has-shell.kb-open #toasts, body:has(.modal-backdrop:not(.closing)) #toasts, body.pdfv-open #toasts {
    top: calc(var(--vv-top, 0px) + env(safe-area-inset-top, 0px) + 8px); bottom: auto;
  }
  body.kb-open #toasts .toast, body:has(.modal-backdrop:not(.closing)) #toasts .toast { animation-name: toastDown; }
}
@keyframes toastDown { from { opacity: 0; transform: translateY(-12px); } }
/* Trash on phones: the stacked rows' sub-lines must not keep the wide-table minimum (5px overflow fix). */
@media (max-width: 640px) { #trashBody table.tbl.stack td small.sub, #transBody table.tbl.stack td { min-width: 0; } }

/* The toast region never blocks clicks itself; only the toasts do. */
#toasts { pointer-events: none; }
#toasts > * { pointer-events: auto; }
/* 11px type floor (Lantern rule 5): the tiny avatars and the Today timeline labels. */
.av.xs { font-size: 11px; letter-spacing: -.02em; }
.tt-slot { font-size: 11px; }
/* 44px on a finger (final review): the password eye and the search clear. */
@media (pointer: coarse) { .pw-toggle, .search-clear { width: 44px; height: 44px; } }

/* Sessions (2026-10-11): the prepared lesson under the student's Next class. */
.td-lesson { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--r-md); border: 1px solid var(--accent-line);
  background: var(--accent-soft); color: var(--text); text-decoration: none; min-width: 0; }
.td-lesson:hover { border-color: var(--accent-fill); }
.td-lesson:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.td-lesson > .td-ic { flex: none; width: 20px; height: 20px; color: var(--accent-text); }
.td-lesson > .td-ic:last-child { width: 16px; height: 16px; color: var(--text-2); margin-inline-start: auto; }
.td-lesson > span { min-width: 0; display: grid; gap: 2px; }
.td-lesson b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.td-lesson small { font-size: var(--fs-xs); color: var(--text-2); }
@container tdnext (min-width: 560px) { .td-next-body > .td-lesson { grid-column: 1 / -1; } }
