/* ═══════════════════════════════════════════════════════════════════
   Ata Ekta — ShikhonBD LMS design tokens + component layer
   Drop-in for apps/pwa/public/app.css. Light only. No dark mode.
   Every value in the design files comes from this sheet.
   ═══════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Hind+Siliguri:wght@300;400;500;600;700&family=Anek+Bangla:wdth,wght@100,400;100,500;100,600;100,700&display=swap');

:root {
  /* ── surfaces ───────────────────────────────────────────── */
  --bg:        #f3f2f2;   /* page ground */
  --surface:   #ffffff;   /* cards, tables, sheets */
  --inset:     #eae9e9;   /* table headers, disabled fields, wells */

  /* ── ink ────────────────────────────────────────────────── */
  --ink:       #201e1d;   /* all primary text, 2px rules */
  --ink-2:     #605d5d;   /* secondary text */
  --ink-3:     #7d7979;   /* labels, meta, placeholders */

  /* ── lines ──────────────────────────────────────────────── */
  --line:      #d7d3d3;   /* 1px card + row edges */
  --rule:      #201e1d;   /* 2px section dividers */

  /* ── the one accent ─────────────────────────────────────── */
  --accent:      #ec3013; /* primary button, active nav. Nowhere else. */
  --accent-ink:  #ae1800; /* accent text on light (passes 4.5:1) */
  --accent-tint: #ffe0d9; /* accent fills */

  /* ── semantic — meaning only, never decoration ──────────── */
  --ok:        #1c7f4f;  --ok-tint:   #e4f1ea;  /* present, paid, published */
  --warn:      #9a6207;  --warn-tint: #f7ecd8;  /* late, pending, review */
  --danger:    #ae1800;  --danger-tint:#ffe0d9; /* absent, overdue, failed */
  --info:      #1d5fa8;  --info-tint: #e3edf9;  /* leave, notices, neutral */

  /* ── neutral ramp ───────────────────────────────────────── */
  --neutral-100:#f8f4f4; --neutral-200:#eae7e7; --neutral-300:#d7d3d3;
  --neutral-400:#bab6b6; --neutral-500:#9b9797; --neutral-600:#7d7979;
  --neutral-700:#605d5d; --neutral-800:#444141; --neutral-900:#2d2b2b;

  /* ── accent ramp ────────────────────────────────────────── */
  --accent-100:#fff2ef; --accent-200:#ffe0d9; --accent-300:#ffc4b8;
  --accent-400:#ff9783; --accent-500:#ff563c; --accent-600:#dd2b0f;
  --accent-700:#ae1800; --accent-800:#7c1405; --accent-900:#4d170e;

  /* ── type ───────────────────────────────────────────────── */
  /* Bangla + all UI text */
  --font-bn:  "Hind Siliguri", system-ui, sans-serif;
  /* EVERY number — Bangla ০-৯ and Latin 0-9. Always with .n */
  --font-num: "Anek Bangla", "Archivo", system-ui, sans-serif;

  --text-display: 40px; --lh-display: 1.1;  --w-display: 700;
  --text-h1:      28px; --lh-h1:      1.2;  --w-h1:      700;
  --text-h2:      22px; --lh-h2:      1.3;  --w-h2:      700;
  --text-h3:      17px; --lh-h3:      1.4;  --w-h3:      600;
  --text-body:    15px; --lh-body:    1.6;  --w-body:    400;
  --text-small:   13px; --lh-small:   1.5;  --w-small:   400;
  --text-label:   11px; --lh-label:   1.4;  --w-label:   700;

  /* ── space ──────────────────────────────────────────────── */
  --space-1:4px; --space-2:8px; --space-3:12px;
  --space-4:16px; --space-6:24px; --space-8:32px;

  /* ── geometry ───────────────────────────────────────────── */
  --r-xs:   4px;          /* dots, tiny marks */
  --r-sm:   8px;          /* chips, small buttons, inputs */
  --r-md:  12px;          /* buttons, cards, table shells */
  --r-lg:  18px;          /* sheets, dialogs, outer frames */
  --r-pill: 999px;        /* avatars, counters, status chips */
  --radius: var(--r-md);  /* the default when nothing else applies */
  --tap-min: 44px;        /* minimum touch target */
  --sidebar-w: 256px;
  --sidebar-rail-w: 48px;
  --content-max: 1200px;
  --desktop-min: 1024px;

  /* ── elevation — floating things only ───────────────────── */
  --shadow-sm: 0 1px 2px  rgba(45,43,43,.14);   /* dropdown */
  --shadow-md: 0 3px 10px rgba(45,43,43,.16);   /* sheet */
  --shadow-lg: 0 12px 32px rgba(45,43,43,.22);  /* dialog */

  /* ── motion ─────────────────────────────────────────────── */
  --ease:        cubic-bezier(.22,.61,.36,1);   /* the default — decelerating */
  --ease-spring: cubic-bezier(.34,1.26,.64,1);  /* small overshoot, for entrances */
  --dur-1: 120ms;   /* press, hover tint */
  --dur-2: 180ms;   /* most state changes */
  --dur-3: 280ms;   /* sheets, panels, page pieces */
}

/* ═══ motion — every interactive thing, one rule ════════════ */
a, button, input, select, textarea, label,
.btn-primary, .btn-secondary, .btn-ghost, .btn-danger, .btn-success,
.ui-icon-btn, .ui-badge, .ui-status, .status-chip, .ui-tab, .ui-filter-chip,
.ui-list-hit, .ui-child-opt, .ui-child-row, .ui-page-btn, .prac-option,
.dnav, .shell-tab, .shell-icon-btn, .card, .shell-menu-item {
  transition:
    background-color var(--dur-2) var(--ease),
    border-color     var(--dur-2) var(--ease),
    color            var(--dur-2) var(--ease),
    box-shadow       var(--dur-2) var(--ease),
    transform        var(--dur-1) var(--ease),
    opacity          var(--dur-2) var(--ease);
}

/* the press — everything clickable gives a little */
.btn-primary:active:not(:disabled),
.btn-secondary:active:not(:disabled),
.btn-ghost:active:not(:disabled),
.btn-danger:active:not(:disabled),
.btn-success:active:not(:disabled),
.ui-icon-btn:active,
.ui-page-btn:active,
.shell-icon-btn:active,
.shell-menu-item:active { transform: scale(.97); }

/* rows sink rather than shrink — a 56px row scaling looks broken */
.ui-list-hit:active:not(.is-static),
.ui-child-row:active,
.prac-option:active,
.dnav:active { background-color: var(--neutral-100); }

@keyframes rise     { from { opacity:0; transform: translateY(8px); }  to { opacity:1; transform:none; } }
@keyframes fade     { from { opacity:0; } to { opacity:1; } }
@keyframes sheet-up { from { opacity:0; transform: translateY(16px) scale(.99); } to { opacity:1; transform:none; } }
@keyframes shimmer  { from { background-position:-200% 0; } to { background-position:200% 0; } }

.shell-view > *   { animation: rise var(--dur-3) var(--ease) both; }
.shell-menu       { animation: sheet-up var(--dur-2) var(--ease-spring) both; }
.sheet, .dialog   { animation: sheet-up var(--dur-3) var(--ease-spring) both; }

/* The loading skeleton is .skel / .skel-bar / .skel-avatar — see the
   feedback.ts block in the component layer below. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .btn-primary:active:not(:disabled), .btn-secondary:active:not(:disabled) { transform: none; }
}

/* ═══ base ══════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-bn);
  font-size: var(--text-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

h1,h2,h3,h4 { margin: 0; font-weight: 700; letter-spacing: -.01em; }
h1 { font-size: var(--text-h1); line-height: var(--lh-h1); }
h2 { font-size: var(--text-h2); line-height: var(--lh-h2); }
h3 { font-size: var(--text-h3); line-height: var(--lh-h3); font-weight: 600; }
p  { margin: 0; text-wrap: pretty; }

a          { color: var(--accent-ink); text-decoration: none; }
a:hover    { color: var(--accent); }
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
::selection { background: var(--accent-tint); color: var(--ink); }

/* EVERY number gets this class. Bangla numerals stay aligned in columns. */
.n {
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* label / eyebrow */
.label {
  font-size: var(--text-label);
  line-height: var(--lh-label);
  font-weight: var(--w-label);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.hr        { height: 2px; background: var(--rule); border: 0; margin: 0; }
.hr-light  { height: 1px; background: var(--line); border: 0; margin: 0; }

/* ═══ buttons ═══════════════════════════════════════════════ */
/* Vocabulary from ui/button.ts: ButtonVariant = primary | secondary | ghost
   | danger | success, emitted as .btn-<variant>. `ui-btn` is a MARKER, not a
   look — button() adds it to reset the width:100% that .btn-primary and
   .btn-success have carried since the app was born. Markup that writes
   className='btn-primary' directly (structure-forms, practice-view) has no
   ui-btn and therefore stays full width. Both paths are preserved here. */

.btn-primary, .btn-secondary, .btn-ghost, .btn-danger, .btn-success {
  font-family: var(--font-bn);
  font-size: var(--text-body);
  font-weight: 600;
  min-height: var(--tap-min);
  padding: 0 18px;
  border: none;
  border-radius: var(--r-md);
  cursor: pointer;
  text-align: left;              /* flush left, never centred */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.btn-primary, .btn-success { width: 100%; }
.ui-btn { width: auto; }         /* the reset — see note above */

.btn-primary:disabled, .btn-secondary:disabled, .btn-ghost:disabled,
.btn-danger:disabled, .btn-success:disabled { opacity: .45; cursor: default; }

.btn-primary   { background: var(--accent); color: #fff; }
.btn-primary:hover:not(:disabled)  { background: var(--accent-600); }
.btn-primary:active:not(:disabled) { background: var(--accent-700); }

/* The most common variant in the codebase — every cancel, every "not this
   one" in a segmented row (staff-attendance-view.ts:319). */
.btn-secondary { background: transparent; color: var(--ink); border: 1px solid var(--ink); }
.btn-secondary:hover:not(:disabled) { background: var(--inset); }

.btn-ghost     { background: transparent; color: var(--accent-ink); padding: 0 14px; }
.btn-ghost:hover:not(:disabled)     { background: var(--accent-tint); }

.btn-danger    { background: transparent; color: var(--danger); border: 2px solid var(--danger); }
.btn-danger:hover:not(:disabled)    { background: var(--danger-tint); }

.btn-success   { background: var(--ok); color: #fff; }
.btn-success:hover:not(:disabled)   { filter: brightness(.94); }

.btn-label   { display: block; }
.btn-spinner {
  width: 14px; height: 14px; flex: none;
  border: 2px solid color-mix(in srgb, currentColor 35%, transparent);
  border-top-color: currentColor; border-radius: var(--r-pill);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.btn-sm    { min-height: 36px; padding: 0 13px; font-size: var(--text-small); border-radius: var(--r-sm); }
.btn-block { width: 100%; justify-content: space-between; }

/* iconButton — ui-icon-btn + is-danger (ui/button.ts:187) */
.ui-icon-btn {
  width: var(--tap-min); height: var(--tap-min);
  display: grid; place-items: center;
  padding: 0; border-radius: var(--r-sm);
  border: 1px solid var(--line); background: transparent; color: var(--ink);
  cursor: pointer;
}
.ui-icon-btn:hover { border-color: var(--ink); background: var(--inset); }
.ui-icon-btn.is-danger { color: var(--danger); }
.ui-icon-btn.is-danger:hover { background: var(--danger-tint); border-color: var(--danger); }

/* buttonRow — ui/button.ts:206 */
.ui-button-row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
/* structure-forms.ts:269 writes its own row with the same job */
.action-row { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }

/* ═══════════════════════════════════════════════════════════
   COMPONENT LAYER
   Every selector below is a class name read out of src/ui/*.ts.
   None is invented. If you rename one in a view, rename it here.
   ═══════════════════════════════════════════════════════════ */

/* ── page-header.ts ─────────────────────────────────────── */
.page-header { padding-bottom: var(--space-3); border-bottom: 2px solid var(--rule); margin-bottom: var(--space-6); }
.page-header-main { display: flex; align-items: flex-start; gap: var(--space-4); flex-wrap: wrap; }
.page-header-text { flex: 1; min-width: 200px; }
.page-title-row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
.page-header h1 { font-size: var(--text-h1); line-height: var(--lh-h1); font-weight: 700; }
.page-sub { margin: 4px 0 0; font-size: var(--text-small); color: var(--ink-2); }
.page-header-actions { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
/* guardian-panel.ts:221 */
.page-header-row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }

.ui-crumb { margin-bottom: var(--space-2); }
.ui-crumb-list { display: flex; align-items: center; gap: 7px; list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.ui-crumb-item { display: flex; align-items: center; gap: 7px; }
.ui-crumb-sep { color: var(--ink-3); font-size: var(--text-small); }
.ui-crumb-link { background: none; border: none; padding: 0; font-family: var(--font-bn);
                 font-size: var(--text-small); color: var(--ink-3); cursor: pointer; }
.ui-crumb-link:hover { color: var(--accent-ink); }
.ui-crumb-current { font-size: var(--text-small); font-weight: 600; color: var(--ink); }

.ui-back { display: inline-flex; align-items: center; gap: 6px; background: none; border: none;
           padding: 0; font-family: var(--font-bn); font-size: var(--text-small); font-weight: 600;
           color: var(--accent-ink); cursor: pointer; min-height: var(--tap-min); }

.ui-section-head { display: flex; align-items: center; gap: var(--space-3);
                   padding-bottom: 6px; border-bottom: 1px solid var(--line); margin-bottom: var(--space-3); }
.ui-section-title { margin: 0; font-size: var(--text-h3); font-weight: 700; flex: 1; min-width: 0; }
.ui-section-action { flex: none; }

/* ── badge.ts — BadgeTone = success | neutral | info | warn | danger ── */
.ui-badge, .ui-status, .status-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: var(--r-pill);
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
  border: 1px solid currentColor;
}
.ui-badge[data-tone="success"], .ui-status[data-tone="success"], .status-chip.success { background: var(--ok-tint);     color: var(--ok); }
.ui-badge[data-tone="warn"],    .ui-status[data-tone="warn"],    .status-chip.warning { background: var(--warn-tint);   color: var(--warn); }
.ui-badge[data-tone="danger"],  .ui-status[data-tone="danger"],  .status-chip.danger  { background: var(--danger-tint); color: var(--danger); }
.ui-badge[data-tone="info"],    .ui-status[data-tone="info"],    .status-chip.info    { background: var(--info-tint);   color: var(--info); }
.ui-badge[data-tone="neutral"], .ui-status[data-tone="neutral"], .status-chip.pending { background: var(--inset);       color: var(--ink-2); }
.ui-count {
  font-family: var(--font-num); font-variant-numeric: tabular-nums;
  background: var(--accent); color: #fff; font-size: 10.5px; font-weight: 700;
  padding: 1px 6px; border-radius: var(--r-pill);
}

/* ── card.ts ────────────────────────────────────────────── */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
.card:hover { box-shadow: var(--shadow-sm); }
.ui-card-head { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-4) 18px; }
.ui-card-glyph { flex: none; width: 34px; height: 34px; display: grid; place-items: center;
                 border-radius: var(--r-sm); background: var(--inset); color: var(--ink-2); }
.ui-card-glyph[data-tone="primary"] { background: var(--accent-tint); color: var(--accent-ink); }
.ui-card-glyph[data-tone="success"] { background: var(--ok-tint);     color: var(--ok); }
.ui-card-glyph[data-tone="warn"]    { background: var(--warn-tint);   color: var(--warn); }
.ui-card-glyph[data-tone="danger"]  { background: var(--danger-tint); color: var(--danger); }
.ui-card-titles { flex: 1; min-width: 0; }
.ui-card-title { margin: 0; font-size: var(--text-h3); font-weight: 600; }
.ui-card-sub { margin: 3px 0 0; font-size: 12.5px; color: var(--ink-3); }
.ui-card-action { flex: none; margin-left: auto; }
.ui-card-chevron { flex: none; color: var(--ink-3); }
.ui-card-body { padding: 0 18px var(--space-4); }
.ui-card-interactive { cursor: pointer; text-align: left; font-family: var(--font-bn); }

.ui-stat-row { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0,1fr);
               border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; background: var(--surface); }
.ui-stat { padding: 14px 16px; border-right: 1px solid var(--line); display: flex; gap: var(--space-3);
           background: var(--surface); border-top: none; border-bottom: none; border-left: none; }
.ui-stat:last-child { border-right: none; }
.ui-stat-glyph { flex: none; color: var(--ink-3); }
.ui-stat-glyph[data-tone="primary"] { color: var(--accent-ink); }
.ui-stat-glyph[data-tone="success"] { color: var(--ok); }
.ui-stat-glyph[data-tone="warn"]    { color: var(--warn); }
.ui-stat-glyph[data-tone="danger"]  { color: var(--danger); }
.ui-stat-text { min-width: 0; }
.ui-stat-label { display: block; font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
                 color: var(--ink-3); font-weight: 700; margin-bottom: 5px; }
.ui-stat-value { display: block; font-family: var(--font-num); font-variant-numeric: tabular-nums;
                 font-size: 26px; font-weight: 600; line-height: 1; }
.ui-stat-note { display: block; font-size: 11.5px; color: var(--ink-3); margin-top: 4px; }

/* ── table.ts ───────────────────────────────────────────── */
.ui-data { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ui-table-scroll { overflow-x: auto; }
.ui-table { width: 100%; border-collapse: collapse; }
.ui-table th {
  text-align: left; padding: 9px 12px;
  font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-2);
  background: var(--inset); border-bottom: 2px solid var(--rule); white-space: nowrap;
}
.ui-table td { padding: 10px 12px; font-size: 14px; border-bottom: 1px solid var(--line); }
.ui-table tbody tr:hover { background: var(--neutral-100); }
.ui-table-action { width: 44px; text-align: right; }
.ui-row-open { background: none; border: none; color: var(--ink-3); cursor: pointer; padding: 4px; }

.ui-list { list-style: none; margin: 0; padding: 0; background: var(--surface);
           border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ui-list-item { border-bottom: 1px solid var(--line); }
.ui-list-item:last-child { border-bottom: none; }
.ui-list-hit { display: flex; align-items: center; gap: var(--space-3); width: 100%;
               min-height: 56px; padding: 8px 14px; background: none; border: none;
               font-family: var(--font-bn); text-align: left; cursor: pointer; }
.ui-list-hit.is-static { cursor: default; }
.ui-list-hit:hover:not(.is-static) { background: var(--neutral-100); }
.ui-list-glyph { flex: none; color: var(--ink-2); }
.ui-list-main { flex: 1; min-width: 0; }
.ui-list-title { display: block; font-size: 15px; font-weight: 600; }
.ui-list-sub { display: block; font-size: 12.5px; color: var(--ink-2); }
.ui-list-meta { display: block; font-size: 12px; color: var(--ink-3); margin-top: 1px; }
.ui-list-cell { display: inline; }
.ui-list-dot { margin: 0 5px; color: var(--ink-3); }
.ui-list-status { flex: none; }
.ui-list-chevron { flex: none; color: var(--ink-3); }

.ui-pagination { display: flex; align-items: center; gap: var(--space-2); padding: 11px 14px;
                 border-top: 2px solid var(--rule); background: var(--surface); flex-wrap: wrap; }
.ui-page-btn { font-family: var(--font-bn); font-size: var(--text-small); font-weight: 600;
               min-height: 36px; padding: 0 13px; border-radius: var(--r-sm);
               background: transparent; color: var(--ink); border: 1px solid var(--ink); cursor: pointer; }
.ui-page-btn:disabled { opacity: .45; cursor: default; }
.ui-page-pos { flex: 1; font-family: var(--font-num); font-variant-numeric: tabular-nums;
               font-size: 12.5px; color: var(--ink-2); }

.ui-timeline { list-style: none; margin: 0; padding: 0; }
.ui-timeline-item { display: flex; gap: var(--space-3); }
.ui-timeline-mark { flex: none; display: flex; flex-direction: column; align-items: center; }
.ui-timeline-mark::before { content: ''; width: 9px; height: 9px; margin-top: 5px;
                            border-radius: var(--r-pill); background: var(--ink-3); }
.ui-timeline-mark::after { content: ''; flex: 1; width: 2px; background: var(--line); min-height: 20px; }
.ui-timeline-item:last-child .ui-timeline-mark::after { display: none; }
.ui-timeline-item[data-tone="success"] .ui-timeline-mark::before { background: var(--ok); }
.ui-timeline-item[data-tone="warn"]    .ui-timeline-mark::before { background: var(--warn); }
.ui-timeline-item[data-tone="danger"]  .ui-timeline-mark::before { background: var(--danger); }
.ui-timeline-body { flex: 1; padding-bottom: var(--space-3); }
.ui-timeline-when { margin: 0; font-family: var(--font-num); font-variant-numeric: tabular-nums;
                    font-size: 11.5px; font-weight: 700; color: var(--ink-3); }
.ui-timeline-title { margin: 2px 0 0; font-size: 13.5px; line-height: 1.5; }
.ui-timeline-detail { margin: 2px 0 0; font-size: 12px; color: var(--ink-2); line-height: 1.5; }

/* ── field.ts ───────────────────────────────────────────── */
.ui-field { display: block; margin-bottom: var(--space-4); }
.ui-field-label { display: block; font-size: var(--text-small); font-weight: 600; margin-bottom: 6px; }
.ui-req { color: var(--danger); margin-left: 2px; }
.ui-field-control { display: flex; align-items: center; gap: var(--space-2); }
.ui-field-help { font-size: 12px; color: var(--ink-3); margin-top: 6px; }
.ui-field-error { font-size: 12px; font-weight: 600; color: var(--danger); margin-top: 6px; }
.ui-input, .ui-select, .field-input {
  width: 100%; font-family: var(--font-bn); font-size: var(--text-body);
  min-height: var(--tap-min); padding: 0 12px;
  border: 1px solid var(--ink-3); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink);
}
textarea.ui-input { padding: 11px 12px; line-height: 1.6; resize: vertical; min-height: 88px; }
.ui-input:focus, .ui-select:focus, .field-input:focus { border: 2px solid var(--accent); outline: none; padding: 0 11px; }
textarea.ui-input:focus { padding: 10px 11px; }
.ui-input:disabled { background: var(--inset); color: var(--ink-3); }
.ui-input.is-error, .ui-field.is-error .ui-input { border: 2px solid var(--danger); background: var(--danger-tint); }
.ui-input.is-num { font-family: var(--font-num); font-variant-numeric: tabular-nums; }

.ui-search { display: block; }
.ui-search-box { display: flex; align-items: center; gap: var(--space-2); }
.ui-search-input { flex: 1; }
.ui-search-clear, .ui-search-submit {
  flex: none; width: var(--tap-min); height: var(--tap-min);
  display: grid; place-items: center; border-radius: var(--r-sm);
  background: transparent; border: 1px solid var(--line); color: var(--ink); cursor: pointer;
}
.ui-search-note { margin: 6px 0 0; font-size: 12px; color: var(--ink-3); }

/* ── upload.ts ──────────────────────────────────────────── */
.ui-upload { display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start; }
.ui-upload-trigger { display: inline-flex; }   /* also carries .btn-secondary */
.ui-upload-chosen { font-size: 12.5px; color: var(--ink-2); font-family: var(--font-num); font-variant-numeric: tabular-nums; }

/* ── overlay.ts — kind = auto | modal | drawer | sheet ──── */
.ui-scrim {
  position: fixed; inset: 0; z-index: 50;
  background: color-mix(in srgb, var(--ink) 22%, transparent);
  display: flex; animation: fade var(--dur-2) var(--ease) both;
}
.ui-scrim[data-kind="modal"]  { align-items: center;     justify-content: center; padding: var(--space-6); }
.ui-scrim[data-kind="drawer"] { align-items: stretch;    justify-content: flex-end; }
.ui-scrim[data-kind="sheet"]  { align-items: flex-end;   justify-content: stretch; }
.ui-scrim[data-kind="auto"]   { align-items: flex-end;   justify-content: stretch; }
@media (min-width: 1024px) { .ui-scrim[data-kind="auto"] { align-items: center; justify-content: center; padding: var(--space-6); } }

.ui-dialog {
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow-lg); display: flex; flex-direction: column;
  max-height: 90dvh; width: 100%; max-width: 460px;
  border-radius: var(--r-lg); overflow: hidden;
  animation: sheet-up var(--dur-3) var(--ease-spring) both;
}
.ui-scrim[data-kind="drawer"] .ui-dialog { max-width: 420px; height: 100dvh; max-height: none; border-radius: 0; }
.ui-scrim[data-kind="sheet"] .ui-dialog,
.ui-scrim[data-kind="auto"]  .ui-dialog { max-width: none; border-radius: var(--r-lg) var(--r-lg) 0 0; }
@media (min-width: 1024px) { .ui-scrim[data-kind="auto"] .ui-dialog { max-width: 460px; border-radius: var(--r-lg); } }

.ui-dialog-head { display: flex; align-items: center; gap: var(--space-3);
                  padding: var(--space-4) 18px; border-bottom: 2px solid var(--rule); }
.ui-dialog-title { margin: 0; flex: 1; min-width: 0; font-size: var(--text-h3); font-weight: 700; }
.ui-dialog-close { flex: none; width: var(--tap-min); height: var(--tap-min); display: grid; place-items: center;
                   background: none; border: none; color: var(--ink-3); cursor: pointer; border-radius: var(--r-sm); }
.ui-dialog-close:hover { background: var(--inset); color: var(--ink); }
.ui-dialog-body { flex: 1; overflow-y: auto; padding: var(--space-4) 18px; }
.ui-dialog-foot { display: flex; gap: var(--space-2); flex-wrap: wrap;
                  padding: var(--space-3) 18px var(--space-4); border-top: 1px solid var(--line); }
.ui-dialog-text { margin: 0; font-size: var(--text-body); line-height: 1.65; color: var(--ink-2); }

/* ── feedback.ts ────────────────────────────────────────── */
.ui-toast-host { position: fixed; left: var(--space-3); right: var(--space-3); bottom: 78px;
                 z-index: 60; display: flex; flex-direction: column; gap: var(--space-2); pointer-events: none; }
@media (min-width: 1024px) { .ui-toast-host { left: auto; right: var(--space-6); bottom: var(--space-6); max-width: 380px; } }
.ui-toast { display: flex; align-items: center; gap: var(--space-3);
            background: var(--ink); color: #fff; padding: 12px 14px;
            border-radius: var(--r-md); box-shadow: var(--shadow-lg); pointer-events: auto;
            animation: sheet-up var(--dur-2) var(--ease-spring) both; }
.ui-toast[data-tone="success"] { border-left: 4px solid var(--ok); }
.ui-toast[data-tone="error"]   { border-left: 4px solid var(--accent-400); }
.ui-toast[data-tone="info"]    { border-left: 4px solid var(--info); }
.ui-toast-text { flex: 1; min-width: 0; font-size: 13.5px; font-weight: 600; }
.ui-toast-action { flex: none; background: none; border: 1px solid currentColor; color: var(--accent-400);
                   font-family: var(--font-bn); font-size: 12.5px; font-weight: 700;
                   min-height: 34px; padding: 0 11px; border-radius: var(--r-sm); cursor: pointer; }
.ui-toast-close { flex: none; background: none; border: none; color: #fff; opacity: .7; cursor: pointer; padding: 4px; }

.ui-inline-loader { display: inline-flex; align-items: center; gap: var(--space-2); }
.ui-spinner { width: 15px; height: 15px; border: 2px solid var(--line); border-top-color: var(--accent);
              border-radius: var(--r-pill); animation: spin .7s linear infinite; }

.ui-progress { display: block; }
.ui-progress-label { margin: 0 0 5px; font-size: 12.5px; color: var(--ink-2); }
.ui-progress-track { height: 8px; background: var(--inset); border-radius: var(--r-pill); overflow: hidden; }
.ui-progress-fill { display: block; height: 100%; background: var(--accent); transition: width var(--dur-3) var(--ease); }

.is-skeleton { pointer-events: none; }
.ui-list-skeleton { display: flex; flex-direction: column; gap: var(--space-2); }
.ui-skel-row { display: flex; align-items: center; gap: var(--space-2); }
.ui-skel-lines { flex: 1; display: flex; flex-direction: column; gap: 5px; }
.skel { display: block; border-radius: var(--r-sm);
        background: linear-gradient(90deg, var(--neutral-200) 25%, var(--neutral-100) 50%, var(--neutral-200) 75%);
        background-size: 200% 100%; animation: shimmer 1.4s linear infinite; }
.skel-avatar { width: 30px; height: 30px; flex: none; border-radius: var(--r-pill); }
.skel-bar { height: 9px; width: 70%; }
.skel-bar.is-short { height: 7px; width: 45%; }

.ui-state { padding: var(--space-6) 18px; text-align: left;
            border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
.ui-state-title { margin: 0 0 5px; font-size: var(--text-h3); font-weight: 700; }
.ui-state-detail { margin: 0; font-size: var(--text-small); color: var(--ink-2); line-height: 1.6; }
.ui-state-denied { background: var(--inset); }
.ui-state-denied .ui-state-title { color: var(--ink-2); }

/* ── attendance-screen.ts status strip ──────────────────── */
.att-status { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4);
              padding: 10px 14px; background: var(--surface); border-bottom: 1px solid var(--line);
              font-family: var(--font-num); font-variant-numeric: tabular-nums;
              font-size: 12.5px; color: var(--ink-2); }
.att-offline-note { margin: 0; width: 100%; color: var(--warn); font-weight: 600; }
.att-sync-line { margin: 0; width: 100%; display: flex; align-items: center; gap: var(--space-2); color: var(--ink-2); }

/* ═══ shell — one DOM, CSS decides ══════════════════════════ */
/* Class names below are lifted verbatim from src/shell.ts. One topbar serves
   both widths: it carries the institution plate on mobile and the breadcrumb
   on desktop, and each hides the other half by media query. */

.shell { min-height: 100dvh; display: flex; background: var(--bg); }
.shell-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.shell-view { flex: 1; padding: var(--space-6) 20px 88px; }
.shell-view > * { max-width: var(--content-max); }
.shell-view:focus { outline: none; }

.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 8px; top: 8px; z-index: 100; background: var(--ink); color: #fff; padding: 10px 14px; }

/* ── topbar ─────────────────────────────────────────────── */
.shell-topbar {
  display: flex; align-items: center; gap: 12px;
  padding: 0 14px; min-height: 56px;
  background: var(--surface); border-bottom: 2px solid var(--rule);
  position: sticky; top: 0; z-index: 20;
}

/* the institution plate — mobile only (shell.ts hides it when unbranded) */
.shell-org { display: flex; align-items: center; gap: 10px; min-width: 0; }
.shell-org-mobile { flex: 1; min-width: 0; }
.shell-org-mark {
  width: 30px; height: 30px; flex: none;
  background: var(--accent); color: #fff;
  display: grid; place-items: center;
  font-size: 14px; font-weight: 700;
  border-radius: var(--r-pill);
}
.shell-org-logo { width: 30px; height: 30px; flex: none; object-fit: contain; border-radius: var(--r-pill); }
.shell-org-name {
  flex: 1; min-width: 0; font-size: 14px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* breadcrumb — desktop only, two crumbs maximum */
.shell-crumb { display: none; align-items: center; gap: 8px; min-width: 0; }
.shell-crumb-part { font-size: 13px; color: var(--ink-3); white-space: nowrap; }
.shell-crumb-part:last-child { font-size: 15px; font-weight: 600; color: var(--ink); }
.shell-crumb-sep { color: var(--ink-3); font-size: 13px; }

.shell-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: none; }

.shell-icon-btn {
  width: var(--tap-min); height: var(--tap-min);
  display: grid; place-items: center;
  background: transparent; border: 1px solid transparent;
  color: var(--ink); cursor: pointer; position: relative;
  border-radius: var(--r-sm);
}
.shell-icon-btn:hover { background: var(--inset); border-color: var(--line); }

.shell-bell-glyph { font-size: 19px; display: grid; }
.shell-bell-badge {
  position: absolute; top: 5px; right: 5px;
  background: var(--accent); color: #fff;
  font-family: var(--font-num); font-variant-numeric: tabular-nums;
  font-size: 10px; font-weight: 700;
  min-width: 16px; padding: 0 4px; text-align: center; line-height: 16px;
  border-radius: var(--r-pill);
}
.shell-bell-badge[hidden] { display: none; }

/* ── demo bar — its own strip, never a chip among the controls ── */
.shell-demobar {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 14px; font-size: 13px;
  background: var(--warn-tint); border-bottom: 1px solid var(--warn); color: var(--ink);
}
.shell-demo-chip {
  flex: none; padding: 3px 9px; border-radius: var(--r-pill);
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  background: var(--warn); color: #fff;
}
.shell-demo-note { flex: 1; min-width: 0; color: var(--ink-2); }
.shell-role {
  font-family: var(--font-bn); font-size: 13px; border-radius: var(--r-sm);
  min-height: 34px; padding: 0 9px;
  border: 1px solid var(--ink-3); background: var(--surface); color: var(--ink);
}

/* ── offline banner ─────────────────────────────────────── */
.offline-banner {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 14px; font-size: 13px;
  background: var(--warn-tint); border-bottom: 1px solid var(--warn); color: var(--ink);
}
.offline-icon { flex: none; font-size: 15px; color: var(--warn); display: grid; }

/* ── bottom tab bar — exactly five, last is always আরও ──── */
.shell-tabbar {
  display: flex; background: var(--surface); border-top: 2px solid var(--rule);
  position: fixed; inset: auto 0 0 0; z-index: 20;
  padding-bottom: env(safe-area-inset-bottom);
}
.shell-tab {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 3px;
  min-height: 58px; color: var(--ink-3); text-decoration: none;
  border-top: 3px solid transparent; margin-top: -2px;
}
.shell-tab[aria-current="page"] { color: var(--accent-ink); border-top-color: var(--accent); }
.shell-tab-glyph { font-size: 19px; display: grid; }
.shell-tab-label { font-size: 10px; font-weight: 600; text-align: center; }

/* ── profile button + menu ──────────────────────────────── */
.d-profile {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 44px; padding: 0;
  background: transparent; border: none; cursor: pointer;
  font-family: var(--font-bn); color: var(--ink); text-align: left;
}
.d-profile:hover { background: var(--inset); }
.shell-avatar-mark {
  width: 30px; height: 30px; flex: none;
  background: var(--inset); border: 1px solid var(--line);
  display: grid; place-items: center; font-size: 13px; font-weight: 600;
  border-radius: var(--r-pill);
}
.shell-who { flex: 1; min-width: 0; }
.shell-who-name { display: block; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shell-who-role { display: block; font-size: 11px; color: var(--ink-3); }

.shell-menu {
  position: absolute; z-index: 40; min-width: 230px;
  background: var(--surface); border: 1px solid var(--line);
  box-shadow: var(--shadow-md); padding: 0;
  border-radius: var(--r-lg); overflow: hidden;
}
.shell-menu[hidden] { display: none; }
.shell-menu-head { padding: 13px 15px; border-bottom: 2px solid var(--rule); }
.shell-menu-name { display: block; font-size: 14px; font-weight: 700; }
.shell-menu-role { display: block; font-size: 12px; color: var(--ink-3); margin-top: 2px; }
.shell-menu-label {
  display: block; padding: 10px 15px 5px;
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 700;
}
.shell-menu-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 44px; padding: 0 15px;
  background: transparent; border: none; border-top: 1px solid var(--line);
  font-family: var(--font-bn); font-size: 14px; color: var(--ink);
  cursor: pointer; text-align: left;
}
.shell-menu-item:hover { background: var(--inset); }
.shell-menu-glyph { flex: none; font-size: 16px; color: var(--ink-3); display: grid; }
.shell-logout { color: var(--accent-ink); }
.shell-logout:hover { background: var(--accent-tint); }
.shell-logout .shell-menu-glyph { color: var(--accent-ink); }


/* ── desktop sidebar ────────────────────────────────────── */
.d-sidebar { display: none; }

/* ═══ desktop ═══════════════════════════════════════════════ */
@media (min-width: 1024px) {
  .shell-tabbar { display: none; }
  .shell-org-mobile { display: none; }
  .shell-crumb { display: flex; }
  .shell-topbar { padding: 0 20px; min-height: 64px; }
  .shell-view { padding: 28px 20px 48px; }

  .d-sidebar {
    display: flex; flex-direction: column;
    width: var(--sidebar-w); flex: none;
    background: var(--surface); border-right: 1px solid var(--line);
    position: sticky; top: 0; height: 100dvh;
  }
  .d-brand {
    display: flex; align-items: center; gap: 10px;
    padding: 14px 16px; min-height: 64px;
    border-bottom: 2px solid var(--rule);
  }
  .d-brand .shell-org-mark, .d-brand .shell-org-logo { width: 32px; height: 32px; font-size: 15px; }
  .d-rail-toggle {
    flex: none; width: 32px; height: 32px; display: grid; place-items: center;
    background: none; border: none; color: var(--ink-3); cursor: pointer;
  }
  .d-rail-toggle:hover { color: var(--ink); background: var(--inset); }

  .d-nav { flex: 1; overflow-y: auto; padding: 8px 0; }
  .d-nav-group { padding: 8px 0 4px; }
  .d-nav-label {
    margin: 0; padding: 6px 16px;
    font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
    color: var(--ink-3); font-weight: 700;
  }
  .dnav {
    display: flex; align-items: center; gap: 11px;
    margin: 0 8px; border-radius: var(--r-sm);
    padding: 0 12px; min-height: 40px;
    font-size: 14px; font-weight: 500; color: var(--ink-2);
    border-left: 3px solid transparent; text-decoration: none;
  }
  .dnav:hover { background: var(--inset); color: var(--ink); }
  .dnav[aria-current="page"] {
    background: var(--accent-tint); color: var(--accent-ink);
    border-left-color: var(--accent); font-weight: 600;
  }
  /* the left bar keeps its square edge against the rounded pill */
  .dnav[aria-current="page"] { border-radius: 2px var(--r-sm) var(--r-sm) 2px; }
  .dnav-glyph { flex: none; font-size: 16px; color: var(--ink-3); display: grid; }
  .dnav[aria-current="page"] .dnav-glyph { color: var(--accent-ink); }
  .dnav-label { flex: 1; min-width: 0; }

  .d-sidebar-foot { border-top: 1px solid var(--line); padding: 10px 16px; min-height: 56px; display: flex; align-items: center; }

  /* icon rail — a preference above 1280, a constraint below it */
  .shell[data-rail="on"] .d-sidebar { width: var(--sidebar-rail-w); }
  .shell[data-rail="on"] .dnav { padding: 0 0 0 13px; }
  .shell[data-rail="on"] .dnav-label,
  .shell[data-rail="on"] .d-nav-label,
  .shell[data-rail="on"] .shell-who,
  .shell[data-rail="on"] .d-brand .shell-org-name { display: none; }
  .shell[data-rail="on"] .d-sidebar-foot,
  .shell[data-rail="on"] .d-brand { padding-left: 8px; padding-right: 8px; }
}
@media (min-width: 1024px) and (max-width: 1279px) {
  .d-sidebar { width: var(--sidebar-rail-w); }
  .d-sidebar .dnav-label,
  .d-sidebar .d-nav-label,
  .d-sidebar .shell-who,
  .d-brand .shell-org-name { display: none; }
  .d-sidebar .dnav { padding: 0 0 0 13px; }
  .d-brand, .d-sidebar-foot { padding-left: 8px; padding-right: 8px; }
}

/* ═══ print ═════════════════════════════════════════════════ */
@media print {
  .d-sidebar, .shell-topbar, .shell-tabbar,
  .offline-banner, .shell-demobar, .shell-menu, .btn { display: none !important; }
  body { background: #fff; }
  .shell-view { padding: 0; }
}


/* ═══ view + component classes the code already emits ═══════
   Everything below is a class name read out of the source, not invented.
   Grouped by the file that emits it. */

/* ── ui/filter.ts — tabs + filterBar ────────────────────── */
.ui-tabs { display: flex; border-bottom: 2px solid var(--rule); overflow-x: auto; }
.ui-tab {
  font-family: var(--font-bn); font-size: 14px; font-weight: 500;
  min-height: var(--tap-min); padding: 0 15px;
  background: transparent; color: var(--ink-2); border: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  border-bottom: 3px solid transparent; margin-bottom: -2px;
}
.ui-tab:hover { color: var(--ink); }
.ui-tab[aria-selected="true"] { color: var(--accent-ink); font-weight: 700; border-bottom-color: var(--accent); }
.ui-tab-count { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: 11px; opacity: .75; }

.ui-filters { display: flex; flex-direction: column; gap: var(--space-2); }
.ui-filters-inline { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.ui-filters-extra { margin-left: auto; }
.ui-filters-open {
  font-family: var(--font-bn); font-size: 13px; font-weight: 600;
  min-height: 36px; padding: 0 13px; border-radius: var(--r-sm);
  background: transparent; color: var(--ink); border: 1px solid var(--line); cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
}
.ui-count {
  font-family: var(--font-num); font-variant-numeric: tabular-nums;
  background: var(--accent); color: #fff; font-size: 10.5px; font-weight: 700;
  padding: 1px 6px; border-radius: var(--r-pill);
}
.ui-filter-sheet { display: flex; flex-direction: column; gap: var(--space-3); padding: var(--space-4); }
.ui-filter-active { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.ui-filter-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: var(--r-pill);
  font-size: 12.5px; font-weight: 600;
  background: var(--accent-tint); color: var(--accent-ink); border: 1px solid var(--accent-ink);
}
.ui-filter-clear { background: none; border: none; color: var(--accent-ink); font-family: var(--font-bn); font-size: 12.5px; font-weight: 600; cursor: pointer; }
.ui-filter-field { display: flex; align-items: center; gap: var(--space-2); }
.ui-filter-field.is-stacked { flex-direction: column; align-items: stretch; gap: 5px; }
.ui-field-label { font-size: var(--text-small); font-weight: 600; }
.ui-sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ── ui/child-selector.ts ───────────────────────────────── */
.ui-child-strip { display: flex; border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ui-child-opt {
  flex: 1; padding: 9px 12px; background: var(--inset); border: none;
  border-right: 1px solid var(--line); cursor: pointer; text-align: left;
  font-family: var(--font-bn); border-bottom: 3px solid transparent;
}
.ui-child-opt:last-child { border-right: none; }
.ui-child-opt[aria-pressed="true"] { background: var(--surface); border-bottom-color: var(--accent); }
.ui-child-opt-text { display: block; min-width: 0; }
.ui-child-opt-name { display: block; font-size: 14px; font-weight: 600; }
.ui-child-opt[aria-pressed="true"] .ui-child-opt-name { font-weight: 700; }
.ui-child-opt-meta { display: block; font-size: 11.5px; color: var(--ink-3); }
.ui-child-button {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: var(--tap-min); padding: 8px 12px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
  cursor: pointer; font-family: var(--font-bn); text-align: left;
}
.ui-child-list { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ui-child-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  min-height: 54px; padding: 8px 12px;
  background: var(--surface); border: none; border-bottom: 1px solid var(--line);
  cursor: pointer; font-family: var(--font-bn); text-align: left;
}
.ui-child-row:last-child { border-bottom: none; }
.ui-child-row:hover { background: var(--neutral-100); }
.ui-child-current { margin-left: auto; font-size: 12px; font-weight: 600; color: var(--accent-ink); }
.ui-child-identity { display: flex; align-items: center; gap: 12px; }
.ui-child-identity-text { min-width: 0; }
.ui-child-identity-name { margin: 0; font-size: 16px; font-weight: 700; }
.ui-child-identity-meta {
  margin: 2px 0 0; font-size: 12px; color: var(--ink-3);
  font-family: var(--font-num); font-variant-numeric: tabular-nums;
}

/* ── ui/table.ts — mobile list roles ────────────────────── */
.ui-list-meta { display: block; font-size: 12px; color: var(--ink-3); margin-top: 1px; }
.ui-list-cell { display: inline; }

/* ── ui/field.ts + forms ────────────────────────────────── */
.ui-form { display: flex; flex-direction: column; gap: var(--space-3); }
.ui-field-error { font-size: 12px; font-weight: 600; color: var(--danger); }
.ui-input, .ui-select, .field-input {
  width: 100%; font-family: var(--font-bn); font-size: var(--text-body);
  min-height: var(--tap-min); padding: 0 12px;
  border: 1px solid var(--ink-3); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink);
}
.ui-input:focus, .ui-select:focus, .field-input:focus { border: 2px solid var(--accent); outline: none; padding: 0 11px; }
.notice-confirm-label { font-size: var(--text-h3); font-weight: 700; }

/* ── practice-view.ts ───────────────────────────────────── */
.prac-rail { display: flex; gap: 5px; margin-bottom: var(--space-3); }
.prac-dot { width: 9px; height: 9px; flex: none; border-radius: var(--r-pill); background: var(--inset); border: 1px solid var(--line); }
.prac-dot.is-done    { background: var(--ok);     border-color: transparent; }
.prac-dot.is-current { background: var(--accent); border-color: transparent; }
.prac-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--space-4); }
.prac-meta { display: flex; align-items: baseline; gap: 10px; margin-bottom: 9px;
             font-family: var(--font-num); font-variant-numeric: tabular-nums;
             font-size: 12px; font-weight: 700; color: var(--ink-3); }
.prac-difficulty { margin-left: auto; letter-spacing: .12em; color: var(--warn); }
.prac-stem { font-size: var(--text-body); font-weight: 600; line-height: 1.55; margin-bottom: var(--space-3); }
.prac-options { display: flex; flex-direction: column; gap: 7px; }
.prac-option {
  display: flex; align-items: center; gap: 10px;
  min-height: var(--tap-min); padding: 0 12px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm);
  cursor: pointer; font-family: var(--font-bn); text-align: left;
}
.prac-option:hover { background: var(--neutral-100); }
.prac-option.is-chosen  { border-color: var(--ink); }
.prac-option.is-correct { background: var(--ok-tint);     border-color: var(--ok); }
.prac-option.is-wrong   { background: var(--danger-tint); border-color: var(--danger); }
.prac-mark { width: 19px; flex: none; text-align: center; font-size: 14px; color: var(--ink-3); }
.prac-option.is-correct .prac-mark { color: var(--ok); }
.prac-option.is-wrong   .prac-mark { color: var(--danger); }
.prac-option-text { flex: 1; min-width: 0; font-size: var(--text-body); }
.prac-option.is-correct .prac-option-text { font-weight: 700; }
.prac-input { font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.prac-verdict { font-size: 13.5px; font-weight: 700; margin: 10px 0 8px; }
.prac-verdict.is-correct { color: var(--ok); }
.prac-verdict.is-wrong   { color: var(--danger); }
.prac-explanation {
  background: var(--info-tint); border-left: 4px solid var(--info);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 11px 13px; font-size: 12.5px; line-height: 1.55; margin-bottom: var(--space-3);
}
.prac-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.prac-retry { flex: none; }

/* ═══ [2] compatibility aliases ════════════════════════════════════
   The screens below this line were styled against the previous token names
   and have not all been restyled yet. Each old name is defined here in terms
   of the NEW palette and scale, so those screens already render in the new
   colours and corners instead of losing their spacing to an undefined var().
   Delete an alias only when nothing below references it.
   ═══════════════════════════════════════════════════════════════════ */
:root {
  --c-accent: var(--danger);
  --c-border-strong: var(--neutral-400);
  --c-danger: var(--danger);
  --c-danger-soft: var(--danger-tint);
  --c-info: var(--info);
  --c-info-soft: var(--info-tint);
  --c-ink: var(--ink);
  --c-ink-1: var(--ink);
  --c-ink-2: var(--ink-2);
  --c-ink-3: var(--ink-3);
  --c-line: var(--line);
  --c-line-2: var(--neutral-200);
  --c-link: var(--accent-ink);
  --c-on-primary: #ffffff;
  --c-primary: var(--accent);
  --c-primary-ink: var(--accent-ink);
  --c-primary-soft: var(--accent-tint);
  --c-primary-text: var(--accent-ink);
  --c-success: var(--ok);
  --c-success-soft: var(--ok-tint);
  --c-surface: var(--inset);
  --c-surface-2: var(--surface);
  --c-surface-3: var(--neutral-200);
  --c-warn: var(--warn);
  --c-warn-soft: var(--warn-tint);
  --color-accent-2: var(--ink-2);
  --color-accent-2-soft: var(--inset);
  --color-accent-2-text: var(--ink-2);
  --color-accent-600: var(--accent-600);
  --color-bg: var(--surface);
  --color-border: var(--line);
  --color-border-strong: var(--neutral-400);
  --color-info: var(--info);
  --color-info-soft: var(--info-tint);
  --color-neutral-100: var(--neutral-100);
  --color-neutral-200: var(--neutral-200);
  --color-neutral-300: var(--neutral-300);
  --color-neutral-400: var(--neutral-400);
  --color-neutral-500: var(--neutral-500);
  --color-neutral-700: var(--neutral-700);
  --color-primary: var(--accent);
  --color-primary-soft: var(--accent-tint);
  --color-text: var(--ink);
  --color-text-faint: var(--ink-3);
  --color-text-muted: var(--ink-2);
  --color-warning: var(--warn);
  --color-warning-soft: var(--warn-tint);
  --font-bn-num: var(--font-num);
  --font-heading: var(--font-bn);
  --lh-ui: 1.5;
  --radius-lg: var(--r-lg);
  --radius-md: var(--r-md);
  --radius-sm: var(--r-sm);
  --s-1: var(--space-1);
  --s-2: var(--space-2);
  --s-3: var(--space-3);
  --s-4: var(--space-4);
  --s-5: var(--space-6);
  --s-6: var(--space-8);
  --shadow-1: var(--shadow-sm);
  --text-2xl: var(--text-h1);
  --text-2xs: var(--text-small);
  --text-3xl: 32px;
  --text-3xs: var(--text-label);
  --text-4xl: var(--text-display);
  --text-base: 16px;
  --text-body-line: var(--lh-body);
  --text-h2-line: var(--lh-h2);
  --text-h2-weight: var(--w-h2);
  --text-lg: 18px;
  --text-read: var(--text-h3);
  --text-sm: var(--text-body);
  --text-xl: var(--text-h2);
  --text-xs: 14px;
  --transition-fast: var(--dur-1) var(--ease);
}

/* ═══ white-label seam ════════════════════════════════════════════════
   tokens/ata-ekta.css writes `.btn-primary { color: #fff }`. A school whose
   brand colour is pale needs dark type on that fill to stay readable, so the
   label reads --on-accent, which branding.ts sets per school. With no school
   set, the fallback is the design's own #fff — pixel-identical to the sheet.
   ═══════════════════════════════════════════════════════════════════ */
.btn-primary { color: var(--on-accent, #fff); }

/* ═══ B-108 — the Bangla numeral face, kept on purpose ════════════════
   A deliberate deviation from tokens/ata-ekta.css, and the only one on this
   sheet that changes a token the design defines.

   The design sets `--font-bn: "Hind Siliguri", …` and routes numbers through
   the `.n` class onto Anek Bangla. That is right for every element whose whole
   content is a figure — tables, stats, marks, money — and `.n` still does it.

   It cannot reach a digit INSIDE A SENTENCE, and most Bangla digits in this
   product live inside sentences: "১০টি শিক্ষার্থী", "১০:৪৫-এ ক্লাস". B-108 §16
   measured what happens to those in Hind Siliguri: its ১ is close enough to ৮
   at UI sizes that "১০টি" reads as "৮০টি" — a mark, a time and a fee each wrong
   by a digit. The fix was a `unicode-range` face over U+09E6–U+09EF only, named
   first so it takes the digits and leaves every letter to Hind Siliguri.

   Swapping in the design sheet left that face defined and referenced nowhere,
   which is the exact failure B-108 was filed for. Naming it first again costs
   nothing a reader can see in a letter, and keeps a fee from reading wrong. */
:root {
  --font-bn: 'ShikhonBnNum', "Hind Siliguri", system-ui, sans-serif;
}

/* ═══ [3] screen-specific rules carried from the previous sheet ═══════
   Everything below styles a class that tokens/ata-ekta.css does not. Rules the
   new sheet replaces, every dark-mode rule and the old token block were removed
   by scripts in the handoff, not by hand — see the build report.
   ═══════════════════════════════════════════════════════════════════ */
/* ShikhonBD — app shell styles.
   Design tokens adopted from "Shikhon Screens (standalone).html"; layout and
   accessibility rules from docs/04-UIUX-ACCESSIBILITY.md and the Wireframe
   Specification v2.0 §1. Reference viewport: 360x640.

   ── Adopting the design system, and the four places it is overridden ──────
   The design file is the source of truth for colour, spacing, radius,
   elevation and heading treatment. Four of its choices are overridden here,
   each because Wireframe §1 lists the conflicting rule as a constraint that
   "has already broken something or is a stated requirement":

   1. FONT. The design uses Archivo, self-hosted as woff2. Archivo carries no
      Bangla glyphs, and this product is Bangla-primary (N-12). A self-hosted
      webfont is also what previously 404'd and broke service-worker install
      outright (TRD §3). Archivo is therefore named in the stack but NOT
      self-hosted: it renders where the device already has it, and falls back
      to the system Bangla face otherwise. No @font-face, no download, no
      precache risk.

   2. LETTER-SPACING. The design tracks headings at -0.015em and h6 at
      +0.08em. Bangla conjuncts break under both: positive tracking severs
      them, negative destroys them. Tracking is applied to Latin-only
      elements and never to [lang='bn'].

   3. TYPE SCALE. The design sets 15px body, 14px controls, 11-13px meta.
      Bangla conjuncts like ক্ষ্ম are unreadable below ~15px at 1x DPI, so the
      floor here is 16px body and 13px absolute minimum.

   4. CONTROL HEIGHT. The design uses 36px buttons and inputs. F-812 requires
      48x48px minimum tap targets with no exceptions, and the target device
      is a shared phone used with a thumb.

   Everything else — the warm neutral ramp, the red accent, square corners,
   the ink-tinted elevation, the 4px spacing scale — is taken as given.

   ── The type scale (the one thing the design file did NOT give) ───────────
   The standalone screens export sets font-size inline, ad hoc: fourteen raw
   pixel values (10 → 32) with no ramp, so a card title is 15px on one screen
   and 16px on the next, and a meta line is 12px here and 13px there. The
   wireframe is explicit that the type scale lives in the design system and
   is deliberately unspecified in the frames — but the design file never
   tokenised it either. This block does. Every size below is drawn from ONE
   eleven-rung ramp (--text-3xs … --text-4xl); no rule sets a raw px size.

   The ramp steps gently through the reading sizes (13→18 in 1px increments,
   because a dense-but-scannable product needs fine control where the words
   are) and widens through the display sizes (20/24/28/32 for the big
   numbers — GPA, score, activation code). Its floor is 13px, and 13px is
   Bangla-safe; the sole exception is --text-3xs (11px), used ONLY for Latin
   digits, monospace codes and table superscripts that never carry a Bangla
   conjunct. The 16px body floor of Override 3 is --text-base, unchanged. */
/* ── Touch ergonomics (mobile is the design floor: 360×640, thumb-driven) ──
   The target device is a shared phone used with a thumb, often one-handed.
   These make every control feel native on it, without touching any layout:
   - manipulation removes the 300ms tap delay and double-tap-zoom on controls,
     so a tap registers instantly (the difference a teacher feels 60 times a
     minute on the attendance grid);
   - the tap-highlight is the browser's blunt blue flash; we already draw our
     own :active feedback, so the default only muddies it;
   - long Bangla compounds and pasted strings must wrap, never widen the page
     past the viewport. */
[role='button'],
[tabindex] {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
/* ── Bangla digits, and only Bangla digits ───────────────────────────────
   U+09E6–U+09EF is ০ through ৯. Named FIRST in --font-body, --font-bn and
   --font-heading, so a digit anywhere in the product takes this face and
   every letter around it stays on Hind Siliguri.

   `local()` only: the header of this file rules out self-hosted webfonts
   after one 404'd and broke the service-worker install, and the precache
   list already states that Bangla renders from the device's own Noto. This
   adds no request, no bytes and no precache risk. On a device without Noto
   Sans Bengali the digits fall through to Hind Siliguri — today's rendering,
   so the worst case of this rule is no change at all.

   No font-weight descriptor, deliberately: one face answers every weight and
   the browser synthesises bold, which is correct for ten digits and avoids
   four local() lookups that would each fail differently across platforms. */
@font-face {
  font-family: 'ShikhonBnNum';
  /* Every platform's own Bangla face, best first. The token above named
     only Noto, which is true of Android and NOT of Windows — measured:
     `local('Noto Sans Bengali')` does not match there at all, and what a
     Windows browser actually falls back to is Nirmala UI. A one-name list
     would have fixed the target device and silently left every desk
     unfixed. If none match, the digit falls through to Hind Siliguri and
     the screen is what it is today. */
  src: local('Noto Sans Bengali'),        /* Android, ChromeOS, most Linux */
       local('NotoSansBengali-Regular'),
       local('Nirmala UI'),               /* Windows */
       local('Kohinoor Bangla'),          /* macOS, iOS */
       local('Bangla MN'),
       local('Kalpurush'),                /* commonly installed in BD */
       local('SolaimanLipi');
  unicode-range: U+09E6-09EF;
  font-display: swap;
}
/* Bangla renders from the device system font, always (Wireframe §1). */
[lang='bn'],
[lang='bn'] button,
[lang='bn'] input,
[lang='bn'] textarea {
  font-family: var(--font-bn);
  letter-spacing: normal;
}
/* The design system's -0.015em tracking, applied only where the text is
   Latin. :not([lang='bn']) rather than a class, so it cannot be forgotten. */
h1:not([lang='bn']),
h2:not([lang='bn']) { letter-spacing: -0.015em; }
/* Bangla has no case; text-transform is a no-op that breaks mixed strings. */

/* ---------------------------------------------------------------- header */
.att-header {
  position: sticky; top: 0; z-index: 2;
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: var(--s-1) var(--s-2);
  /* Safe-area top: in a standalone PWA on a notched phone the header sits
     under the status bar without it. max() keeps the normal padding when
     there is no inset. */
  padding: max(var(--s-3), env(safe-area-inset-top)) var(--s-4) var(--s-3);
  background: var(--c-surface);
  border-bottom: 1px solid var(--c-line);
}
.att-header h1 { grid-column: 1; }
.att-sub { grid-column: 1; margin: 0; color: var(--c-ink-2); font-size: var(--text-xs); }
.sync-chip {
  grid-column: 2; grid-row: 1 / span 2;
  padding: var(--s-1) var(--s-2);
  border-radius: 999px; font-size: var(--text-xs); white-space: nowrap;
}
.sync-chip[data-state='synced'] { color: var(--c-success); background: var(--c-success-soft); }
.sync-chip[data-state='queued'] { color: var(--c-warn);    background: var(--c-warn-soft); }
.sync-chip[data-state='failed'] { color: var(--c-accent);  background: var(--c-danger-soft); }
/* --------------------------------------------------------------- counters */





/* Total is the completeness check; push it to the end so it reads as the
   sum of what precedes it, not another category. */


/* Legend — one quiet row keying the three tap states to their marks. */






/* ------------------------------------------------------------------ grid */

.tile {
  min-width: 56px; min-height: 56px;    /* > 48px AAA target size */
  display: grid; place-items: center; gap: 0;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  background: var(--c-surface);
  box-shadow: var(--shadow-1);
  cursor: pointer;
  padding: var(--s-1);
}


/* Status is never signalled by colour alone — each state also has a distinct
   glyph, for the ~8% of male students with a colour-vision deficiency. */
.tile[data-status='present'] { border-color: var(--c-success); }

.tile[data-status='absent'] { border-color: var(--c-accent); background: var(--c-danger-soft); }

.tile[data-status='late'] { border-color: var(--c-warn); background: var(--c-warn-soft); }

.tile[data-status='excused'] { border-style: dashed; }
/* Visible focus on EVERY interactive element — never outline:none. F-812
   makes this a requirement, not a nicety: the target device is often driven
   by an external keyboard in a computer lab, and a lost focus ring strands
   that user. One rule covers the whole product so a new control cannot ship
   without it; individual components used to redeclare this ad hoc (and some
   forgot). */
summary:focus-visible,
.tile:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
}
/* Text-entry focus is the accent ring drawn on the border rather than the
   outline, so the field visibly "arms" without shifting layout. Unified
   here so every input/select/textarea behaves identically — the old file
   set this on .field-input only, and .login-input, .marks-input and the
   rest had no focus treatment at all. :focus (not :focus-visible) because a
   deliberate tap into a field should show the same armed state as a keyboard
   tab into it. */
input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--c-primary);
  box-shadow: inset 0 0 0 1px var(--c-primary);
}
/* ---------------------------------------------------------------- buttons */
/* P12-3. A colour variant must not carry a layout margin.
   This rule used to end `margin: 0 var(--s-4)`, and the horizontal half of it
   caused a real defect: `.ui-button-row > * { width: 100% }` applies below
   1024px, and a 100%-wide element with 16px side margins is wider than its
   container by exactly those margins — the hazard already written down on
   `.ui-card` further down this file. On `#/academic` at 375px that pushed the
   document to 391px and the whole page could be dragged sideways; the fixed
   tab bar stretching to 391px was the symptom, not the cause.
   The margin was never wanted in most places either: four separate rules
   (`.empty-state`, `.prac-actions`, `.choice-footer`, `.editor-holding`)
   existed only to undo it. Removing it here deletes the cause instead of
   adding a fifth patch. Vertical rhythm belongs to the container's `gap`. */
.att-footer {
  position: fixed; inset: auto 0 0 0;
  /* Safe-area bottom: clears the home indicator on gesture-nav phones so the
     submit button is never half under it. */
  padding: var(--s-3) var(--s-4) max(var(--s-3), env(safe-area-inset-bottom));
  background: var(--c-surface);
  border-top: 1px solid var(--c-line);
}
.snackbar {
  margin-top: var(--s-2); text-align: center;
  font-size: var(--text-xs); color: var(--c-ink-2);
}
/* ------------------------------------------------------------- responsive */
/* Layout must survive 200% zoom and a 320px viewport with no horizontal
   scroll (WCAG 2.2 reflow). */
@media (max-width: 320px) {

}
/* ------------------------------------------------------------- status-chip */
/* Named in the wireframe's component vocabulary (§3) with states success /
   warning / danger / neutral / pending, and used across six screens — but
   never actually defined, so every caller fell back to unstyled text. It is
   a component now, and one-off chips (.assign-chip, .system-chip, .subj-chip)
   layer their palette on top of this base rather than redefining the shape.

   Modelled on the design system's .tag: small, tight, low-chrome. Colour is
   always paired with the label text it wraps, so it never carries state
   alone (F-812). */
/* ==========================================================================
   SHELL — the application chrome, in two deliberate layouts   (UI plan, P1)

   One DOM, two layouts. Below 1024px the sidebar is display:none and the
   bottom bar is the navigation; at 1024px and up the bottom bar is gone and
   the sidebar is persistent. `display:none` removes a subtree from the
   accessibility tree as well as the page, so a screen reader only ever meets
   the navigation that is actually on screen.

   Before P1 this file had ONE desktop breakpoint in 2,542 lines, and it
   styled the branding editor. Everything else — every list, every table,
   every form — was the phone layout stretched to the window width.
   ========================================================================== */
/* ──────────────────────────────────────────────────────────────────────────
   `hidden` must win. Found by P1's rendered sweep, shipped 2026-08-11.

   `.offline-banner` sets `display:flex`, and a display declaration beats the
   UA sheet's `[hidden]{display:none}` at equal specificity — so the banner
   the shell hides with `banner.hidden = navigator.onLine` was drawn anyway.
   Every screen, every role, online or off, has been carrying a 41px strip
   reading "অফলাইন — কাজ চালিয়ে যান" for 58 commits. `hidden` was true the
   whole time; nothing in the DOM looked wrong, which is why only a rendered
   check could find it.

   Global rather than scoped to that one class: this is the correct default
   for the attribute, and the next component to set `display` on something it
   also hides would otherwise repeat the bug in a new place.
   ────────────────────────────────────────────────────────────────────────── */
[hidden] { display: none !important; }
/* Keyboard users land here first. Without it, reaching the page content past
   a seventeen-row sidebar costs seventeen Tab presses on every navigation. */
/* -- top bar ---------------------------------------------------------- */
/* `min-width: 0` matters: without it the actions cluster refuses to shrink
   and the institution's name absorbs every pixel of overflow instead. At
   390px in demo mode — chip + role picker + bell + avatar — that left the
   school called "শা". The name is the one thing in this bar that identifies
   which install a teacher is holding, so it shrinks LAST. */

/* ── Shell: whose school this is, on every screen ───────────────────── */
/* Declared AFTER `.shell-org` on purpose — it narrows the base rule, and at
   equal specificity the later declaration is the one that wins. */
/* No logo yet: the school's own initial, never a platform mark (D11). A blank
   square where the identity goes is worse than a letter. */
/* Icon-only chrome buttons — bell, search. 48px because F-812 allows no
   exceptions and these are pressed with a thumb on a shared phone. */
/* Search is a chrome affordance on desktop, where there is room for it beside
   the breadcrumb. On a phone the same destination is a row in More, and a
   third icon in a 360px header pushes the school's name out. */

/* §30. The demo strip. Present only on /demo and ?demo=1; a school's staff
   never render this element. It sits under the app bar rather than inside it
   so the marker reads as a statement about the whole environment, not as one
   more control — and so it cannot squeeze the institution's name. */
/* The fill and the label are the SAME token pair in both themes, and they
   invert together. White-on-warning was 4.94:1 in light and 1.85:1 in dark,
   because `--color-warning-ink` is the dark step in light mode and the
   LIFTED step in dark — its job is to be readable against its own ground,
   not to be a fill. Using a soft/ink pair keeps the chip solid either way.
   Measured: 6.0:1 light, 7.9:1 dark. */
/* -- breadcrumb (desktop only) ---------------------------------------- */
/* Deliberately not a page <h1>: 26 views render their own, and repeating it
   in the chrome is the "same information twice" the brief forbids. This is a
   13px orientation cue that ends with the page name, not a second title. */
/* -- the profile control and its menu --------------------------------- */


/* On a phone the avatar is the whole control: at 360px the name plus a role
   beside a bell and a school name is four things competing for one bar. */
/* Logout is destructive-adjacent, not destructive: it loses nothing but the
   session. Danger ink on hover only, so the menu is not shouting at rest. */
/* -- content ---------------------------------------------------------- */
/* clear the fixed tab bar */
/* focused programmatically */
/* -- bottom bar (mobile) ---------------------------------------------- */
/* Active tab needs an unmistakable signal — a coloured bar on top plus the
   primary tint. The colour-only change we had before wasn't enough to tell a
   first-time user which page they were on. */


/* -- desktop sidebar (hidden until 1024) ------------------------------ */
/* The active row carries THREE signals — tint, weight and a leading bar —
   because the brand hue is tenant-chosen and a school with a pale primary
   would otherwise have a nearly invisible "you are here". */


/* A touch device wide enough for the sidebar (a landscape tablet) gets the
   full touch target. `pointer: coarse` asks the question that matters —
   what is being used to hit this — rather than inferring it from width. */
/* Home cards get a corner chevron so their tappability is unmistakable —
   several users read the first cut as static tiles. */
.home-card::after {
  content: '›';
  position: absolute; top: var(--s-2); right: var(--s-3);
  font-size: var(--text-xl); line-height: 1; color: var(--c-ink-3);
  font-weight: 400;
}
.home-card { position: relative; }

/* ---------------------------------------------------------------- login */
/* Ata Ekta LMS layout: brand-mark tile, name, tagline, form. Centered
   with generous top padding so the screen looks intentional on tall
   viewports. */
.login-wrap {
  max-width: 360px; margin: 0 auto;
  padding: var(--s-6) var(--s-4);
  display: flex; flex-direction: column; align-items: stretch;
  min-height: 100dvh; justify-content: center;
}

.login-brandmark {
  width: 56px; height: 56px; margin: 0 auto var(--s-3);
  border-radius: var(--radius-lg);
  background: var(--color-primary); color: var(--c-on-primary);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-bn); font-weight: 700; font-size: 22px;
}
.login-brandname {
  font-size: var(--text-xl); font-weight: 700; color: var(--color-text);
}

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

.login-label { display: flex; flex-direction: column; gap: var(--s-1); font-size: var(--text-xs); color: var(--c-ink-2); }
.login-input {
  min-height: var(--tap-min); padding: 0 var(--s-3);
  border: 1px solid var(--color-border-strong); border-radius: var(--radius-md);
  font-size: var(--text-base); background: var(--color-bg);
}
.login-input:focus {
  outline: none; border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-soft);
}


.login-error { color: var(--c-accent); font-size: var(--text-xs); margin: 0; }
/* F-102 cooldown. Warn, not error — the system is working; you are waiting. */
.login-cooldown {
  color: var(--c-warn); font-size: var(--text-xs); margin: 0;
  padding: var(--s-2) var(--s-3);
  background: var(--c-warn-soft); border-radius: var(--radius);
}
/* -------------------------------------------------------------- offline banner */
/* ── Icon system (see src/icon.ts) ─────────────────────────────────────────
   Every navigation/action glyph is inline SVG sized in em, so the container's
   font-size (set on .home-glyph, .shell-tab-glyph, etc.) still controls it,
   and coloured by currentColor so it tints with its container. display:block
   drops the inline-SVG baseline gap that would knock it off-centre. */
.home-glyph svg { display: block; }
/* ----------------------------------------------------------------- roster */


.roster-roll { width: 2.5em; color: var(--c-ink-2); font-variant-numeric: tabular-nums; }
.roster-name { flex: 1; }
/* ---------------------------------------------------------------- routine */








/* ------------------------------------------------------------------ marks */











/* F-709 over-max: the field flags red and states, in words, that the value
   was not saved — so the number still sitting in the box is never mistaken
   for a stored mark. */


/* Completeness — "have I marked everyone?" Quiet until it is done, then it
   goes green so the teacher can leave the screen without counting rows. */


/* ------------------------------------------------------------------- fees */
/* ------------------------------------------------------------------- more */

/* --------------------------------------------------------------------- ai */


/* ------------------------------------------------------------------- chat */





/* ── ShikhoAI answer states (F-1302, §6.7) ────────────────────────────────
   Every assistant turn is a bubble plus a state line naming where the answer
   came from. The line is the requirement: a student must be able to tell the
   textbook from the model's general knowledge without being told twice. */



/* Grounded is the reassuring state and the only one that earns the accentless
   success tone; ungrounded is a caution, not an error; refused and
   unavailable are quiet facts. */








/* ------------------------------------------------------------- substitute */
/* ============================================================== redesign
   New surfaces introduced with the home dashboard + answer-script capture.
   The older component blocks above are kept working; these add the hero,
   card grid, refreshed page-header, field, and script-page primitives. */
.page-sub.empty { padding: var(--s-4); text-align: center; color: var(--c-ink-3); }
.section-heading {
  margin: var(--s-5) var(--s-4) var(--s-2);
  font-size: var(--text-2xs); font-weight: 700;
  /* Was --c-ink-3 (#7d7979 ≈ 3.9:1 on the ground) — below AA, and this is
     the only label separating grouped content, so it must clear it. --c-ink-2
     (#605d5d) is 5.8:1. */
  color: var(--c-ink-2); text-transform: uppercase;
}
/* Bangla is never tracked (Override 2: positive tracking severs conjuncts,
   negative destroys them). Two rules were tracking these always-Bangla
   labels: this class once set 0.02em, and the h1/h2:not([lang='bn']) rule
   still applies -0.015em — both because the headings inherit `bn` from the
   root without carrying the attribute the guard checks. This wins on source
   order (equal specificity to the h2 rule) and holds every section heading
   at normal tracking. Every .section-heading in the app is an <h2>. */
h2.section-heading { letter-spacing: normal; }
/* Ata Ekta LMS teacher-home layout: plain hero (no chrome), white cards
   with a hairline border, glyphs in tinted soft squares. */
.hero {
  margin: 0;
  padding: var(--s-5) var(--s-4) var(--s-3);
  background: transparent;
  border: 0;
  color: var(--color-text);
}



/* Card — white base with hairline border, small resting shadow. */
/* Home tiles ------------------------------------------------------------- */



.home-card {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-2);
  min-height: 96px; padding: var(--s-4);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: none;
  text-align: left; font: inherit; color: inherit; cursor: pointer;
  transition: transform 80ms ease-out, box-shadow 80ms ease-out, border-color 120ms ease-out;
}
.home-card:hover { border-color: var(--color-border-strong); }
.home-card:active { transform: scale(0.98); }

.home-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 10px;
  background: var(--color-primary-soft); color: var(--color-primary);
  font-size: var(--text-lg); line-height: 1;
}
/* Rotate through the design's accent tints so the grid reads as a set of
   distinct actions, not four copies of the same tile. */







/* Form fields (used on the scripts capture card) ------------------------ */
.card-form { margin: var(--s-3) var(--s-4); padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-3); }
.field { display: flex; flex-direction: column; gap: var(--s-1); font-size: var(--text-2xs); color: var(--c-ink-2); }
/* Focus is the unified input:focus rule near the top of this file. */
/* 44px is the universal touch floor (Apple HIG). These secondary/inline
   controls were 36px — comfortably tappable on a mouse, a mis-tap on a
   thumb. Primary actions stay at the product's 48px --tap-min. */
.btn-small { min-height: 44px; padding: 0 var(--s-3); font-size: var(--text-xs); }
.inline-notice {
  margin: var(--s-2) var(--s-4);
  padding: var(--s-2) var(--s-3);
  background: var(--c-warn-soft); color: var(--c-warn);
  border: 1px solid color-mix(in srgb, var(--c-warn) 35%, transparent); border-radius: var(--radius);
  font-size: var(--text-xs);
}
/* Script pages ---------------------------------------------------------- */

/* =============================================================== roles */


/* ============================================================== ledger */
/* ============================================================== system */
.system-list { list-style: none; margin: 0; padding: 0 var(--s-4) var(--s-5); display: flex; flex-direction: column; gap: var(--s-2); }
/* .system-row is a <button> (documents-view, system-view, student search).
   It never set a background, so it inherited the USER-AGENT button face —
   invisible in the light theme, and #6B6B6B under `color-scheme: dark`,
   where --c-ink-2 on it measures 2.59:1 and fails AA. Found by the P0
   contrast sweep; the defect pre-dates P0 in both palettes. A row in a list
   belongs to the card it sits on, so it takes no fill of its own. */
.system-row {
  display: grid; grid-template-columns: 1fr auto; gap: var(--s-3); padding: var(--s-3);
  background: none; border: 0; color: inherit; font: inherit; text-align: start;
  width: 100%;
}
.system-title { font-weight: 600; font-size: var(--text-sm); }
.system-desc { font-size: var(--text-2xs); color: var(--c-ink-2); }

/* =============================================================== learn
   Syllabus browse + lesson reader — the student-facing learning surface. */
.back-bar { padding: var(--s-3) var(--s-4) 0; }
.back-btn { min-height: 44px; font-size: var(--text-xs); }
/* Chapter list ---------------------------------------------------------- */
.chapter-list { list-style: none; margin: 0; padding: 0 var(--s-4); display: flex; flex-direction: column; gap: var(--s-2); }
.chapter-card {
  display: grid; grid-template-columns: 52px 1fr; gap: var(--s-3); align-items: center;
  width: 100%; padding: var(--s-3); text-align: left; font: inherit; color: inherit;
  cursor: pointer; background: var(--c-surface);
  border: 1px solid var(--c-line); border-radius: var(--radius); box-shadow: var(--shadow-1);
}
.chapter-card:active { transform: scale(.995); }
/* Progress ring drawn with conic-gradient — no SVG, no JS, cheap to composite. */





.chapter-title { font-weight: 600; font-size: var(--text-sm); }

.chapter-pre { font-size: var(--text-2xs); color: var(--c-warn); }

/* Lesson list ----------------------------------------------------------- */
/* Reader ---------------------------------------------------------------- */
.lesson-reader {
  padding: 0 var(--s-4);
  /* Bangla body copy needs a slightly longer measure than Latin to avoid
     conjunct-heavy lines breaking awkwardly. */
  max-width: 68ch;
  font-size: var(--text-read); line-height: 1.85;
}
/* Reader text-size control (§6.3). Right-aligned above the reading, two
   thumb-sized steps showing the change they make — a small অ and a large অ. */
.reader-tools {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 0 var(--s-4) var(--s-2); margin-top: var(--s-1);
}
.reader-tools-label { margin-right: auto; font-size: var(--text-2xs); color: var(--c-ink-3); }
.reader-size {
  min-width: var(--tap-min); min-height: var(--tap-min);
  border: 1px solid var(--c-line); border-radius: var(--radius);
  background: var(--c-surface); color: var(--c-ink); cursor: pointer;
  font-family: var(--font-bn); line-height: 1;
}
.reader-size { font-size: var(--text-xs); }
/* the "smaller" step */
.reader-size-lg { font-size: var(--text-lg); }
/* the "bigger" step */
.reader-size:disabled { opacity: .4; cursor: default; }
.block-text { margin: 0 0 var(--s-4); }
.block-formula {
  margin: var(--s-3) 0 var(--s-4); padding: var(--s-3) var(--s-4);
  background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--radius);
  font-family: ui-monospace, "SF Mono", monospace; font-size: var(--text-lg); text-align: center;
  overflow-x: auto; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
/* The tinted background already says "this is the key point"; the accent
   rail was doing the same job twice. Unlike the state rails elsewhere in
   this file, it encoded nothing — there is only one kind of key point. */
.block-key-point {
  margin: var(--s-3) 0 var(--s-4); padding: var(--s-3) var(--s-4);
  background: var(--c-primary-soft); border-radius: var(--radius);
  font-size: var(--text-base);
}
.block-example,
.block-practice {
  margin: var(--s-3) 0 var(--s-4); padding: var(--s-3) var(--s-4);
  background: var(--c-surface); border: 1px solid var(--c-line); border-radius: var(--radius);
}
.block-practice { border-style: dashed; }
.block-label {
  display: block; font-size: var(--text-3xs); font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--c-ink-3); margin-bottom: var(--s-1);
}
.block-example p,
.block-practice p { margin: 0; }
.block-figure { margin: var(--s-3) 0 var(--s-4); }
.block-figure img { width: 100%; height: auto; border-radius: var(--radius); background: var(--c-surface-3); }
.block-figure figcaption { margin-top: var(--s-1); font-size: var(--text-2xs); color: var(--c-ink-2); }
/* ============================================================== results */

/* Demo role picker in the top bar */
/* ========================================================== assignments */
/* urgency-rail-card — a named component in the wireframe's vocabulary (§3),
   with states high / medium / low / none, and drawn in §6.1 as the leading
   ▐ on every suggestion card. The rail is how the list scans without
   reading; F-812 is satisfied because .assign-chip states the same urgency
   in words beside it, so colour is never the only carrier. */
.assign-instructions {
  margin: var(--s-2) var(--s-4); padding: var(--s-3) var(--s-4);
  font-size: var(--text-sm); line-height: 1.7; white-space: pre-wrap;
}
.assign-answer { min-height: 160px; padding: var(--s-3); line-height: 1.7; resize: vertical; }
/* Autosave reassurance — quiet, success-toned, so the student trusts that
   leaving the screen will not lose the answer (§6.6). */
.assign-draft-status { min-height: 1.2em; font-size: var(--text-2xs); color: var(--c-success); }
.assign-graded {
  margin: var(--s-2) var(--s-4); padding: var(--s-4);
  background: var(--c-primary-soft); border-color: transparent; text-align: center;
}
.assign-score {
  font-size: var(--text-3xl); font-weight: 700; color: var(--c-primary-text);
  font-variant-numeric: tabular-nums; line-height: 1.2;
}
.assign-feedback { margin: var(--s-2) 0 0; font-size: var(--text-xs); color: var(--c-ink-2); }
/* Teacher review list */
.sub-list { list-style: none; margin: 0; padding: 0 var(--s-4) var(--s-5); display: flex; flex-direction: column; gap: var(--s-2); }
.sub-item { padding: var(--s-3); }

.sub-head { display: flex; justify-content: space-between; gap: var(--s-3); align-items: baseline; }
.sub-who { font-weight: 600; font-size: var(--text-sm); }


.sub-body {
  margin: var(--s-2) 0 0; font-size: var(--text-xs); line-height: 1.6; color: var(--c-ink-2);
  white-space: pre-wrap;
}
.sub-grade-row { display: flex; gap: var(--s-2); margin-top: var(--s-3); align-items: center; }
.sub-mark { width: 5.5em; flex: none; }
.sub-feedback { flex: 1; min-width: 0; }

/* F-103 grading conflict. Warn-toned, not error-toned: nothing failed, two
   people did the same work. Sits above the submission list because it is
   the only thing on the screen waiting on the teacher. */
.grade-conflict { background: var(--c-warn-soft); margin-bottom: var(--s-4); }
.grade-conflict h3 { margin: 0 0 var(--s-2); font-size: var(--text-base); }
.conflict-who { margin: 0 0 var(--s-3); font-size: var(--text-xs); color: var(--c-ink-2); }
.conflict-compare {
  display: grid; grid-template-columns: auto 1fr;
  gap: var(--s-1) var(--s-3); margin: 0 0 var(--s-4);
  font-size: var(--text-sm);
}
.conflict-compare dt { color: var(--c-ink-2); }
.conflict-compare dd { margin: 0; font-variant-numeric: tabular-nums; }
.conflict-actions { display: flex; gap: var(--s-2); }
.conflict-actions button { flex: 1; }
/* ============================================================= practice */
.prac-wrap { padding-bottom: var(--s-5); }
/* The mark, not the colour, is what says right or wrong. Green and red
   backgrounds alone are unreadable to a red-green colour-blind student —
   about one boy in twelve — so the glyph carries it and the colour only
   reinforces. */
/* Correct is marked even when they picked it wrong — showing only the
   error teaches nothing about what the right answer was. */
/* ============================================================ next block */


.next-card {
  display: grid; grid-template-columns: auto 1fr; gap: var(--s-3); align-items: center;
  width: 100%; padding: var(--s-3); text-align: left; font: inherit; color: inherit;
  cursor: pointer; background: var(--c-surface);
  border: 1px solid var(--c-line); border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  transition: transform 80ms ease-out;
}
.next-card:active { transform: scale(0.99); }
/* urgency-rail-card again (§3, §6.1), matching the assignment list so the
   two read as one system. .next-why states the reason in words on every
   card — the endpoint guarantees a non-empty one — so the rail adds scan
   speed rather than carrying the meaning alone. */
.next-card { border-left: 3px solid transparent; }
.next-card[data-urgency='high'] { border-left-color: var(--c-warn); }
.next-card[data-urgency='medium'] { border-left-color: var(--c-primary); }
.next-card[data-urgency='low'] { border-left-color: var(--c-line); }






/* next-block load states (harden). The skeleton holds the slot's height from
   first paint so the primary grid below never jumps under a thumb on a slow
   connection — the same shape the real cards will take, never a spinner. */


/* Empty ("nothing due") and failure ("couldn't load, retry") — two distinct
   answers where the old code showed the same nothing for both. */




/* ============================================================ my subjects */
/* F-802, wireframe §6.2. */


/* Button reset for the openable variant (it is a real <button> now, so it
   arrives with the browser's font, centre alignment and default colour). */


/* The same corner chevron the home cards carry. Those got it because "several
   users read the first cut as static tiles" — subject cards open the reader
   and had no affordance at all, which is the identical trap. */




/* Requirement type carries a LABEL in every case, so colour is reinforcement
   and never the signal (F-812). */




.progress-track { height: 8px; background: var(--c-surface-3); overflow: hidden; }
.progress-fill { height: 100%; background: var(--c-primary); }
/* "with numeric label, never bar-only" — §3 component vocabulary. */



/* Skeleton — a shape of the real layout, not a spinner (§4). */
.skel-title { height: 18px; width: 55%; }
.skel-line { height: 13px; width: 40%;  margin-top: var(--s-2); }
@media (prefers-reduced-motion: no-preference) {
@keyframes skel-pulse { 0%,100% { opacity: 1 } 50% { opacity: .55 } }
}
.empty-state { display: flex; flex-direction: column; align-items: center; gap: var(--s-3);
               padding: var(--s-6) var(--s-4); text-align: center; color: var(--c-ink-2); }
.empty-glyph { font-size: var(--text-4xl); line-height: 1; color: var(--c-ink-3); }
.empty-state p { margin: 0; font-size: var(--text-sm); max-width: 30ch; }
.empty-state .btn-secondary { margin: 0; }
/* ============================================================ my results */
/* F-805, wireframe §6.5. */






/* data-table (§3): dense, horizontally scrollable, frozen first column —
   six mark columns do not fit 360px, and the subject name is the one thing
   that must stay in view while the rest scrolls. */
.table-scroll { margin: 0 var(--s-4); overflow-x: auto; -webkit-overflow-scrolling: touch;
                overscroll-behavior-x: contain; }
.data-table { width: 100%; border-collapse: collapse; font-size: var(--text-xs); }
.data-table th,
.data-table td { padding: var(--s-2); white-space: nowrap; }
.data-table thead th {
  text-align: left; font-size: var(--text-3xs); font-weight: 700;
  color: var(--c-ink-2); border-bottom: 2px solid var(--c-line);
}
.data-table tbody th {
  text-align: left; font-weight: 600; font-size: var(--text-xs);
  position: sticky; left: 0; background: var(--c-surface-2);
}
.data-table tbody tr { border-bottom: 1px solid var(--c-line-2); }
.data-table td { text-align: right; font-variant-numeric: tabular-nums; }



.data-table sup { font-size: var(--text-3xs); color: var(--c-link); margin-left: 2px; }
/* Separated by a rule, not a rail. The design system marks a break with
   .hr — a 2px divider — and uses no left borders anywhere. The accent rail
   here also encoded nothing: there is one kind of footnote, and the text
   already opens with the ৪ that ties it to the table row. */








/* ========================================================= my attendance */
/* F-806. Excused is never folded into the headline figure and never shares
   a colour with an unexcused absence — that distinction is the screen. */
/* P6: the horizontal inset is gone — this is a `card()` now, and the card
   sits inside the content column that already provides it. */









/* Below 75% a school starts intervening. The bar changes tone AND the count
   beside it says the same thing in words — colour is never the only carrier. */
.progress-fill[data-low='true'] { background: var(--c-warn); }
/* --------------------------------------------------------- segmented bar */
/* Wireframe §6.6's [ বাকি ] [ জমা ] [ মূল্যায়িত ]. Three options all visible
   and one tap away — a dropdown would hide two of the three answers to the
   only question this screen exists to answer. */
.seg-bar { display: flex; gap: 0; margin: 0 var(--s-4) var(--s-3);
           border: 1px solid var(--c-line); background: var(--c-surface); }


/* Selection is a filled block plus aria-selected — not colour alone. */

/* ── Exam routine with per-student clash check (F-510, wireframe §8.3) ──
   The screen "that proves the subject-based model". Everything below
   exists to make one thing readable at 360px: which papers clash, and
   which named children are caught by them. */
/* A flagged paper is tinted AND carries a labelled chip in its own cell.
   The tint alone would be colour-as-only-signal (F-812). */

/* The reschedule affordance sits under the paper it moves, so there is
   never any doubt which row a date picker belongs to. */







/* Roll numbers are identifiers: Latin digits, tabular, so a column of
   them scans as a column. */




.inline-notice.is-danger { color: var(--c-accent); background: var(--c-danger-soft); }
/* ── Group & optional-subject selection (F-305/F-304, §10.3) ───────────
   Derived subjects are TEXT; only the pools are controls. The visual split
   is the requirement: nothing that isn't a decision should look pressable. */




/* Chosen is a filled block, not a tint: at 360px in daylight a tint is not
   a reliable answer to "which one did I pick?". */








/* ── Routine editor (F-502/504/506, wireframe §8.1) ────────────────────
   The coordinator's hardest screen. Built on .data-table so it inherits the
   horizontal scroll and the frozen first column (§11) — six columns never
   fit 360px, and the period is what must stay in view while the rest moves. */
/* An explicit min-width is what makes the grid SCROLL instead of squeezing.
   Under table-layout:fixed a table sized to its container divides the width
   evenly and ignores per-column minimums, which crammed all five days into
   360px and broke "পদার্থবিজ্ঞান" across lines. Sized past the viewport
   (56 + 5x104), the columns get their real width and .table-scroll does its
   job — ~3 days visible at the 360px floor, exactly as §11 describes. */
.routine-grid { table-layout: fixed; min-width: 576px; }
.routine-grid th,
.routine-grid td { padding: 2px; vertical-align: top; }
.routine-grid thead th { width: 104px; text-align: center; font-size: var(--text-2xs); }
.routine-grid thead th:first-child { width: 56px; }



/* The break spans the week as one band, as §8.1 draws it. */

.routine-cell { padding: 2px !important; }
.routine-slot {
  display: flex; flex-direction: column; gap: 1px;
  width: 100%; min-height: var(--tap-min);          /* F-812, no exceptions */
  padding: var(--s-2) var(--s-1);
  border: 1px solid var(--c-line); border-radius: var(--radius);
  background: var(--c-surface); color: var(--c-ink);
  font: inherit; text-align: left; cursor: pointer; white-space: normal;
}
.routine-slot-subject { font-size: var(--text-2xs); font-weight: 700; line-height: 1.3; }
.routine-slot-meta { font-size: var(--text-3xs); color: var(--c-ink-2); line-height: 1.3; }
.routine-slot-meta[data-missing='true'] { color: var(--c-warn); font-weight: 600; }
.routine-slot-empty { font-size: var(--text-3xs); color: var(--c-ink-3); }

/* Held. The picked-up class stays obvious while the coordinator scrolls the
   grid looking for somewhere to put it — the whole reason this is a
   selection and not a drag. */
.routine-slot[data-selected='true'] {
  border-color: var(--c-primary); background: var(--c-primary-soft);
  box-shadow: inset 0 0 0 1px var(--c-primary);
}
/* Reachable. Marked across the WHOLE grid at once while something is held —
   the feedback a drag can only give for the one cell under the pointer.
   Dashed, not filled: these are candidates the database has not yet blessed. */
.routine-slot[data-target='true'] {
  border-style: dashed; border-color: var(--c-primary); color: var(--c-primary-ink);
}
.routine-slot[data-pinned='true'] { background: var(--c-surface-3); }
.routine-slot:disabled { cursor: default; opacity: 1; }
.routine-slot[data-filled='false']:disabled { border-style: dashed; opacity: .6; }
/* The pick-up banner: what is in hand, and what to do with it. */






/* ── Bulk import (F-1601, wireframe §10.2) ─────────────────────────────
   The screen a head teacher meets on day one with 784 rows. Almost all of
   this is about the sixteen that are wrong. */










/* Line numbers are what the operator types into Excel's "go to row" box,
   so they get a fixed column and tabular figures. */
/* The primary action carries both counts, so the skipped students cannot
   be pressed past without being read. It needs room to say so. */

/* P5 removed `.import-card input[type='file']`, which styled the raw file
   input this screen used before `fileUpload()` existed.
   It did not become harmless when the screen migrated — it became a BUG. The
   primitive hides its real input with `.ui-sr-only` and draws a styled label
   in front of it, and this rule is `(0,2,1)` against sr-only's `(0,1,0)`, so
   `width: 100%` won: a 1270px invisible input sat inside a 1280px viewport
   and the page scrolled sideways. Found by the acceptance sweep at 1280,
   which is the width B-34 did not drive. */
/* ── Routine generation result (F-503/F-505, wireframe §8.2) ───────────
   The screen where a coordinator decides whether to accept a machine's
   timetable for 1,200 children. The trade-offs sit ABOVE the accept
   button, never behind a disclosure — "nothing is silently accepted" is a
   layout requirement as much as a data one. */








/* The cause is what turns a complaint into an argument for a hire, so it
   is quieter than the fact but never hidden. */

/* Un-run rules read as an admission, not as a result. */


/* Background only, matching .gen-unchecked above. The left rails elsewhere
   in this file (.assign-card, .next-card) earn their colour by encoding
   state — urgency, overdue, done. This panel has no state to encode, so a
   rail here would be ornament wearing the clothes of a signal. */




/* ── Guardian home (F-1001/F-1002/F-203, wireframe §9.1) ───────────────
   "This persona has the lowest technical comfort in the product and may
   use the app four times a year — it must survive being forgotten."
   Everything below is sized and worded for somebody who does not remember
   what anything meant last time. */
/* The switcher never scrolls away — §9.1 calls it the single most-used
   control on this surface. */
/* Below ~340px two cards side by side start truncating the money, which is
   the one number that must never be clipped. */
@media (max-width: 359px) {

}
/* The status line is the largest thing in the card: it is the answer to
   the question the guardian opened the app to ask. */
/* Payment is one tap from home (§9.1), so the control is full-width and
   the last thing on the screen — where a thumb already is. */
.ward-cta { padding: 0 var(--s-4) var(--s-4); }

/* The binding shortage (F-503, §8.2). Sits above the soft-constraint list
   because it is the REASON periods are missing — a coordinator reading
   "৪টি পিরিয়ড বসানো যায়নি" without it is left to guess. This is the block
   somebody screenshots for a budget meeting, so it stays plain. */


/* ── F-202: issuing an activation code from the roster ─────────────────
   The one and only place the code is visible, sized to be read across a
   desk and copied onto a slip of paper by hand. */
.roster-issue { margin-left: auto; }
.issued-code-card { margin: 0 var(--s-4) var(--s-3); padding: var(--s-4);
                    display: grid; gap: var(--s-2); text-align: center; }
.issued-code-who { margin: 0; font-size: var(--text-xs); color: var(--c-ink-2); }
.issued-code-value { margin: 0; font-size: var(--text-4xl); font-weight: 700;
                     letter-spacing: 0.12em; font-variant-numeric: tabular-nums;
                     color: var(--c-ink-1); user-select: all; }
.issued-code-note { margin: 0; font-size: var(--text-2xs); color: var(--c-ink-3); line-height: 1.6; }
/* ── §7.5 class performance (F-1501) ─────────────────────────────────────
   Bars, not a chart library. Four rows at 360px need to be readable at a
   glance and survive a 2GB phone; a canvas chart would cost a dependency
   and read worse. */






/* The only tone in the panel. Below half a component's own maximum is an
   NCTB component-failure risk, not a design flourish. */


/* The panel's conclusion, so it carries weight rather than decoration.
   It had a 3px side tab; the only other side-borders in this system are
   transparent reserved gutters, and .perf-wide-note — the same kind of
   callout on this same screen — sets itself apart with a fill alone. Two
   callouts styled differently for no reason is the defect; font-weight
   does the emphasis without inventing a third grouping device. */

/* ── §7.5 attention list (F-1502) ────────────────────────────────────────
   Deliberately undecorated. No severity colour, no badge, no ordering cue.
   A visual hierarchy across children IS the ranking F-1502 forbids, so the
   rows are identical to each other by construction and the only thing that
   varies is the text of the observations. */



/* .card carries no padding in this system — each child insets itself, the
   way .section-heading does with its own margin. These children were
   written as if the card padded them and ran flush to the viewport edge. */

/* ── F-902 submission capture ────────────────────────────────────────────
   Hidden while SUBMISSION_MEDIA_ENABLED is false; styled now so turning it
   on is one constant, not a design task. */
.assign-capture { display: flex; flex-wrap: wrap; gap: var(--space-2);
                  align-items: center; margin-top: var(--space-3); }
.assign-capture-held { margin: 0; flex: 1 1 100%; font-size: var(--text-xs);
                       color: var(--c-ink-2); }
/* ── Browser surfaces ────────────────────────────────────────────────────
   The parts nobody draws still ship with the browser's own design: a blue
   selection highlight, a blue caret, a grey scrollbar, an underline welded
   to the baseline. On a warm-neutral page with a single red accent, every
   one of those reads as a different product showing through.

   Selection is tinted from the accent rather than set to it. A student
   selecting a Bangla paragraph to copy needs the text to stay readable, and
   full-strength #ec3013 behind dark ink does not. */
/* One accent, so the insertion point belongs to this product. */
[contenteditable] { caret-color: var(--color-accent-600); }
/* Native checkbox and radio fills — otherwise system blue. */
/* Underlines clear of Bangla descenders. The default sits on the baseline
   and cuts straight through ্র and ্য, which is illegible rather than
   merely untidy. */
/* A scrollbar in the page's own greys. Kept at a real width, not the
   hairline: the routine grid and ledger scroll horizontally, and on a
   low-end Android the scrollbar is the only affordance saying so. */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--color-neutral-400);
                            border: 2px solid var(--color-bg); }
::-webkit-scrollbar-thumb:hover { background: var(--color-neutral-500); }
/* ══ Dark theme — F-1607 ═══════════════════════════════════════════════════
   Every rule in this file resolves through the semantic aliases, so dark
   mode is a palette remap, not a second stylesheet. The neutral ramp is
   inverted end-for-end, which carries --c-surface, --c-line, --c-ink-2 and
   the rest along with it automatically; only the handful of tokens that
   need a different RUNG rather than a different value are restated below.

   One block, keyed on an attribute, rather than the usual pair of a
   @media query and an attribute override — that pattern duplicates thirty
   declarations and they drift. The boot script in index.html sets
   data-theme from localStorage or the OS preference before first paint, so
   there is no flash. Gating the theme on JS costs nothing here: this whole
   UI is built in TypeScript at runtime, so a page without JS has no app to
   theme in the first place.

   Not pure black. On the LCD panels these phones actually ship with there
   is no battery saving in #000, and on the OLED ones it smears while
   scrolling Bangla text. Warm near-black keeps the product's identity —
   the light theme is warm-neutral, and a cold grey dark mode would read as
   a different app after sunset. */
/* Browser surfaces follow the theme. The light-theme selection tint is a
   pale pink that would flare on near-black, and the scrollbar thumb needs
   to sit above the track rather than below it. */
/* F-1607 theme picker (More screen). Three equal segments — the choice is
   between peers, so none of them is a primary action. */
/* ═══════════════════════════════════════════════════════════════════════
   R-1 — tenant identity  (docs/11-MASTER-PLAN.md)

   Written against the semantic aliases like every rule above, so a
   tenant's colours reach these surfaces through the same --c-primary
   seam the rest of the app uses. No school-specific selectors exist and
   none may be added: per-institution CSS is what R-1 was built to avoid.
   ═══════════════════════════════════════════════════════════════════════ */
/* ── Shell: whose school this is ────────────────────────────────────────
   The `.shell-org*` rules MOVED to the shell block at the top of this file
   in P1. They lived here, 1,700 lines below the shell they belong to, and
   the distance was not cosmetic: `.shell-org { min-width: 0 }` silently beat
   `.shell-org-mobile { min-width: 88px }` on source order, and the school's
   name collapsed to two letters at 390px with no rule looking wrong.
   Identity rules for OTHER surfaces (login, documents) stay below. */
/* ── Login: the institution's mark, never the platform's ───────────── */
.login-brandmark.has-logo { background: transparent; padding: 0; }
.login-brandlogo { width: 56px; height: 56px; object-fit: contain;
                   border-radius: var(--radius-lg); display: block; }
/* ── Branding editor ───────────────────────────────────────────────── */
/* The screen header uses .att-header (the app-wide sticky header) and only
   needs the sub-line to sit under the title rather than beside it, since
   .att-header is a two-column grid. */





/* The preview sits beside the form once there is room for both to be
   legible; below that it follows the form, because a preview above the
   fold that pushes every input off it is worse than no preview. */
@media (min-width: 900px) {


}

.brand-card { padding: var(--s-4); }





/* --c-bg is not a defined token — the same bug the .chat-form comment above
   records, still present here in a third place. A swatch on a transparent
   background shows whatever is behind it, which for a colour PICKER is the
   one thing it must not do. */


/* A contrast warning is advice, not a refusal — a school may have a light
   brand colour and a good reason. It reads as a caution, not an error. */










/* ── Live preview ──────────────────────────────────────────────────── */






/* The paper preview renders ui-core's brandedLetterhead() output, so the
   class names below are that function's and must not be renamed here
   without changing it — they are one contract, which is the point. */









/* ═══════════════════════════════════════════════════════════════════════
   R-2 — notices and the notification bell
   ═══════════════════════════════════════════════════════════════════════ */
/* ── The bell ──────────────────────────────────────────────────────── */
/* Geometry comes from .shell-icon-btn, which the search control shares; only
   the badge below is the bell's own. */
/* The badge is a count, not a dot: "how many" is the question a teacher
   returning from leave is actually asking. */
/* ── Inbox ─────────────────────────────────────────────────────────── */

.notice-card { background: var(--color-bg); border: 1px solid var(--c-line);
               border-radius: var(--radius-lg); overflow: hidden; }
/* Unread carries a left rule and a heavier title, not only a tint — a pale
   background difference is the first thing to vanish in daylight on the
   2 GB reference phone. */


.notice-head { display: flex; align-items: flex-start; gap: var(--s-3);
               width: 100%; min-height: var(--tap-min);
               padding: var(--s-3); background: none; border: 0;
               text-align: start; cursor: pointer; font-family: inherit;
               color: var(--c-ink); }


.notice-main { display: flex; flex-direction: column; gap: 2px;
               flex: 1; min-width: 0; }
.notice-title { font-size: var(--text-sm); font-weight: 500; color: var(--c-ink);
                overflow-wrap: anywhere; }

.notice-meta { font-size: var(--text-2xs); color: var(--c-ink-2, var(--color-text-muted)); }


/* ── Composer ──────────────────────────────────────────────────────── */






.sms-toggle { display: flex; align-items: center; gap: var(--s-2);
              min-height: var(--tap-min); margin-top: var(--s-2);
              font-size: var(--text-sm); cursor: pointer; }
/* The cost sits with the toggle that causes it, and updates as the body is
   typed — SMS is ~80% of the infrastructure bill and the moment to learn
   that a notice is five segments is while writing it. */
.sms-cost { margin: var(--s-1) 0 0; font-size: var(--text-2xs);
            font-weight: 600; color: var(--c-warn); }
/* The audience restated in words, immediately above the send button: the
   last thing read before an irreversible action. */
.notice-confirm { display: flex; flex-wrap: wrap; align-items: baseline;
                  gap: var(--s-2); margin-top: var(--s-4); padding: var(--s-3);
                  border: 1px solid var(--c-line); border-radius: var(--radius-md);
                  background: var(--c-surface); }
.notice-confirm-line { margin: 0; font-size: var(--text-sm); font-weight: 600;
                       color: var(--c-ink); flex: 1; min-width: 0; }
/* B-7. `.notice-confirm` is a ROW — label, one line, two buttons — and that is
   right for a yes/no. Ending a guardianship asks for a reason in the same
   step, because the reason is required and a yes/no followed by a 400 is an
   obstacle rather than a confirmation. Six children in a row layout produced
   a squeezed strip of vertical text; this stacks them. */
.notice-confirm.is-stacked { flex-direction: column; align-items: stretch;
                             gap: var(--s-3); }
.notice-confirm.is-stacked .notice-confirm-line { flex: none; }
.notice-confirm.is-stacked .action-row { justify-content: flex-end; }
/* -- principal dashboard (P5) --------------------------------------------
   Mobile stacks; desktop puts exams, notices and fees side by side. A phone
   in a corridor is read top to bottom and a 1440px office screen that does
   the same wastes two thirds of itself — which is the difference between
   "responsive" and "genuinely desktop". */

/* ── Academic calendar (R-4) ───────────────────────────────────────────
   A month grid is tabular data, so it is a <table> and inherits
   .data-table's scroll container and header rules. Only the cell itself
   needs new styling.

   Every marker here is a SHAPE or a BORDER as well as a colour: the
   reference device is a 2 GB Android phone held in Dhaka daylight, where a
   pale tint is the first thing to stop being visible, and a colour-blind
   head teacher must still be able to see which day is the holiday. */





/* The weekend the TENANT configured — never a hardcoded Friday. */


/* A holiday is an underline as well as a tint, so it survives greyscale.
   Square bottom corners: an inset shadow follows the border-radius and
   renders as a curved "U" rather than a rule, which reads as decoration
   instead of a marker. Found by looking at it on a 375px viewport. */

/* Today is a ring, not a fill: a filled "today" competes with selection. */









/* 320px, 200% zoom: the grid must not push the page sideways (WCAG reflow).
   .data-table's own overflow-x container already handles the extreme case;
   this keeps it from being needed at ordinary phone widths. */
@media (max-width: 360px) {


}
/* P5. The month grid's gutters, on a narrow phone.
   Measured at 360: `.table-scroll` gave the grid 16px of margin AND 16px of
   padding on each side, so 64px of a 360px screen went to whitespace and the
   seven day cells came out 40px wide — under the 44px minimum, on the exact
   device this product is built for. At 390 they were 45px and passed, which
   is why only the 360/375 sweep found it.
   Below 400px the inner padding goes and the margin halves; 7 × 44 = 308,
   which fits 360 with room to spare. */

@media (max-width: 399px) {

.cal-grid .cal-day { min-width: 44px; }
}
/* ── Working weekend (R-4.1) ───────────────────────────────────────────
   Three states now share the grid, and two of them fall on the same
   columns: a Saturday is normally shut, and a make-up Saturday is open.
   So the working-weekend cell has to actively UNDO the weekend shading
   rather than merely add to it — a day that reads as closed while the
   system treats it as open is the calendar lying about what will happen.

   Like the holiday rule, the marker is a shape (a top rule) as well as a
   colour, so it survives greyscale and daylight on a cheap screen. */



/* The legend. Only the states present in the month on screen are drawn,
   so this is never a key to markers nobody can see. */





/* ── Document preview (R-5) ────────────────────────────────────────────
   The preview is an iframe holding a complete A4 document with its own
   stylesheet — see documents-view.ts for why. It only needs a frame and a
   sensible height here; everything inside it is the document's own.

   4:3-ish rather than A4's 1:1.41 on purpose: a full-height A4 preview on a
   phone is a page of whitespace you have to scroll past to reach the print
   button. The frame scrolls; the document inside is unchanged. */
.doc-preview {
  display: block; width: calc(100% - var(--s-4) * 2); height: 60vh; min-height: 320px;
  margin: 0 var(--s-4) var(--s-4);
  border: 1px solid var(--c-line); border-radius: var(--radius);
  background: #fff;
}
@media (min-width: 700px) {
.doc-preview { height: 70vh; }
}
/* When the app itself is printed (a user hitting Ctrl+P on the screen
   rather than the preview's own print button), print nothing: the shell,
   the tab bar and a scaled-down iframe are not a document. The real print
   path is iframe.contentWindow.print(), which prints only the document. */
/* ── R-6 · student search and one child's history ─────────────────────
   The screen is a list that becomes a record. Everything below is the
   record half; the list reuses .system-list / .system-row, because a
   search result and a settings row are the same shape and inventing a
   second one would mean two things to keep aligned. */

/* Tabs scroll sideways rather than wrap. Six labels wrap to two lines on a
   360px phone, and a two-line tab strip pushes the content people came for
   below the fold on the smallest screen the product supports. */


.tab {
  flex: none;
  min-height: var(--tap-min);
  padding: 0 var(--s-3);
  background: transparent; border: 0;
  border-bottom: 2px solid transparent;
  font-size: var(--text-sm); font-weight: 600;
  color: var(--c-ink-2); cursor: pointer;
  white-space: nowrap;
}
.tab.is-active {
  color: var(--c-primary);
  border-bottom-color: var(--c-primary);
}
.tab:focus-visible { outline: 2px solid var(--c-primary); outline-offset: -2px; }
.stu-panel { display: flex; flex-direction: column; }
/* The timeline. A year is a row, not a card: four to ten of them stack, and
   cards would put nine borders between a person and the year they want. */


/* Current is marked by weight and a rule on the leading edge, never by
   colour alone (F-812) — and the heading above it says "বর্তমান ভর্তি" in
   words, so the distinction survives a monochrome screen entirely. */






/* Profile pairs. Two columns on anything wider than a small phone, one
   column below it, because a label and a value squeezed side by side at
   360px leaves neither readable. */
.detail-list { margin: 0; padding: 0 var(--s-4); display: grid; gap: var(--s-2); }
.detail-list > div { display: flex; gap: var(--s-2); align-items: baseline; }
.detail-list dt { flex: none; min-width: 7.5rem; font-size: var(--text-2xs); color: var(--c-ink-2); }
.detail-list dd { margin: 0; font-size: var(--text-sm); overflow-wrap: anywhere; }
@media (min-width: 480px) {
.detail-list { grid-template-columns: 1fr 1fr; }
}

/* `.page-sub` normally sits inside `.page-header`, which supplies the
   horizontal padding. Used on its own — the result count, and the note
   explaining a withheld field — it hugged the screen edge while the list
   beside it was indented. Caught at 375px, where the misalignment is
   obvious and on a wide screen it is not. */

/* ==========================================================================
   COMPONENT SYSTEM  (UI integration plan, P2)

   Everything here is written against the semantic aliases (--c-*), never a
   literal colour, so a tenant's brand and both themes reach these surfaces
   through the same seam every other rule uses.

   Mobile-first: the rules below are the phone. The desktop half lives in the
   responsive block at the END of this file, for the reason recorded there —
   a single-class override written here loses on source order to any component
   rule declared after it, silently, with the media query matching.
   ========================================================================== */
/* -- visually hidden, but present for a screen reader --------------------- */
/* Not `display:none` and not `visibility:hidden` — both remove it from the
   accessibility tree, which is the one thing this class must not do. */
/* P5. The same declarations again, `!important`, for the CONTROLS.
   A visually-hidden control still matches every legacy `input`/`select`
   descendant selector in this file, and any of them with a `width` beats
   `.ui-sr-only` on specificity — which is how `fileUpload`'s hidden input
   became 1270px wide inside a 1280px viewport and scrolled the page
   sideways. "Hidden" has to be unarguable: this class exists so a screen
   reader can reach the control and an eye cannot, and a stray descendant
   rule must not be able to make it visible. */
/* -- focus, once, for everything ------------------------------------------ */
/* 04-UIUX §5: a visible 2px outline with 2px offset on every interactive
   element, and never `outline: none`. Declared here so a component cannot
   forget it, and `:focus-visible` so a mouse click does not draw a ring. */
.ui-icon { display: inline-flex; width: 1em; height: 1em; }
.ui-icon svg { width: 100%; height: 100%; }
/* -- buttons -------------------------------------------------------------- */
/* .btn-primary/.btn-secondary/.btn-ghost already exist above and are used by
   130 call sites; these add only what the system needs on top of them, so the
   two can coexist while P3–P6 migrate screen by screen. */
/* Destructive is its own colour, never a tinted primary: a delete that looks
   like save is how a section disappears under a hand reaching for save. */
/* `.btn-primary` and `.btn-success` set `width: 100%` far above — correct for
   the phone-only app they were written for, wrong for a button in a table row
   or a page header. This marker restores intrinsic width for every button the
   component system builds; `.btn-block` opts back in where full width is the
   design (a form's submit, a sheet's confirm). Legacy call sites carry neither
   class and are untouched. */
/* Also a flex container. `.btn-primary` computes to `display: block`, so a
   glyph, a label and a spinner inside it laid out as inline flow — which is
   why the busy spinner rendered as a 4x30 vertical bar instead of a 16px ring
   until the gallery showed it. Legacy buttons contain one text node and never
   noticed. */


/* A busy button keeps its width (pinned in JS) so nothing beside it moves. */

/* Primary LAST in the DOM. On a phone the column reverses so the primary is
   bottom-most under the thumb; on desktop the row keeps source order and the
   primary finishes the line on the right. */
/* One rule, everywhere: DOM order is PRIORITY order, least important first.
   On a phone that column puts the primary action at the BOTTOM, under the
   thumb; on desktop the same source order becomes a row and the primary
   finishes the line on the right. `column-reverse` was the first attempt and
   did the opposite of what its own comment claimed — the rendered gallery is
   what caught it. */
/* -- cards ---------------------------------------------------------------- */


/* P5. A grid of choice-cards. Used where the rows are a CHOICE with a
   sentence each — which document to print, which setting lives where —
   rather than records with fields, which is what `dataTable` is for. One
   column on a phone; the desktop half is in the responsive block at the end. */
.ui-card-grid { display: grid; grid-template-columns: 1fr; gap: var(--s-3); }
.ui-card-grid > .ui-card { margin: 0; }
/* P6. The week routine, as a school draws it on a wall.
   Mobile-first here means the GRID is hidden and the stacked day list shows;
   the swap is in the responsive block at the end of this file, for the reason
   recorded there. A 7-column grid at 360px is unreadable, and a stack of
   seven days at 1440 makes "Wednesday, period 3" a scrolling exercise. */

.routine-grid { width: 100%; border-collapse: collapse; }
.routine-grid th,
.routine-grid td {
  border: 1px solid var(--c-line); padding: var(--s-2); vertical-align: top;
  text-align: start; font-size: var(--text-2xs); }
.routine-grid thead th { background: var(--c-surface-2); font-weight: 700;
  color: var(--c-ink-2); white-space: nowrap; }
.routine-grid-period { background: var(--c-surface-2); white-space: nowrap;
  display: flex; flex-direction: column; gap: 2px; }
/* P9-8. The period column is PURE number, which is what `--font-bn-num` was
   written for — "numerals only … letters stay on Hind Siliguri". B-108's
   `ShikhonBnNum` face already routes every ০-৯ in the product, including the
   ones inside sentences that no class selector can reach; this states the
   convention on the element where the whole content is a figure, and is safe
   here precisely because there are no letters in it to drag along. */
.routine-grid-no { font-weight: 700; color: var(--c-ink-1);
  font-family: var(--font-bn-num); }
.routine-grid-time { font-family: var(--font-bn-num); font-size: var(--text-3xs);
  color: var(--c-ink-2); line-height: 1.3; white-space: nowrap; }
.routine-grid-time { color: var(--c-ink-3); font-variant-numeric: tabular-nums; }
/* P9-9 §5. The break, on screen. Its own row spanning the whole grid — the
   same shape the printed sheet gives it, so the screen a head checks and
   the paper they pin up show the same day. This is SCREEN styling; the
   sheet's own band is in `routineSheetCss()` and shares nothing but the
   idea (§22). */



/* P9-9. The word after the ordinal, small and muted: the column says
   '৩য় পিরিয়ড' without the word competing with the number. */






/* A word, never a tint: the day list says "বদলি" too, and a teacher reading
   the grid must not have to learn a second vocabulary. */



/* P5. A group of related checkboxes with a legend. `fieldset` carries the
   grouping to a screen reader; the browser's default border and padding are
   removed because the card already draws the box. */
.ui-fieldset { border: 0; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: var(--s-2); }
.ui-fieldset > .ui-field-label { padding: 0; }
/* P5. The three shapes a card's body takes when it holds a fact rather than a
   list: one figure, one qualifier under it, or a set of labelled pairs. Added
   here rather than as one-off inline styles because five screens now need
   exactly these and each was inventing its own margin. */
.ui-card-lead { margin: 0; font-size: var(--text-lg); font-weight: 600;
  color: var(--c-ink-1); line-height: 1.3; }
.ui-card-note { margin: var(--s-1) 0 0; font-size: var(--text-2xs);
  color: var(--c-ink-3); }
.ui-card-lead + .ui-card-note { margin-top: var(--s-1); }
/* P9. Three layout hooks the routine screens had been using with no rule
   behind them — `.ui-stack` since P9-1, `.setup-period-row` since P9-2. They
   rendered as bare block elements: legible, touching each other, and wrong on
   a phone, where a row of five bell-time inputs became five full-width boxes
   with no gap. Named `ui-` because they are generic and three views share
   them; a fourth would otherwise invent a fourth margin. */
.ui-stack { display: flex; flex-direction: column; gap: var(--s-2); }
/* A badge, a fact and a control on one line, wrapping rather than
   overflowing — 360px cannot hold all three side by side. */

.ui-cell-meta { font-size: var(--text-2xs); color: var(--c-ink-3);
  font-variant-numeric: tabular-nums; }
/* Name, start, end, kind, remove. On a phone the name takes the full width
   and the two times share the next line, because a 45-minute period is read
   as a pair and splitting it across rows loses that. */


@media (min-width: 640px) {


}
/* A <dl> of label/value pairs. Stacks on a phone, pairs up from 480px — the
   width at which a label and its value both fit on one line without either
   wrapping, measured rather than guessed. */
.ui-facts { display: grid; grid-template-columns: 1fr; gap: var(--s-1) var(--s-3);
  margin: 0; }
.ui-facts-key { font-size: var(--text-2xs); color: var(--c-ink-3); }
.ui-facts-val { margin: 0 0 var(--s-2); font-size: var(--text-sm);
  color: var(--c-ink-1); font-weight: 500; }
/* A form laid out inside a card: fields stacked, the button row separated. */
.ui-card-form { display: flex; flex-direction: column; gap: var(--s-3); }
.ui-card-form > .ui-button-row { margin-top: var(--s-1); }
/* The action cluster inside a table row or list item. Wraps rather than
   overflowing: two buttons at 360px do not fit on one line beside a name. */
.ui-row-actions { display: flex; flex-wrap: wrap; gap: var(--s-2);
  align-items: center; justify-content: flex-end; }
/* A checkbox with a real hit area.
   The bare <input type=checkbox> is 13px. That is not a touch target, and
   B-34's sweep reported it as one until the probe was corrected to measure
   the enclosing label — so the label has to actually BE the target. */
.ui-check { display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; margin: calc(var(--s-2) * -1); cursor: pointer; }
.ui-check-box { width: 20px; height: 20px; accent-color: var(--c-primary);
  cursor: pointer; }
.ui-check:focus-within { outline: 2px solid var(--c-primary); outline-offset: -4px;
  border-radius: var(--radius-sm); }





/* -- stat cards ----------------------------------------------------------- */
/* The label reads first to a screen reader and second to the eye. */
/* -- avatar --------------------------------------------------------------- */




/* Six fixed tints, each chosen to carry white at AA. Not tenant-branded: a
   roster is scannable because the colours DIFFER, and a class of sixty in one
   brand hue would defeat the point.
   The ratios against white are measured, not assumed: the terracotta was
   #A76A47 until P4 put an avatar in the child selector and the sweep measured
   it at 4.38:1 — under AA for 11px text, which every .is-sm avatar is. The
   hue is unchanged; only the lightness moved, to 5.20:1. */

/* 6.27:1 */

/* 4.63:1 */

/* 4.78:1 */

/* 5.20:1 */

/* 6.17:1 */

/* 5.49:1 */
/* -- page header ---------------------------------------------------------- */
/* 24px minimum height even though these are inline links in a trail, which
   WCAG 2.2 exempts from target size. The exemption is about not breaking
   prose; a breadcrumb is a control strip that happens to read like prose, and
   23px was what the sweep measured. */
/* P5. A crumb may be a <button> when the depth is in-page rather than in the
   URL (see Crumb.onClick). It must be indistinguishable from the anchor. */
/* -- badges --------------------------------------------------------------- */


/* -- fields --------------------------------------------------------------- */
/* Icon + text, never colour alone (04-UIUX §5). */
/* -- search --------------------------------------------------------------- */
/* -- upload --------------------------------------------------------------- */
/* -- tables and lists ----------------------------------------------------- */
/* The desktop table is hidden on a phone; the list is hidden on desktop. Both
   are in the DOM and `display:none` removes one from the accessibility tree
   as well as the page — see the module header for why this beats re-rendering
   on a breakpoint cross. */
/* -- timeline ------------------------------------------------------------- */
/* The rail and dot are decoration, so they are pseudo-elements: a reader hears
   the entries, not a column of bullets. */
/* -- tabs ----------------------------------------------------------------- */
/* -- filters -------------------------------------------------------------- */
/* Compact for a mouse, full size for a finger — the same question the sidebar
   asks. A chip that removes a filter is recoverable if mis-tapped, but a row
   of three 34px targets on a phone is a row of three mistakes. */
/* -- overlays ------------------------------------------------------------- */
/* A sheet rises; a modal fades. Both respect the reduced-motion block below. */
/* -- toasts --------------------------------------------------------------- */


/* -- loaders and progress ------------------------------------------------- */
/* -- permission / error states -------------------------------------------- */


/* ==========================================================================
   TEACHER HOME  (P3)

   One dominant action and a day, not a wall of statistics. Everything below
   is built from the P2 components; these rules only place them.
   ========================================================================== */
/* The urgent block. Accent GROUND rather than an accent button on white —
   there is exactly one of these on the screen, so it can afford to be the
   thing the eye lands on, and when every register is in it is replaced by a
   plain card rather than a quieter version of itself. */

/* Happening now: a left rule, because the tint is already spent on "urgent"
   and a second tint would say "more urgent" without meaning it. */





/* A substitution is explained, never just badged: "why am I in this room"
   is the question, and a chip reading "বদলি" does not answer it. */





/* The period happening now, in the day list. A left rule and a weight — not
   a background, which would compete with the urgent block above it. */


/* ==========================================================================
   ATTENDANCE — the status a teacher must always be able to read  (P3)

   §"The teacher must always know: what section, what date, what
   subject/period, how many students, how many marked, whether changes are
   saved, whether changes are only queued locally." Every one of those is a
   WORD below. Colour echoes; it never carries.
   ========================================================================== */




/* Offline is stated on this screen as well as in the shell banner. The shell
   says "you are offline"; this says what that means for the register in front
   of you, which is the only question a teacher actually has. */
.att-offline-glyph { display: flex; width: 16px; height: 16px; flex: none; margin-top: 2px; }
.att-offline-glyph svg { width: 100%; height: 100%; }
/* The queued/failed line, with the retry that did not exist before P3: the
   chip has said "৩টি পাঠানো যায়নি" since R-0 with no way to act on it. */
.att-sync-text { flex: 1; min-width: 0; font-size: var(--text-2xs); color: var(--c-ink-2); }

.att-host { display: block; }
/* ── routine: a substitution explains itself (P3) ───────────────────────── */
/* The old `.routine-sub-tag` said "পরিবর্তী ক্লাস" — it named the fact and
   answered none of the question a teacher standing in an unfamiliar corridor
   is actually asking. */



/* ==========================================================================
   STUDENT & GUARDIAN  (UI integration plan, P4)

   §3: "never make a parent wonder which child they are viewing." The child
   selector and the identity block below are the whole of that promise, and
   they are the only new visual language this phase introduces — everything
   else is P2 components placed.
   ========================================================================== */
/* -- the child selector: two or three children, side by side -------------- */
/* Permanently on screen, because a control that answers "which child" only
   after you tap it answers it at the moment the answer stops mattering. */
/* Three signals on the selected child — tint, weight and a border — because
   this is the one control whose state a person must never have to guess. */
/* -- four or more: a button that names the current child ------------------ */
.ui-child-caret { display: flex; margin-inline-start: auto; flex: none; }
.ui-child-caret svg { width: 18px; height: 18px; }
/* A word, not only a tint: this row IS the answer to "which child". */
/* -- the identity block: whose screen this is ----------------------------- */
.ward-cta { margin-top: var(--s-4); }

/* -- student home --------------------------------------------------------- */


/* An urgent item gets a rule, not a wash: the badge already says "জরুরি" and
   a tinted row would say it a second time, louder and less clearly. */

/* ==========================================================================
   RESPONSIVE — the desktop layouts, deliberately LAST in this file  (P1)

   Placement is load-bearing, not tidiness. Custom properties cascade by
   specificity and then by source order, and almost every component rule in
   this file is a single class. A desktop override written where the shell
   block sits (line ~560) is a single class too, so it LOSES to any component
   rule declared after it — silently, with the media query matching and the
   declaration simply overridden.

   P1 hit this three times in one afternoon: the school's name rendered twice
   on desktop (`.shell-org` at line 2160 beat `.shell-org-mobile{display:none}`
   inside the query), and the home grid stayed two-up because `.secondary-grid`
   is declared at line 1180. Neither looks wrong in the source. Both are
   obvious the moment the query is last.

   Rule for every phase after this one: responsive overrides go here, at the
   bottom, or they go into a selector specific enough to prove they meant it.
   ========================================================================== */
@media (min-width: 1024px) {
/* The rail: icons, tooltips (the rows carry `title`), nothing else. */
/* Chrome that belongs to the phone. The school's name was rendering twice
     on desktop — once in the sidebar, once in the topbar beside the
     breadcrumb — because `.shell-org { display:flex }` was declared 1,700
     lines below this hide rule and won on source order. Both halves of that
     fix are in place now: the identity rules moved up beside the shell, and
     this query is last in the file. The descendant selector stays as belt
     and braces, since this is the rule whose failure is most visible. */

/* The home grids were laid out for a 360px phone: two columns of tall
     tiles. At 1200px that is six tiles and a screenful of nothing beneath
     them — exactly the "giant empty spaces" the brief rules out. The COLUMN
     COUNT is the responsive fix. The tiles, their order, their contents and
     which role sees which are untouched: the dashboards themselves are P3–P5,
     and reflowing a grid is not redesigning one. */



/* ── component system: the desktop half (P2) ─────────────────────────── */
/* Buttons sit in a row again, primary last on the right where the eye
     finishes. The mobile rule is column-reverse so the primary is bottom-most
     under the thumb; this is the same source order, laid out the other way. */
/* auto-fit, not a fixed 4. `repeat(4, 1fr)` is right for a row of four and
     wrong for every other count: the guardian home and the principal's
     "today" band both carry TWO stat cards, and at 1440 they were rendering
     at a quarter width each with half the row empty. auto-fit gives two cards
     two columns and four cards four. */
/* The table appears and the list disappears. Neither is re-rendered — see
     the ui/table.ts header for why both live in the DOM. */
/* A modal, not a sheet: centred, with breathing room, and capped so a long
     form scrolls inside the dialog rather than growing past the viewport. */
/* ── teacher home (P3) ────────────────────────────────────────────────── */
/* The urgent block becomes a band: the action sits beside its context
     rather than under it, because on a laptop a full-width button under a
     two-line heading is a hundred pixels of nothing. */







/* ── attendance (P3) ─────────────────────────────────────────────────── */
/* A real desktop grid, not a stretched phone one. 56px tiles at auto-fill
     across a 1200px column give ~18 per row, which is a wall; capping the
     tile at 84px and the grid at a readable width keeps a class of sixty to
     four scannable rows. The sticky footer becomes a normal one — there is no
     thumb to reach on a laptop and 96px of reserved space is 96px wasted. */

.att-footer { position: static; padding: var(--s-4) 0; }
.att-footer .btn-primary { width: auto; min-width: 220px; }
/* The facts read as a row of labelled columns rather than a wrapped list. */


.att-header { padding-inline: 0; }
/* ── student & guardian (P4) ──────────────────────────────────────────── */

/* The child strip stops stretching: three names across 1200px would put a
     child's name at each end of the screen and the question back on the
     reader. */
}
/* Large desktop: more air in the gutters, same 1200px column. */
/* P5. The principal dashboard's middle band, at desktop widths. Placed at the
   END of this file on purpose: the responsive overrides here are equal in
   specificity to the base rules, so source order is what decides, and P1 spent
   a day on a school name that rendered twice because a hide rule sat 1,700
   lines above the thing it was hiding. */
@media (min-width: 1024px) {

}
@media (min-width: 1440px) {

}
/* P5. The label/value pairs go two-up once there is room for both halves of a
   pair on one line. Here, not beside the base rule, for the reason this whole
   block exists. */
@media (min-width: 480px) {
.ui-facts { grid-template-columns: max-content minmax(0, 1fr); align-items: baseline; }
.ui-facts-key { padding-top: 2px; }
.ui-facts-val { margin-bottom: var(--s-1); }
}
/* P5. The choice-card grid, at desktop widths. `auto-fit` rather than a fixed
   count: this grid carries four cards on the settings hub and six on the
   documents picker, and a hard `repeat(3, 1fr)` is the bug `.ui-stat-row` had
   until B-34 measured a two-card row rendering at a quarter width. */
@media (min-width: 640px) {
.ui-card-grid { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
}
/* P6. The week routine swaps shape at the desktop breakpoint. Declared here,
   at the END, because these are single-class overrides and source order is
   what decides — the rule this whole block exists for. */
@media (min-width: 1024px) {


}
/* A guardian's phone number, as a call.  (P-pilot-hardening)
   Inside `.att-sub`, which is --text-xs: a bare anchor there is a tap target
   well under the touch floor, and this one is pressed on a phone by somebody
   who has just seen a child marked absent. Inline-block with vertical padding
   rather than a button, because it belongs in the sentence beside the
   relation — and the number itself stays Latin, per the R-8 rule that
   identifiers are not written in Bangla numerals. */
.ui-call {
  display: inline-block; min-height: var(--tap-min); line-height: var(--tap-min);
  padding: 0 var(--s-1); margin: calc(var(--s-1) * -1) 0;
  color: var(--c-link); text-decoration: underline;
  text-underline-offset: 2px; font-variant-numeric: tabular-nums;
}
.ui-call:hover { color: var(--c-primary); }
.ui-call:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 2px; }
/* ── Routine findings (P9-4) ───────────────────────────────────────────
   One list of problems, ordered by severity, each row a way into the
   explanation drawer. The severity is a WORD before it is a colour: a red
   dot is invisible to a screen reader and to anyone who cannot separate it
   from the amber one, so `statusBadge` carries the label and the left rail
   only reinforces it. */





/* The whole row is the control: one tap target on a phone, one tab stop
   for a keyboard, rather than a line of text with a small link at its end. */







/* ── Routine editor: lock and undo (P9-5) ──────────────────────────────
   The lock is a WORD before it is a padlock. A glyph alone says nothing to
   a screen reader and nothing to a coordinator who has not been told what
   it means, and the consequence — a later solver run will leave this alone
   — is the part that actually matters. */

.routine-slot[data-pinned='true'] {
  /* Background, not a left rail: the cell is already inside a grid whose
     borders carry structure, and a second rail there would read as an
     error state rather than as a deliberate choice the coordinator made. */
  background: var(--c-surface-2);
}
/* Above the grid, where the edit just happened. Wraps rather than
   truncating: the button names what it will reverse, and a name cut in half
   is worse than a wrapped line. */

/* ── Scoped re-solve: what just moved (P9-6 §16) ───────────────────────
   Marked until the coordinator's next action, not on a timer: a highlight
   that vanishes while somebody is still reading the grid is worse than
   none. The accessible name carries the same fact, because §22 forbids
   state that exists only as a colour. */
.routine-slot[data-changed='true'] {
  box-shadow: inset 0 0 0 2px var(--c-primary);
}

/* ═══ [4] Ata Ekta — wave 1: shared components ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── ui-page-header ── */
.ui-crumb-link.n { font-family: var(--font-num); }
.ui-back .ui-icon { width: 14px; height: 14px; flex: none; }
.page-header .page-header-text h1,
.ui-section-head .ui-section-title { letter-spacing: -.01em; }

/* ── ui-button ── */
button[data-busy="true"]:disabled { opacity: .85; cursor: progress; }
.btn-glyph { display: inline-flex; width: 1em; height: 1em; flex: none; }
.btn-glyph svg { width: 100%; height: 100%; }
.ui-icon-btn { font-size: var(--text-h3); }
.ui-icon-btn:disabled,
.ui-icon-btn.is-danger:disabled { opacity: .45; cursor: default; background: transparent; border-color: var(--line); }
:where(.btn-sm) { position: relative; }
.btn-sm::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: var(--tap-min); transform: translateY(-50%); }
@media (prefers-reduced-motion:reduce) {
.btn-ghost:active:not(:disabled),
.btn-danger:active:not(:disabled),
.btn-success:active:not(:disabled),
.ui-icon-btn:active,
.ui-page-btn:active,
.shell-icon-btn:active,
.shell-menu-item:active { transform: none; }
}

/* ── ui-card ── */
.card.ui-card-interactive { display: block; width: 100%; padding: 0; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; }
.ui-card-body:first-child { padding-top: var(--space-4); }
.card:not(.ui-card-interactive):hover { box-shadow: none; }
.ui-stat.ui-card-interactive { width: 100%; color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; cursor: pointer; }
.ui-stat.ui-card-interactive:hover { background: var(--neutral-100); }
.ui-stat.ui-card-interactive:focus-visible { outline-offset: -2px; }
.card.ui-card-interactive:active,
.ui-stat.ui-card-interactive:active { background-color: var(--neutral-100); }
.ui-card-glyph[data-tone="info"] { background: var(--info-tint); color: var(--info); }
.ui-stat-glyph[data-tone="info"] { color: var(--info); }
.ui-stat-glyph[data-tone="accent2"] { color: var(--ink-2); }
.ui-stat[data-tone="success"] .ui-stat-value { color: var(--ok); }
.ui-stat[data-tone="warn"] .ui-stat-value { color: var(--warn); }
.ui-stat[data-tone="danger"] .ui-stat-value { color: var(--danger); }
@media (max-width:1023.98px) {
.ui-stat-row { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width:1023.98px) {
.ui-stat-row>.ui-stat:nth-child(2n) { border-right: none; }
}
@media (max-width:1023.98px) {
.ui-stat-row>.ui-stat:nth-child(n+3) { border-top: 1px solid var(--line); }
}
@media (max-width:1023.98px) {
.ui-stat-row[data-count="1"],
.ui-stat-row[data-count="3"],
.ui-stat-row[data-count="5"],
.ui-stat-row[data-count="7"],
.ui-stat-row[data-count="9"] { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width:1023.98px) {
.ui-stat-row[data-count="3"]>.ui-stat,
.ui-stat-row[data-count="5"]>.ui-stat,
.ui-stat-row[data-count="7"]>.ui-stat,
.ui-stat-row[data-count="9"]>.ui-stat { border-right: none; }
}
@media (max-width:1023.98px) {
.ui-stat-row[data-count="3"]>.ui-stat+.ui-stat,
.ui-stat-row[data-count="5"]>.ui-stat+.ui-stat,
.ui-stat-row[data-count="7"]>.ui-stat+.ui-stat,
.ui-stat-row[data-count="9"]>.ui-stat+.ui-stat { border-top: 1px solid var(--line); }
}
.ui-avatar { display: inline-grid; place-items: center; flex: none; overflow: hidden; border-radius: var(--r-pill); background: var(--inset); border: 1px solid var(--line); color: var(--ink); font-family: var(--font-bn); font-weight: 600; line-height: 1; object-fit: cover; }
.ui-avatar.is-sm { width: 30px; height: 30px; font-size: 13px; }
.ui-avatar.is-md { width: 40px; height: 40px; font-size: 16px; }
.ui-avatar.is-lg { width: 52px; height: 52px; font-size: 22px; }

/* ── ui-badge ── */
.ui-badge-glyph { display: inline-flex; flex: none; width: 12px; height: 12px; }
.ui-badge-glyph svg { display: block; width: 100%; height: 100%; stroke-width: 2; }

/* ── ui-field ── */
.ui-input::placeholder { color: var(--ink-3); opacity: 1; }
.ui-input:focus,
.ui-select:focus { box-shadow: none; }
.ui-input:disabled { border-color: var(--line); }
.ui-field.is-error .ui-input { padding: 0 11px; }
.ui-field.is-error textarea.ui-input { padding: 10px 11px; }
.ui-field.is-error .ui-input:focus { outline: 2px solid var(--danger); outline-offset: 2px; }
.ui-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.ui-search-input { -webkit-appearance: none; appearance: none; }

/* ── ui-upload ── */
.ui-upload { position: relative; }
.ui-upload .ui-upload-input { position: absolute; width: 1px; height: 1px; min-height: 0; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.ui-upload-input:focus-visible+.ui-upload-trigger { outline: 2px solid var(--accent); outline-offset: 2px; }
.ui-upload-chosen,
.ui-upload>.ui-field-error { align-self: stretch; }
.ui-upload-file { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-top: 1px solid var(--line); }
.ui-upload-file-glyph { display: inline-flex; flex: none; width: 16px; height: 16px; }
.ui-upload-file-mark { display: inline-flex; flex: none; width: 15px; height: 15px; color: var(--ink-3); }
.ui-upload-file[data-state="done"] .ui-upload-file-mark { color: var(--ok); }
.ui-upload-file-glyph svg,
.ui-upload-file-mark svg { width: 100%; height: 100%; }
.ui-upload-file-text { flex: 1; min-width: 0; }
.ui-upload-file-name { display: block; font-weight: 600; overflow-wrap: anywhere; }
.ui-upload-file-meta { display: block; }

/* ── ui-filter ── */
.ui-tabs { overflow-y: hidden; }
.ui-tab:focus-visible { outline-offset: -2px; }
.ui-filters-inline>.ui-filter-field { display: none; }
.ui-filters-inline:not(:has(>.ui-filters-extra)) { display: none; }
.ui-filters-extra { width: 100%; }
@media (min-width:1024px) {
.ui-filters>.ui-filters-inline,
.ui-filters-inline>.ui-filter-field { display: flex; }
}
@media (min-width:1024px) {
.ui-filters-extra { margin-left: auto; width: auto; }
}
@media (min-width:1024px) {
.ui-filters-open { display: none; }
}
.ui-filters-open { align-self: flex-start; }
.ui-filter-chip { min-height: var(--tap-min); font-family: var(--font-bn); cursor: pointer; }
.ui-filter-clear { min-height: var(--tap-min); padding: 0 var(--space-2); }
.ui-filter-field.is-stacked .ui-field-label { margin-bottom: 0; }

/* ── ui-table ── */
.ui-data[data-shape="table-list"]>.ui-table-scroll { display: none; }
@media (min-width:1024px) {
.ui-data[data-shape="table-list"]>.ui-table-scroll { display: block; }
}
@media (min-width:1024px) {
.ui-data[data-shape="table-list"]>.ui-list { display: none; }
}
.ui-data[data-shape="table-list"]>.ui-list { border: none; border-radius: 0; }
.ui-table [data-numeric="true"] { text-align: right; }
.ui-table tbody th { padding: 10px 12px; font-size: 14px; font-weight: 400; letter-spacing: normal; text-transform: none; color: var(--ink); background: transparent; border-bottom: 1px solid var(--line); white-space: normal; }
.ui-table tbody tr:last-child>th,
.ui-table tbody tr:last-child>td { border-bottom: none; }
.ui-table .ui-table-action { padding-top: 0; padding-bottom: 0; }
.ui-row-open { display: inline-grid; place-items: center; vertical-align: middle; min-width: var(--tap-min); min-height: var(--tap-min); border-radius: var(--r-sm); font-size: var(--text-body); }
.ui-row-open:hover { background: var(--inset); color: var(--ink); }
.ui-row-open:active { transform: scale(.97); }
.ui-list-hit { color: var(--ink); font-size: inherit; line-height: inherit; }
.ui-list-glyph>.ui-icon,
.ui-list-chevron>.ui-icon { display: block; }
.ui-data[data-shape="table-list"]>.ui-list .ui-list-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-list-status[data-tone] { font-size: var(--text-body); font-weight: 700; }
.ui-list-status[data-tone="success"] { color: var(--ok); }
.ui-list-status[data-tone="warn"] { color: var(--warn); }
.ui-list-status[data-tone="danger"] { color: var(--danger); }
.ui-list-status[data-tone="info"] { color: var(--info); }
.ui-list-status[data-tone="neutral"] { color: var(--ink); }

/* ── ui-overlay ── */
@media (max-width:1023.98px) {
.ui-scrim[data-kind="modal"],
.ui-scrim[data-kind="drawer"] { align-items: flex-end; justify-content: stretch; padding: 0; }
}
@media (max-width:1023.98px) {
.ui-scrim[data-kind="modal"] .ui-dialog,
.ui-scrim[data-kind="drawer"] .ui-dialog { max-width: none; height: auto; max-height: 90dvh; border-radius: var(--r-lg) var(--r-lg) 0 0; }
}
.ui-scrim[data-kind="sheet"] .ui-dialog::before { content: ""; display: block; flex: none; width: 34px; height: 4px; margin: var(--space-2) auto 0; border-radius: var(--r-pill); background: var(--line); }
@media (max-width:1023.98px) {
.ui-scrim[data-kind="auto"] .ui-dialog::before,
.ui-scrim[data-kind="modal"] .ui-dialog::before,
.ui-scrim[data-kind="drawer"] .ui-dialog::before { content: ""; display: block; flex: none; width: 34px; height: 4px; margin: var(--space-2) auto 0; border-radius: var(--r-pill); background: var(--line); }
}
@media (max-width:1023.98px) {
.ui-dialog-foot>.ui-button-row { flex: 1 1 auto; }
}
@media (max-width:1023.98px) {
.ui-dialog-foot>.ui-button-row>:last-child { flex: 1 1 auto; }
}
.ui-dialog-glyph { display: inline-flex; flex: none; width: 20px; height: 20px; color: var(--danger); }
.ui-dialog-glyph svg { width: 100%; height: 100%; }
.ui-dialog-close .ui-icon { width: 18px; height: 18px; }
.ui-dialog { padding-bottom: env(safe-area-inset-bottom, 0px); }

/* ── ui-feedback ── */
.ui-toast-glyph { display: flex; flex: none; width: 16px; height: 16px; }
.ui-toast-glyph svg { width: 100%; height: 100%; }
.ui-toast[data-tone="success"] .ui-toast-glyph { color: var(--ok); }
.ui-toast[data-tone="error"] .ui-toast-glyph { color: var(--accent-400); }
.ui-toast[data-tone="info"] .ui-toast-glyph { color: var(--info); }
.ui-toast-close { display: inline-flex; align-items: center; justify-content: center; min-width: var(--tap-min); min-height: var(--tap-min); margin: -12px -10px -12px 0; }
.ui-inline-loader-label { font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.ui-progress-head { display: flex; align-items: baseline; gap: var(--space-2); }
.ui-progress-head .ui-progress-label { flex: 1; min-width: 0; }
.ui-progress-pct { flex: none; font-size: 12.5px; font-weight: 700; color: var(--ink); }
.ui-list-skeleton>.ui-skel-row:nth-child(3n+2) .skel-bar { width: 58%; }
.ui-list-skeleton>.ui-skel-row:nth-child(3n+2) .skel-bar.is-short { width: 38%; }
.ui-list-skeleton>.ui-skel-row:nth-child(3n) .skel-bar { width: 46%; }
.ui-list-skeleton>.ui-skel-row:nth-child(3n) .skel-bar.is-short { width: 31%; }
.ui-state-denied .ui-state-glyph { color: var(--ink-2); }

/* ── ui-child-selector ── */
.ui-child-opt[aria-selected="true"] { background: var(--surface); border-bottom-color: var(--accent); }
.ui-child-opt[aria-selected="true"] .ui-child-opt-name { font-weight: 700; color: var(--ink); }
.ui-child-opt[aria-selected="false"] .ui-child-opt-name { color: var(--ink-2); }
.ui-child-opt-name { color: var(--ink); }
.ui-child-opt { min-width: 0; min-height: var(--tap-min); }
.ui-child-opt-name,
.ui-child-opt-meta { overflow-wrap: anywhere; }
.ui-child-opt:focus-visible { outline-offset: -3px; }
.ui-child-identity-text { flex: 1; }

/* ── view-states ── */
.ui-skeleton { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4); }
.ui-skeleton .skel-title { margin-bottom: var(--space-1); }
.ui-state-glyph { display: flex; width: 1em; height: 1em; font-size: var(--text-h2); margin-bottom: var(--space-2); color: var(--ink-3); }
.ui-state-glyph svg { width: 100%; height: 100%; }
.ui-state-error .ui-state-title,
.ui-state-error .ui-state-glyph { color: var(--danger); }
.ui-state-action { margin: var(--space-3) 0 0 -14px; }
.ui-data>.ui-state,
.card>.ui-state { border: 0; border-radius: 0; }
.ui-success-note { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-3) 0; padding: var(--space-2) var(--space-3); background: var(--ok-tint); border-left: 4px solid var(--ok); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
.ui-success-note-glyph { flex: none; display: flex; width: 1em; height: 1em; font-size: var(--text-body); color: var(--ok); }
.ui-success-note-glyph svg { width: 100%; height: 100%; }
.ui-success-note-text { flex: 1; min-width: 0; }
.notice-confirm.ui-confirm { display: block; margin: var(--space-3) 0; padding: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ui-confirm .ui-dialog-body { overflow: visible; }
.ui-confirm .notice-confirm-line { font-weight: 400; color: var(--ink-2); flex: none; }
.ui-dialog-glyph { font-size: var(--text-h2); }

/* ── lead: R8 beats R1 on the tap floor ──
   The merge refused these because the ata-ekta section sets a smaller value
   for the same property. R8 (accessibility never regresses) outranks R1: the
   pre-redesign sheet guaranteed a 44px target on every one of them, and the
   touch probe measures it. Nothing else about the controls changes. */
.ui-page-btn, .ui-filters-open { min-height: var(--tap-min); }
/* iOS Safari zooms the whole page when an input under 16px takes focus, and
   does not zoom back. The design's 15px body size is kept everywhere else;
   only iOS form controls get the 16px floor the previous sheet had. */
@supports (-webkit-touch-callout: none) {
  input, select, textarea { font-size: max(16px, 1em); }
}
/* No dark mode (spec §5), so say so to the browser too. Without it a phone in
   system dark mode draws native selects, date pickers and scrollbars dark on
   this light page. The sheet is silent on color-scheme. */
:root { color-scheme: light; }

/* ── ui/irreversible.ts — §7 / R11, as drawn in 05 publishScreen and 08
   rolloverScreen. One panel for the four actions that cannot be undone. The
   tick is --ink, not the accent: the accent belongs to the primary button
   the tick unlocks. ── */
.irrev { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.irrev-head { padding: var(--space-3) var(--space-4); background: var(--danger-tint); border-bottom: 2px solid var(--danger); }
.irrev-statement { margin: 0 0 var(--space-1); font-size: var(--text-body); line-height: var(--lh-h3); font-weight: 700; color: var(--danger); }
.irrev-detail { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.irrev-body { padding: var(--space-4); }
.irrev-list-label { display: block; margin: 0 0 var(--space-3); }
.irrev-list { list-style: none; margin: 0; padding: 0; }
.irrev-item { display: flex; align-items: center; gap: var(--space-3); padding: calc(var(--space-2) + var(--space-1) / 2) 0; border-bottom: 1px solid var(--line); }
.irrev-item:last-child { border-bottom: 0; }
.irrev-glyph { flex: none; font-size: var(--text-h3); color: var(--ink-2); }
.irrev-item[data-tone="success"] .irrev-glyph { color: var(--ok); }
.irrev-item[data-tone="info"]    .irrev-glyph { color: var(--info); }
.irrev-item[data-tone="warn"]    .irrev-glyph { color: var(--warn); }
.irrev-item[data-tone="danger"]  .irrev-glyph { color: var(--danger); }
.irrev-item-text { flex: 1; min-width: 0; font-size: var(--text-body); line-height: var(--lh-body); }
.irrev-item-meta { flex: none; font-size: var(--text-small); color: var(--ink-2); text-align: right; }
.irrev-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: 2px solid var(--rule); }
.irrev-ack { flex: 1 1 12rem; display: flex; align-items: center; gap: var(--space-2); min-height: var(--tap-min); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); cursor: pointer; }
.irrev-ack-box { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--ink); cursor: pointer; }

/* ═══ [4] Ata Ekta — wave 2A: shell and common screens ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── shell ── */
.shell-tab { background: transparent; border-left: 0; border-right: 0; border-bottom: 0; padding: 0; min-width: 0; font-family: var(--font-bn); cursor: pointer; }
.shell-avatar { flex: none; display: grid; place-items: center; width: var(--tap-min); height: var(--tap-min); padding: 0; background: transparent; border: 1px solid transparent; border-radius: var(--r-sm); color: var(--ink); font-family: var(--font-bn); cursor: pointer; }
.shell-avatar:hover { background: var(--inset); border-color: var(--line); }
.shell-avatar .shell-who { display: none; }
.shell-avatar:active { transform: scale(.97); }
@media (prefers-reduced-motion:reduce) {
.shell-avatar:active { transform: none; }
}
.shell-search { display: none; }
@media (min-width:1024px) {
.shell-search { display: grid; }
}
@media (min-width:1024px) {
.shell-avatar { display: none; }
}
@media (max-width:1023.98px) {
.shell-menu { position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; min-width: 0; border: 0; border-top: 2px solid var(--rule); border-radius: var(--r-lg) var(--r-lg) 0 0; box-shadow: 0 0 0 100vmax color-mix(in srgb, var(--ink) 22%, transparent), var(--shadow-md); padding-bottom: env(safe-area-inset-bottom); }
}
@media (max-width:1023.98px) {
.shell-menu::before { content: ""; display: block; width: 34px; height: 4px; margin: var(--space-2) auto 0; border-radius: var(--r-pill); background: var(--line); }
}
@media (min-width:1024px) {
.d-sidebar { z-index: 30; }
}
@media (min-width:1024px) {
.d-sidebar-foot { position: relative; }
}
@media (min-width:1024px) {
.d-sidebar-foot>.shell-menu { left: var(--space-2); bottom: calc(100% + var(--space-2)); }
}
@media (min-width:1024px) {
.d-rail-toggle { font-size: 18px; padding: 0; }
}
@media (min-width:1024px) and (max-width:1279px) {
.d-rail-toggle { display: none; }
}
@media (min-width:1024px) and (max-width:1279px) {
.d-brand { justify-content: center; }
}
@media (min-width:1024px) and (max-width:1279px) {
.d-sidebar .dnav-count,
.d-sidebar .d-profile-glyph { display: none; }
}
@media (min-width:1024px) {
.shell[data-rail="on"] .dnav-count,
.shell[data-rail="on"] .d-profile-glyph { display: none; }
}
@media (min-width:1024px) {
.dnav-count { flex: none; }
}
.d-profile-glyph { flex: none; display: grid; font-size: 16px; color: var(--ink-3); }
@media (min-width:1280px) {
.shell[data-rail="on"] .d-brand .shell-org-mark,
.shell[data-rail="on"] .d-brand .shell-org-logo { display: none; }
}
@media (min-width:1280px) {
.shell[data-rail="on"] .d-brand { justify-content: center; }
}
@media (pointer:coarse) and (min-width:1024px) {
.dnav { min-height: var(--tap-min); }
}
.offline-pending { margin-left: auto; flex: none; white-space: nowrap; font-weight: 600; color: var(--warn); }

/* ── login ── */
.login-wrap { max-width: 440px; margin: 0 auto; padding-block: var(--space-8); padding-inline: var(--space-4); min-height: 100dvh; display: flex; flex-direction: column; align-items: stretch; justify-content: center; }
.login-card { padding: var(--space-8) 28px; }
.login-brandmark { width: 52px; height: 52px; margin: 0 0 20px; padding: 0; display: grid; place-items: center; background: var(--accent); color: var(--on-accent, var(--surface)); font-family: var(--font-bn); font-size: 24px; font-weight: 700; line-height: 1; border-radius: 0; }
.login-brandmark.has-logo { background: transparent; }
.login-brandlogo { width: 52px; height: 52px; object-fit: contain; display: block; border-radius: 0; }
.login-card .login-brandname { margin: 0 0 6px; font-size: var(--text-h2); line-height: var(--lh-h2); font-weight: var(--w-h2); letter-spacing: normal; color: var(--ink); }
.login-sub { margin: 0 0 26px; font-size: 14px; line-height: var(--lh-body); color: var(--ink-2); }
.login-card .login-panel { margin: 0 0 20px; padding: 14px var(--space-4); border-left: 4px solid; border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.login-card .login-error { background: var(--danger-tint); border-left-color: var(--danger); }
.login-card .login-cooldown { background: var(--warn-tint); border-left-color: var(--warn); }
.login-panel-title { margin: 0; font-size: 14px; font-weight: 600; line-height: var(--lh-body); }
.login-error .login-panel-title { color: var(--danger); }
.login-cooldown .login-panel-title { color: var(--ink); }
.login-panel-detail { margin: var(--space-1) 0 0; font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.login-submit { margin-top: 6px; }
.login-card .btn-block[data-busy="true"] { justify-content: flex-start; }
.login-foot { margin: 10px 0 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-3); text-align: center; }
.login-foot.login-foot-note { margin-top: 18px; }

/* ── security ── */
.card.sec-devices { max-width: 720px; margin-top: var(--space-4); overflow: hidden; }
.sec-devices>.ui-card-head { border-bottom: 2px solid var(--rule); }
.sec-devices>.ui-list { border: none; border-radius: 0; }
.sec-devices .ui-list-glyph { font-size: 22px; }
.sec-devices>.ui-list-skeleton { padding: var(--space-4) 18px; }
.sec-devices-foot { padding: 18px; border-top: 1px solid var(--line); }
.sec-devices-note { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.sec-this-device { display: inline-flex; align-items: center; min-height: 36px; padding: 0 13px; font-size: var(--text-small); font-weight: 600; color: var(--ink-3); border: 1px solid var(--line); border-radius: var(--r-sm); white-space: nowrap; }
.sec-row-btn { white-space: nowrap; }

/* ── more ── */
.more-list .ui-list-glyph { font-size: 19px; }
.more-list .ui-list-chevron { font-size: 16px; }
.more-list .ui-list-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.more-list .ui-list-hit:focus-visible { outline-offset: -2px; }
@media (min-width:1024px) {
.ui-list.more-list { max-width: 720px; }
}

/* ── notifications ── */
.push-banner { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); padding: 15px 18px; margin-bottom: var(--space-6); background: var(--info-tint); border: 1px solid var(--line); border-radius: var(--r-md); }
.push-banner[data-push-state="on"] { background: var(--ok-tint); }
.push-banner-glyph { flex: none; display: flex; font-size: var(--text-h2); color: var(--info); }
.push-banner[data-push-state="on"] .push-banner-glyph { color: var(--ok); }
.push-banner-text { flex: 1; min-width: 180px; }
.push-banner-title { margin: 0 0 2px; font-size: 14.5px; line-height: var(--lh-h3); font-weight: 600; letter-spacing: 0; }
.push-banner-detail { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.push-banner>.ui-btn { flex: none; }

/* ── inbox ── */
.notice-list { display: block; gap: 0; margin: 0; padding: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.notice-list .notice-card { background: var(--surface); border: 0; border-bottom: 1px solid var(--line); border-radius: 0; overflow: visible; }
.notice-list .notice-card:last-child { border-bottom: 0; }
.notice-list .notice-card.unread { background: var(--accent-100); border-left: 0; }
.notice-list .notice-card:not(.unread):hover { background: var(--neutral-100); }
.notice-list .notice-head { display: flex; align-items: flex-start; flex-wrap: wrap; column-gap: 11px; row-gap: 0; width: 100%; min-height: var(--tap-min); margin: 0; padding: 13px 14px; background: none; border: 0; border-radius: 0; text-align: left; font-family: var(--font-bn); font-size: var(--text-body); line-height: var(--lh-small); color: var(--ink); cursor: pointer; }
@media (min-width:1024px) {
.notice-list .notice-head { flex-wrap: nowrap; column-gap: 13px; padding: 14px 18px; }
}
.notice-list .notice-head:active { background-color: var(--neutral-100); }
.notice-list .notice-head:focus-visible { outline-offset: -2px; }
.notice-list .notice-dot { display: block; flex: none; width: 8px; height: 8px; margin-top: 7px; border-radius: var(--r-xs); background: transparent; }
.notice-list .notice-card.unread .notice-dot { background: var(--accent-ink); }
.notice-list .notice-main { display: block; flex: 1 1 0; min-width: 0; }
.notice-list .notice-title { display: block; margin-bottom: 2px; font-size: var(--text-body); line-height: var(--lh-small); font-weight: 500; color: var(--ink); overflow-wrap: anywhere; }
.notice-list .notice-card.unread .notice-title { font-weight: 700; }
.notice-list .notice-meta { display: block; margin-bottom: 2px; font-size: 12px; line-height: var(--lh-small); color: var(--ink-3); }
.notice-list .notice-urgent { color: var(--danger); font-weight: 600; }
.notice-list .notice-preview { display: block; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.notice-list .notice-time { flex: 0 0 100%; margin-top: 4px; padding-left: 19px; font-size: 12px; line-height: var(--lh-small); color: var(--ink-3); white-space: nowrap; }
@media (min-width:1024px) {
.notice-list .notice-time { flex: none; margin-top: 0; padding-left: 0; }
}
.notice-list .notice-body { margin: 0; padding: 0 14px 13px 33px; font-size: var(--text-body); line-height: var(--lh-body); color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }
@media (min-width:1024px) {
.notice-list .notice-body { padding: 0 18px 14px 39px; }
}

/* ── compose ── */
.compose { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.compose-body { padding: 18px; }
.audience-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.audience-chip { font-family: var(--font-bn); font-size: 13.5px; font-weight: 600; line-height: 1.3; min-height: var(--tap-min); padding: 0 14px; border-radius: var(--r-sm); background: var(--surface); border: 1px solid var(--line); color: var(--ink); text-align: left; cursor: pointer; }
.audience-chip:hover:not([aria-pressed="true"]) { background: var(--inset); }
.audience-chip:active { transform: scale(.97); }
.audience-chip[aria-pressed="true"] { background: var(--accent-tint); border-color: var(--accent-ink); color: var(--accent-ink); }
.audience-sections { display: flex; flex-direction: column; margin-top: var(--space-3); max-height: 240px; overflow-y: auto; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
.audience-section { display: flex; align-items: center; gap: var(--space-2); min-height: var(--tap-min); padding: 0 var(--space-3); font-size: var(--text-body); border-bottom: 1px solid var(--line); cursor: pointer; }
.audience-section:last-child { border-bottom: none; }
.audience-section:hover { background: var(--neutral-100); }
.audience-sections>.ui-state { border: 0; border-radius: 0; }
.audience-sections>.ui-list-skeleton { padding: var(--space-3); }
.compose .audience-section>input[type="checkbox"],
.compose .sms-toggle>input[type="checkbox"] { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--ink); cursor: pointer; }
.compose-count { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) 28px; margin: 7px 0 0; overflow: hidden; font-size: 12.5px; line-height: var(--lh-small); color: var(--ink-2); }
.compose-count>span:empty { display: none; }
.compose-count>span::before { content: "·"; display: inline-block; width: 28px; margin-left: -28px; text-align: center; color: var(--ink-3); font-weight: 400; }
.compose-count-warn { color: var(--warn); font-weight: 600; }
.compose-options { padding-top: var(--space-4); border-top: 1px solid var(--line); }
@media (min-width:1024px) {
.compose-options { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-4); }
}
.compose-sms { grid-column: 1 / -1; }
.compose-sms .sms-toggle { margin-top: 0; font-size: var(--text-body); color: var(--ink); }
.compose-panel { display: flex; flex-direction: column; gap: var(--space-3); padding: 15px 18px; background: var(--inset); border-top: 2px solid var(--rule); }
.compose-panel[data-gated="true"] { background: var(--danger-tint); border-top-color: var(--danger); }
.compose-stats { display: flex; flex-wrap: wrap; gap: 20px; }
.compose-stat-label { display: block; margin-bottom: 3px; font-size: var(--text-label); line-height: var(--lh-label); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-2); }
.compose-stat-value { display: block; font-size: 21px; font-weight: 700; line-height: 1.2; color: var(--ink); }
.compose-panel[data-gated="true"] .compose-stat-label,
.compose-panel[data-gated="true"] .compose-stat-value { color: var(--danger); }
.compose-line { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink); overflow-wrap: anywhere; }
.compose-line-label { font-weight: 700; }
.compose-notice { margin-bottom: var(--space-4); }

/* ── offline-page ── */
body.offline-page { background: var(--surface); }
.offline-page-main { min-height: 100dvh; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; padding: 56px var(--space-6) 28px; text-align: center; }
.offline-page-glyph { display: block; flex: none; width: 56px; height: 56px; margin: 0 0 var(--space-4); color: var(--ink-2); }
.offline-page-main .offline-page-title { margin: 0 0 var(--space-2); font-size: 20px; line-height: 1.3; font-weight: 700; letter-spacing: 0; color: var(--ink); }
.offline-page-text { margin: 0; font-size: var(--text-body); line-height: 1.65; color: var(--ink-2); }

/* ── system ── */
.sys-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0,1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
@media (min-width:1024px) {
.sys-grid { grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (min-width:1024px) {
.sys-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
.sys-tile { background: var(--surface); padding: 15px 17px; min-width: 0; }
.sys-tile-head { display: flex; align-items: center; gap: var(--space-2); margin-bottom: 5px; }
.sys-dot { width: 9px; height: 9px; flex: none; border-radius: var(--r-pill); background: var(--ink-2); }
.sys-dot[data-tone="success"] { background: var(--ok); }
.sys-dot[data-tone="info"] { background: var(--info); }
.sys-dot[data-tone="warn"] { background: var(--warn); }
.sys-dot[data-tone="danger"] { background: var(--danger); }
.sys-tile-title { margin: 0; min-width: 0; font-size: 14.5px; font-weight: 600; line-height: var(--lh-h3); color: var(--ink); }
.sys-tile-detail { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }
.sys-tile-skel { display: inline-block; width: 64px; height: 9px; vertical-align: middle; }
.sys-tile-path { display: block; margin-top: var(--space-1); font-family: var(--font-bn); font-size: 12px; line-height: 1.45; color: var(--ink-3); overflow-wrap: anywhere; }
.sys-legend { margin-top: var(--space-6); }
.ui-facts-key.sys-legend-key { display: flex; align-items: center; gap: var(--space-2); font-size: 14.5px; font-weight: 600; color: var(--ink); }

/* ── export ── */
.export-intro { margin: 0 0 14px; font-size: 14px; line-height: var(--lh-body); color: var(--ink-2); }
.export-files .ui-list-glyph { font-size: 19px; }
.export-files .ui-list-hit { flex-wrap: wrap; }
.export-files .ui-list-status { flex-basis: 100%; padding-inline-start: calc(19px + var(--space-3)); }
.export-files .ui-list-status .ui-btn { width: 100%; justify-content: space-between; }
@media (min-width:1024px) {
.export-files .ui-list-hit { flex-wrap: nowrap; }
}
@media (min-width:1024px) {
.export-files .ui-list-status { flex-basis: auto; padding-inline-start: 0; }
}
@media (min-width:1024px) {
.export-files .ui-list-status .ui-btn { width: auto; justify-content: center; }
}

/* ── audit ── */
.audit-panel { overflow: hidden; }
.audit-filters { padding: 11px 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.audit-filters .ui-filter-field { flex: 1 1 120px; min-width: 0; }
.audit-filters .ui-filter-field:first-child { flex-basis: 150px; }
.audit-dates { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.audit-date { display: flex; align-items: center; gap: var(--space-2); margin: 0; }
.audit-date .ui-field-label { margin: 0; white-space: nowrap; }
.audit-list { list-style: none; margin: 0; padding: 0; }
.audit-row { border-bottom: 1px solid var(--line); }
.audit-row:last-child { border-bottom: 0; }
.audit-head { display: flex; align-items: center; gap: 13px; width: 100%; min-height: 54px; margin: 0; padding: 0 18px; background: none; border: 0; font-family: var(--font-bn); font-size: inherit; line-height: inherit; color: var(--ink); text-align: left; cursor: pointer; }
.audit-head:hover,
.audit-head:active,
.audit-head[aria-expanded="true"] { background-color: var(--neutral-100); }
.audit-head:focus-visible { outline-offset: -2px; }
.audit-mark { flex: none; width: 3px; height: 26px; background: var(--ink-2); }
.audit-row[data-tone="danger"] .audit-mark { background: var(--danger); }
.audit-row[data-tone="success"] .audit-mark { background: var(--ok); }
.audit-row[data-tone="info"] .audit-mark { background: var(--info); }
.audit-when { flex: none; width: 110px; font-size: 12px; line-height: var(--lh-small); color: var(--ink-3); }
.audit-who { flex: none; width: 130px; font-size: 13.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.audit-what { flex: 1; min-width: 0; }
.audit-action { display: block; font-size: 13.5px; line-height: 1.5; }
.audit-detail { display: block; font-size: 12px; line-height: 1.5; color: var(--ink-3); }
.audit-diff { padding: var(--space-1) 18px var(--space-4) 34px; }
.audit-diff-note { font-size: var(--text-small); color: var(--ink-2); }
.audit-panel>.ui-list-skeleton { padding: var(--space-4) 18px; }
.audit-note { padding: var(--space-3) 18px; border-top: 2px solid var(--rule); font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.audit-panel>.ui-pagination+.audit-note { border-top: 1px solid var(--line); }
@media (max-width:1023.98px) {
.audit-filters { padding: var(--space-3) 14px; }
}
@media (max-width:1023.98px) {
.audit-filters .ui-filters-open,
.audit-filters .ui-filter-active { order: -1; }
}
@media (max-width:1023.98px) {
.audit-dates,
.audit-date { flex: 1 1 100%; }
}
@media (max-width:1023.98px) {
.audit-date .ui-field-label { min-width: 40px; }
}
@media (max-width:1023.98px) {
.audit-date .ui-field-control { flex: 1; min-width: 0; }
}
@media (max-width:1023.98px) {
.audit-head { display: grid; grid-template-columns: 3px minmax(0, 1fr) auto; grid-template-areas: "mark what what" "mark who when"; column-gap: var(--space-3); row-gap: 2px; min-height: 56px; padding: 10px 14px; }
}
@media (max-width:1023.98px) {
.audit-mark { grid-area: mark; height: auto; align-self: stretch; }
}
@media (max-width:1023.98px) {
.audit-what { grid-area: what; }
}
@media (max-width:1023.98px) {
.audit-action { font-size: var(--text-body); font-weight: 600; }
}
@media (max-width:1023.98px) {
.audit-who { grid-area: who; width: auto; font-size: 12px; font-weight: 400; color: var(--ink-2); }
}
@media (max-width:1023.98px) {
.audit-when { grid-area: when; width: auto; text-align: right; white-space: nowrap; }
}
@media (max-width:1023.98px) {
.audit-diff { padding: 0 14px var(--space-3); }
}
@media (max-width:1023.98px) {
.audit-note { padding: var(--space-3) 14px; }
}
@media (max-width:1023.98px) {
.audit-panel>.ui-list-skeleton { padding: var(--space-3) 14px; }
}

/* ── lead: two more R8/stacking exceptions, refused by the merge ──
   `.shell-role` is the demo role SELECT, a real control: the pre-redesign
   sheet gave it the 44px floor and the new one draws it at 34px (R8 wins, as
   for .ui-page-btn). The topbar raise is not a look at all: the mobile account
   sheet lives inside the topbar, and the fixed tab bar shares its z-index and
   comes later in the DOM, so the sheet's log-out row was painting under it. */
.shell-role { min-height: var(--tap-min); }
.shell-topbar { z-index: 30; }

/* ═══ [4] Ata Ekta — wave 2B: teacher, student and shared academic screens ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── teacher-home ── */
.th-urgent { padding: 15px; margin-bottom: var(--space-3); }
.th-urgent-kicker { margin: 0 0 3px; font-size: 11.5px; line-height: var(--lh-small); color: var(--ink-2); }
.th-urgent-title { margin: 0 0 11px; font-size: 18px; font-weight: 700; line-height: var(--lh-h2); letter-spacing: normal; overflow-wrap: anywhere; }
.th-sub-note { display: flex; align-items: flex-start; gap: var(--space-2); margin: 0 0 11px; padding: var(--space-2) var(--space-3); background: var(--inset); border-radius: var(--r-sm); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
.th-sub-glyph { display: flex; width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--warn); }
.th-sub-glyph svg { width: 100%; height: 100%; }
.ui-stat-row.th-stats[data-count="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ui-stat-row.th-stats[data-count="3"]>.ui-stat:not(:last-child) { border-right: 1px solid var(--line); }
.ui-stat-row.th-stats[data-count="3"]>.ui-stat+.ui-stat { border-top: none; }
.th-stats .ui-stat-text { display: flex; flex-direction: column; }
.th-stats .ui-stat-value { margin-top: auto; }
.th-day-card { margin-bottom: var(--space-3); }
.th-note { margin: 0 0 var(--space-3); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.th-note:last-child { margin-bottom: 0; }
.th-day-card .ui-card-body>.btn-ghost { margin-left: -14px; }
.th-tasks { margin-top: var(--space-3); }
.th-tasks .ui-list-glyph { font-size: 19px; }
.th-tasks .ui-list-hit:focus-visible { outline-offset: -2px; }
@media (min-width:1024px) {
.th-urgent { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: 'kicker action' 'title action' 'note action'; column-gap: var(--space-6); align-items: center; padding: var(--space-4) var(--space-6); }
}
@media (min-width:1024px) {
.th-urgent-kicker { grid-area: kicker; }
}
@media (min-width:1024px) {
.th-urgent-title { grid-area: title; margin-bottom: 0; }
}
@media (min-width:1024px) {
.th-sub-note { grid-area: note; margin: var(--space-2) 0 0; }
}
@media (min-width:1024px) {
.th-urgent .th-urgent-go { grid-area: action; width: auto; min-width: 180px; }
}

/* ── roster ── */
.roster-panel { overflow: hidden; }
.roster-note { margin-bottom: var(--space-4); }
.roster-code.issued-code-card { margin: 0 0 var(--space-4); text-align: left; }
.roster-bar { display: flex; flex-direction: column; gap: var(--space-2); padding: 10px 14px; background: var(--surface); border-bottom: 1px solid var(--line); }
.ui-field.roster-picker { margin: 0; }
.roster-summary { padding: 10px 14px; background: var(--inset); border-bottom: 1px solid var(--line); }
.roster-body>.ui-state,
.roster-body>.ui-data { border: 0; border-radius: 0; }
.roster-body>.ui-list-skeleton { padding: var(--space-3) 14px; }
.roster-data .ui-list-main { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--space-3); align-items: center; }
.roster-data .ui-list-title { display: contents; }
.roster-data .ui-list .ui-avatar { grid-column: 1; grid-row: 1 / span 2; width: 34px; height: 34px; font-size: 14px; }
.roster-data .roster-student-name,
.roster-data .ui-list-meta { grid-column: 2; }
.roster-student-name { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roster-data .ui-table .ui-avatar,
.roster-data .ui-table .roster-roll-word { display: none; }
@media (min-width:1024px) {
.roster-bar { flex-direction: row; align-items: center; gap: var(--space-3); }
}
@media (min-width:1024px) {
.ui-field.roster-picker { flex: 0 1 320px; }
}
@media (min-width:1024px) {
.roster-bar .ui-search { flex: 1 1 auto; min-width: 0; }
}

/* ── marks ── */
.marks-sheet { overflow: clip; }
.marks-sheet>.ui-list-skeleton { padding: var(--space-4) 18px; }
.marks-lock { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) 18px; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); background: var(--info-tint); border-bottom: 1px solid var(--line); }
.marks-lock .ui-icon { flex: none; font-size: 15px; color: var(--info); }
.marks-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px var(--space-4); padding: var(--space-3) 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.marks-filters>.marks-filter { flex: 0 1 auto; min-width: 0; max-width: 100%; margin: 0; }
@media (min-width:1024px) {
.marks-filters>.marks-filter { display: flex; align-items: center; gap: var(--space-2); }
}
@media (min-width:1024px) {
.marks-filter .ui-field-label { margin: 0; white-space: nowrap; }
}
@media (min-width:1024px) {
.marks-filter .ui-field-control { min-width: 0; }
}
.marks-complete { margin: 0 0 0 auto; font-size: var(--text-small); line-height: var(--lh-small); font-weight: 600; color: var(--ink-2); }
.marks-complete[data-done="true"] { color: var(--ok); }
.marks-table { min-width: 560px; }
.marks-table thead th:not(.marks-col-name) { width: 1%; }
.marks-table td { vertical-align: middle; }
.marks-table tbody th.marks-name { vertical-align: middle; }
.marks-table td.marks-roll { color: var(--ink-2); }
.marks-table td.marks-cell { min-width: 96px; }
.marks-input { width: 62px; min-height: var(--tap-min); margin: 0; padding: 0 var(--space-2); font-size: var(--text-body); text-align: right; color: var(--ink); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm); }
.marks-input.n { font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.marks-input:focus { outline: none; box-shadow: none; border: 2px solid var(--accent); padding: 0 7px; }
.marks-input:disabled { background: var(--inset); color: var(--ink-3); }
.marks-input[aria-invalid="true"] { border: 2px solid var(--danger); background: var(--danger-tint); padding: 0 7px; }
.marks-error { display: block; margin-top: var(--space-1); font-size: 12px; line-height: var(--lh-label); font-weight: 600; color: var(--danger); text-align: right; }
.marks-table td.marks-total { font-weight: 700; color: var(--ink); white-space: nowrap; }
.marks-absent { display: inline-flex; align-items: center; justify-content: center; min-width: var(--tap-min); min-height: var(--tap-min); cursor: pointer; }
.marks-absent input { width: 20px; height: 20px; margin: 0; accent-color: var(--ink); cursor: pointer; }
.marks-savebar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-3) 18px; background: var(--surface); border-top: 2px solid var(--rule); }
.marks-note { display: flex; align-items: center; gap: 6px; flex: 1 1 auto; min-width: 0; margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.marks-note .ui-icon { flex: none; font-size: 15px; }
@media (min-width:1024px) {
.marks-save-bottom { display: none; }
}
@media (max-width:1023.98px) {
.marks-save-top { display: none; }
}
@media (max-width:1023.98px) {
.marks-lock { padding: var(--space-2) 14px; }
}
@media (max-width:1023.98px) {
.marks-sheet>.ui-list-skeleton { padding: var(--space-3) 14px; }
}
@media (max-width:1023.98px) {
.marks-filters { padding: 10px 14px; }
}
@media (max-width:1023.98px) {
.marks-filters>.marks-filter { flex: 1 1 100%; }
}
@media (max-width:1023.98px) {
.marks-complete { margin-left: 0; }
}
@media (max-width:1023.98px) {
.marks-table tbody th.marks-name { font-size: var(--text-body); }
}
@media (max-width:1023.98px) {
.marks-table .marks-col-roll,
.marks-table .marks-roll { position: sticky; left: 0; z-index: 1; width: 48px; min-width: 48px; max-width: 48px; }
}
@media (max-width:1023.98px) {
.marks-table .marks-col-name,
.marks-table .marks-name { position: sticky; left: 48px; z-index: 1; min-width: 112px; max-width: 40vw; }
}
@media (max-width:1023.98px) {
.marks-table td.marks-roll { background: var(--surface); box-shadow: inset 0 -1px 0 var(--line); }
}
@media (max-width:1023.98px) {
.marks-table tbody th.marks-name { background: var(--surface); box-shadow: inset -2px 0 0 var(--rule), inset 0 -1px 0 var(--line), 3px 0 6px color-mix(in srgb, var(--neutral-900) 12%, transparent); }
}
@media (max-width:1023.98px) {
.marks-table th.marks-col-roll { box-shadow: inset 0 -2px 0 var(--rule); }
}
@media (max-width:1023.98px) {
.marks-table th.marks-col-name { box-shadow: inset -2px 0 0 var(--rule), inset 0 -2px 0 var(--rule), 3px 0 6px color-mix(in srgb, var(--neutral-900) 12%, transparent); }
}
@media (max-width:1023.98px) {
.marks-savebar { position: sticky; bottom: calc(58px + env(safe-area-inset-bottom, 0px)); z-index: 5; padding: 10px 14px; }
}
@media (max-width:1023.98px) {
.marks-note { flex: 1 1 100%; }
}

/* ── assignments ── */
.assign-tabs { background: var(--surface); border-top: 1px solid var(--line); border-left: 1px solid var(--line); border-right: 1px solid var(--line); border-radius: var(--r-md) var(--r-md) 0 0; }
.assign-tabs+.assign-data { border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
@media (max-width:1023.98px) {
.assign-tabs .ui-tab { flex: 1 1 0; justify-content: center; padding: 0 var(--space-1); }
}
.assign-data .ui-list-hit { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; row-gap: 0; }
.assign-data .ui-list-main { display: contents; }
.assign-data .ui-list-title { grid-column: 1 / -1; margin-bottom: 3px; }
.assign-data .ui-list-sub { grid-column: 1 / -1; margin-bottom: 9px; }
.assign-data .ui-list-meta { grid-column: 1; }
.assign-data .ui-list-status { grid-column: 2; justify-self: end; }
.assign-data.is-student .ui-list-title { margin-bottom: 4px; }
.assign-data.is-student .ui-list-sub { margin-bottom: 10px; }
.assign-data.is-student .ui-list-status { grid-column: 1 / -1; justify-self: start; }
.assign-data .ui-list-chevron { display: none; }
.assign-data .ui-list-hit:focus-visible { outline-offset: -2px; }
.assign-count { font-weight: 600; }
.assign-count[data-tone="warn"] { color: var(--warn); }
.assign-count[data-tone="success"] { color: var(--ok); }
.assign-offline { margin: 0 0 var(--space-4); }
.assign-eyebrow { margin: 0 0 var(--space-2); }
.assign-instructions { margin: 0 0 var(--space-4); padding: var(--space-4); }
.assign-notice { margin-bottom: var(--space-4); }
.assign-graded { margin: 0 0 var(--space-4); padding: var(--space-4); background: var(--surface); border-color: var(--line); text-align: left; }
.assign-score-label { margin: 0 0 var(--space-1); }
.assign-score { margin: 0; font-family: var(--font-num); font-variant-numeric: tabular-nums; font-size: var(--text-h1); line-height: var(--lh-h1); font-weight: 700; color: var(--ink); }
.assign-form { margin: 0 0 var(--space-4); }
.assign-draft-status { display: block; margin-top: 6px; }
.assign-note { display: flex; align-items: flex-start; gap: var(--space-2); margin: 0 0 var(--space-4); padding: var(--space-2) var(--space-3); background: var(--warn-tint); border-left: 4px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
.assign-note>.ui-icon { flex: none; margin-top: 2px; font-size: var(--text-body); color: var(--warn); }
.grade-conflict { padding: var(--space-4); }
.conflict-actions { flex-wrap: wrap; }
.conflict-actions>.ui-btn { flex: 1 1 auto; }
.sub-list { padding: 0; gap: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.sub-item { padding: 14px; border-bottom: 1px solid var(--line); }
.sub-item:last-child { border-bottom: 0; }
.sub-head { align-items: center; }
.sub-who { min-width: 0; }
.sub-roll { margin-right: var(--space-2); color: var(--ink-2); }

/* ── scripts ── */
.scripts-pickers { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-4); }
.scripts-pickers .ui-field { margin-bottom: 0; }
@media (min-width:1024px) {
.scripts-pickers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: end; }
}
.scripts-offline { margin: 0 0 var(--space-4); }
.scripts-note { margin: 0 0 14px; padding: var(--space-3) 14px; background: var(--info-tint); border-left: 4px solid var(--info); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.scripts-capture { align-items: stretch; gap: 0; margin-bottom: var(--space-4); }
.scripts-capture .ui-upload-trigger { display: flex; width: 100%; min-height: 96px; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: var(--space-3); background: var(--surface); color: var(--ink); border: 2px dashed var(--ink-3); border-radius: var(--r-sm); font-size: var(--text-body); font-weight: 600; text-align: center; }
.scripts-capture .ui-upload-trigger:hover { background: var(--neutral-100); border-color: var(--ink-2); }
.scripts-capture .ui-upload-trigger .btn-glyph { width: 26px; height: 26px; color: var(--ink-2); }
.scripts-notice { margin: 0 0 var(--space-4); padding: var(--space-2) var(--space-3); background: var(--warn-tint); border-left: 4px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
h2.label.scripts-grid-label { margin: 0 0 var(--space-2); letter-spacing: .12em; }
.scripts-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); }
@media (min-width:1024px) {
.scripts-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
}
.scripts-tile { display: flex; flex-direction: column; min-width: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.scripts-tile-thumb { display: block; width: 100%; height: 70px; object-fit: cover; background: var(--inset); }
.scripts-tile-foot { padding: 5px 7px; border-top: 1px solid var(--line); }
.scripts-tile-name { display: block; font-size: var(--text-label); line-height: var(--lh-label); font-weight: 600; color: var(--ink); }
.scripts-tile-state { display: block; font-size: 10px; line-height: var(--lh-label); color: var(--ink-2); overflow-wrap: anywhere; }
.scripts-tile-state.is-ok { color: var(--ok); }
.scripts-tile-state.is-warn { color: var(--warn); }
.scripts-tile-state.is-danger { color: var(--danger); }
.scripts-tile-actions { display: flex; flex-direction: column; gap: var(--space-2); margin-top: auto; padding: 0 7px 7px; }
.scripts-tile-actions .btn-block[data-busy="true"] { justify-content: flex-start; }

/* ── substitute ── */
.subst-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.subst-panel>.ui-data { border: 0; border-radius: 0; }
.subst-panel>.ui-list-skeleton { padding: var(--space-4) 14px; }
.subst-alert { padding: var(--space-3) 14px; background: var(--danger-tint); border-bottom: 1px solid var(--line); }
.subst-alert-title { margin: 0 0 2px; font-size: 14px; font-weight: 700; color: var(--danger); }
.subst-alert-count { margin: 0; font-size: 12.5px; color: var(--ink-2); }
.subst-day .ui-list-hit { flex-wrap: wrap; }
.subst-day .ui-list-main { flex: 1 1 100%; display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.subst-day .ui-list-title { flex: none; }
.subst-day .ui-list-sub { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subst-day .ui-list-meta { flex: 0 1 auto; min-width: 0; margin-left: auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.subst-day .ui-list-chevron { margin-left: auto; }
@media (min-width:1024px) {
.subst-date { max-width: 320px; }
}

/* ── classperf ── */
.ui-data.perf-table[data-shape="table-list"]>.ui-list .ui-list-title { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: break-word; }
.perf-card { margin-top: var(--space-4); }
.perf-card .perf-eyebrow { margin: 0 0 var(--space-3); letter-spacing: .12em; }
.perf-card .perf-note { margin: 0 0 var(--space-3); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.perf-card .perf-note:last-child { margin-bottom: 0; }
.perf-bars { display: grid; gap: var(--space-3); margin: 0; }
.perf-bar { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "label value" "track track"; align-items: center; column-gap: var(--space-3); row-gap: var(--space-2); }
.perf-bar-label { grid-area: label; min-width: 0; font-size: var(--text-small); font-weight: 400; color: var(--ink); }
.perf-bar-track { grid-area: track; position: relative; display: block; height: 22px; background: var(--inset); border: 0; border-radius: var(--r-pill); overflow: hidden; }
.perf-bar-fill { display: block; height: 100%; background: var(--ink-2); border-radius: var(--r-pill); }
.perf-bar-fill[data-tone="low"] { background: var(--danger); }
.perf-bar-value { grid-area: value; min-width: 34px; text-align: right; white-space: nowrap; }
.perf-bar-pct { font-size: 14px; font-weight: 700; color: var(--ink); }
.perf-bar-value[data-level="low"] .perf-bar-pct { color: var(--danger); }
.perf-bar-value[data-level="none"] .perf-bar-pct { color: var(--ink-3); font-weight: 600; }
.perf-bar-avg { font-size: 12px; font-weight: 400; color: var(--ink-3); }
.perf-callout,
.perf-reteach,
.perf-wide-note { padding: var(--space-3) var(--space-4); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); font-weight: 400; line-height: var(--lh-body); color: var(--ink); }
.perf-callout { margin: var(--space-4) 0 0; background: var(--danger-tint); border-left: 4px solid var(--danger); }
.perf-reteach { margin: var(--space-3) 0 0; background: var(--warn-tint); border-left: 4px solid var(--warn); }
.perf-wide-note { margin: 0 0 var(--space-3); background: var(--info-tint); border-left: 4px solid var(--info); }
.perf-att-signals { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-1); }
.perf-att-signals li { font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.perf-exam { white-space: normal; max-width: 100%; }
@media (min-width:1024px) {
.perf-picker { max-width: 420px; }
}
@media (min-width:1024px) {
.perf-bars { grid-template-columns: 110px minmax(0, 1fr) auto; column-gap: var(--space-3); align-items: center; }
}
@media (min-width:1024px) {
.perf-bars>.perf-bar { display: contents; }
}
@media (min-width:1024px) {
.perf-bar>.perf-bar-label,
.perf-bar>.perf-bar-track,
.perf-bar>.perf-bar-value { grid-area: auto; }
}

/* ── calendar ── */
.cal-month-ctl { display: flex; align-items: center; gap: var(--space-2); }
@media (max-width:1023px) {
.cal-month-ctl { display: none; }
}
.cal-nav { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-3); }
@media (min-width:1024px) {
.cal-nav { display: none; }
}
.cal-nav-month { flex: 1; min-width: 0; margin: 0; text-align: center; font-size: 16px; font-weight: 700; line-height: var(--lh-h3); color: var(--ink); }
.cal-filter.seg-bar { display: flex; flex-wrap: wrap; gap: 7px; margin: 0 0 var(--space-4); padding: 0; border: 0; background: transparent; }
.cal-filter .seg-opt { flex: none; position: relative; display: inline-flex; align-items: center; min-height: 34px; padding: 0 11px; font-family: var(--font-bn); font-size: 12.5px; font-weight: 600; color: var(--ink); background: transparent; border: 1px solid var(--line); border-radius: var(--r-pill); cursor: pointer; }
.cal-filter .seg-opt::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: var(--tap-min); transform: translateY(-50%); }
.cal-filter .seg-opt:hover:not([data-active="true"]) { background: var(--inset); }
.cal-filter .seg-opt[data-active="true"] { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.cal-filter .seg-opt:active { transform: scale(.97); }
.cal-board { margin: 0 0 14px; }
@media (min-width:1024px) {
.cal-board { padding: var(--space-4) 18px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); margin: 0 0 var(--space-4); }
}
.cal-scroll { display: flow-root; margin: 0; padding: 0; }
.cal-grid { width: calc(100% + 4px); margin: -2px; table-layout: fixed; border-collapse: separate; border-spacing: 2px; }
.cal-grid th { padding: 4px 0 6px; text-align: center; font-size: 10.5px; font-weight: 700; line-height: var(--lh-label); color: var(--ink-3); background: transparent; border: 0; text-transform: none; letter-spacing: normal; }
@media (min-width:1024px) {
.cal-grid th { padding: 6px 0; font-size: var(--text-label); color: var(--ink-2); background: var(--inset); }
}
.cal-grid th.cal-weekend { color: var(--ink); }
@media (max-width:1023px) {
.cal-wd-full { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
@media (min-width:1024px) {
.cal-wd-short { display: none; }
}
.cal-grid td { padding: 0; vertical-align: top; border: 0; background: transparent; }
.cal-day { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; width: 100%; aspect-ratio: 1; min-height: var(--tap-min); margin: 0; padding: 0; background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-sm); font-family: var(--font-bn); font-size: 12px; font-weight: 400; line-height: 1; cursor: pointer; }
.cal-day:hover { border-color: var(--ink-3); }
.cal-day:active { transform: scale(.97); }
.cal-num { font-size: 12px; line-height: 1; }
.cal-dots { display: none; }
.cal-cell[data-kind="holiday"],
.cal-dot[data-kind="holiday"],
.cal-legend-swatch[data-kind="holiday"],
.cal-up-date[data-kind="holiday"] { --cal-tone: var(--danger); }
.cal-cell[data-kind="event"],
.cal-dot[data-kind="event"],
.cal-legend-swatch[data-kind="event"],
.cal-up-date[data-kind="event"] { --cal-tone: var(--info); }
.cal-cell[data-kind="exam"],
.cal-dot[data-kind="exam"],
.cal-legend-swatch[data-kind="exam"],
.cal-up-date[data-kind="exam"] { --cal-tone: var(--warn); }
.cal-cell[data-kind="working_weekend"],
.cal-dot[data-kind="working_weekend"],
.cal-legend-swatch[data-kind="working_weekend"],
.cal-up-date[data-kind="working_weekend"] { --cal-tone: var(--ok); }
.cal-cell[data-kind="ramadan_schedule"],
.cal-dot[data-kind="ramadan_schedule"],
.cal-legend-swatch[data-kind="ramadan_schedule"],
.cal-up-date[data-kind="ramadan_schedule"] { --cal-tone: var(--ink-2); }
.cal-cell[data-state="weekend"] .cal-day { background: var(--inset); }
@media (max-width:1023px) {
.cal-grid .cal-cell[data-kind] .cal-day { background: var(--cal-tone, var(--ink-2)); color: var(--surface); font-weight: 700; }
}
@media (min-width:1024px) {
.cal-day { aspect-ratio: auto; min-height: 62px; padding: 5px 6px; align-items: stretch; justify-content: flex-start; border-radius: var(--r-md); text-align: left; }
}
@media (min-width:1024px) {
.cal-num { align-self: flex-start; color: var(--ink-2); font-weight: 600; }
}
@media (min-width:1024px) {
.cal-dots { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
}
@media (min-width:1024px) {
.cal-dot { display: block; min-width: 0; padding: 2px 4px; font-size: 10px; line-height: 1.3; color: var(--surface); background: var(--cal-tone, var(--ink-2)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
.cal-today .cal-num { font-weight: 700; text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
.cal-selected .cal-day { border-color: var(--ink); box-shadow: 0 0 0 1px var(--ink), inset 0 0 0 1px var(--surface); }
.cal-cell[data-state="holiday"] .cal-day { border-bottom: 3px solid var(--ink); border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.cal-cell[data-state="working_weekend"] .cal-day,
.cal-cell[data-kind="working_weekend"] .cal-day { border-top: 3px solid var(--ink); border-top-left-radius: 0; border-top-right-radius: 0; }
.cal-legend { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.cal-legend-item { display: flex; align-items: center; gap: 5px; font-size: 11.5px; line-height: var(--lh-small); color: var(--ink-2); }
.cal-legend-swatch { flex: none; width: 11px; height: 11px; border: 0; border-radius: 0; background: var(--cal-tone, var(--ink-2)); }
.cal-legend-swatch[data-kind="holiday"] { border-bottom: 3px solid var(--ink); }
.cal-legend-swatch[data-kind="working_weekend"] { border-top: 3px solid var(--ink); }
.cal-legend-swatch[data-state="weekend"] { background: var(--inset); border: 1px solid var(--line); }
@media (min-width:1024px) {
.cal-legend { gap: 14px; }
}
@media (min-width:1024px) {
.cal-legend-item { gap: 6px; font-size: 12px; }
}
@media (min-width:1024px) {
.cal-legend-swatch { width: 12px; height: 12px; }
}
.cal-day-panel { margin: 0 0 var(--space-4); }
.cal-day-panel>*+* { margin-top: var(--space-3); }
.cal-hint { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.cal-up-date { flex: none; width: 46px; font-size: var(--text-small); font-weight: 700; color: var(--cal-tone, var(--ink-2)); }
@media (prefers-reduced-motion:reduce) {
.cal-day:active,
.cal-filter .seg-opt:active { transform: none; }
}

/* ── documents ── */
.doc-kinds .ui-list-hit { min-height: 62px; }
.doc-kinds .ui-list-glyph { font-size: 20px; }
.doc-kinds .doc-go { display: flex; align-items: center; }
.doc-kinds .doc-go-m { font-size: 19px; color: var(--ink); }
.doc-kinds .doc-go-d,
.doc-kinds .ui-list-chevron,
.doc-receipts .ui-list-chevron { display: none; }
.doc-kinds .ui-list-hit:focus-visible,
.doc-receipts .ui-list-hit:focus-visible { outline-offset: -2px; }
.doc-state { margin-bottom: var(--space-4); }
.doc-steps .ui-list { margin-bottom: var(--space-4); }
.doc-receipts .ui-list-hit[aria-current="true"] { background: var(--inset); }
.doc-pick input { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--ink); cursor: pointer; }
.doc-roll { min-width: 2.5em; font-size: var(--text-small); font-weight: 600; }
.doc-actions { margin-bottom: var(--space-6); }
.doc-count { flex-basis: 100%; margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.doc-preview-note { margin: 0 0 var(--space-2); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.doc-preview.doc-frame { width: 100%; height: 60vh; min-height: 320px; margin: 0; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }
@media (min-width:1024px) {
.doc-kinds { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: var(--line); }
}
@media (min-width:1024px) {
.doc-kinds>.ui-list-item { display: flex; border-bottom: 0; background: var(--surface); }
}
@media (min-width:1024px) {
.doc-kinds>.ui-list-item:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (min-width:1024px) {
.doc-kinds .ui-list-hit { align-items: flex-start; gap: 13px; min-height: var(--tap-min); padding: var(--space-4) 18px; }
}
@media (min-width:1024px) {
.doc-kinds .ui-list-glyph { font-size: 21px; }
}
@media (min-width:1024px) {
.doc-kinds .ui-list-meta { margin-top: 3px; font-size: 12.5px; line-height: 1.5; }
}
@media (min-width:1024px) {
.doc-kinds .doc-go-m { display: none; }
}
@media (min-width:1024px) {
.doc-kinds .doc-go-d { display: inline-flex; font-size: 17px; color: var(--ink-3); }
}
@media (min-width:1024px) {
.doc-preview.doc-frame { height: 70vh; }
}

/* ── learn ── */
@media (max-width:1023.98px) {
.learn-list { margin: 0 -20px; }
}
@media (min-width:1024px) {
.learn-list { max-width: 720px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
}
.learn-subject { padding: var(--space-3) 14px; background: var(--inset); border-bottom: 1px solid var(--line); }
.learn-subject .ui-field { margin-bottom: 0; }
.chapter-list { display: block; list-style: none; margin: 0; padding: 0; }
.chapter-card { display: block; width: 100%; min-height: var(--tap-min); margin: 0; padding: 13px 14px; background: var(--surface); color: var(--ink); border: 0; border-bottom: 1px solid var(--line); border-radius: 0; box-shadow: none; font-family: var(--font-bn); font-size: inherit; line-height: inherit; text-align: left; cursor: pointer; }
.chapter-card:hover,
.chapter-card:active { background-color: var(--neutral-100); transform: none; }
.chapter-card:focus-visible { outline-offset: -2px; }
@media (min-width:1024px) {
.chapter-list>li:last-child .chapter-card { border-bottom: 0; }
}
.chapter-head { display: flex; align-items: center; gap: 10px; margin-bottom: var(--space-2); }
.chapter-title { flex: 1; min-width: 0; font-size: 14.5px; font-weight: 600; line-height: 1.4; color: var(--ink); }
.chapter-head .ui-status { flex: none; }
.chapter-pct { flex: none; font-size: var(--text-small); font-weight: 700; color: var(--ink-3); }
.chapter-card[data-progress-tone="success"] .chapter-pct { color: var(--ok); }
.chapter-card[data-progress-tone="warn"] .chapter-pct { color: var(--warn); }
.chapter-card[data-progress-tone="danger"] .chapter-pct { color: var(--danger); }
.chapter-card .ui-progress-track { display: block; }
.chapter-card .ui-progress-fill { border-radius: var(--r-pill); background: var(--ink-3); }
.chapter-card[data-progress-tone="success"] .ui-progress-fill { background: var(--ok); }
.chapter-card[data-progress-tone="warn"] .ui-progress-fill { background: var(--warn); }
.chapter-card[data-progress-tone="danger"] .ui-progress-fill { background: var(--danger); }
.chapter-pre { display: block; margin: 0 0 var(--space-2); font-size: 12.5px; line-height: var(--lh-small); color: var(--ink-2); }
.topic-card[data-state="completed"] .ui-list-glyph { color: var(--ok); }
.learn-offline { margin: 0 0 var(--space-3); border: 1px solid var(--warn); border-radius: var(--r-md); }
.lesson-reader { max-width: 68ch; padding: 0; line-height: 1.85; color: var(--ink); }
.reader-tools { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-3); padding: 0; }
.reader-tools-label { margin-right: auto; font-size: var(--text-small); color: var(--ink-2); }
.reader-size { min-width: var(--tap-min); min-height: var(--tap-min); padding: 0; display: grid; place-items: center; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--surface); color: var(--ink); font-family: var(--font-bn); font-size: 14px; line-height: 1; cursor: pointer; }
.reader-size-lg { font-size: 18px; }
.reader-size:hover:not(:disabled) { border-color: var(--ink); background: var(--inset); }
.reader-size:active:not(:disabled) { transform: scale(.97); }
@media (prefers-reduced-motion:reduce) {
.reader-size:active:not(:disabled) { transform: none; }
}
.reader-size:disabled { opacity: .45; cursor: default; }
.block-text { margin: 0 0 var(--space-4); }
.block-formula { margin: var(--space-3) 0 var(--space-4); padding: var(--space-3) var(--space-4); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); font-family: var(--font-num); font-size: inherit; text-align: left; overflow-x: auto; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; }
.block-key-point { margin: var(--space-3) 0 var(--space-4); padding: var(--space-3) var(--space-4); background: var(--inset); border-radius: var(--r-md); font-size: inherit; }
.block-example,
.block-practice { margin: var(--space-3) 0 var(--space-4); padding: var(--space-3) var(--space-4); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
.block-practice { border-style: dashed; }
.block-label { display: block; margin: 0 0 var(--space-1); letter-spacing: .12em; }
.block-figure img { display: block; width: 100%; height: auto; border-radius: var(--r-md); background: var(--inset); }
.prac-wrap { margin-top: var(--space-6); padding-bottom: var(--space-6); }
.topic-done { margin-top: var(--space-6); }
.topic-done-alt { margin-top: var(--space-2); }

/* ── my-attendance ── */
.myatt-offline { margin-bottom: var(--space-4); }
.myatt-now { max-width: 480px; }
@media (max-width:1023.98px) {
.ui-stat-row.myatt-stats[data-count="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width:1023.98px) {
.ui-stat-row.myatt-stats[data-count="3"]>.ui-stat { border-right: 1px solid var(--line); }
}
@media (max-width:1023.98px) {
.ui-stat-row.myatt-stats[data-count="3"]>.ui-stat:last-child { border-right: none; }
}
@media (max-width:1023.98px) {
.ui-stat-row.myatt-stats[data-count="3"]>.ui-stat+.ui-stat { border-top: none; }
}
.myatt-month { display: block; margin: var(--space-4) 0 var(--space-2); }
.myatt-cal { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
.myatt-day { aspect-ratio: 1; display: grid; place-items: center; min-width: 0; border-radius: var(--r-sm); border: 1px solid var(--line); background: var(--surface); color: var(--ink-2); font-size: 10px; line-height: 1; }
.myatt-day[data-status="future"] { background: var(--inset); border-color: transparent; color: var(--ink-3); }
.myatt-day[data-status="present"],
.myatt-day[data-status="absent"],
.myatt-day[data-status="late"],
.myatt-day[data-status="half_day"],
.myatt-day[data-status="excused"] { border-color: transparent; color: var(--surface); }
.myatt-day[data-status="present"],
.myatt-swatch[data-status="present"] { background: var(--ok); }
.myatt-day[data-status="absent"],
.myatt-swatch[data-status="absent"] { background: var(--danger); }
.myatt-day[data-status="late"],
.myatt-day[data-status="half_day"],
.myatt-swatch[data-status="late"] { background: var(--warn); }
.myatt-day[data-status="excused"],
.myatt-swatch[data-status="excused"] { background: var(--info); }
.myatt-key { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-3); }
.myatt-key-item { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--ink-2); }
.myatt-swatch { display: block; width: 11px; height: 11px; flex: none; }
.myatt-note { margin: var(--space-3) 0 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.myatt-section { margin-top: var(--space-6); }
.ui-table .myatt-word { display: none; }
.myatt-skeleton .ui-stat-text { flex: 1; }
.myatt-skel-value { height: 26px; width: 50%; margin-top: 5px; }
.myatt-skel-day { aspect-ratio: 1; }

/* ── results ── */
.page-header-actions>.exam-select-field { margin-bottom: 0; min-width: 200px; }
.result-offline { margin: 0 0 var(--space-3); border: 1px solid var(--warn); border-radius: var(--r-md); }
.result-sheet { margin: 0 0 var(--space-4); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.result-sheet>.ui-data { border: 0; border-radius: 0; }
.result-hero { padding: 18px var(--space-4); background: var(--ok); color: var(--surface); text-align: left; }
.result-hero[data-outcome="fail"] { background: var(--danger); }
.result-hero-exam { margin: 0 0 3px; font-size: 12px; line-height: 1.5; }
.result-hero-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3); }
.result-hero-gpa { font-size: 38px; font-weight: 700; line-height: 1; }
.result-hero-grade { font-size: 20px; font-weight: 700; }
.result-hero-rank { margin-left: auto; font-size: var(--text-small); }
.result-hero-date { margin: var(--space-2) 0 0; font-size: 12px; line-height: 1.5; }
.result-hero-fail { display: flex; align-items: center; gap: 6px; margin: var(--space-2) 0 0; font-size: var(--text-small); font-weight: 700; }
.result-hero-fail .ui-icon { flex: none; font-size: 15px; }
.result-trend-note { display: flex; align-items: center; gap: 9px; margin: 0; padding: var(--space-3) 14px; background: var(--info-tint); border-bottom: 1px solid var(--line); font-size: var(--text-small); color: var(--ink-2); }
.result-trend-note .ui-icon { flex: none; font-size: 16px; color: var(--info); }
.result-subjects .ui-table .result-part-label { display: none; }
.result-subjects sup { margin-left: 2px; font-size: 11px; color: var(--ink-3); }
.result-total { font-weight: 600; color: var(--ink-2); }
.result-grade { font-weight: 700; color: var(--ink-3); }
.result-grade[data-grade="ok"] { color: var(--ok); }
.result-grade[data-grade="warn"] { color: var(--warn); }
.result-grade[data-grade="danger"] { color: var(--danger); }
.result-subjects .ui-list .result-total { display: inline-block; width: 38px; text-align: right; font-size: 15px; }
.result-subjects .ui-list .result-grade { display: inline-block; width: 42px; text-align: right; font-size: 14px; }
.result-optional-note { margin: 0 0 var(--space-6); font-size: var(--text-small); line-height: 1.6; color: var(--ink-2); }
.result-history { margin: 0 0 var(--space-6); }
.result-history-list { display: flex; gap: var(--space-2); margin: 0; padding: 0; list-style: none; overflow-x: auto; overscroll-behavior-x: contain; }
.result-history-point { flex: 1 0 auto; min-width: 88px; padding: 10px 12px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
.result-history-point[data-current="true"] { padding: 9px 11px; border: 2px solid var(--ink); }
.result-history-gpa { display: block; font-size: 18px; font-weight: 600; line-height: 1.2; }
.result-history-exam { display: block; font-size: 11.5px; color: var(--ink-3); }

/* ── routine ── */
.routine-mode { margin-bottom: var(--space-4); }
.routine-offline { margin: 0 0 var(--space-4); }
.routine-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.routine-list { list-style: none; margin: 0; padding: 0; }
.routine-row { display: flex; align-items: center; gap: var(--space-3); min-height: 62px; padding: 0 14px; background: var(--surface); border-bottom: 1px solid var(--line); border-left: 4px solid transparent; }
.routine-row:last-child { border-bottom: 0; }
.routine-time { flex: none; width: 52px; font-size: 14px; font-weight: 600; color: var(--ink-2); }
.routine-body { flex: 1; min-width: 0; padding: var(--space-2) 0; }
.routine-class { display: block; font-size: var(--text-body); font-weight: 600; color: var(--ink); }
.routine-subject { display: block; font-size: 12.5px; color: var(--ink-3); }
.routine-room { flex: none; font-size: 12.5px; color: var(--ink-3); }
.routine-row[data-now="true"] { background: var(--neutral-100); border-left-color: var(--rule); }
.routine-row[data-now="true"] .routine-time { color: var(--ink); font-weight: 700; }
.routine-row:not([data-kind="teaching"]) { min-height: var(--tap-min); background: var(--inset); }
.routine-row:not([data-kind="teaching"]) .routine-time { font-size: var(--text-small); font-weight: 400; color: var(--ink-3); }
.routine-kind { display: block; font-size: var(--text-small); font-style: italic; color: var(--ink-3); }
.routine-sub-note { display: flex; align-items: flex-start; gap: var(--space-1); margin-top: var(--space-1); font-size: 12.5px; line-height: var(--lh-small); color: var(--warn); }
.routine-sub-glyph { display: flex; flex: none; width: 13px; height: 13px; margin-top: 3px; }
.routine-sub-glyph svg { width: 100%; height: 100%; }
.routine-days { background: var(--surface); }
.routine-days .ui-tab { flex: 1 1 0; min-width: var(--tap-min); justify-content: center; padding: 0; font-size: var(--text-small); font-weight: 500; color: var(--ink-2); border-bottom: 0; margin-bottom: 0; border-right: 1px solid var(--line); }
.routine-days .ui-tab:last-child { border-right: 0; }
.routine-days .ui-tab[aria-selected="true"] { background: var(--ink); color: var(--surface); font-weight: 700; }
.routine-day-panel>.ui-state { border: 0; border-radius: 0; }
.routine-week-scroll { display: none; }
@media (min-width:1024px) {
.routine-week-scroll { display: block; margin: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
}
@media (min-width:1024px) {
.routine-week-stack { display: none; }
}
.routine-week-scroll .routine-grid { border-style: hidden; }
.routine-week-scroll .routine-grid thead th { background: var(--inset); color: var(--ink); text-align: center; vertical-align: middle; }
.routine-week-scroll .routine-grid td { text-align: center; vertical-align: middle; }
.routine-week-scroll .routine-grid-period { display: table-cell; text-align: right; vertical-align: middle; }
.routine-week-scroll .routine-grid-period>span { display: block; }
.routine-grid-day { display: block; font-size: var(--text-small); font-weight: 700; color: var(--ink); }
.routine-grid-date { display: block; font-size: var(--text-label); font-weight: 400; color: var(--ink-3); }
.routine-grid-cell { min-width: 108px; background: var(--surface); }
.routine-grid-cell>span { display: block; }
.routine-grid-cell[data-kind]:not([data-kind="teaching"]) { background: var(--inset); color: var(--ink-3); }
.routine-grid-cell[data-substitution="true"] { background: var(--warn-tint); }
.routine-grid-subject { font-weight: 600; color: var(--ink); }
.routine-grid-meta { font-size: 12.5px; color: var(--ink-3); }
.routine-grid-kind { font-style: italic; color: var(--ink-3); }
.routine-grid-sub { margin-top: 2px; font-size: 12.5px; font-weight: 700; color: var(--warn); }

/* ═══ [4] Ata Ekta — wave 2C: principal, admin and routine screens ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── principal-home ── */
.ph-date { font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-3); white-space: nowrap; }
.ph-board { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ph-board.ph-more { margin-top: var(--space-6); }
.ph-band { padding: var(--space-4) 18px; background: var(--surface); border-bottom: 1px solid var(--line); }
.ph-band .ui-stat-value { overflow-wrap: anywhere; }
@media (max-width:1023.98px) {
.ph-band { padding: 0; }
}
@media (max-width:1023.98px) {
.ph-band>.ui-stat-row { border: 0; border-radius: 0; }
}
.ph-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1px; background: var(--line); }
@media (min-width:1024px) {
.ph-grid { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
}
.ph-panel { min-width: 0; padding: var(--space-4) 18px; background: var(--surface); }
.ui-section-head.ph-panel-head { min-height: 20px; padding-bottom: 0; border-bottom: 0; margin-bottom: var(--space-3); }
.ph-panel-head .ui-section-title { font-size: var(--text-label); line-height: var(--lh-label); font-weight: var(--w-label); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.ph-panel-head .ui-section-action { margin: -8px 0; }
.ph-panel>.ui-list,
.ph-panel>.ui-data,
.ph-panel>.ui-stat-row { border: 0; border-radius: 0; }
.ph-panel>.ui-state { padding: 0; border: 0; border-radius: 0; }
.ph-panel .ui-list-hit { padding-left: 0; padding-right: 0; }
.ph-panel .ui-list-hit:focus-visible { outline-offset: -2px; }
.ph-panel .ui-stat-row>.ui-stat { padding: 0; }
.ph-attention .ui-list-hit { min-height: var(--tap-min); padding-top: 9px; padding-bottom: 9px; gap: 10px; align-items: flex-start; }
.ph-attention .ui-list-hit::before { content: ""; flex: none; width: 6px; height: 6px; margin-top: 8px; background: var(--warn); }
@media (min-width:1024px) {
.ph-attention .ui-list-hit::before,
.ph-calm::before { margin-top: 7px; }
}
.ph-attention .ui-list-title { font-weight: 400; line-height: 1.5; }
@media (min-width:1024px) {
.ph-attention .ui-list-title,
.ph-calm { font-size: 13.5px; }
}
.ph-attention .ui-list-chevron { display: none; }
.ph-calm { display: flex; gap: 10px; align-items: flex-start; margin: 0; padding: 9px 0; line-height: 1.5; color: var(--ink); }
.ph-calm::before { content: ""; flex: none; width: 6px; height: 6px; margin-top: 8px; background: var(--ok); }
.ph-note { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.ph-panel>.ui-data+.ph-note { margin-top: var(--space-3); }
.ph-skel-value { display: block; height: 26px; width: 50%; margin-top: 5px; }
.ph-skel-head { display: block; margin-bottom: var(--space-4); }
.ph-skel-line { display: block; margin-top: var(--space-3); }
.ph-skeleton .ui-stat-text { flex: 1; }

/* ── academic ── */
.ac-tree-shell { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ac-tree-intro { display: flex; align-items: center; gap: var(--space-2); margin: 0; padding: 10px; background: var(--info-tint); border-bottom: 1px solid var(--line); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.ac-tree-intro-glyph { flex: none; font-size: 15px; color: var(--info); }
.ac-tree,
.ac-tree-group { list-style: none; margin: 0; padding: 0; }
.ac-row { display: flex; align-items: center; gap: 11px; min-height: 50px; padding: 0 var(--space-1) 0 10px; border-bottom: 1px solid var(--line); background: var(--surface); }
.ac-row.is-open { background: var(--inset); }
.ac-node:not(.is-empty)>.ac-row:not(.is-open):hover { background: var(--neutral-100); }
.ac-node[data-depth="1"]>.ac-row { padding-left: 24px; }
.ac-node[data-depth="2"]>.ac-row { padding-left: 38px; }
.ac-node-hit { flex: 1; min-width: 0; display: flex; align-items: center; gap: 11px; min-height: var(--tap-min); padding: var(--space-1) 0; background: none; border: none; font-family: var(--font-bn); color: var(--ink); text-align: left; cursor: pointer; }
.ac-node-hit:focus-visible { outline-offset: -2px; }
.ac-node-toggle { flex: none; display: grid; place-items: center; width: 15px; height: 15px; font-size: 15px; color: var(--ink-3); }
.ac-node-glyph { flex: none; display: grid; place-items: center; width: 16px; height: 16px; font-size: 16px; color: var(--ink-2); }
.ac-node[data-depth="0"]>.ac-row .ac-node-glyph { color: var(--ink); }
.ac-node-text { flex: 1; min-width: 0; }
.ac-node-head { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-1) var(--space-2); }
.ac-node-name { font-size: 15px; font-weight: 600; line-height: 1.4; overflow-wrap: anywhere; }
.ac-node[data-depth="0"]>.ac-row .ac-node-name { font-weight: 700; }
.ac-node-meta { display: block; font-size: 12px; line-height: 1.5; color: var(--ink-3); }
.ac-node-actions { display: none; flex: none; align-items: center; gap: 6px; }
.ac-node-more { display: flex; flex: none; }
.ac-node-actions .ui-icon-btn,
.ac-node-more .ui-icon-btn { font-size: 15px; }
.ac-node.is-empty>.ac-row { flex-wrap: wrap; gap: var(--space-1) var(--space-3); padding-block: var(--space-2); }
.ac-node-empty-text { flex: 1 1 12rem; min-width: 0; margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.ac-tree-foot { margin: 0; padding: 11px 10px; background: var(--surface); border-top: 2px solid var(--rule); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
@media (min-width:1024px) {
.ac-tree-intro { padding: 10px 18px; }
}
@media (min-width:1024px) {
.ac-row { padding: 0 var(--space-3) 0 18px; }
}
@media (min-width:1024px) {
.ac-node[data-depth="1"]>.ac-row { padding-left: 44px; }
}
@media (min-width:1024px) {
.ac-node[data-depth="2"]>.ac-row { padding-left: 70px; }
}
@media (min-width:1024px) {
.ac-node-name { font-size: 14.5px; }
}
@media (min-width:1024px) {
.ac-node-actions { display: flex; min-width: calc(var(--tap-min) * 2 + 6px); }
}
@media (min-width:1024px) {
.ac-node-more { display: none; }
}
@media (min-width:1024px) {
.ac-tree-foot { padding: 11px 18px; }
}
.ac-detail>*+* { margin-top: var(--space-4); }
.ac-detail>*+.ui-section-head { margin-top: var(--space-6); }

/* ── students ── */
.stu-search { overflow: hidden; }
.stu-filters { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px; padding: var(--space-3) 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.stu-filters>.ui-search { flex: 1 1 220px; min-width: 0; }
.stu-filters>.ui-filters { flex: 0 1 auto; min-width: 0; }
@media (min-width:1024px) {
.stu-filters>.ui-search { flex: 2 1 200px; }
}
@media (min-width:1024px) {
.stu-filters>.ui-filters { flex: 1 1 120px; }
}
.stu-filters .ui-filter-field { flex: 1 1 auto; min-width: 0; }
.stu-search>.ui-data { border: 0; border-radius: 0; }
.stu-search .ui-table [data-col="status"] { text-align: right; }
.stu-search>.ui-list-skeleton { padding: var(--space-4) 18px; }
.stu-record { margin-top: var(--space-3); overflow: hidden; }
.stu-record-head { display: flex; align-items: flex-start; gap: var(--space-3); padding: var(--space-4) 18px; }
.stu-record-titles { flex: 1; min-width: 0; }
.stu-record-name { overflow-wrap: anywhere; }
.stu-record-code { margin-top: var(--space-1); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.stu-tabs { padding: 0 var(--space-1); }
.stu-panel { display: flex; flex-direction: column; gap: var(--space-6); padding: var(--space-4) 18px; }
.stu-note { font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.stu-panel .ui-table .stu-cell-word { display: none; }
.stu-fees .ui-table [data-col="due"] { text-align: right; }

/* ── users ── */
.users-note { margin-bottom: var(--space-4); }
.users-panel { overflow: hidden; margin-bottom: var(--space-4); }
.users-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: var(--space-3) 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.users-filters .ui-search { flex: 2 1 200px; min-width: 0; }
.ui-field.users-role { flex: 1 1 120px; min-width: 0; margin: 0; }
.users-panel>.ui-data,
.users-panel>.ui-state { border: 0; border-radius: 0; }
.users-panel>.ui-list-skeleton { padding: var(--space-4) 18px; }
.users-panel .ui-table th[data-col="status"],
.users-panel .ui-table td[data-col="status"],
.users-panel .ui-table th[data-col="actions"],
.users-panel .ui-table td[data-col="actions"] { text-align: right; }
.users-foot { padding: var(--space-3) 18px; border-top: 2px solid var(--rule); font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.users-foot-cap { margin-bottom: var(--space-1); color: var(--ink); }
.users-create { padding: var(--space-4) 18px; margin-bottom: var(--space-4); }
@media (min-width:1024px) {
.users-create-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-4); }
}
.users-create-note { margin: 0 0 var(--space-3); }
.users-code.issued-code-card { margin: 0 0 var(--space-4); text-align: left; }
.users-code .ui-btn { justify-self: start; }
.users-panel .ui-list .ui-row-actions { justify-content: flex-start; margin-top: var(--space-1); }
.users-panel .ui-list .ui-row-actions>.btn-ghost:first-child { margin-left: -13px; }
.users-panel .ui-list-dot:has(+.ui-list-cell>.ui-row-actions) { display: none; }
@media (max-width:1023.98px) {
.users-filters,
.users-foot { padding: var(--space-3) 14px; }
}
@media (max-width:1023.98px) {
.users-panel>.ui-list-skeleton { padding: var(--space-3) 14px; }
}
@media (max-width:1023.98px) {
.users-create { padding: var(--space-4) 14px; }
}

/* ── roles ── */
.ui-data.roles-matrix[data-shape="table-list"]>.ui-table-scroll { display: block; }
.ui-data.roles-matrix[data-shape="table-list"]>.ui-list { display: none; }
.roles-note { margin: 0; padding: var(--space-3) 18px; background: var(--info-tint); border-bottom: 1px solid var(--line); font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.roles-matrix .ui-table { min-width: 520px; }
.roles-matrix .ui-table thead th:not(:first-child),
.roles-matrix .ui-table td { text-align: center; }
.roles-mark { display: inline-flex; align-items: center; vertical-align: middle; font-size: 16px; line-height: 1; }
.roles-mark[data-allowed="true"] { color: var(--ok); }
.roles-mark[data-allowed="false"] { color: var(--line); }
@media (max-width:1023.98px) {
.roles-matrix .ui-table thead th:first-child,
.roles-matrix .ui-table tbody th { position: sticky; left: 0; z-index: 1; }
}
@media (max-width:1023.98px) {
.roles-matrix .ui-table tbody th { background: var(--surface); white-space: nowrap; box-shadow: inset -2px 0 0 var(--rule), 3px 0 6px color-mix(in srgb, var(--neutral-900) 12%, transparent); }
}
@media (max-width:1023.98px) {
.roles-matrix .ui-table thead th:first-child { width: 1%; box-shadow: inset -2px 0 0 var(--rule), 3px 0 6px color-mix(in srgb, var(--neutral-900) 12%, transparent); }
}
@media (max-width:1023.98px) {
.roles-matrix .ui-table tbody tr:hover>th { background: var(--neutral-100); }
}

/* ── subjects ── */
.subj-rows .ui-list-hit { min-height: 58px; padding-top: var(--space-1); padding-bottom: var(--space-1); }
.subj-rows .ui-list-hit:focus-visible { outline-offset: -2px; }
.subj-rows .ui-list-glyph { font-size: 19px; }
.subj-rows .ui-list-chevron { display: none; }
@media (max-width:1023.98px) {
.ui-list.subj-rows { margin: 0 -20px; border-left: 0; border-right: 0; border-radius: 0; }
}
@media (max-width:1023.98px) {
.offline-banner.subj-offline { margin: 0 -20px; }
}
@media (max-width:1023.98px) {
.subj-offline+.ui-list.subj-rows { border-top: 0; }
}
@media (min-width:1024px) {
.ui-list.subj-rows { max-width: 720px; }
}
@media (min-width:1024px) {
.offline-banner.subj-offline { max-width: 720px; margin: 0 0 var(--space-3); border: 1px solid var(--warn); border-radius: var(--r-md); }
}

/* ── rooms ── */
.rooms-table .ui-table [data-col="state"],
.rooms-table .ui-table [data-col="actions"] { text-align: right; white-space: nowrap; }
.rooms-table .ui-table .rooms-actions { justify-content: flex-end; flex-wrap: nowrap; }
.rooms-table .ui-table { min-width: 480px; }
.rooms-table .ui-list .rooms-actions { margin-top: var(--space-2); }
.rooms-table .ui-list-dot:has(+.ui-list-cell>.rooms-actions) { display: none; }
.rooms-caps .btn-secondary[aria-pressed="true"] { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.rooms-caps .btn-secondary[aria-pressed="true"]:hover:not(:disabled) { background: var(--neutral-800); border-color: var(--neutral-800); }

/* ── teachingassignments ── */
.ta-error { margin-bottom: var(--space-4); }
.ui-data.ta-shell { overflow: clip; }
.ta-picker { display: flex; flex-wrap: wrap; align-items: center; gap: 10px var(--space-4); padding: var(--space-3) 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.ta-picker>.ta-class { display: flex; align-items: center; gap: var(--space-2); flex: 0 1 auto; min-width: 0; max-width: 100%; margin: 0; }
.ta-class .ui-field-label { margin: 0; white-space: nowrap; }
.ta-class .ui-field-control { min-width: 0; }
.ui-table.assign-matrix { min-width: 520px; border-collapse: separate; border-spacing: 0; }
.ui-table.assign-matrix thead th { padding: 10px 12px; vertical-align: bottom; }
.assign-matrix .assign-subject { display: block; }
.assign-matrix .ta-load { display: block; margin-top: 2px; font-size: var(--text-label); font-weight: 400; letter-spacing: normal; text-transform: none; color: var(--ink-3); }
.ui-table.assign-matrix tbody th { padding: 8px 12px; font-weight: 600; background: var(--inset); white-space: nowrap; vertical-align: middle; }
.ui-table.assign-matrix td { padding: 4px 8px; vertical-align: middle; }
.ui-table.assign-matrix th:first-child { position: sticky; left: 0; z-index: 1; }
.assign-matrix .assign-cell { min-width: max-content; min-height: var(--tap-min); padding: 0 9px; font-size: 13.5px; line-height: 1.3; border-color: var(--line); white-space: nowrap; cursor: pointer; appearance: none; -webkit-appearance: none; }
.assign-matrix .assign-cell option { color: var(--ink); background: var(--surface); }
.assign-matrix .assign-cell[data-dirty="true"] { border-color: var(--ink); }
.assign-matrix .assign-cell[data-empty="true"] { background: var(--danger-tint); border-color: var(--danger); color: var(--danger); }
.assign-matrix .assign-cell:focus { border: 2px solid var(--accent); padding: 0 8px; }
.ta-legend { margin: 0; padding: var(--space-3) 18px 0; border-top: 2px solid var(--rule); font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.assign-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-1) 18px var(--space-3); background: var(--surface); }
.ta-status { flex: 1 1 auto; min-width: 0; margin: 0; font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.assign-bar .assign-dirty { font-weight: 600; color: var(--warn); }
@media (min-width:1024px) {
.ta-save-bottom { display: none; }
}
@media (max-width:1023.98px) {
.ta-save-top { display: none; }
}
@media (max-width:1023.98px) {
.ta-picker { padding: 10px 14px; }
}
@media (max-width:1023.98px) {
.ta-picker>.ta-class { flex: 1 1 100%; }
}
@media (max-width:1023.98px) {
.ta-class .ui-field-control { flex: 1 1 auto; }
}
@media (max-width:1023.98px) {
.ui-table.assign-matrix th:first-child { border-right: 2px solid var(--rule); box-shadow: 3px 0 6px color-mix(in srgb, var(--neutral-900) 12%, transparent); }
}
@media (max-width:1023.98px) {
.ta-legend { padding: 10px 14px; }
}
@media (max-width:1023.98px) {
.assign-bar { position: sticky; bottom: calc(58px + env(safe-area-inset-bottom, 0px)); z-index: 5; padding: 10px 14px; border-top: 2px solid var(--rule); }
}
@media (max-width:1023.98px) {
.ta-status { flex: 1 1 100%; }
}

/* ── timetable ── */
.tt-body { padding: var(--space-3) 14px; }
@media (min-width:1024px) {
.tt-body { padding: 14px 18px; }
}
.tt-body>.ui-state,
.tt-shift>.ui-state { border: 0; border-radius: 0; padding-left: 0; padding-right: 0; }
.tt-shift+.tt-shift { margin-top: var(--space-6); }
.tt-tabs .ui-tab { flex: 1 1 0; min-width: var(--tap-min); justify-content: center; padding: 0 var(--space-2); font-size: 13.5px; font-weight: 500; color: var(--ink-2); border-bottom: 0; margin-bottom: 0; border-right: 1px solid var(--line); }
.tt-tabs.tt-scope-tabs .ui-tab { min-width: auto; padding: 0 var(--space-3); }
.tt-tabs .ui-tab:last-child { border-right: 0; }
.tt-tabs .ui-tab:hover:not([aria-selected="true"]) { color: var(--ink); background: var(--inset); }
.tt-tabs .ui-tab[aria-selected="true"] { background: var(--ink); color: var(--surface); font-weight: 700; }
.tt-week { display: none; }
@media (min-width:1024px) {
.tt-week { display: block; }
}
@media (min-width:1024px) {
.tt-day { display: none; }
}
.routine-grid.tt-grid { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 2px; }
.routine-grid.tt-grid th,
.routine-grid.tt-grid td { padding: 0; border: 0; background: transparent; color: var(--ink); font-size: 11.5px; line-height: 1.3; vertical-align: middle; text-align: center; white-space: normal; }
.routine-grid.tt-grid thead th { width: auto; padding: 5px 0; background: var(--inset); font-weight: 700; }
.routine-grid.tt-grid thead th:first-child { width: 80px; background: transparent; }
.routine-grid.tt-grid .routine-grid-period { display: table-cell; padding: 0 5px 0 0; text-align: right; font-weight: 400; }
.tt-grid .routine-grid-time { font-family: var(--font-bn); font-size: 11px; line-height: 1.3; color: var(--ink-3); white-space: normal; }
.tt-grid .routine-grid-time .n { display: block; white-space: nowrap; }
.routine-grid.tt-grid td.routine-cell { height: 38px; border: 1px solid var(--line); background: var(--surface); }
.routine-grid.tt-grid td.tt-band-cell { height: 38px; border: 1px solid var(--line); background: var(--inset); color: var(--ink-3); }
.tt-grid .routine-slot { display: flex; flex-direction: column; align-items: center; gap: 1px; min-height: 0; padding: 2px; border: 0; border-radius: 0; background: transparent; color: var(--ink); text-align: center; cursor: default; }
.tt-grid .routine-slot+.routine-slot { margin-top: 2px; padding-top: 4px; border-top: 1px solid var(--line); }
.tt-grid .routine-slot-subject { font-size: 11.5px; font-weight: 400; line-height: 1.3; }
.tt-grid .routine-slot-meta { font-size: var(--text-label); line-height: 1.3; color: var(--ink-3); }
.tt-grid .routine-slot-empty { font-size: 11.5px; color: var(--ink-3); }
.tt-day { margin: 0 -14px; }
.tt-body>.tt-shift:first-child>.tt-week:first-child+.tt-day { margin-top: calc(var(--space-3) * -1); }
.tt-day .ui-list { border: 0; border-radius: 0; }
.tt-day-time { flex: none; width: 88px; font-size: var(--text-small); font-weight: 600; line-height: 1.3; color: var(--ink-2); }
.tt-day-time .n { display: block; white-space: nowrap; }
.tt-day .ui-list-title { overflow-wrap: anywhere; }
.tt-day .ui-list-status { max-width: 40%; text-align: right; }
.tt-day-break .ui-list-hit { background: var(--inset); }
.tt-day-break .ui-list-title { font-weight: 500; color: var(--ink-3); }
.tt-foot { display: flex; flex-direction: column; gap: 2px; margin-top: var(--space-4); }
.tt-note { font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-3); }
.tt-print .ui-note-warn { margin: 0; padding: 12px 14px; background: var(--warn-tint); border-left: 4px solid var(--warn); font-size: 13.5px; line-height: 1.55; color: var(--ink); }
.tt-print .doc-preview { width: 100%; height: 60vh; min-height: 320px; margin: 0; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); }

/* ── routineeditor ── */
.editor-toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-4); margin-bottom: var(--space-4); }
.editor-toolbar>.ui-field { flex: 0 1 320px; min-width: 200px; margin-bottom: 0; }
.editor-undo { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); min-height: var(--tap-min); }
@media (min-width:1024px) {
.editor-undo { margin-left: auto; justify-content: flex-end; }
}
.editor-undo-more { font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-3); }
.editor-hold { display: grid; gap: var(--space-1); margin: 0 0 var(--space-3); padding: var(--space-3) 14px; background: var(--surface); border: 1px solid var(--line); border-left: 4px solid var(--rule); border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.editor-hold-what { margin: 0; font-size: var(--text-body); line-height: var(--lh-small); font-weight: 600; color: var(--ink); }
.editor-hold-how { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.editor-hold .ui-button-row { margin-top: var(--space-2); }
.editor-frame { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: clip; }
.editor-grid-scroll { padding: 14px 14px 12px 0; overscroll-behavior-x: contain; }
@media (min-width:1024px) {
.editor-grid-scroll { padding: 14px 14px 12px; }
}
.editor-grid { width: 100%; min-width: calc(62px + var(--editor-days, 5) * 81px); table-layout: fixed; border-collapse: separate; border-spacing: 0; }
.editor-grid th,
.editor-grid td { padding: 3px 0 0 3px; border: 0; background: transparent; vertical-align: middle; font-weight: 400; text-align: center; }
.editor-grid thead th { padding-top: 0; }
.editor-grid .editor-corner { width: 62px; padding: 0; background: var(--surface); }
.editor-grid .editor-day-label { display: block; padding: 5px 0; background: var(--inset); color: var(--ink); font-size: 12px; font-weight: 700; line-height: var(--lh-small); text-align: center; white-space: nowrap; }
.editor-grid .editor-period { padding: 3px 6px 0 0; background: var(--surface); text-align: right; }
.editor-grid .editor-period-time { font-size: 11.5px; line-height: 1.3; color: var(--ink-3); white-space: nowrap; }
.editor-grid .editor-corner,
.editor-grid .editor-period { position: sticky; left: 0; z-index: 1; box-shadow: 0 1px 0 var(--surface); }
@media (max-width:1023.98px) {
.editor-grid .editor-period { border-right: 2px solid var(--rule); box-shadow: 0 1px 0 var(--surface), 6px 0 6px -3px color-mix(in srgb, var(--neutral-900) 12%, transparent); }
}
@media (max-width:1023.98px) {
.editor-grid .editor-corner { background: var(--inset); border-right: 2px solid var(--rule); box-shadow: inset 0 -2px 0 var(--rule), 0 1px 0 var(--surface), 6px 0 6px -3px color-mix(in srgb, var(--neutral-900) 12%, transparent); }
}
@media (max-width:1023.98px) {
.editor-grid .editor-day-label { box-shadow: inset 0 -2px 0 var(--rule); }
}
.editor-grid .editor-cell,
.editor-grid .editor-break { height: 1px; }
.editor-grid .editor-slot { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; width: 100%; height: 100%; min-height: var(--tap-min); margin: 0; padding: 4px 6px; background: var(--surface); border: 1px solid var(--line); border-radius: 0; box-shadow: none; color: var(--ink); font-family: var(--font-bn); font-size: 12px; font-weight: 500; line-height: 1.3; text-align: center; white-space: normal; overflow-wrap: anywhere; cursor: pointer; }
.editor-grid .editor-slot:hover:not(:disabled) { background: var(--neutral-100); }
.editor-grid .editor-slot-subject { font-weight: 500; color: var(--ink); }
.editor-grid .editor-slot-meta { font-size: 11px; color: var(--ink-3); }
.editor-grid .editor-slot-meta[data-missing="true"] { color: var(--danger); font-weight: 600; }
.editor-grid .editor-slot-empty { font-size: 11px; color: var(--ink-3); }
.editor-grid .editor-slot-lock { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; color: var(--ink-2); }
.editor-grid .editor-slot-note { font-size: 11px; font-weight: 600; color: var(--info); }
.editor-mark { margin-left: 3px; font-weight: 400; color: var(--ink-2); }
.editor-legend .editor-mark { margin-left: 0; }
.editor-grid .editor-slot[data-selected="true"] { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.editor-grid .editor-slot[data-target="true"] { border-style: dashed; border-color: var(--ink-2); }
.editor-grid .editor-slot[data-changed="true"] { border-color: var(--info); box-shadow: inset 0 0 0 1px var(--info); }
.editor-grid .editor-slot:disabled { cursor: default; opacity: 1; }
.editor-grid .editor-slot[data-filled="false"]:disabled { border-style: dashed; opacity: 1; }
.editor-grid .editor-break-label { display: flex; align-items: center; justify-content: center; height: 100%; min-height: var(--tap-min); padding: 0 4px; background: var(--inset); border: 1px solid var(--line); color: var(--ink); font-size: 12px; font-weight: 500; line-height: 1.3; cursor: default; }
.editor-legend { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-4); padding: 0 14px 14px; font-size: 12px; line-height: var(--lh-small); color: var(--ink-3); }
.editor-legend-item { display: inline-flex; align-items: center; gap: 5px; }
.editor-notice { margin: 0; padding: 12px 18px; background: var(--danger-tint); border-top: 2px solid var(--danger); color: var(--ink); font-size: 13.5px; line-height: 1.55; }
.editor-notice[data-tone="ok"] { background: var(--ok-tint); border-top-color: var(--ok); }
.editor-notice[data-tone="warn"],
.editor-notice[data-tone="offline"] { background: var(--warn-tint); border-top-color: var(--warn); }
.editor-notice.is-standalone { margin-bottom: var(--space-4); border-radius: 0 0 var(--r-sm) var(--r-sm); }
.editor-foot { padding: 10px 14px; background: var(--surface); border-top: 2px solid var(--rule); }
@media (max-width:1023.98px) {
.editor-dock { position: sticky; bottom: calc(58px + env(safe-area-inset-bottom, 0px)); z-index: 5; }
}
@media (min-width:1024px) {
.editor-foot { display: none; }
}
@media (max-width:1023.98px) {
.page-header .editor-publish-top { display: none; }
}
.editor-resolve .editor-verdict { margin: 0; font-size: var(--text-h3); line-height: var(--lh-h3); font-weight: 600; color: var(--ink); }
.editor-counts,
.editor-moves { list-style: none; margin: 0; padding: 0; }
.editor-counts { border-top: 1px solid var(--line); }
.editor-count,
.editor-move { margin: 0; padding: var(--space-2) 0; border-bottom: 1px solid var(--line); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
.editor-move { display: grid; gap: 2px; }
.editor-move-before { color: var(--ink-3); }
.editor-move-after { color: var(--ink); font-weight: 600; }
.editor-resolve-more { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-3); }
.editor-preview-note { margin: 0; padding: var(--space-2) var(--space-3); background: var(--info-tint); border-left: 4px solid var(--info); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }

/* ── routinegenerate ── */
.card.rgen-frame { overflow: hidden; }
.rgen-frame+.rgen-frame { margin-top: var(--space-4); }
.rgen-frame>.ui-card-head { border-bottom: 2px solid var(--rule); }
.rgen-frame>.ui-list.rgen-list { border: none; border-radius: 0; }
.rgen-frame>.rgen-block+.rgen-block,
.rgen-frame>.rgen-block+.rgen-list,
.rgen-frame>.rgen-list+.rgen-block { border-top: 1px solid var(--line); }
.rgen-block { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-4) 18px; }
.rgen-block>.ui-field { margin-bottom: 0; }
.rgen-block>.ui-success-note { margin: 0; }
.rgen-block>.rgen-eyebrow { margin-top: var(--space-3); }
.rgen-block>.ui-button-row { margin-top: var(--space-1); }
.rgen-block>.ui-button-row>.btn-ghost:first-child { margin-left: -14px; }
.rgen-lead { margin: 0; font-size: var(--text-body); line-height: var(--lh-body); font-weight: 600; color: var(--ink); }
.rgen-sub { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.rgen-meta { margin: 0; font-size: 14px; line-height: var(--lh-body); color: var(--ink); }
.rgen-note { padding: var(--space-3) 14px; background: var(--warn-tint); border-left: 4px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.rgen-note[data-tone="danger"] { background: var(--danger-tint); border-left-color: var(--danger); }
.rgen-note-text { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink); }
.rgen-note-sub { margin: var(--space-1) 0 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.rgen-step .ui-list-glyph,
.rgen-live .ui-list-glyph { font-size: 20px; }
.rgen-step .ui-list-glyph,
.rgen-step .ui-list-sub { color: var(--danger); }
.rgen-live .ui-list-glyph { color: var(--ok); }
.rgen-verdict { margin: 0; font-size: var(--text-h3); line-height: var(--lh-h3); font-weight: 700; color: var(--ink); }
.rgen-verdict[data-tone="success"] { color: var(--ok); }
.rgen-verdict[data-tone="warn"] { color: var(--warn); }
.rgen-verdict[data-tone="danger"] { color: var(--danger); }
.rgen-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: var(--space-3) 18px; border-top: 2px solid var(--rule); }
.rgen-foot-note { flex: 1 1 200px; min-width: 0; margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.rgen-foot>.ui-button-row { flex: 1 1 auto; }
.rgen-foot>.rgen-foot-note+.ui-button-row { flex: 0 1 auto; }
.rgen-foot .ui-button-row>.btn-primary { margin-left: auto; }
@media (max-width:1023.98px) {
.rgen-foot { flex-direction: column; align-items: stretch; }
}
@media (max-width:1023.98px) {
.rgen-foot>.rgen-foot-note { flex: none; }
}
@media (max-width:1023.98px) {
.rgen-foot .ui-button-row>.ui-btn { flex: 1 1 auto; }
}
@media (max-width:1023.98px) {
.rgen-foot .ui-button-row>.btn-primary { margin-left: 0; }
}
.rgen-run-progress { padding: 22px 18px; border-bottom: 1px solid var(--line); }
.rgen-run-track { position: relative; height: 12px; margin-bottom: var(--space-3); overflow: hidden; background: var(--inset); border-radius: var(--r-pill); }
.rgen-run-fill { position: absolute; top: 0; bottom: 0; left: 0; width: 32%; background: var(--info); border-radius: var(--r-pill); animation: rgen-sweep 1.6s var(--ease) infinite; }
@media (prefers-reduced-motion:reduce) {
.rgen-run-track { display: none; }
}
.rgen-run-figures { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); margin: 0; }
.rgen-run-figure { font-size: var(--text-h1); line-height: 1; font-weight: 700; color: var(--ink); }
.rgen-run-unit { font-size: 14px; color: var(--ink-2); }
.rgen-run-what { margin-left: auto; font-size: var(--text-small); color: var(--ink-3); }
@media (max-width:1023.98px) {
.rgen-run-what { margin-left: 0; flex-basis: 100%; }
}
.rgen-run-why { margin: var(--space-2) 0 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-3); }
.rgen-run-rules { padding: var(--space-4) 18px; }
.rgen-run-rules>.rgen-eyebrow { margin: 0 0 var(--space-3); }
.rgen-rules { list-style: none; margin: 0; padding: 0; }
.rgen-rule { display: flex; align-items: center; gap: 11px; padding: var(--space-2) 0; border-bottom: 1px solid var(--line); font-size: 14px; line-height: var(--lh-body); }
.rgen-rule:last-child { border-bottom: none; }
.rgen-rule-glyph { flex: none; font-size: 17px; color: var(--ok); }
.rgen-rule[data-when="after"] .rgen-rule-glyph { color: var(--ink-3); }
.rgen-rule-text { flex: 1; min-width: 0; }
.rgen-rule-meta { flex: none; font-size: var(--text-small); color: var(--ink-3); }
.gen-findings { list-style: none; margin: 0; padding: 0; }
.gen-finding { border-bottom: 1px solid var(--line); }
.gen-finding:last-child { border-bottom: none; }
.gen-finding-open { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); width: calc(100% + 2 * var(--space-2)); min-height: var(--tap-min); margin: 0 calc(-1 * var(--space-2)); padding: 10px var(--space-2); border: 0; border-radius: var(--r-sm); background: none; font-family: var(--font-bn); font-size: inherit; line-height: inherit; color: var(--ink); text-align: left; cursor: pointer; }
.gen-finding-open:hover,
.gen-finding-open:active { background-color: var(--neutral-100); }
.gen-finding-open:focus-visible { outline-offset: -2px; }
.gen-finding-title { flex: 1 1 12rem; min-width: 0; font-size: 13.5px; line-height: 1.5; }
.gen-finding-more { flex: none; font-size: var(--text-small); font-weight: 600; color: var(--ink-2); text-decoration: underline; text-underline-offset: 2px; }
.gen-affected { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.rgen-explain { display: flex; flex-direction: column; gap: var(--space-2); }
.rgen-explain>.rgen-eyebrow { margin-top: var(--space-3); }

/* ── routinepublish ── */
.card.rpub-panel+.card.rpub-panel { margin-top: var(--space-4); }
.rpub-panel>.ui-card-head { align-items: center; flex-wrap: wrap; border-bottom: 2px solid var(--rule); }
.rpub-panel>.ui-card-head>.ui-card-titles { flex: 1 1 10rem; }
.rpub-facts { padding: var(--space-4) 18px; }
.rpub-verdict { margin: 0; font-size: var(--text-body); line-height: var(--lh-body); font-weight: 600; color: var(--ink); }
.rpub-meta { margin: var(--space-1) 0 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.rpub-facts>.ui-stat-row { margin-top: var(--space-3); }
.rpub-facts+.rpub-body { border-top: 1px solid var(--line); }
.rpub-body { padding: 18px; }
.rpub-group+.rpub-group { margin-top: var(--space-6); }
.rpub-list-head { margin: 0 0 var(--space-3); }
.rpub-list { list-style: none; margin: 0; padding: 0; }
.rpub-item { display: flex; align-items: flex-start; gap: 11px; padding: 9px 0; border-bottom: 1px solid var(--line); font-size: 14px; line-height: 1.5; }
.rpub-item:last-child { border-bottom: 0; }
.rpub-dot { flex: none; width: 6px; height: 6px; margin-top: calc(.75em - 3px); background: var(--ink-3); }
.rpub-list[data-tone="danger"] .rpub-dot { background: var(--danger); }
.rpub-list[data-tone="warn"] .rpub-dot { background: var(--warn); }
.rpub-item-text { flex: 1; min-width: 0; }
.rpub-what { display: block; color: var(--ink); }
.rpub-why { display: block; margin-top: 2px; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.rpub-foot { padding: var(--space-3) 18px; border-top: 2px solid var(--rule); }
.rpub-foot .rpub-publish { margin-left: auto; }
.rpub-note { margin: 0 0 var(--space-4); padding: var(--space-2) var(--space-3); background: var(--warn-tint); border-left: 4px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
@media (max-width:1023.98px) {
.rpub-foot .ui-button-row { flex-direction: column; align-items: stretch; }
}
@media (max-width:1023.98px) {
.rpub-foot .rpub-publish { margin-left: 0; }
}
@media (max-width:1023.98px) {
.rpub-foot .ui-btn { justify-content: flex-start; }
}
@media (max-width:1023.98px) {
.rpub-item { font-size: var(--text-body); }
}

/* ── routinesetup ── */
.setup-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.setup-panel>.ui-list { border: 0; border-radius: 0; }
.setup-panel>.ui-list-skeleton { padding: var(--space-4) 18px; }
.setup-screen>.ui-state { margin-bottom: var(--space-4); }
.setup-step>.ui-list-hit { padding-left: 18px; padding-right: 18px; gap: 13px; }
.setup-step .ui-list-glyph { font-size: 20px; }
.setup-step[data-state="ok"] .ui-list-glyph { color: var(--ok); }
.setup-step[data-state="warn"] .ui-list-glyph { color: var(--warn); }
.setup-step[data-state="blocked"] .ui-list-glyph { color: var(--danger); }
.setup-step .ui-list-sub { color: var(--ink-3); }
.setup-step[data-state="warn"] .ui-list-sub { color: var(--warn); }
.setup-step[data-state="blocked"] .ui-list-sub { color: var(--danger); }
.setup-step-state { font-weight: 600; }
.setup-step .ui-list-status .ui-btn { white-space: nowrap; }
.setup-step[data-state="ok"] .ui-list-status .btn-ghost { color: var(--ink-2); }
.setup-step[data-state="ok"] .ui-list-status .btn-ghost:hover:not(:disabled) { background: var(--inset); color: var(--ink); }
.setup-step-editor { padding: var(--space-4) 18px; border-top: 1px solid var(--line); }
.setup-editor { display: flex; flex-direction: column; gap: var(--space-3); }
.setup-editor .ui-field { margin-bottom: 0; }
.setup-editor-note { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.setup-period-list { display: flex; flex-direction: column; gap: var(--space-3); }
.setup-period-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); align-items: center; padding-bottom: var(--space-3); border-bottom: 1px solid var(--line); }
.setup-period-row>:first-child { grid-column: 1 / -1; }
.setup-period-row>.ui-btn { justify-self: end; }
.setup-demand-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2) var(--space-3); align-items: end; padding-bottom: var(--space-3); border-bottom: 1px solid var(--line); }
.setup-demand-name { grid-column: 1 / -1; }
.setup-demand-title { font-size: var(--text-body); font-weight: 600; }
.setup-demand-lab { font-size: var(--text-small); color: var(--ink-3); }
.setup-avail-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); padding-bottom: var(--space-3); border-bottom: 1px solid var(--line); }
.setup-avail-fact { font-size: var(--text-body); font-weight: 600; }
.setup-avail-reason { font-size: var(--text-small); color: var(--ink-3); }
.setup-avail-row>.ui-btn { margin-left: auto; }
.setup-avail-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); }
.setup-avail-form>.setup-avail-wide { grid-column: 1 / -1; }
.setup-foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: 14px 18px; background: var(--surface); border-top: 2px solid var(--rule); }
.setup-foot-text { flex: 1; min-width: 200px; margin: 0; font-size: 13.5px; line-height: var(--lh-small); color: var(--ink-2); }
@media (min-width:1024px) {
.setup-screen { max-width: 760px; }
}
@media (min-width:1024px) {
.setup-step-editor { padding-left: 51px; }
}
@media (min-width:1024px) {
.setup-picker { max-width: 50%; }
}
@media (min-width:1024px) {
.setup-period-row { grid-template-columns: minmax(0, 2fr) minmax(0, 1.25fr) minmax(0, 1.25fr) minmax(0, 1.5fr) auto; }
}
@media (min-width:1024px) {
.setup-period-row>:first-child { grid-column: auto; }
}
@media (min-width:1024px) {
.setup-demand-row { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr); }
}
@media (min-width:1024px) {
.setup-demand-name { grid-column: auto; align-self: center; }
}
@media (min-width:1024px) {
.setup-avail-form { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width:1024px) {
.setup-avail-form>.setup-avail-wide { grid-column: auto; }
}

/* ── examroutine ── */
.exam-routine-tabs { margin-bottom: var(--space-4); }
.exam-routine-table .ui-table-scroll { position: relative; }
.exam-routine-table .ui-table { min-width: 520px; }
.exam-routine-table .ui-table [data-col="date"],
.exam-routine-table .ui-table [data-col="time"] { white-space: nowrap; }
.exam-routine-table .ui-table [data-col="status"] { text-align: right; }
.exam-routine-table tr.is-flagged:has(+tr.row-action)>* { border-bottom: 0; }
.exam-routine-table tr.row-action>td { padding: 0 var(--space-3) var(--space-3); }
.exam-routine-table .inline-form { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.exam-routine-table .inline-form .ui-input { width: auto; flex: 0 1 180px; }
.clash-panel { padding: 13px 18px; background: var(--danger-tint); border-top: 2px solid var(--danger); }
.clash-panel .clash-head { margin: 0; font-size: 13.5px; line-height: 1.55; font-weight: 400; letter-spacing: normal; color: var(--ink); }
.clash-panel .clash-consequence { margin: var(--space-1) 0 0; font-size: var(--text-small); line-height: var(--lh-small); font-weight: 600; color: var(--danger); }
.clash-panel .clash-list { list-style: none; margin: var(--space-2) 0 0; padding: 0; }
.clash-panel .clash-list li { display: grid; grid-template-columns: minmax(4ch, max-content) minmax(0, 1fr); gap: 0 var(--space-2); align-items: baseline; padding: var(--space-2) 0; border-top: 1px solid var(--line); }
.clash-panel .clash-list li:last-child { padding-bottom: 0; }
.clash-panel .clash-roll { font-size: 13.5px; font-weight: 700; color: var(--ink-2); }
.clash-panel .clash-name { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.clash-panel .clash-subjects { grid-column: 2; font-size: var(--text-small); color: var(--ink-2); }
.clash-panel .clash-when { grid-column: 2; font-size: 12.5px; color: var(--ink-2); }
.exam-routine-note { margin: 0; padding: var(--space-3) 18px; background: var(--surface); border-top: 2px solid var(--rule); font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }

/* ── exams ── */
.exams-register { overflow: hidden; }
.exams-register>.ui-data { border: 0; border-radius: 0; }
.exams-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: var(--space-3) 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.exams-filters>.ui-field { margin: 0; min-width: 0; }
.exams-filters>.ui-field[data-kind="search"] { flex: 2 1 200px; }
.exams-filters>.ui-field[data-kind="select"] { flex: 1 1 120px; }
.exams-foot { padding: var(--space-3) 18px; background: var(--surface); border-top: 2px solid var(--rule); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.exams-foot>p+p { margin-top: var(--space-1); }
.exams-na { color: var(--ink-3); }
.exams-table [data-col="status"],
.exams-table [data-col="actions"] { text-align: right; }
.exams-table td[data-col="actions"] .ui-button-row { justify-content: flex-end; flex-wrap: nowrap; }
.exams-table .ui-list-hit:has(>.ui-list-status+.ui-list-status) { flex-wrap: wrap; }
.exams-table .ui-list-hit:has(>.ui-list-status+.ui-list-status)>.ui-list-main { flex-basis: 100%; }
.exams-form .btn-secondary[aria-pressed="true"] { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.exams-form .btn-secondary[aria-pressed="true"]:hover:not(:disabled) { background: var(--neutral-800); border-color: var(--neutral-800); }
@media (max-width:1023.98px) {
.exams-filters,
.exams-foot { padding: var(--space-3) 14px; }
}

/* ── publish ── */
.pub-tabs { margin-bottom: var(--space-4); }
.pub-alert { margin-bottom: var(--space-4); }
.pub-published { margin-top: var(--space-8); }
.pub-published .pub-card+.pub-card { margin-top: var(--space-3); }
.pub-irrev .pub-subjects { margin-top: var(--space-4); }
.pub-card .pub-subjects { margin-top: var(--space-3); }
@media (max-width:1023.98px) {
.pub-irrev .irrev-ack { flex-basis: 100%; }
}
@media (max-width:1023.98px) {
.pub-irrev .irrev-foot .ui-button-row { flex: 1 1 100%; }
}
@media (max-width:1023.98px) {
.pub-irrev .irrev-foot .ui-btn { flex: 1 1 auto; }
}

/* ── rollover ── */
.roll-steps { display: none; list-style: none; margin: 0 0 var(--space-4); padding: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
@media (min-width:1024px) {
.roll-steps { display: flex; }
}
.roll-step { flex: 1 1 0; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 6px; padding: var(--space-3) var(--space-2); font-size: 12.5px; font-weight: 500; line-height: var(--lh-small); color: var(--ink-3); text-align: center; border-right: 1px solid var(--line); box-shadow: inset 0 -3px 0 transparent; }
.roll-step:last-child { border-right: 0; }
.roll-step[data-state="done"] { color: var(--ok); font-weight: 700; }
.roll-step[data-state="current"] { color: var(--ink); font-weight: 700; box-shadow: inset 0 -3px 0 var(--rule); }
.roll-step-mark { flex: none; display: inline-flex; align-items: center; }
.roll-step-mark>.ui-icon { font-size: 14px; }
.roll-step-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roll-steps-compact { margin: 0 0 var(--space-4); padding: var(--space-3); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
@media (min-width:1024px) {
.roll-steps-compact { display: none; }
}
.roll-steps-head { display: flex; align-items: baseline; gap: var(--space-2); margin: 0 0 var(--space-2); }
.roll-steps-name { min-width: 0; font-size: var(--text-small); font-weight: 700; color: var(--ink); }
.roll-steps-count { flex: none; margin-left: auto; font-size: var(--text-label); color: var(--ink-3); }
.roll-steps-bar { display: flex; gap: 2px; height: 7px; }
.roll-steps-seg { flex: 1 1 0; background: var(--inset); }
.roll-steps-seg[data-on="true"] { background: var(--ink); }
.roll-years { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4); background: var(--inset); border: 1px solid var(--line); border-radius: var(--r-md); }
@media (min-width:1024px) {
.roll-years { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.roll-years>.roll-year { margin-bottom: 0; }
.roll-error { margin-bottom: var(--space-4); }
.roll-gate .roll-blocked { margin-top: var(--space-6); }
.roll-blocked-why { margin: 0 0 var(--space-3); font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.roll-list { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); margin-top: var(--space-4); }
.roll-list>.ui-data { align-self: stretch; }
.roll-gate .irrev-foot>.ui-button-row { margin-left: auto; }
.roll-foot-note { flex: 1 1 12rem; min-width: 0; margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.roll-foot-note.is-full { flex-basis: 100%; }
.roll-gate[data-blocked="true"] .irrev-ack,
.roll-gate[data-blocked="true"] .irrev-ack-box { color: var(--ink-3); cursor: default; }
@media (max-width:1023.98px) {
.roll-gate .irrev-foot>.ui-button-row { flex: 1 1 100%; }
}
@media (max-width:1023.98px) {
.roll-gate .irrev-foot>.ui-button-row>.ui-btn { flex: 1 1 auto; }
}
.roll-done { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); padding: var(--space-4); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
.roll-done>.ui-success-note { align-self: stretch; margin: 0; }
.roll-done>.roll-foot-note { flex: none; }
.roll-done>.roll-list { align-self: stretch; margin-top: 0; }

/* ── import ── */
.import-kind { margin-bottom: var(--space-4); }
@media (max-width:1023.98px) {
.page-header .import-step-chip { display: none; }
}
.import-wizard { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.import-wizard .stepper { display: flex; gap: 0; list-style: none; margin: 0; padding: 0; background: var(--surface); border-bottom: 2px solid var(--rule); }
.import-wizard .stepper-step { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: center; gap: 6px; padding: 11px 8px; margin-bottom: -2px; font-size: 12.5px; font-weight: 500; line-height: var(--lh-small); color: var(--ink-3); text-align: center; border-right: 1px solid var(--line); border-bottom: 3px solid transparent; }
.import-wizard .stepper-step:last-child { border-right: none; }
.import-wizard .stepper-step[data-state="done"] { color: var(--ok); font-weight: 700; border-bottom-color: transparent; }
.import-wizard .stepper-step[data-state="current"] { color: var(--ink); font-weight: 700; border-bottom-color: var(--rule); }
.import-wizard .stepper-num { display: inline-flex; align-items: center; flex: none; }
.import-wizard .stepper-num .ui-icon { font-size: 14px; }
.import-wizard .stepper-label { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.import-wizard .stepper-compact { display: block; margin: 0; padding: 11px 13px; background: var(--surface); border-bottom: 2px solid var(--rule); }
.import-wizard .stepper-compact-head { display: flex; align-items: baseline; gap: var(--space-2); margin: 0 0 var(--space-2); }
.import-wizard .stepper-compact-name { font-size: 13px; font-weight: 700; color: var(--ink); }
.import-wizard .stepper-compact-count { margin-left: auto; font-size: 11px; color: var(--ink-3); }
.import-wizard .stepper-compact-bar { display: flex; gap: 2px; height: 7px; background: var(--inset); }
.import-wizard .stepper-compact-seg { flex: 1; background: var(--inset); }
.import-wizard .stepper-compact-seg[data-on="true"] { background: var(--ink); }
@media (min-width:1024px) {
.import-wizard .stepper-compact { display: none; }
}
@media (max-width:1023.98px) {
.import-wizard .stepper { display: none; }
}
.import-wizard>.ui-state { border: 0; border-radius: 0; }
.import-wizard>.ui-state+.import-body { border-top: 1px solid var(--line); }
.import-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; padding: 18px; background: var(--surface); }
.import-lead { margin: 0; font-size: 14px; line-height: var(--lh-body); color: var(--ink-2); }
.import-note { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.import-body>.ui-success-note,
.import-body>.ui-confirm { margin: 0; }
.import-callout { padding: 12px 14px; background: var(--warn-tint); border-left: 4px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.import-callout>p { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink); }
.import-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 12px 18px; background: var(--surface); border-top: 2px solid var(--rule); }
.import-wizard .import-go { min-height: var(--tap-min); padding: var(--space-2) 18px; line-height: 1.4; white-space: normal; }
.import-foot>.import-go { margin-left: auto; }
@media (max-width:1023.98px) {
.import-foot { flex-direction: column; align-items: stretch; }
}
@media (max-width:1023.98px) {
.import-foot>.ui-btn { width: 100%; margin-left: 0; }
}

/* ── adminsettings ── */
.set-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.set-panel-note { margin: 0; padding: var(--space-3) 18px; background: var(--info-tint); border-bottom: 1px solid var(--line); font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.set-panel .set-group { margin: 0; padding: var(--space-3) 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.set-panel .set-group .ui-section-title { font-size: 10.5px; line-height: var(--lh-label); letter-spacing: .12em; text-transform: uppercase; font-weight: 700; color: var(--ink-3); }
.set-panel .set-row+.set-group { border-top: 1px solid var(--line); }
.set-row { display: grid; grid-template-columns: minmax(0, 1fr); align-items: center; column-gap: 14px; margin: 0; padding: 14px 18px; border-bottom: 1px solid var(--line); }
.set-row-text { min-width: 0; }
.set-row-title { display: block; margin: 0 0 2px; font-size: var(--text-body); font-weight: 600; color: var(--ink); }
.set-row-sub { display: block; margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }
.set-row-sub+.set-row-sub { margin-top: var(--space-1); }
.set-row-control { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-top: 7px; }
.set-row .ui-field { display: grid; grid-template-columns: minmax(0, 1fr); margin: 0; }
.set-row .ui-field-label { grid-row: 1; margin: 0 0 2px; font-size: var(--text-body); font-weight: 600; }
.set-row .ui-field-help { grid-row: 2; margin: 0; font-size: 12.5px; line-height: 1.5; }
.set-row .ui-field-control { grid-row: 3; margin-top: 7px; flex-wrap: wrap; }
.set-row .ui-field-control .ui-input { flex: 1 1 100%; }
.set-row .ui-field-error { grid-row: 4; }
.set-row-note { grid-column: 1 / -1; margin: 6px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.set-row .inline-notice { grid-column: 1 / -1; margin: var(--space-2) 0 0; padding: 10px 12px; background: var(--warn-tint); color: var(--ink); border: 0; border-left: 4px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: 12.5px; line-height: 1.5; }
.set-switch { position: relative; flex: none; display: inline-flex; align-items: center; justify-content: center; min-width: var(--tap-min); min-height: var(--tap-min); cursor: pointer; }
.set-switch-input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.set-switch-input:disabled { cursor: default; }
.set-switch-track { display: block; position: relative; width: 42px; height: 24px; background: var(--ink-3); border-radius: var(--r-pill); }
.set-switch-track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; background: var(--surface); border-radius: var(--r-pill); }
.set-switch-track,
.set-switch-track::after { transition: background-color var(--dur-2) var(--ease), transform var(--dur-2) var(--ease), opacity var(--dur-2) var(--ease); }
.set-switch-input:checked+.set-switch-track { background: var(--ok); }
.set-switch-input:checked+.set-switch-track::after { transform: translateX(18px); }
.set-switch-input:focus-visible+.set-switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.set-switch-input:disabled+.set-switch-track { opacity: .45; }
.set-panel .ui-list { border: 0; border-radius: 0; }
.set-panel .ui-list-hit { padding: 14px 18px; }
.set-panel .ui-list-title { margin-bottom: 2px; }
.set-panel .ui-list-sub { line-height: 1.5; color: var(--ink-3); }
.set-panel .ui-list-hit:focus-visible { outline-offset: -2px; }
@media (min-width:1024px) {
.set-row { grid-template-columns: minmax(0, 1fr) auto; }
}
@media (min-width:1024px) {
.set-row-control { grid-column: 2; grid-row: 1; margin-top: 0; justify-content: flex-end; }
}
@media (min-width:1024px) {
.set-row .ui-field { grid-column: 1 / -1; grid-template-columns: minmax(0, 1fr) auto; column-gap: 14px; align-items: center; }
}
@media (min-width:1024px) {
.set-row .ui-field-label { grid-column: 1; }
}
@media (min-width:1024px) {
.set-row .ui-field-help { grid-column: 1; }
}
@media (min-width:1024px) {
.set-row .ui-field-control { grid-column: 2; grid-row: 1 / span 2; margin-top: 0; flex-wrap: nowrap; }
}
@media (min-width:1024px) {
.set-row .ui-field-error { grid-column: 1 / -1; grid-row: 3; }
}
@media (min-width:1024px) {
.set-row .ui-field-control .ui-input { flex: none; width: 100px; text-align: right; }
}

/* ── branding ── */
.brand-notice { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0; padding: var(--space-2) var(--space-3); background: var(--danger-tint); border-left: 4px solid var(--danger); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--danger); }
.brand-notice[data-tone="warn"] { background: var(--warn-tint); border-left-color: var(--warn); color: var(--ink); }
.brand-notice>.brand-notice-glyph { flex: none; font-size: var(--text-body); color: var(--danger); }
.brand-notice[data-tone="warn"]>.brand-notice-glyph { color: var(--warn); }
.brand-notice-text { flex: 1; min-width: 0; font-weight: 600; }
.brand-notice>.brand-notice-action { flex: none; }
.brand-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.brand-rows>.brand-group { margin: 0; padding: var(--space-3) 18px; background: var(--inset); border-bottom: 1px solid var(--line); font-size: 10.5px; line-height: var(--lh-label); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }
.brand-rows>.brand-group:not(:first-child) { border-top: 1px solid var(--line); }
.brand-rows>.brand-row { margin: 0; padding: 14px 18px; border-bottom: 1px solid var(--line); }
.brand-rows>.brand-row:last-child { border-bottom: none; }
.brand-row>.brand-row-text { margin: 0 0 7px; }
.brand-row-text>.ui-field-label,
.brand-row-text>.brand-row-title { display: block; margin: 0 0 2px; font-size: var(--text-body); line-height: var(--lh-small); font-weight: 600; color: var(--ink); }
.brand-row-text>.ui-field-help,
.brand-row-text>.brand-row-sub { display: block; margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--ink-3); }
.brand-row>.ui-field-error,
.brand-row>.brand-warn { margin: 6px 0 0; }
.brand-row>.brand-row-control { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.brand-color-row .brand-color-swatch { flex: none; width: 44px; height: 44px; padding: 2px; border: 3px solid var(--ink); border-radius: var(--r-sm); background: var(--surface); cursor: pointer; }
.brand-color-swatch::-webkit-color-swatch-wrapper { padding: 0; }
.brand-color-swatch::-webkit-color-swatch { border: none; border-radius: var(--r-xs); }
.brand-color-swatch::-moz-color-swatch { border: none; border-radius: var(--r-xs); }
.brand-color-row .brand-color-swatch:disabled { cursor: default; border-color: var(--line); }
.brand-color-row .brand-color-hex { flex: 1; min-width: 0; }
.brand-row>.brand-warn { font-size: 12px; font-weight: 600; line-height: 1.5; color: var(--warn); }
.brand-thumb { width: 44px; height: 44px; flex: none; display: grid; place-items: center; overflow: hidden; border-radius: var(--r-sm); font-size: 19px; font-weight: 700; line-height: 1; }
.brand-thumb.is-mark { background: var(--preview-primary, var(--accent)); color: var(--preview-on-primary, var(--surface)); }
.brand-thumb.has-img { background: var(--surface); border: 1px solid var(--line); }
.brand-thumb>img { display: block; width: 100%; height: 100%; object-fit: contain; }
.brand-row-control>.brand-asset-empty { font-size: 12.5px; color: var(--ink-3); }
.brand-panel>.brand-sample { padding: var(--space-4) 18px; background: var(--inset); border-top: 2px solid var(--rule); }
.brand-panel>.brand-sample:focus-visible { outline-offset: -2px; }
.brand-sample>.brand-sample-label { margin: 0 0 10px; font-size: var(--text-label); line-height: var(--lh-label); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.brand-sample .brand-preview-paper { position: relative; overflow: hidden; padding: 14px var(--space-4); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); color: var(--ink); }
.brand-sample .brand-preview-watermark { position: absolute; inset: 0; background-repeat: no-repeat; background-position: center; background-size: 65% auto; opacity: .07; pointer-events: none; }
.brand-preview-paper .doc-head { position: relative; display: flex; align-items: center; gap: var(--space-3); padding-bottom: 0; border-bottom: 0; }
.brand-preview-paper .doc-logo { width: 38px; height: 38px; flex: none; object-fit: contain; border-radius: var(--r-sm); }
.brand-preview-paper .doc-ident { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.brand-preview-paper .doc-org { margin: 0; font-size: var(--text-body); line-height: 1.4; font-weight: 700; color: var(--ink); }
.brand-preview-paper .doc-addr,
.brand-preview-paper .doc-contact { margin: 0; font-size: 11.5px; line-height: 1.5; color: var(--ink-3); }
.brand-preview-paper .brand-preview-sig { position: relative; margin-top: var(--space-3); text-align: right; }
.brand-preview-sig>img { max-height: 34px; max-width: 130px; object-fit: contain; }
.brand-preview-sig>.brand-preview-signame { display: inline-block; min-width: 110px; padding-top: 3px; border-top: 1px solid var(--ink-2); font-size: 11.5px; color: var(--ink-3); }
@media (min-width:1024px) {
.brand-rows>.brand-row { display: flex; flex-wrap: wrap; align-items: center; column-gap: 14px; }
}
@media (min-width:1024px) {
.brand-row>.brand-row-text { flex: 1; min-width: 0; margin: 0; }
}
@media (min-width:1024px) {
.brand-row>.ui-field-control { flex: none; width: 240px; }
}
@media (min-width:1024px) {
.brand-row>.brand-row-control { flex: none; justify-content: flex-end; }
}
@media (min-width:1024px) {
.brand-row>.ui-field-error,
.brand-row>.brand-warn { flex-basis: 100%; }
}

/* ── structure-forms ── */
.card-form.structure-form { margin: 0 0 var(--space-4); max-width: 460px; }
.structure-form .field { gap: 6px; font-size: var(--text-small); font-weight: 600; color: var(--ink); }
.structure-form .field-input::placeholder { color: var(--ink-3); opacity: 1; }
.structure-form .field-input:focus { box-shadow: none; }
.structure-form .field-input.n { font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.structure-form .structure-select { position: relative; display: block; }
.structure-form .structure-select>.field-input { -webkit-appearance: none; appearance: none; padding-right: calc(var(--space-3) + var(--space-6)); }
.structure-form .structure-select>.field-input:focus { padding-right: calc(var(--space-3) + var(--space-6) - 1px); }
.structure-form .structure-select-glyph { position: absolute; top: 50%; right: var(--space-3); transform: translateY(-50%); display: flex; width: 1em; height: 1em; font-size: var(--text-body); color: var(--ink-3); pointer-events: none; }
.structure-form .structure-select-glyph svg { width: 100%; height: 100%; }
.structure-form .structure-form-check { display: flex; align-items: center; gap: var(--space-2); min-height: var(--tap-min); font-size: var(--text-body); line-height: var(--lh-small); color: var(--ink); cursor: pointer; }
.structure-form .structure-form-check>input[type="checkbox"] { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--ink); cursor: pointer; }
.structure-form .structure-form-note { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.structure-form .structure-form-error { margin: 0; padding: 10px var(--space-3); background: var(--danger-tint); border-left: 4px solid var(--danger); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
.structure-form>.ui-state { padding: 0; }
.structure-rename>.ui-field { margin-bottom: 0; }
.structure-rename>.ui-field-error { margin-top: 0; }

/* ── staffattendance ── */
.staff-att-date-text { display: inline-block; font-size: var(--text-small); line-height: calc(var(--text-h1) * var(--lh-h1)); color: var(--ink-3); white-space: nowrap; }
.staff-att-date .ui-input { max-width: 240px; }
.ui-state-error+.staff-att-date { margin-top: var(--space-4); }
.staff-att-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.staff-att-band { padding: 14px 18px; border-bottom: 1px solid var(--line); }
@media (max-width:1023.98px) {
.staff-att-band { padding: var(--space-3); }
}
.staff-att-band .ui-stat[data-tone="info"] .ui-stat-value { color: var(--info); }
.staff-att-panel>.ui-data { border: 0; border-radius: 0; }
.staff-att-table .ui-table [data-col="status"] { text-align: right; }
.staff-att-mark { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.staff-att-mark .ui-field { flex: 1 1 10rem; min-width: 0; margin-bottom: 0; }
.staff-att-seg { display: inline-flex; flex: none; border: 1px solid var(--ink); border-radius: var(--r-sm); overflow: hidden; background: var(--surface); }
.staff-att-choice { min-height: var(--tap-min); padding: 0 18px; font-family: var(--font-bn); font-size: 14px; font-weight: 600; line-height: var(--lh-small); color: var(--ink); background: transparent; border: 0; border-radius: 0; text-align: left; white-space: nowrap; cursor: pointer; }
.staff-att-choice+.staff-att-choice { border-left: 1px solid var(--ink); }
.staff-att-choice:hover:not(:disabled):not([aria-pressed="true"]) { background: var(--inset); }
.staff-att-choice:active:not(:disabled):not([aria-pressed="true"]) { background: var(--neutral-300); }
.staff-att-choice[aria-pressed="true"] { background: var(--ink); color: var(--surface); }
.staff-att-choice:disabled { opacity: .45; cursor: default; }
.staff-att-choice:focus-visible { outline-offset: -4px; }
.staff-att-table .ui-list-hit { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--space-3); row-gap: 0; }
.staff-att-table .ui-list-main { display: contents; }
.staff-att-table .ui-list-title { grid-column: 1; grid-row: 1; }
.staff-att-table .ui-list-sub { grid-column: 1; grid-row: 2; }
.staff-att-table .ui-list-status { grid-column: 2; grid-row: 1 / span 2; }
.staff-att-table .ui-list-meta { grid-column: 1 / -1; grid-row: 3; margin-top: var(--space-2); }
.staff-att-table .ui-list .staff-att-seg { flex: 1 1 100%; }
.staff-att-table .ui-list .staff-att-choice { flex: 1 1 0; min-width: 0; padding: 0 var(--space-2); }

/* ── generation ── */
.gen-result .gen-stats { padding: var(--space-4) 18px; border-bottom: 1px solid var(--line); }
.gen-result .gen-block { padding: 18px; }
.gen-result .gen-block+.gen-block { border-top: 1px solid var(--line); }
.gen-result .gen-head { margin: 0 0 var(--space-3); font-size: var(--text-label); line-height: var(--lh-label); letter-spacing: .12em; color: var(--ink-3); }
.gen-result .gen-shortage { padding: var(--space-3) 14px; background: var(--warn-tint); border-left: 4px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.gen-result .gen-shortage-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-1); }
.gen-result .gen-shortage-list li { font-size: 13.5px; line-height: 1.55; color: var(--ink); }
.gen-result .gen-trades { list-style: none; margin: 0; padding: 0; display: block; }
.gen-result .gen-trades li { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); padding: 10px 0; border-bottom: 1px solid var(--line); font-size: 13.5px; line-height: 1.5; }
.gen-result .gen-trades li:last-child { border-bottom: none; }
.gen-result .gen-trades .gen-trade-what { flex: 1 1 16rem; min-width: 0; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.gen-result .gen-trades .gen-trade-why { flex: 1 1 16rem; min-width: 0; font-size: var(--text-small); color: var(--danger); }
.gen-result .gen-unchecked-list .gen-trade-why { color: var(--ink-2); }
.gen-result .gen-unchecked { background: transparent; }
.gen-result .gen-more { margin-top: var(--space-2); }
.gen-result .gen-none { margin: 0; font-size: 13.5px; color: var(--ink-2); }
.gen-result .gen-explain { margin-top: var(--space-3); padding: 11px 13px; background: var(--info-tint); border-left: 4px solid var(--info); border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.gen-result .gen-explain-head { margin: 0 0 var(--space-1); font-size: 12.5px; font-weight: 700; color: var(--ink-2); }
.gen-result .gen-explain-line { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink); }
.gen-result .gen-explain-line+.gen-explain-line { margin-top: var(--space-1); }
.gen-result .gen-foot { padding: var(--space-3) 18px; border-top: 2px solid var(--rule); }
.gen-result .gen-foot>.btn-primary { margin-left: auto; }
@media (max-width:1023.98px) {
.gen-result .gen-foot>.ui-btn { flex: 1 1 100%; }
}

/* ── subjectchoice ── */
@media (min-width:1024px) {
.choice-body { max-width: 720px; }
}
.choice-callout { margin: 0 0 var(--space-4); padding: var(--space-3) 14px; background: var(--warn-tint); border-left: 4px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--text-small); line-height: 1.55; color: var(--ink); }
.choice-callout[data-tone="danger"] { background: var(--danger-tint); border-left-color: var(--danger); }
.choice-section { margin: 0 0 18px; }
.choice-label { margin: 0 0 var(--space-2); font-size: var(--text-small); line-height: var(--lh-small); font-weight: 700; letter-spacing: 0; color: var(--ink); }
.choice-panel { display: flex; align-items: center; min-height: 48px; margin: 0; padding: 0 14px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); font-size: var(--text-body); line-height: var(--lh-body); color: var(--ink); }
.choice-panel-text { flex: 1; min-width: 0; }
.choice-panel.choice-group-value { font-weight: 600; }
.choice-panel.choice-derived { padding: var(--space-3) 14px; line-height: 1.7; }
.choice-panel.choice-derived-empty { color: var(--ink-3); }
.choice-hint { margin: 6px 0 0; font-size: 12px; line-height: 1.5; color: var(--ink-3); }
.choice-options { display: block; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.choice-option { display: flex; align-items: center; gap: 11px; width: 100%; min-height: 48px; margin: 0; padding: 0 14px; background: var(--surface); color: var(--ink); border: 0; border-bottom: 1px solid var(--line); border-radius: 0; font-family: var(--font-bn); font-size: var(--text-body); font-weight: 400; line-height: var(--lh-body); text-align: left; cursor: pointer; }
.choice-option:last-child { border-bottom: 0; }
.choice-option[data-chosen="true"] { background: var(--accent-tint); color: var(--ink); border-color: var(--line); font-weight: 600; }
.choice-option:hover:not(:disabled):not([data-chosen="true"]) { background: var(--neutral-100); }
.choice-option:active:not(:disabled) { background-color: var(--neutral-100); }
.choice-option:disabled { opacity: .45; cursor: default; }
.choice-option:focus-visible { outline-offset: -2px; }
.choice-mark { flex: none; width: 18px; height: 18px; border: 2px solid var(--ink-3); border-radius: 0; background: transparent; }
.choice-option[data-chosen="true"] .choice-mark { border-color: var(--accent-ink); background: var(--accent-ink); }
.choice-option-text { flex: 1; min-width: 0; }
.choice-religion .ui-field { margin-bottom: 0; }
.choice-footer { display: flex; flex-direction: column; gap: var(--space-2); padding: 10px 14px; background: var(--surface); border-top: 2px solid var(--rule); }
@media (max-width:1023.98px) {
.choice-footer { position: sticky; bottom: calc(58px + env(safe-area-inset-bottom, 0px)); z-index: 5; margin: 0 -20px; padding: 10px 20px; }
}
.choice-note { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.choice-callout.choice-warning { margin: 0; }
.choice-confirm-row { display: flex; gap: var(--space-2); align-items: stretch; }
.choice-confirm-row .btn-primary { flex: 1; min-width: 0; }
.choice-confirm-row .btn-secondary { flex: none; }

/* ── lead: routinegenerate's running sweep. A keyframes block cannot ride the
   merge script's selector/declarations shape, so it is added here. The sweep
   is decoration on a live region that already says "তৈরি হচ্ছে" in words;
   with reduced motion the bar simply sits still. ── */
@keyframes rgen-sweep { from { transform: translateX(-100%); } to { transform: translateX(320%); } }
@media (prefers-reduced-motion: reduce) { .rgen-run-fill { animation: none; } }

/* ═══ [4] Ata Ekta — attendance path খ ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── attendance ── */
@media (max-width:1023px) {
.att-page-header { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
}
@media (max-width:1023px) {
.att-register { margin-inline: -20px; margin-top: calc(-1 * var(--space-6)); }
}
@media (max-width:1023px) {
:root:has(.att-register) { scroll-padding-top: 58px; scroll-padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 80px); }
}
@media (max-width:1023px) {
:root:has(.att-footer[data-state="blocked"]) { scroll-padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 150px); }
}
@media (max-width:1023px) {
:root:has(.att-register .att-undo:not([hidden])) { scroll-padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 80px + 84px); }
}
@media (max-width:1023px) {
:root:has(.att-footer[data-state="blocked"] .att-undo:not([hidden])) { scroll-padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 150px + 84px); }
}
@media (min-width:1024px) {
.att-register { max-width: 720px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: clip; }
}
.att-register .att-status:empty { display: none; }
.att-register .att-offline-note { display: flex; align-items: flex-start; gap: var(--space-2); padding: var(--space-2) var(--space-3); background: var(--warn-tint); border-radius: var(--r-sm); }
.att-pickers { display: flex; gap: var(--space-2); padding: 10px 14px; background: var(--surface); border-bottom: 1px solid var(--line); }
.att-pickers .ui-field { flex: 1; min-width: 0; margin-bottom: 0; }
.att-pickers .ui-field-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.att-bulk { padding: 12px 14px; background: var(--ok-tint); border-bottom: 1px solid var(--line); }
.att-bulk-note { margin: 0 0 9px; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.att-bulk .btn-success { min-height: 46px; font-weight: 700; }
.att-bulk .btn-success[aria-disabled="true"] { opacity: .45; cursor: default; }
.att-progress { padding: 10px 14px; background: var(--surface); border-bottom: 1px solid var(--line); }
.att-progress .ui-progress-label { font-size: var(--text-small); font-weight: 600; color: var(--ink-2); }
.att-progress .ui-progress-track { height: 6px; }
.att-progress .ui-progress-fill { background: var(--ink-3); }
.att-progress[data-tone="ok"] .ui-progress-label,
.att-progress[data-tone="ok"] .ui-progress-pct { color: var(--ok); }
.att-progress[data-tone="ok"] .ui-progress-fill { background: var(--ok); }
.att-progress[data-tone="warn"] .ui-progress-label,
.att-progress[data-tone="warn"] .ui-progress-pct { color: var(--warn); }
.att-progress[data-tone="warn"] .ui-progress-fill { background: var(--warn); }
.att-list { list-style: none; margin: 0; padding: 0; background: var(--surface); }
.att-row { border-bottom: 1px solid var(--line); border-left: 4px solid var(--ok); background: var(--surface); }
.att-row-hit { display: flex; align-items: center; gap: 11px; width: 100%; min-height: 54px; padding: 0 14px; background: transparent; border: none; font-family: var(--font-bn); color: var(--ink); text-align: left; cursor: pointer; transition: background-color var(--dur-2) var(--ease); }
.att-row-hit:active { background-color: var(--neutral-100); }
.att-row-hit:focus-visible { outline-offset: -2px; }
.att-row .att-roll { width: 26px; flex: none; font-size: 14px; font-weight: 600; color: var(--ink-2); }
.att-row .att-name { flex: 1; min-width: 0; font-size: var(--text-body); color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-row .att-state { flex: none; display: inline-flex; }
.att-row .att-unset { font-size: 12.5px; font-style: italic; color: var(--ink-3); }
.att-row[data-status="absent"] { border-left-color: var(--danger); background: color-mix(in srgb, var(--danger-tint) 18%, var(--surface)); }
.att-row[data-status="late"] { border-left-color: var(--warn); background: color-mix(in srgb, var(--warn-tint) 20%, var(--surface)); }
.att-row[data-status="excused"] { border-left-color: var(--info); }
.att-row[data-status="absent"] .att-name,
.att-row[data-status="late"] .att-name,
.att-row[data-status="excused"] .att-name { font-weight: 600; color: var(--ink); }
.att-row[data-status="unset"] { border-left: 4px dashed var(--ink-3); background: color-mix(in srgb, var(--inset) 20%, var(--surface)); }
.att-row[data-status="unset"] .att-roll,
.att-row[data-status="unset"] .att-name { color: var(--ink-3); }
.att-switch { display: flex; gap: 6px; padding: 0 14px 12px; }
.att-switch[hidden] { display: none; }
.att-switch .att-opt.btn-secondary { flex: 1; min-width: 0; min-height: var(--tap-min); padding: 0 6px; font-size: 13.5px; font-weight: 500; color: var(--ink-2); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-sm); transition: background-color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease), color var(--dur-2) var(--ease); }
.att-switch .att-opt[aria-pressed="true"] { font-weight: 700; color: var(--surface); }
.att-switch .att-opt[aria-pressed="true"][data-status="present"] { background: var(--ok); border-color: var(--ok); }
.att-switch .att-opt[aria-pressed="true"][data-status="absent"] { background: var(--danger); border-color: var(--danger); }
.att-switch .att-opt[aria-pressed="true"][data-status="late"] { background: var(--warn); border-color: var(--warn); }
.att-footer[data-state] { position: sticky; bottom: calc(60px + env(safe-area-inset-bottom, 0px)); z-index: 10; padding: 10px 14px; background: var(--surface); border-top: 2px solid var(--rule); }
.att-footer[data-state] .btn-primary { min-height: 46px; font-weight: 700; }
.att-footer[data-state="blocked"] { padding: 12px 14px; background: var(--warn-tint); border-top-color: var(--warn); }
.att-guard-text { margin: 0 0 10px; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
.att-guard-actions { display: flex; gap: 9px; }
.att-guard-actions .att-guard-go.btn-secondary { flex: 1; font-weight: 700; color: var(--surface); background: var(--ink); border-color: var(--ink); }
.att-guard-actions .att-guard-go.btn-secondary:hover:not(:disabled) { background: var(--neutral-800); }
.att-guard-actions .att-guard-anyway.btn-secondary { flex: none; padding: 0 13px; font-size: var(--text-small); color: var(--ink-2); border-color: var(--ink-3); }
.att-footer .att-undo { position: absolute; left: var(--space-3); right: var(--space-3); bottom: calc(100% + var(--space-3)); z-index: 30; }
.att-footer .att-undo[hidden] { display: none; }
.att-undo .att-undo-name { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-undo .att-undo-detail { display: block; white-space: normal; overflow-wrap: anywhere; font-weight: 600; }
.att-undo .att-undo-time { display: block; font-size: 11.5px; font-weight: 400; opacity: .7; }
.att-undo .att-undo-btn { min-height: var(--tap-min); font-size: 13.5px; padding: 0 13px; }
@media (min-width:1024px) {
.att-footer[data-state] { position: relative; bottom: auto; }
}
@media (min-width:1024px) {
.att-footer .att-undo { position: fixed; left: auto; right: var(--space-6); bottom: var(--space-6); max-width: 380px; }
}
.att-confirm .ui-dialog-body { padding: 0; }
.att-confirm .att-confirm-sub { margin: 0; padding: var(--space-3) 18px; font-size: 12.5px; color: var(--ink-3); border-bottom: 2px solid var(--rule); }
.att-confirm .att-confirm-ok { display: flex; align-items: center; gap: 11px; padding: 14px 18px; background: var(--ok-tint); border-bottom: 1px solid var(--line); font-size: var(--text-body); font-weight: 600; }
.att-confirm .att-confirm-ok .ui-icon { flex: none; display: grid; font-size: 20px; color: var(--ok); }
.att-confirm .att-confirm-group { padding: 14px 18px; border-bottom: 1px solid var(--line); }
.att-confirm .att-confirm-heading { margin: 0 0 10px; font-size: var(--text-small); font-weight: 700; color: var(--ink-2); }
.att-confirm .att-confirm-heading[data-tone="danger"] { color: var(--danger); }
.att-confirm .att-confirm-heading[data-tone="warn"] { color: var(--warn); }
.att-confirm .att-confirm-heading[data-tone="info"] { color: var(--info); }
.att-confirm .att-confirm-list { list-style: none; margin: 0; padding: 0; }
.att-confirm .att-confirm-row { display: flex; align-items: center; gap: 10px; padding: 2px 0; }
.att-confirm .att-confirm-roll { width: 26px; flex: none; font-size: var(--text-small); color: var(--ink-3); }
.att-confirm .att-confirm-name { flex: 1; min-width: 0; font-size: 14.5px; font-weight: 600; overflow-wrap: anywhere; }
.att-confirm .att-confirm-change.btn-ghost { flex: none; padding: 0 var(--space-2); font-size: 12.5px; }
.att-confirm .att-confirm-sms { display: flex; align-items: flex-start; gap: 9px; padding: 12px 18px; background: var(--info-tint); border-bottom: 1px solid var(--line); font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.att-confirm .att-confirm-sms .ui-icon { flex: none; display: grid; margin-top: 2px; font-size: 15px; color: var(--info); }
.att-confirm .att-confirm-error { margin: 0; padding: 12px 18px; background: var(--danger-tint); color: var(--danger); font-size: var(--text-small); line-height: var(--lh-small); font-weight: 600; border-bottom: 1px solid var(--line); }
.att-confirm .att-confirm-error:empty { display: none; }
.att-confirm .ui-dialog-foot .ui-button-row { flex-wrap: nowrap; gap: 10px; width: 100%; }
.att-confirm .ui-dialog-foot .btn-primary { flex: 1; min-height: 46px; font-weight: 700; }
.att-confirm .ui-dialog-foot .btn-secondary { flex: none; min-height: 46px; }

/* ── lead: the focus ring on checkboxes and radios ──
   The carried `input:focus { outline: none }` rule (same specificity as the
   sheet's `input:focus-visible` ring, and later in source) draws text-field
   focus on the border instead — which a checkbox or radio does not have. So
   every checkbox lost its keyboard focus ring, including "আমি বুঝেছি এটি
   ফেরানো যাবে না" on all four irreversible screens. Restored with the sheet's
   own ring, for keyboard focus only. */
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ═══ [4] Ata Ekta — wave 2D: finance, student, guardian, AI helpers, platform console ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── fees ── */
.fees-offline { margin: 0 0 var(--space-4); border: 1px solid var(--warn); border-radius: var(--r-md); }
.fees-sheet { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.fees-sheet>.ui-data { border: 0; border-radius: 0; }
.fees-sheet .ui-table { min-width: 540px; }
.fees-due { padding: var(--space-4) 14px; background: var(--danger-tint); border-bottom: 1px solid var(--line); }
.fees-due.is-multi { padding: 18px var(--space-4); }
.fees-due-label { margin: 0 0 3px; font-size: 12px; line-height: var(--lh-small); font-weight: 600; color: var(--danger); }
.fees-due.is-multi .fees-due-label { font-size: 12.5px; }
.fees-due-amount { display: block; margin: 0 0 var(--space-1); font-size: 30px; font-weight: 700; line-height: 1.2; color: var(--danger); }
.fees-due.is-multi .fees-due-amount { font-size: 34px; }
.fees-due-note { margin: 0; font-size: 12.5px; line-height: var(--lh-small); color: var(--ink-2); }
.label.fees-list-head { margin: 0; padding: 10px 14px; background: var(--inset); border-bottom: 1px solid var(--line); letter-spacing: .1em; }
.fees-sheet.is-family .ui-list-hit { min-height: 50px; }
.fees-sheet.is-family .ui-list-title { font-size: 14.5px; font-weight: 400; }
.fees-sheet>.ui-data[data-shape="table-list"]>.ui-list .ui-list-title { white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }
.fees-sheet.is-family .ui-list .fees-amount { font-size: 14px; font-weight: 600; }
.fees-sheet.is-family .ui-list-chevron { display: none; }
.fees-paid-mark { display: none; }
.fees-sheet.is-family .ui-list .fees-paid-mark { display: inline-flex; font-size: 16px; color: var(--ok); }
.fees-sheet.is-family .ui-list .fees-paid-word { display: none; }
.fees-sheet .ui-table .fees-list-only { display: none; }
.fees-sheet .ui-list .fees-table-only { display: none; }
.fees-sheet .ui-table .fees-balance { font-weight: 700; }
.fees-sheet .fees-balance[data-owed="true"] { color: var(--danger); }
.fees-filter { display: flex; flex-wrap: wrap; gap: 10px 9px; padding: 11px 14px; background: var(--inset); border-bottom: 1px solid var(--line); }
@media (min-width:1024px) {
.fees-filter { padding: 11px 18px; }
}
.fees-filter-opt { position: relative; display: inline-flex; align-items: center; min-height: 34px; padding: 0 13px; font-family: var(--font-bn); font-size: var(--text-small); font-weight: 600; line-height: var(--lh-small); color: var(--ink); background: transparent; border: 1px solid var(--line); border-radius: var(--r-sm); cursor: pointer; }
.fees-filter-opt::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: var(--tap-min); transform: translateY(-50%); }
.fees-filter-opt:hover:not([aria-pressed="true"]) { background: var(--surface); }
.fees-filter-opt[aria-pressed="true"] { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.fees-filter-opt:active { transform: scale(.97); }
@media (prefers-reduced-motion:reduce) {
.fees-filter-opt:active { transform: none; }
}

/* ── feestructures ── */
.page-header-actions>.fs-search,
.page-header-actions>.fs-year { margin: 0; min-width: 0; }
.page-header-actions>.fs-search { flex: 1 1 100%; }
@media (min-width:1024px) {
.page-header-actions>.fs-search { flex: none; width: 13rem; }
}
.fs-error { margin-bottom: var(--space-4); }
.fs-frame { overflow: hidden; }
.fs-frame>.ui-data { border: 0; border-radius: 0; }
.fs-table .ui-table { min-width: 500px; }
.fs-table .fs-amount { font-weight: 700; }
.fs-table .fs-amount,
.fs-table .fs-money { white-space: nowrap; }
.fs-table .ui-table [data-col="status"],
.fs-table .ui-table [data-col="actions"] { text-align: right; white-space: nowrap; }
.fs-table .ui-table .fs-actions { justify-content: flex-end; flex-wrap: nowrap; }
.fs-table .fs-terms { display: block; margin-top: 2px; line-height: 1.45; color: var(--ink-3); }
.fs-table .ui-table .fs-terms { font-size: 12.5px; }
.fs-table .ui-table .fs-scope-word { display: none; }
.fs-table .ui-list .fs-actions { margin-top: var(--space-2); }
.fs-table .ui-list-dot:has(+.ui-list-cell>.fs-actions) { display: none; }
.fs-note { padding: var(--space-3) 18px; background: var(--surface); border-top: 2px solid var(--rule); font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.fs-note>p+p { margin-top: var(--space-1); }
@media (max-width:1023.98px) {
.fs-note { padding: var(--space-3) 14px; }
}

/* ── invoices ── */
.inv-alert { margin-bottom: var(--space-4); }
.inv-note { display: flex; align-items: flex-start; gap: var(--space-2); padding: var(--space-3) var(--space-4); background: var(--info-tint); border-bottom: 1px solid var(--line); }
.inv-note-glyph { flex: none; margin-top: calc(var(--space-1) / 2); font-size: var(--text-body); color: var(--info); }
.inv-note-text { flex: 1; min-width: 0; margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.inv-period { padding: var(--space-4); border-bottom: 1px solid var(--line); }
.inv-period>.ui-field { max-width: 280px; margin-bottom: 0; }
.inv-gate .irrev-ack-box:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.inv-gate .irrev-foot>.ui-button-row { margin-left: auto; }
@media (max-width:1023.98px) {
.inv-gate .irrev-ack { flex-basis: 100%; }
}
@media (max-width:1023.98px) {
.inv-gate .irrev-foot>.ui-button-row { flex: 1 1 100%; }
}
@media (max-width:1023.98px) {
.inv-gate .irrev-foot .ui-btn { flex: 1 1 auto; }
}
.inv-recent { margin-top: var(--space-8); }
.inv-table [data-col="collect"] { text-align: right; }
.inv-settled { color: var(--ink-3); }
.inv-table .ui-list-hit { flex-wrap: wrap; row-gap: var(--space-2); }
.inv-table .ui-list-main { flex-basis: 100%; }
.inv-table .ui-list-status:last-child { margin-left: auto; }
.inv-pay>.ui-field-error { margin: 0 0 var(--space-3); }
.inv-pay-who { margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4); background: var(--inset); border-radius: var(--r-sm); }
.inv-pay-name { margin: 0 0 calc(var(--space-1) / 2); font-size: var(--text-body); line-height: var(--lh-small); font-weight: 600; color: var(--ink); }
.inv-pay-meta { margin: 0; font-size: 12px; line-height: var(--lh-small); color: var(--ink-3); }
.inv-pay-due { margin: 0 0 var(--space-4); font-size: 26px; line-height: 1.1; font-weight: 700; color: var(--danger); }
.inv-pay-methods { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); margin: 0 0 var(--space-4); }
.inv-pay-methods>.ui-btn:last-child:nth-child(odd) { grid-column: 1 / -1; }
.inv-pay-methods>.btn-secondary[aria-pressed="true"] { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.inv-pay-methods>.btn-secondary[aria-pressed="true"]:hover:not(:disabled) { background: var(--neutral-800); border-color: var(--neutral-800); }
.inv-pay-receipts { list-style: none; margin: 0; padding: 0; }
.inv-pay-receipt { font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.inv-pay-receipt+.inv-pay-receipt { margin-top: var(--space-1); }
.inv-pay-sheet>.ui-dialog-foot>.ui-button-row { flex: 1 1 auto; }
.inv-pay-sheet>.ui-dialog-foot>.ui-button-row>:last-child { flex: 1 1 auto; }

/* ── ledger ── */
.ledger-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; margin-bottom: var(--space-6); }
.ledger-stats { padding: 14px 18px; background: var(--surface); border-bottom: 1px solid var(--line); }
@media (max-width:1023.98px) {
.ledger-stats { padding: 0; }
}
@media (max-width:1023.98px) {
.ledger-stats>.ui-stat-row { border: 0; border-radius: 0; }
}
.ledger-panel>.ui-data { border: 0; border-radius: 0; }
.ledger-panel .ui-table { min-width: 560px; }
.ledger-panel .ui-table .ledger-dir,
.ledger-recon .ui-table .ledger-dir { display: none; }
.ledger-panel .ui-list-cell:has(>.ledger-amt.is-none),
.ledger-panel .ui-list-dot:has(+.ui-list-cell>.ledger-amt.is-none) { display: none; }
.ledger-mismatch { padding: var(--space-3) 18px; background: var(--danger-tint); border-top: 2px solid var(--danger); }
@media (max-width:1023.98px) {
.ledger-mismatch { padding: var(--space-3) 14px; }
}
.ledger-mismatch-text { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink); }
@media (max-width:1023.98px) {
.ledger-mismatch-text { font-size: var(--text-body); }
}
.ledger-mismatch-text+.ledger-mismatch-text { margin-top: var(--space-1); }
.ledger-recon { margin-bottom: var(--space-6); }
.ledger-recon .ledger-fig { white-space: nowrap; }

/* ── student-home ── */
.sh-now { padding: 15px; margin-bottom: var(--space-3); }
.sh-now-when { margin: 0 0 3px; font-size: 11.5px; line-height: var(--lh-small); color: var(--ink-2); }
.sh-now-subject { margin: 0 0 4px; font-size: 18px; font-weight: 700; line-height: var(--lh-h2); letter-spacing: normal; overflow-wrap: anywhere; }
.sh-now-subject:last-child { margin-bottom: 0; }
.sh-now-where { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); overflow-wrap: anywhere; }
.sh-now-empty { margin-bottom: var(--space-3); }
.sh-stats .ui-stat-text { display: flex; flex-direction: column; }
.sh-stats .ui-stat-value { margin-top: auto; }
.sh-due { margin-top: var(--space-3); overflow: hidden; }
.sh-due-head { padding: 10px 14px; background: var(--inset); border-bottom: 1px solid var(--line); }
.sh-due>.ui-list { border: none; border-radius: 0; }
.sh-due .ui-list-status { flex: 0 1 auto; max-width: 50%; text-align: right; }
.sh-due .ui-list-status[data-tone] { font-size: 12px; line-height: var(--lh-small); font-weight: 600; }
.sh-due .ui-list-chevron { display: none; }
.sh-due .ui-list-hit:focus-visible { outline-offset: -2px; }
.sh-due>.ui-list-skeleton { padding: 12px 14px; }
.sh-day,
.sh-study { margin-top: var(--space-6); }

/* ── guardian-home ── */
.hv-home { display: flex; flex-direction: column; gap: var(--space-3); }
.hv-primary { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
.hv-group { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ui-section-head.hv-group-head { margin: 0; padding: 10px 14px; background: var(--inset); border-bottom: 1px solid var(--line); }
.hv-group-head .ui-section-title { font-size: var(--text-label); line-height: var(--lh-label); font-weight: var(--w-label); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-2); }
.hv-group>.ui-list { border: none; border-radius: 0; }
.hv-group>.ui-list-skeleton { padding: var(--space-3) 14px; }
.hv-group>.ui-state { border: none; border-radius: 0; }
.hv-group .ui-list-hit:focus-visible { outline-offset: -2px; }
.hv-home .ui-list-glyph { font-size: 20px; }
.hv-note { margin: 0; padding: var(--space-3) 14px; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
@media (min-width:1024px) {
.hv-home { max-width: 720px; }
}
@media (min-width:1024px) {
.hv-primary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── guardian ── */
.ward-switch { margin-bottom: var(--space-3); }
.ward-offline { margin: 0 0 var(--space-3); border: 1px solid var(--warn); border-radius: var(--r-md); }
.ward-panel { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.ward-panel>.ward-id { padding: var(--space-4) 14px; }
.ward-panel>.ui-stat-row.ward-stats { border: 0; border-top: 1px solid var(--line); border-radius: 0; }
.ward-panel>.ward-cta { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; padding: 14px; border-top: 1px solid var(--line); }
.ward-panel>.ward-cta>.btn-secondary { flex: 1 1 0; min-width: max-content; }
@media (min-width:1024px) {
.ward-panel>.ward-cta>.btn-secondary { flex: none; min-width: 0; }
}
.gp-card { padding: var(--space-4); margin: 0 0 var(--space-3); }
.gp-name { margin: 0; font-size: var(--text-body); line-height: var(--lh-h3); font-weight: 700; color: var(--ink); }
.gp-meta { margin: var(--space-1) 0 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.gp-toggle { margin: var(--space-3) 0 0; }
.gp-toggle>.sms-toggle { margin-top: 0; color: var(--ink); }
.gp-toggle>.gp-meta { margin-top: 0; }
.gp-card .sms-toggle>input[type="checkbox"],
.gp-form .sms-toggle>input[type="checkbox"] { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--ink); cursor: pointer; }
.gp-actions { margin-top: var(--space-2); }
.gp-actions>.btn-ghost:first-child,
.gp-cancel { margin-left: -13px; }
.gp-end .ui-dialog-body { display: flex; flex-direction: column; gap: var(--space-2); }
.card-form.gp-form { margin: 0 0 var(--space-3); }
.gp-form .field { gap: 6px; font-size: var(--text-small); font-weight: 600; color: var(--ink); }
.gp-form .field-input.n { font-family: var(--font-num); font-variant-numeric: tabular-nums; }
.gp-form .sms-toggle { margin-top: 0; font-size: var(--text-body); color: var(--ink); }
.system-list.gp-candidates { margin: 0 0 var(--space-3); padding: 0; gap: 0; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.gp-candidates>.system-row { min-height: var(--tap-min); align-items: center; cursor: pointer; }
.gp-candidates>.system-row+.system-row { border-top: 1px solid var(--line); }
.gp-candidates>.system-row:hover { background: var(--neutral-100); }

/* ── shikho ── */

.page-header-actions>.chat-class-field { display: flex; align-items: center; gap: var(--space-2); margin-bottom: 0; }
.chat-class-field .ui-field-label { margin-bottom: 0; }
.chat-log { flex: 1 0 auto; display: flex; flex-direction: column; gap: var(--space-3); }
.chat-bubble { margin: 0; max-width: 85%; padding: var(--space-3) 14px; border-radius: var(--r-md); font-size: var(--text-body); line-height: var(--lh-body); color: var(--ink); white-space: pre-wrap; overflow-wrap: anywhere; }
.chat-user { align-self: flex-start; background: var(--inset); }
.chat-ai { background: var(--surface); border: 1px solid var(--line); line-height: 1.65; }
.chat-answer { align-self: flex-end; max-width: 92%; display: flex; flex-direction: column; gap: var(--space-1); }
.chat-answer>.chat-bubble { max-width: none; }
.chat-source { margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-3); }
.chat-answer[data-kind="grounded"] .chat-source { color: var(--ok); font-weight: 600; }
.chat-answer[data-kind="ungrounded"] .chat-source { color: var(--warn); }
.chat-answer[data-kind="refused"] .chat-ai,
.chat-answer[data-kind="unavailable"] .chat-ai { color: var(--ink-2); }
.chat-offline-cta { align-self: flex-start; margin-top: var(--space-1); }
.chat-log>.chat-typing { align-self: flex-end; display: flex; flex-direction: column; gap: var(--space-2); width: 60%; max-width: 92%; }
.chat-log~.ui-state { margin-top: var(--space-3); }
.chat-form { position: sticky; bottom: calc(58px + env(safe-area-inset-bottom, 0px)); z-index: 5; display: flex; align-items: center; gap: var(--space-2); margin: var(--space-3) -20px calc(env(safe-area-inset-bottom, 0px) - 30px); padding: 10px 20px; background: var(--surface); border-top: 1px solid var(--line); max-width: calc(var(--content-max) + 40px); }
@media (min-width:1024px) {
.chat-form { bottom: 0; margin-bottom: -48px; }
}
.chat-form .chat-input { flex: 1 1 0%; min-width: 0; }
.chat-send { flex: none; width: var(--tap-min); padding: 0; border-radius: var(--r-sm); }
.chat-send .btn-label { display: none; }
.chat-send .btn-glyph { width: 18px; height: 18px; }
@media (min-width:1024px) {
.chat-user { max-width: min(85%, 66ch); }
}
@media (min-width:1024px) {
.chat-answer { max-width: min(92%, 66ch); }
}

/* ── sikhok ── */
.sikhok-body { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.sikhok-tasks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
@media (min-width:1024px) {
.sikhok-tasks { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.sikhok-task { display: block; width: 100%; min-width: 0; min-height: 80px; margin: 0; padding: var(--space-4) var(--space-3); background: var(--surface); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-sm); font-family: var(--font-bn); text-align: left; cursor: pointer; }
.sikhok-task:hover { background: var(--neutral-100); }
.sikhok-task[aria-pressed="true"] { border: 2px solid var(--ink); padding: calc(var(--space-4) - 1px) calc(var(--space-3) - 1px); }
.sikhok-task[aria-pressed="true"] .sikhok-task-label { font-weight: 700; }
.sikhok-task:active { transform: scale(.97); }
@media (prefers-reduced-motion:reduce) {
.sikhok-task:active { transform: none; }
}
.sikhok-task-glyph { display: block; width: 20px; height: 20px; margin-bottom: var(--space-2); color: var(--ink-2); }
.sikhok-task-glyph svg { display: block; width: 100%; height: 100%; }
.sikhok-task-label { display: block; font-size: 14px; font-weight: 600; line-height: var(--lh-h3); overflow-wrap: anywhere; }
.card.sikhok-latest { padding: 14px; }
.card.sikhok-latest>.ui-card-body { padding: 0; }
.sikhok-latest .ui-skeleton { padding: 0; }
.sikhok-latest-kicker { margin: 0 0 var(--space-2); }
.sikhok-latest-title { margin: 0 0 3px; font-size: 14.5px; font-weight: 600; line-height: var(--lh-h3); letter-spacing: normal; overflow-wrap: anywhere; }
.sikhok-latest-meta { margin: 0; font-size: 12px; line-height: var(--lh-small); color: var(--ink-3); }
.sikhok-latest-trust { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-3); }
.sikhok-note { margin: var(--space-2) 0 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-2); }
.sikhok-output { margin: var(--space-3) 0 0; padding: var(--space-3); min-width: 0; background: var(--inset); color: var(--ink); border-radius: var(--r-sm); white-space: pre-wrap; overflow-wrap: anywhere; font-family: var(--font-bn); font-size: var(--text-body); line-height: var(--lh-body); }

/* ── practice ── */
.prac-option { color: var(--ink); }
.prac-option:disabled { cursor: default; }
.prac-option:disabled:not(.is-correct):not(.is-wrong) { background: var(--surface); }
.prac-options+.prac-actions,
.prac-input+.prac-actions { margin-top: var(--space-3); }
.prac-difficulty { font-weight: 400; }

/* ── platform-console ── */
.platform-shell { display: flex; min-height: 100dvh; background: var(--bg); }
.plat-sidebar { width: 190px; flex: none; display: flex; flex-direction: column; background: var(--ink); color: var(--surface); position: sticky; top: 0; height: 100dvh; }
.plat-brand { padding: var(--space-4); border-bottom: 1px solid color-mix(in srgb, var(--surface) 20%, transparent); }
.plat-wordmark { margin: 0 0 2px; font-size: 15px; line-height: 1.3; font-weight: 700; letter-spacing: -.01em; }
.plat-brand-sub { margin: 0; font-size: 10.5px; line-height: 1.4; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; opacity: .6; }
.plat-nav { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; padding: var(--space-2) 0; }
.plat-nav-item { display: flex; align-items: center; gap: 10px; width: 100%; min-height: var(--tap-min); padding: 0 var(--space-4); border: 0; border-radius: 0; background: transparent; color: var(--surface); opacity: .75; font-family: var(--font-bn); font-size: 13.5px; font-weight: 500; text-align: left; cursor: pointer; transition: background-color var(--dur-2) var(--ease), opacity var(--dur-2) var(--ease); }
.plat-nav-item:hover { opacity: 1; background: color-mix(in srgb, var(--surface) 10%, transparent); }
.plat-nav-item[aria-current="page"] { opacity: 1; background: var(--accent); font-weight: 700; }
.plat-nav-item:focus-visible { outline: 2px solid var(--surface); outline-offset: -2px; }
.plat-nav-glyph { flex: none; display: grid; font-size: 15px; }
.plat-nav-label { flex: 1; min-width: 0; }
.plat-sidebar-foot { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-top: 1px solid color-mix(in srgb, var(--surface) 20%, transparent); font-size: 12px; }
.plat-who { flex: 1; min-width: 0; opacity: .7; }
.plat-sidebar-foot .plat-signout { padding: 0 var(--space-2); color: var(--surface); font-size: 12px; }
.plat-sidebar-foot .plat-signout:hover:not(:disabled) { background: color-mix(in srgb, var(--surface) 12%, transparent); }
.plat-sidebar-foot .plat-signout:focus-visible { outline: 2px solid var(--surface); outline-offset: 2px; }
.platform-main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--surface); }
.page-header.plat-bar { padding-top: var(--space-6); padding-left: 18px; padding-right: 18px; background: var(--surface); }
.plat-date { font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink-3); white-space: nowrap; }
.plat-band { padding: var(--space-4) 18px; background: var(--surface); border-bottom: 1px solid var(--line); }
.plat-band-inset { padding: 11px 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.plat-flash>.ui-success-note { margin: 0; }
.ui-section-head.plat-label { min-height: 0; padding-bottom: 0; border-bottom: 0; margin-bottom: var(--space-3); }
.plat-label .ui-section-title { font-size: var(--text-label); line-height: var(--lh-label); font-weight: var(--w-label); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.plat-band-inset .ui-section-head.plat-label { margin-bottom: 0; }
.plat-note { margin: 0 0 var(--space-3); max-width: 72ch; font-size: var(--text-small); line-height: 1.55; color: var(--ink-2); }
.plat-note:last-child { margin-bottom: 0; }
.plat-note.plat-more { margin: var(--space-3) 0 0; }
.plat-stats .ui-stat[data-tone="accent2"] .ui-stat-value { color: var(--ink-2); }
.plat-stats>.ui-section-head.plat-label { margin-bottom: var(--space-3); }
.ui-list.plat-attn { border: 0; border-radius: 0; background: transparent; }
.plat-attn .ui-list-hit { min-height: var(--tap-min); padding: 11px 0; gap: var(--space-3); }
.plat-attn .ui-list-hit::before { content: ''; flex: none; width: 3px; height: 26px; background: var(--warn); }
.plat-attn .ui-list-item[data-level="danger"] .ui-list-hit::before { background: var(--danger); }
.plat-attn .ui-list-title { font-size: 14.5px; font-weight: 600; }
.plat-attn .ui-list-sub { font-size: 12.5px; color: var(--warn); }
.plat-attn .ui-list-item[data-level="danger"] .ui-list-sub { color: var(--danger); }
.ui-tabs.plat-filters { flex-wrap: wrap; gap: var(--space-2); border-bottom: 0; overflow: visible; }
.plat-filters .ui-tab { min-height: var(--tap-min); margin-bottom: 0; padding: 0 12px; gap: 7px; border: 1px solid var(--line); border-radius: var(--r-sm); background: transparent; color: var(--ink); font-size: var(--text-small); font-weight: 600; }
.plat-filters .ui-tab:hover { background: var(--surface); }
.plat-filters .ui-tab[aria-selected="true"] { background: var(--ink); color: var(--surface); border-color: var(--ink); font-weight: 600; }
.plat-tools { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3); }
.plat-tools .ui-field { margin-bottom: 0; }
.plat-tools>.ui-field { flex: 1 1 240px; min-width: 0; }
.plat-sort { display: flex; flex-wrap: nowrap; align-items: flex-end; gap: var(--space-2); }
.plat-tools>.plat-sort { flex: none; max-width: 100%; }
.plat-sort .ui-field { flex: 0 0 200px; min-width: 0; }
.plat-sort>.ui-btn { flex: none; white-space: nowrap; }
.plat-fleet>.ui-data { border: 0; border-radius: 0; }
.plat-fleet .ui-table [data-col="access"] { text-align: right; }
.plat-pager,
.fleet-pager { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding: 11px 18px; background: var(--surface); border-top: 2px solid var(--rule); }
.plat-pager-count,
.fleet-count { flex: 1 1 auto; margin: 0; font-size: var(--text-small); color: var(--ink-2); }
.plat-pager-of,
.fleet-page-of { font-size: var(--text-small); color: var(--ink-2); }
.plat-plan-grid { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 1px; background: var(--line); border-bottom: 2px solid var(--rule); }
.plat-plan-cell { display: flex; flex: 1 1 calc((100% - 2px) / 3); min-width: 0; background: var(--surface); }
.plat-plan { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; width: 100%; min-height: var(--tap-min); margin: 0; padding: var(--space-4) 17px; border: 0; border-radius: 0; background: var(--surface); color: var(--ink); font-family: var(--font-bn); text-align: left; cursor: pointer; transition: background-color var(--dur-2) var(--ease); }
.plat-plan:hover { background: var(--neutral-100); }
.plat-plan:focus-visible { outline-offset: -2px; }
.plat-plan-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.plat-plan-name { font-size: 14px; line-height: 1.4; font-weight: 700; }
.plat-plan.is-retired .plat-plan-name { color: var(--ink-2); }
.plat-plan-price { display: block; font-size: 18px; line-height: 1.3; font-weight: 700; }
.plat-plan-meta { display: block; font-size: 12px; line-height: 1.5; color: var(--ink-3); }
.ui-list.plat-operators { border: 0; border-radius: 0; }
.plat-operators .ui-list-hit { min-height: 52px; padding: 0 18px; gap: 13px; }
.plat-operators .ui-list-title { font-size: 14px; font-weight: 600; }
.plat-operators .ui-list-sub { font-size: 12px; color: var(--ink-3); }
.ui-tabs.plat-detail-tabs { padding: 0 var(--space-1); background: var(--surface); }
.plat-detail-tabs .ui-tab { font-size: var(--text-small); }
.plat-band.plat-detail { display: flex; flex-direction: column; gap: var(--space-4); border-bottom: 0; }
.plat-detail>section { display: flex; flex-direction: column; gap: var(--space-3); min-width: 0; }
.plat-detail .ui-section-head.plat-label,
.plat-detail .plat-note { margin-bottom: 0; }
.ui-list.plat-settings { border: 0; border-radius: 0; background: transparent; }
.plat-settings .ui-list-hit { min-height: var(--tap-min); padding: 10px 0; gap: 13px; }
.plat-settings .ui-list-title { font-size: 14px; font-weight: 500; }
.plat-settings .ui-row-actions { flex-wrap: nowrap; }
.plat-switch { position: relative; flex: none; display: inline-flex; align-items: center; justify-content: flex-start; width: 40px; height: 23px; padding: 2px; border: 0; border-radius: var(--r-pill); background: var(--ink-3); cursor: pointer; transition: background-color var(--dur-2) var(--ease); }
.plat-switch::before { content: ''; position: absolute; left: -2px; right: -2px; top: 50%; height: var(--tap-min); transform: translateY(-50%); }
.plat-switch[aria-checked="true"] { justify-content: flex-end; background: var(--ok); }
.plat-switch-knob { width: 19px; height: 19px; border-radius: var(--r-pill); background: var(--surface); }
.plat-switch:disabled { opacity: .45; cursor: default; }
.plat-back { padding-top: var(--space-2); padding-bottom: var(--space-2); }
.plat-back .plat-note { margin: 0 0 var(--space-2); }
.plat-secondary { border-bottom: 0; }
.plat-band.plat-secondary { margin-top: auto; }
.platform-state { padding: var(--space-4) 18px; background: var(--surface); border-bottom: 1px solid var(--line); }
.platform-state .detail-list { padding: 0; }
.platform-main .inline-notice { margin: 0; }
.state-ok { color: var(--ink); }
.state-pending { color: var(--warn); }
.plat-state-glyph { display: inline-flex; margin-right: var(--space-1); vertical-align: -2px; }
.state-ok .plat-state-glyph { color: var(--ok); }
.platform-main .mono { font-family: ui-monospace, monospace; font-size: var(--text-small); overflow-wrap: anywhere; }
.platform-code { margin: var(--space-3) 0; padding: var(--space-3); border: 1px dashed var(--line); border-radius: var(--r-md); background: var(--inset); font-family: ui-monospace, monospace; font-size: var(--text-h2); font-weight: 700; letter-spacing: .18em; text-align: center; overflow-wrap: anywhere; }
.platform-code .n { font-family: inherit; }
.platform-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--space-4); }
.plat-status-actions>.ui-field { flex: 1 1 100%; margin-bottom: 0; }
.plat-form-band>* { max-width: 640px; }
.plat-form-band>.status-chip,
.plat-form-band>.plat-download { align-self: flex-start; }
.plat-weekend { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0; }
.plat-weekend>legend { float: left; width: 100%; }
.check-inline { display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--tap-min); margin-right: var(--space-3); font-size: var(--text-small); cursor: pointer; }
.wizard-steps { display: flex; gap: var(--space-1); list-style: none; margin: var(--space-2) 0 0; padding: 0 0 var(--space-1); overflow-x: auto; scrollbar-width: none; }
.wizard-step { flex: none; display: inline-flex; align-items: center; gap: var(--space-1); min-height: 34px; padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: transparent; color: var(--ink-2); font-size: var(--text-small); font-weight: 600; white-space: nowrap; }
.wizard-step.is-done { color: var(--ink); }
.wizard-step.is-current { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.plat-step-glyph { display: inline-flex; color: var(--ok); }
.platform-search { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.platform-search>.field-input { flex: 1 1 220px; min-width: 0; }
.fleet-filter { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-small); color: var(--ink-2); }
.fleet-filter .field-input { flex: 0 0 auto; width: auto; min-width: 120px; }
.fleet-bands { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 11px 18px; background: var(--inset); border-bottom: 1px solid var(--line); }
.fleet-band { min-height: var(--tap-min); padding: 0 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: transparent; color: var(--ink); font-family: var(--font-bn); font-size: var(--text-small); font-weight: 600; cursor: pointer; }
.fleet-band:hover { background: var(--surface); }
.fleet-band.is-on { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.fleet-sort { padding: 0; border: 0; background: none; font: inherit; font-weight: 700; letter-spacing: inherit; text-transform: inherit; color: inherit; text-align: inherit; cursor: pointer; }
.fleet-sort.is-active,
.fleet-sort:hover { text-decoration: underline; }
.fleet-cards { display: none; list-style: none; margin: 0; padding: var(--space-3) 18px; }
.fleet-card { margin-bottom: var(--space-2); padding: var(--space-3); background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); }
.fleet-card-top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.fleet-card-name { font-weight: 700; }
.fleet-card-sub { margin: 0 0 var(--space-2); font-size: 12px; color: var(--ink-3); }
.fleet-card-facts { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; margin: 0 0 10px; font-size: 12px; }
.fleet-card-facts dt { margin: 0; color: var(--ink-3); }
.fleet-card-facts dd { margin: 0; font-weight: 600; }
@media (max-width:1023.98px) {
.platform-shell { flex-direction: column; }
}
@media (max-width:1023.98px) {
.plat-sidebar { position: static; width: auto; height: auto; flex-direction: row; flex-wrap: wrap; align-items: center; }
}
@media (max-width:1023.98px) {
.plat-brand { padding: var(--space-2) var(--space-4); border-bottom: 0; }
}
@media (max-width:1023.98px) {
.plat-sidebar-foot { margin-left: auto; padding: var(--space-2) var(--space-4); border-top: 0; }
}
@media (max-width:1023.98px) {
.plat-who { flex: none; }
}
@media (max-width:1023.98px) {
.plat-nav { order: 3; flex: 1 0 100%; flex-direction: row; overflow-x: auto; scrollbar-width: none; padding: 0; border-top: 1px solid color-mix(in srgb, var(--surface) 20%, transparent); }
}
@media (max-width:1023.98px) {
.plat-nav-item { flex: none; width: auto; white-space: nowrap; }
}
@media (max-width:1023.98px) {
.page-header.plat-bar { padding-top: var(--space-4); padding-left: var(--space-4); padding-right: var(--space-4); }
}
@media (max-width:1023.98px) {
.plat-band,
.plat-band-inset,
.platform-state,
.fleet-bands,
.plat-pager,
.fleet-pager { padding-left: var(--space-4); padding-right: var(--space-4); }
}
@media (max-width:1023.98px) {
.platform-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width:1023.98px) {
.plat-plan-cell { flex-basis: 100%; }
}
@media (max-width:1023.98px) {
.plat-operators .ui-list-hit { padding: var(--space-2) var(--space-4); }
}
@media (max-width:1023.98px) {
.plat-settings .ui-list-hit { flex-wrap: wrap; }
}
@media (max-width:1023.98px) {
.plat-settings .ui-list-main { flex: 1 1 100%; }
}
@media (max-width:1023.98px) {
.plat-settings .ui-list-status { margin-left: auto; }
}
@media (max-width:1023.98px) {
.plat-settings .ui-row-actions { flex-wrap: wrap; }
}
@media (max-width:1023.98px) {
.plat-tools,
.plat-sort,
.platform-search { flex-direction: column; align-items: stretch; }
}
@media (max-width:1023.98px) {
.plat-tools>.ui-field,
.plat-sort .ui-field,
.platform-search>.field-input { flex: none; }
}
@media (max-width:1023.98px) {
.fleet-filter { justify-content: space-between; }
}
@media (max-width:1023.98px) {
.fleet-filter .field-input { flex: 1 1 auto; }
}
@media (max-width:1023.98px) {
.fleet-wide { display: none; }
}
@media (max-width:1023.98px) {
.fleet-cards { display: block; padding-left: var(--space-4); padding-right: var(--space-4); }
}

/* ── lead: the session-ended card (01 Shell & Auth §ক "সময় শেষ") ──
   It reuses the login card's frame and its warn panel, so the only rules are
   the glyph and the type the drawing gives the card itself. */
.session-ended .session-ended-glyph { display: block; width: 32px; height: 32px; margin: 0 0 var(--space-4); color: var(--ink-2); }
.session-ended .session-ended-glyph[data-tone="warn"] { color: var(--warn); }
.session-ended .session-ended-glyph svg { width: 100%; height: 100%; }
.session-ended .session-ended-title { margin: 0 0 10px; font-size: var(--text-h2); line-height: var(--lh-h2); font-weight: 700; letter-spacing: normal; }
.session-ended .session-ended-text { margin: 0 0 var(--space-6); font-size: var(--text-body); line-height: 1.65; color: var(--ink-2); }
.session-ended .session-ended-queue { margin: 0 0 22px; }

/* ═══ [5] lead — UX sweep fixes: shell, money figures, marks, profile tabs, attendance end ═══
   Fixes from the real-browser sweep (confirmed findings 16, 59, 48, 25, 33,
   7, 36, 50). Each rule is scoped to the defect it closes and says why. Later
   in the sheet on purpose: same-specificity rules here replace earlier ones
   without rewriting those sections. */

/* 16, 59 — focus must never park behind the sticky topbar or the fixed tab
   bar (WCAG 2.4.11). Chrome scrolls a newly focused control only to the
   viewport edge; scroll-padding moves that edge inside the bars. Values are
   the bar heights (topbar 56 / 64 at desktop, tab bar 58 + its 2px rule) plus
   room for the 2px focus ring. The attendance register's own
   `:root:has(.att-register…)` rules are more specific and keep winning. */
@media (max-width:1023.98px) {
:root { scroll-padding-top: 64px; scroll-padding-bottom: calc(68px + env(safe-area-inset-bottom, 0px)); }
}
@media (min-width:1024px) {
:root { scroll-padding-top: 72px; scroll-padding-bottom: 8px; }
}
/* the marks sheet's save bar is sticky above the tab bar below 1024 (98–117px
   tall), so a focused mark box must clear it too */
@media (max-width:1023.98px) {
:root:has(.marks-savebar) { scroll-padding-bottom: calc(68px + env(safe-area-inset-bottom, 0px) + 128px); }
}

/* 48 — the entrance animation must not leave a transform behind. With fill
   mode `both` the finished `rise` keeps `transform:none` computed as an
   identity matrix, which makes every screen root the containing block for
   its position:fixed children (the attendance undo toast landed at the card's
   foot, below the fold). `backwards` still starts from the `from` frame and
   lets go when the animation ends. */
.shell-view > * { animation-fill-mode: backwards; }

/* 25, 33 (and minor 35) — a money figure is read as one number, so it stays
   on one line. formatBdt's "৳ 12,50,000.00" does not fit a half-width phone
   stat cell at 26px; the band's figures step down with the viewport instead
   of breaking (16px at 320, 18.75px at 375, the sheet's 26px from 520px up).
   The earlier `overflow-wrap:anywhere` on these bands allowed "30,000.0 / 0". */
.ph-band .ui-stat-value,
.ledger-stats .ui-stat-value,
.ward-stats .ui-stat-value { white-space: nowrap; overflow-wrap: normal; font-size: clamp(16px, 5vw, 26px); }

/* 7 — marks sheet on phones. The 560px min-width handed all spare width to
   the frozen name column (206px of a 278px scroller), leaving no mark box in
   view. Below 1024 the table shrinks to content, the name column settles at
   its 112px minimum (long words break rather than widen it), and the
   scroller's scroll-padding keeps a focused box clear of the frozen 48px roll
   + 112px name columns when Tab / the keyboard's "next" moves along a row. */
@media (max-width:1023.98px) {
.marks-table { min-width: 0; }
.marks-table .marks-col-name,
.marks-table .marks-name { overflow-wrap: anywhere; }
.marks-sheet > .ui-table-scroll { scroll-padding-left: 164px; }
}

/* 36 — the student profile's six tabs are wider than a phone card, and a
   scrolled strip hid ফি and নথি with no hint. Below 1024 the tabs lay out in
   as many equal columns as fit (3 + 3 on a phone, one row on a tablet), so no
   tab is ever off-screen. */
@media (max-width:1023.98px) {
.ui-tabs.stu-tabs { display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr)); overflow-x: visible; }
.stu-tabs .ui-tab { justify-content: center; padding: 0 var(--space-2); white-space: normal; text-align: center; }
}

/* 50 — at the end of the register the last rows must be able to scroll above
   the undo toast, which floats ~80px above the sticky footer below 1024.
   Permanent (not only while the toast shows) so the list never jumps when
   the toast hides. 84px matches the toast allowance in the scroll-padding
   rules above. */
@media (max-width:1023.98px) {
.att-list { padding-bottom: 84px; }
}

/* minor 89 — the account menu clips overflow, so the item's outside ring was
   cut to a line that read as a divider. Draw it inside. */
.shell-menu-item:focus-visible { outline-offset: -2px; }

/* minor 16/80 — আরও row descriptions carry the warning half of the sentence
   ("… প্রকাশের পর নম্বর অপরিবর্তনীয়"); an ellipsis cut it off on phones. */
.more-list .ui-list-sub { overflow: visible; text-overflow: clip; white-space: normal; }

/* ═══ [4] Ata Ekta — ux fixes from the browser sweep ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ux-fix:infra-js (finding 60, CSS half) is not repeated here: the [5] lead
   section above already sets :root scroll-padding-top to 64px below 1024 and
   72px from 1024 up, which clears the 56/64px topbar with room for the ring. */

/* ── ux-fix:practice ── */
.prac-input-error+.prac-actions { margin-top: var(--space-3); }
.prac-input.is-error,
.prac-input.is-error:focus { border-color: var(--danger); padding: 0 11px; }

/* ── ux-fix:results ── */
.result-child-switch { margin-bottom: var(--space-3); }
.result-child-id { margin: 0 0 var(--space-3); }

/* ── ux-fix:invoices ── */
.inv-table .ui-table .inv-amt-word { display: none; }

/* ── ux-fix:assignments ── */
.sub-grade-error { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-2); }
.sub-grade-error>.ui-field-error { margin: 0; flex: 1 1 12em; min-width: 0; }
.sub-grade-saved { margin: var(--space-3) 0 0; }

/* ── ux-fix:documents ── */
.doc-steps .doc-child { margin-bottom: var(--space-4); }
.doc-actions .doc-invalid { flex-basis: 100%; margin: 0; }

/* ── ux-fix:guardian-fees ── */
.fees-sheet.is-family>.fees-kids { border: 0; border-radius: 0; border-bottom: 1px solid var(--line); }
.fees-sheet.is-family>.fees-kids .ui-list-hit { padding: 14px; }
.fees-sheet.is-family>.fees-kids .ui-list-title { font-size: var(--text-body); font-weight: 600; }
.fees-sheet.is-family>.fees-kids .fees-kid-owed { font-size: 16px; font-weight: 700; white-space: nowrap; }
.fees-sheet.is-family>.fees-kid-head { padding: 10px 14px; font-size: var(--text-body); line-height: var(--lh-small); font-weight: 600; color: var(--ink); background: var(--surface); border-bottom: 1px solid var(--line); }
.fees-sheet.is-family>.ui-data+.fees-kid-head { border-top: 1px solid var(--line); }

/* ── ux-fix:students ── */
@media all {
.stu-money { white-space: nowrap; }
}
@media all {
.stu-pair { display: inline-block; }
}

/* ── ux-fix:export ── */
.export-files .export-result { padding: 0 14px var(--space-3) calc(14px + 19px + var(--space-3)); }
.export-files .export-result>.ui-state { padding: var(--space-3) var(--space-4); }
.export-files .export-result>.ui-success-note { margin: 0; }

/* ── ux-fix:attendance ── */
.att-footer[data-state="saved"] .att-saved-text { margin: 0; min-height: 46px; display: flex; flex-direction: column; justify-content: center; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
.att-saved-text .att-saved-head { font-weight: 700; }
.att-saved-text .att-saved-tally { color: var(--ink-2); }
.att-footer[data-state="saved"]:has(.att-saved-text[data-delivery="sent"]) { border-top-color: var(--ok); }
.att-footer[data-state="saved"]:has(.att-saved-text[data-delivery="failed"]) { border-top-color: var(--danger); }
@media (max-width:1023.98px) {
:root:has(.att-footer[data-state]) .ui-toast-host { bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 80px + var(--space-2)); }
}
@media (max-width:1023.98px) {
:root:has(.att-footer[data-state="blocked"]) .ui-toast-host { bottom: calc(60px + env(safe-area-inset-bottom, 0px) + 150px + var(--space-2)); }
}

/* ═══ [4] Ata Ekta — ux fixes round 2 ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── ux-fix2:focus-shell ── */
.ui-focus-landing[tabindex]:focus-visible { outline: none; text-decoration-line: underline; text-decoration-thickness: 2px; text-underline-offset: 6px; text-decoration-color: var(--accent); text-decoration-skip-ink: none; }

/* ── ux-fix2:compose-demo ── */
.compose-panel>.compose-notice { margin: 0; }
.compose-panel>.offline-banner.compose-notice { border: 1px solid var(--warn); border-radius: var(--r-sm); }

/* ── ux-fix2:learn ── */
.learn-missing { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) 9px; margin: 0; padding: var(--space-3) 14px; background: var(--info-tint); border-bottom: 1px solid var(--line); }
.learn-missing .ui-icon { flex: none; font-size: 16px; color: var(--info); }
.learn-missing-text { flex: 1 1 14em; min-width: 0; margin: 0; font-size: var(--text-small); line-height: var(--lh-small); color: var(--ink); }
.learn-missing-action { flex: none; margin-left: auto; }
.topic-done[aria-disabled="true"],
.topic-done-alt[aria-disabled="true"] { opacity: .45; cursor: default; }
.btn-primary.topic-done[aria-disabled="true"]:hover,
.btn-primary.topic-done[aria-disabled="true"]:active { background: var(--accent); }
.btn-secondary.topic-done-alt[aria-disabled="true"]:hover { background: transparent; }
.topic-done[aria-disabled="true"]:active,
.topic-done-alt[aria-disabled="true"]:active { transform: none; }

/* ── ux-fix2:fees ── */
.fees-sheet.is-family .ui-list .fees-left { display: inline-flex; flex-direction: column; align-items: flex-end; }
.fees-sheet.is-family .ui-list .fees-left-word { font-family: var(--font-bn); font-variant-numeric: normal; font-feature-settings: normal; font-size: 12px; line-height: 1.2; font-weight: 400; color: var(--ink-2); }
.fees-sheet.is-family .ui-list .fees-left .fees-amount { line-height: 1.3; }

/* ── ux-fix2:ledger ── */
.ledger-mismatch-text .ledger-mismatch-fig { white-space: nowrap; }

/* ── ux-fix2:results-guardian ── */
.ui-field.result-exam-pick { margin: 0 0 var(--space-3); }
@media (min-width:1024px) {
.ui-field.result-exam-pick { max-width: 320px; }
}

/* ── ux-fix2:roster ── */
.roster-code.issued-code-card { scroll-margin-top: var(--space-2); }

/* ── ux-fix2:platform ── */
.plat-title { width: fit-content; max-width: 100%; }

/* ═══ [4] Ata Ekta — ux fixes round 3 (shell route container, roster code note) ═══════════════════════════════════════════
   Rules the redesign's units needed that the one stylesheet is silent on.
   Merged by script: a declaration the ata-ekta section already sets for the
   same selector was refused (the sheet wins), as was any raw hex.
   ═══════════════════════════════════════════════════════════════════ */

/* ── ux-fix3:shell ── */
.shell-route { display: contents; }
.shell-route>* { animation: rise var(--dur-3) var(--ease) backwards; }
.shell-route>* { max-width: var(--content-max); }
.shell-view:has(>.shell-route>.chat-form) { display: flex; flex-direction: column; }

/* ── ux-fix3:roster ── */
.roster-issue-note { display: flex; align-items: flex-start; gap: var(--space-2); margin: 0; font-size: var(--text-small); line-height: var(--lh-small); font-weight: 600; color: var(--danger); }
.roster-issue-note-glyph { flex: none; margin-top: calc((var(--lh-small) - 1) * 0.5em); }
.roster-issue-note.is-list { padding: 0 14px var(--space-2) calc(14px + 34px + var(--space-3)); }
.roster-issue-note.is-table { width: 0; min-width: 100%; margin-top: var(--space-1); }
.roster-issue-note.is-body { padding: 10px 14px; border-bottom: 1px solid var(--line); }

/* ── lead: fees, the two facts a late part-paid bill carries (ux round 3) ──
   A bill that is both late and part paid used to show only মেয়াদোত্তীর্ণ, so
   the money already paid was invisible in the very filter that lists it
   (আংশিক). The second word sits under the badge — a word, not a colour — and
   never widens the row: it wraps as its own line. */
.fees-status.has-also { display: inline-flex; flex-direction: column; }
.fees-sheet .ui-list .fees-status.has-also { align-items: flex-end; }
.fees-sheet .ui-table .fees-status.has-also { align-items: flex-start; }
.fees-status-also { font-weight: 400; white-space: nowrap; }
/* A family's phone row: at 320 the wider badge pushed the month onto two
   lines ("আগস্ট" / "২০২৬"). The month keeps its own width and the status moves
   under the amount instead. The office rows and the per-child summary rows are
   left as they were. */
.fees-sheet.is-family .ui-list:not(.fees-kids) > .ui-list-item > .ui-list-hit {
  flex-wrap: wrap; justify-content: flex-end; }
.fees-sheet.is-family .ui-list:not(.fees-kids) > .ui-list-item > .ui-list-hit > .ui-list-main {
  flex: 0 0 auto; max-width: 100%; }
