/* MISOS app additions — built on mis-design-system.css tokens, not a second theme. */

/* Restore the native [hidden] behavior: the design system's .btn (and potentially
   other components) set an explicit `display`, which beats the browser's default
   [hidden]{display:none} UA rule — without this, hidden elements stay visible. */
[hidden] {
  display: none !important;
}

/* Inline translation captions, from the bl() helper in src/helpers.php.
   Sized relative to the parent (em), so it scales in headings, labels, and
   buttons alike without needing a size variant per context. */
.i18n-cn, .i18n-th {
  font-size: 0.8em;
  font-weight: 400;
  opacity: 0.75;
}

/* --- Header brand lockup (icon mark + wordmark), same header bar as mastersinternationalschool.org --- */
.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.site-header__brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

.site-header__brand-mark {
  width: 34px;
  height: 34px;
  object-fit: contain;
  flex-shrink: 0;
}

.site-header__brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.site-header__brand-text strong {
  font-family: var(--font-serif);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--mis-accent);
  letter-spacing: 0.01em;
}

.site-header__brand-text small {
  font-family: var(--font-sans);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mis-ink-muted);
}

/* Account area on the right of the header (email + sign out), sits alongside .site-header__nav */
.site-header__account {
  display: flex;
  align-items: center;
  gap: 16px;
}

.site-header__account-email {
  color: var(--mis-ink-muted);
  font-size: 0.85rem;
}

/* --- Compact hero for app pages (login/register/etc) — same treatment as the marketing hero, less tall --- */
.hero-section--compact {
  padding-block: 2.75rem 3.25rem;
}

.hero-section--compact .hero-section__heading {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  margin-bottom: 0.35em;
}

.hero-section--compact .hero-section__sub {
  font-size: 1.1rem;
  max-width: 48ch;
}

/* Section directly under a hero, holding the actual form card */
.auth-section {
  display: flex;
  justify-content: center;
  padding-block: 3rem;
}

/* --- Forms --- */
.form-row {
  margin-bottom: 16px;
}

.form-row label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--mis-ink-soft);
}

.input, .select, textarea {
  width: 100%;
  border: 1px solid var(--mis-rule);
  border-radius: 8px;
  padding: 10px 12px;
  font-family: var(--font-sans);
  font-size: 0.95rem;
  color: var(--mis-ink);
  background: var(--mis-surface);
}

.input:focus, .select:focus, textarea:focus {
  outline: 2px solid var(--mis-accent-soft);
  border-color: var(--mis-accent);
}

.form-actions {
  display: flex;
  gap: 12px;
  margin-top: 24px;
}
/* Modifier for an action row whose buttons are too wide to sit side by side on a phone.
   Additive: .form-actions itself is used across many pages and keeps its unwrapped default. */
.form-actions--wrap { flex-wrap: wrap; }

.form-card {
  max-width: 480px;
  width: 100%;
}

.form-card--wide {
  max-width: 720px;
}

.form-card h1 {
  font-size: 1.5rem;
}

.form-card p:last-child {
  margin-bottom: 0;
}

.form-card a {
  color: var(--mis-accent);
}

/* Helper text under a field, and any secondary line that should recede.
   Used by many pages already (the form standard names it) — it just had no
   rule anywhere until now. */
.text-muted {
  color: var(--mis-ink-muted);
}

/* --- Table --- */
/* Wrap <table class="table"> in <div class="table-scroll">...</div> so
   wide tables scroll horizontally on a phone instead of overflowing the
   page or squeezing every column unreadably. New pages should wrap
   their main data table in this from the start; existing unwrapped
   tables (~77 files per the 2026-09-23 mobile audit) are migrated in a
   separate follow-up pass, not this change. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Long tables: the table scrolls inside its own box so the header row stays put (sticky only works against the scrolling box). */
.table-scroll--sticky { max-height: calc(100vh - 140px); overflow-y: auto; }
.table-scroll--sticky > .table thead th { position: sticky; top: 0; z-index: 2; box-shadow: 0 1px 0 var(--mis-rule); }

/* Freeze panes (reusable): <div class="table-scroll table-freeze" tabindex="0" aria-label="..."><table class="table">.
   The box scrolls both ways inside the viewport; the header row and the FIRST column stay put (public/js/table-freeze.js
   adds .is-scrolled-x / .is-scrolled-y and sets --tf-w). Every sticky cell has an OPAQUE background so nothing shows through.
   A full-width row (colspan) keeps its cell non-sticky; put its content in .table-freeze__full to keep it in view sideways. */
.table-freeze { position: relative; overflow: auto; max-height: max(320px, calc(100vh - 120px)); -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
@supports (height: 100svh) { .table-freeze { max-height: max(320px, calc(100svh - 120px)); } }
.table-freeze:focus-visible { outline: 2px solid var(--mis-accent, #223369); outline-offset: 2px; }
.table-freeze > .table { overflow: visible; }
.table-freeze > .table thead th { position: sticky; top: 0; z-index: 3; background: var(--mis-rule-soft, #eef0f4); box-shadow: 0 1px 0 var(--mis-rule, #e2e5ec); }
.table-freeze > .table thead th[data-key]:hover { background: #e2e6f0; }
.table-freeze > .table thead th:first-child { left: 0; z-index: 4; }
.table-freeze > .table tbody td:first-child, .table-freeze > .table tbody th:first-child { position: sticky; left: 0; z-index: 2; }
.table-freeze > .table tbody td[colspan]:first-child { position: static; z-index: auto; box-shadow: none; }
/* zero-specificity defaults: a table's own zebra/hover colours on its cells still win, but the cell is never see-through */
:where(.table-freeze > .table tbody td:first-child, .table-freeze > .table tbody th:first-child) { background: var(--mis-surface, #fff); }
.table-freeze.is-scrolled-x > .table thead th:first-child { box-shadow: 0 1px 0 var(--mis-rule, #e2e5ec), 3px 0 4px -1px rgba(34, 51, 105, 0.22); }
.table-freeze.is-scrolled-x > .table tbody td:first-child:not([colspan]) { box-shadow: 3px 0 4px -1px rgba(34, 51, 105, 0.22); }
.table-freeze .table-freeze__full { position: sticky; left: 16px; width: var(--tf-w, auto); box-sizing: border-box; }
@media (max-width: 640px) {
  .table-freeze > .table thead th:first-child, .table-freeze > .table tbody td:first-child:not([colspan]) { max-width: 42vw; width: 42vw; min-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-left: 10px; padding-right: 8px; }
  .table-freeze .table-freeze__full { left: 10px; }
}
@media print {
  .table-freeze { max-height: none; overflow: visible; }
  .table-freeze > .table thead th, .table-freeze > .table tbody td:first-child, .table-freeze > .table thead th:first-child { position: static; box-shadow: none; }
  .table-freeze .table-freeze__full { position: static; width: auto; }
}

/* Roster-style tables: the PAGE scrolls vertically (no inner scroll box); only sideways scrolling stays inside the wrapper.
   The first two columns (tick + name) stay put while scrolling sideways; the header row is pinned to the top of the
   screen by public/js/sticky-table-head.js (position: sticky cannot reach the viewport from inside an overflow-x box). */
.table-scroll--cols { overflow-y: visible; }
.table-scroll--cols > .table { overflow: visible; border-left: 0; border-right: 0; border-radius: 0; }
.table-scroll--cols > .table th:nth-child(1), .table-scroll--cols > .table td:nth-child(1),
.table-scroll--cols > .table th:nth-child(2), .table-scroll--cols > .table td:nth-child(2) { position: sticky; background: var(--mis-surface, #fff); z-index: 1; }
.table-scroll--cols > .table thead th:nth-child(1), .table-scroll--cols > .table thead th:nth-child(2),
.table-scroll--cols > .table tfoot th:nth-child(1), .table-scroll--cols > .table tfoot th:nth-child(2) { background: var(--mis-rule-soft); z-index: 2; }
.table-scroll--cols > .table th:nth-child(1), .table-scroll--cols > .table td:nth-child(1), .sticky-head-clone th:nth-child(1) { left: 0; min-width: 44px; width: 44px; box-sizing: border-box; padding-left: 8px; padding-right: 8px; text-align: center; }
.table-scroll--cols > .table th:nth-child(2), .table-scroll--cols > .table td:nth-child(2) { left: 44px; min-width: 160px; box-shadow: 2px 0 4px -1px rgba(34, 51, 105, 0.18); }
.table-scroll--cols > .table tr:hover td:nth-child(1), .table-scroll--cols > .table tr:hover td:nth-child(2) { background: var(--mis-surface, #fff); }
.table-scroll--cols > .table tr.roster-group td:nth-child(1) { box-shadow: none; }
/* People not paid in this run are dimmed through their content, not the row, so the pinned cells stay solid. */
#roster-table tr.roster-out > td > * { opacity: 0.6; }
/* The pinned copy of the header row (built by sticky-table-head.js). */
.sticky-head-clone { position: fixed; top: 0; z-index: 40; overflow: hidden; display: none; box-shadow: 0 2px 6px rgba(34, 51, 105, 0.18); background: var(--mis-rule-soft); }
.sticky-head-clone__inner { position: relative; will-change: transform; }
.sticky-head-clone table { border-radius: 0; border-top: 0; margin: 0; width: auto; table-layout: fixed; border-collapse: collapse; }
.sticky-head-clone th { position: static; box-sizing: border-box; white-space: nowrap; cursor: pointer; user-select: none; }
.sticky-head-clone .sortable-table-arrow { margin-left: 4px; font-size: 0.7em; opacity: 0.35; }
.sticky-head-clone .sortable-table-arrow.active { opacity: 1; }
.sticky-head-clone th.is-pinned { position: relative; z-index: 2; background: var(--mis-rule-soft); box-shadow: 2px 0 4px -1px rgba(34, 51, 105, 0.18); }

.table {
  width: 100%;
  border-collapse: collapse;
  background: var(--mis-surface);
  border: 1px solid var(--mis-rule);
  border-radius: 12px;
  overflow: hidden;
}

.table th, .table td {
  text-align: left;
  padding: 12px 16px;
  border-bottom: 1px solid var(--mis-rule-soft);
  font-size: 0.9rem;
}

.table th {
  font-weight: 600;
  color: var(--mis-ink-soft);
  background: var(--mis-rule-soft);
}

.table tr:last-child td {
  border-bottom: none;
}

/* --- Badge --- */
.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
}

.badge--active, .badge--approved {
  background: #e3f2e6;
  color: #1f7a3d;
}

.badge--inactive, .badge--rejected {
  background: var(--mis-clay-soft);
  color: var(--mis-clay-ink);
}

.badge--pending, .badge--submitted {
  background: #fdf3d8;
  color: var(--mis-gold-ink);
}

.badge--draft {
  background: #e8e8e8;
  color: #555;
}

.badge--passed { background: #e3f2e6; color: #1f7a3d; }
.badge--failed { background: var(--mis-clay-soft); color: var(--mis-clay-ink); }
.badge--extended { background: #fdf3d8; color: var(--mis-gold-ink); }
.badge--accountant_signed_off { background: #e0e7ff; color: #3730a3; }
.badge--reimbursed { background: #e3f2e6; color: #1f7a3d; }

/* --- Misc --- */
.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}

.toolbar__filters {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

/* Reusable 2/3-column form-field grids — replaces the inline
   `style="display:grid;grid-template-columns:1fr 1fr"` pattern found
   ad-hoc across ~50 pages (see the 2026-09-23 mobile audit), none of
   which collapsed on a phone. New pages should use these classes
   instead of hand-rolling a grid; existing pages are migrated to them
   in a separate follow-up pass, not this change. */
.form-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.form-grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
/* A form field whose own help text needs the whole row: inside a grid it spans every
   column. On a phone the grid has collapsed to one column, and 1 / -1 still means "all". */
.form-span-all { grid-column: 1 / -1; }
@media (max-width: 768px) {
  .form-grid-2, .form-grid-3 { grid-template-columns: 1fr; }
}

.otp-code-input {
  font-size: 1.5rem;
  letter-spacing: 0.5em;
  text-align: center;
}

.alert {
  padding: 12px 16px;
  border-radius: 8px;
  margin-bottom: 16px;
  font-size: 0.9rem;
}

.alert--error {
  background: var(--mis-clay-soft);
  color: var(--mis-clay-ink);
}

.alert--info {
  background: var(--mis-wash);
  color: var(--mis-accent-ink);
}

/* A batch that changed nothing is not a success. Used by the bulk bar on
   public/uniforms/orders.php, where ticking a row that is already handled and
   pressing "Mark issued" used to report itself as a green "0 lines marked
   issued" — which reads as though it worked. */
.alert--warning {
  background: #fdf3d8;
  color: var(--mis-gold-ink);
}

/* --- Dashboard Layout --- */
.dashboard {
  display: flex;
  min-height: 100vh;
}

.dashboard-sidebar {
  width: 260px;
  background: var(--mis-navy, #1a2332);
  color: #fff;
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 100;
  transition: width 0.2s ease;
  overflow-y: auto;
}

.dashboard-sidebar.collapsed {
  width: 64px;
}

.dashboard-sidebar__header {
  padding: 20px 16px;
  border-bottom: 1px solid rgba(255,255,255,0.1);
}

.dashboard-sidebar__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: #fff;
}

.dashboard-sidebar__brand-mark {
  width: 32px;
  height: 40px;
  object-fit: contain;
  flex-shrink: 0;
}

.dashboard-sidebar__brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

.dashboard-sidebar__brand-text strong {
  font-family: var(--font-serif);
  font-size: 0.95rem;
  font-weight: 600;
  color: #fff;
}

.dashboard-sidebar__brand-text small {
  font-family: var(--font-sans);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.6);
}

.collapsed .dashboard-sidebar__brand-text {
  display: none;
}

/* ── AQI / PM2.5 widget ─────────────────────────────────────────── */

.dashboard-sidebar__aqi {
  margin: 12px 16px;
  padding: 12px 14px;
  border-radius: 10px;
  background: #fff;
  border: 1px solid rgba(0,0,0,0.08);
  animation: aqi-fade-in 0.4s ease-out;
}

@keyframes aqi-fade-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.dashboard-sidebar__aqi-row {
  display: flex;
  align-items: center;
  gap: 12px;
}

.dashboard-sidebar__aqi-value {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  min-width: 40px;
  border-radius: 10px;
  font-size: 1rem;
  font-weight: 700;
  color: #fff;
  flex-shrink: 0;
  box-shadow: 0 2px 6px rgba(0,0,0,0.25);
}

.dashboard-sidebar__aqi-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.dashboard-sidebar__aqi-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  line-height: 1.2;
}

.dashboard-sidebar__aqi-detail {
  font-size: 0.72rem;
  color: rgba(30,27,75,0.55);
  line-height: 1.2;
  white-space: nowrap;
}

.dashboard-sidebar__aqi-location {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 0.68rem;
  color: rgba(30,27,75,0.4);
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(0,0,0,0.07);
}

.collapsed .dashboard-sidebar__aqi {
  margin: 8px;
  padding: 8px;
  text-align: center;
}

.collapsed .dashboard-sidebar__aqi-row {
  flex-direction: column;
  gap: 2px;
}

.collapsed .dashboard-sidebar__aqi-info,
.collapsed .dashboard-sidebar__aqi-location {
  display: none;
}

/* ── Compact AQI / on-premises badges with hover-to-expand cards ──── */

.dashboard-sidebar__widgets-row {
  display: flex;
  gap: 8px;
  margin: 12px 16px;
}

.dashboard-sidebar__widget {
  position: relative;
}

.dashboard-sidebar__widget-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  font-size: 1rem;
  font-weight: 700;
  box-shadow: 0 2px 6px rgba(0,0,0,0.25);
  cursor: default;
}

.dashboard-sidebar__widget-panel {
  position: absolute;
  top: 0;
  left: 0;
  width: 216px;
  z-index: 30;
  margin: 0;
  box-shadow: 0 10px 28px rgba(0,0,0,0.35);
  animation: none;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
  pointer-events: none;
}

.dashboard-sidebar__widget:hover .dashboard-sidebar__widget-panel,
.dashboard-sidebar__widget:focus-within .dashboard-sidebar__widget-panel,
.dashboard-sidebar__widget-panel.show {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
}

.collapsed .dashboard-sidebar__widgets-row {
  flex-direction: column;
  align-items: center;
  margin: 8px;
}

.collapsed .dashboard-sidebar__widget-panel {
  top: 0;
  left: 100%;
  margin-left: 8px;
}

/* ── Staff on-premises popover (fixed-position, escapes sidebar clipping) ── */

.onprem-popover {
  position: fixed;
  z-index: 9999;
  width: 280px;
  max-height: 360px;
  overflow-y: auto;
  background: #1e1b4b;
  color: #fff;
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0,0,0,0.35);
  padding: 12px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
  pointer-events: none;
  cursor: pointer;
}

.onprem-popover.show {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
}

/* Each popover matches its own widget's badge color instead of the
   shared indigo default — parents=red, visitors=yellow (with dark text,
   since white-on-yellow is unreadable). Staff keeps the base indigo. */
#parents-onprem-popover {
  background: #dc2626;
}

#visitors-onprem-popover {
  background: #eab308;
  color: #1e1b4b;
}

#visitors-onprem-popover .onprem-popover__count {
  background: rgba(30, 27, 75, 0.15);
}

#visitors-onprem-popover .onprem-popover__row {
  border-bottom-color: rgba(30, 27, 75, 0.12);
}

.onprem-popover__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 700;
  font-size: 0.95rem;
}

.onprem-popover__count {
  background: rgba(255,255,255,0.15);
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 0.8rem;
}

.onprem-popover__hint {
  font-size: 0.75rem;
  opacity: 0.7;
  margin: 4px 0 8px;
}

.onprem-popover__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.onprem-popover__row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.85rem;
  padding: 4px 0;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}

.onprem-popover__row:last-child {
  border-bottom: none;
}

.onprem-popover__name {
  font-weight: 600;
  flex: 1 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.onprem-popover__role {
  opacity: 0.75;
  flex: 0 0 auto;
  font-size: 0.75rem;
}

.onprem-popover__time {
  opacity: 0.6;
  flex: 0 0 auto;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.onprem-toast {
  position: fixed;
  bottom: 2rem;
  left: 50%;
  transform: translateX(-50%);
  background: var(--mis-accent, #1e1b4b);
  color: #fff;
  padding: 0.5rem 1.25rem;
  border-radius: 6px;
  font-size: 0.85rem;
  z-index: 10000;
  opacity: 0;
  transition: opacity 0.3s;
  pointer-events: none;
}

.onprem-toast.show {
  opacity: 1;
}

.dashboard-sidebar__toggle {
  position: absolute;
  top: 20px;
  right: -14px;
  width: 28px;
  height: 28px;
  background: var(--mis-navy, #1a2332);
  border: 2px solid rgba(255,255,255,0.2);
  border-radius: 50%;
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  z-index: 101;
}

.dashboard-sidebar__toggle:hover {
  background: var(--mis-accent);
  border-color: var(--mis-accent);
}

.dashboard-sidebar__nav {
  flex: 1;
  padding: 8px 0;
  overflow-y: auto;
  scroll-behavior: smooth;
}

/* ── Sidebar search input ── */
.dashboard-sidebar__search {
  display: flex;
  align-items: center;
  margin: 4px 12px 4px;
  padding: 0 8px;
  background: rgba(255,255,255,0.08);
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.12);
  transition: border-color 0.2s;
}

.dashboard-sidebar__search:focus-within {
  border-color: rgba(255,255,255,0.3);
  background: rgba(255,255,255,0.12);
}

.dashboard-sidebar__search .material-symbols-outlined {
  font-size: 18px;
  color: rgba(255,255,255,0.4);
  flex-shrink: 0;
}

.dashboard-sidebar__search input {
  background: none;
  border: none;
  outline: none;
  color: #fff;
  font-size: 0.85rem;
  padding: 7px 6px;
  width: 100%;
  font-family: inherit;
}

.dashboard-sidebar__search input::placeholder {
  color: rgba(255,255,255,0.35);
}

.collapsed .dashboard-sidebar__search {
  display: none;
}

/* Phone-only search drawer (rules in the 768px block below): the icon in the
   rail, and the close button that lives inside the search box itself. */
.dashboard-sidebar__search-open,
.dashboard-sidebar__search-close {
  display: none;
}

/* Flat-layout group heading (a role with no sidebar submenu overrides: parents,
   staff, students). The selector line for this block was lost in 76d5c6b when the
   search-filter rules were inserted above it, which left the declarations orphaned
   and the headings rendering as plain body text. */
.dashboard-sidebar__group-label {
  padding: 12px 16px 4px;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.4);
  margin-top: 4px;
}

.collapsed .dashboard-sidebar__group-label {
  display: none;
}

.dashboard-sidebar__link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 16px;
  color: rgba(255,255,255,0.75);
  text-decoration: none;
  font-size: 0.88rem;
  font-weight: 500;
  transition: background 0.15s, color 0.15s;
  border-radius: 0;
}

.dashboard-sidebar__link:hover {
  background: rgba(255,255,255,0.08);
  color: #fff;
}

.dashboard-sidebar__link.active {
  background: rgba(255,255,255,0.12);
  color: #fff;
  border-right: 3px solid var(--mis-gold, #d4a843);
}

.dashboard-sidebar__link .material-symbols-outlined {
  font-size: 20px;
  flex-shrink: 0;
}

.collapsed .dashboard-sidebar__link span:not(.material-symbols-outlined) {
  display: none;
}

/* ── Collapsible sidebar sections (<details>/<summary>) ── */
.dashboard-sidebar__section {
  margin: 0;
  padding: 0;
}

.dashboard-sidebar__section-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px 4px;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.4);
  cursor: pointer;
  user-select: none;
  list-style: none;              /* remove default marker */
  margin-top: 4px;
}

.dashboard-sidebar__section-label::-webkit-details-marker {
  display: none;
}

/* Chevron indicator */
.dashboard-sidebar__section-label::after {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  border-right: 1.5px solid rgba(255,255,255,0.35);
  border-bottom: 1.5px solid rgba(255,255,255,0.35);
  transform: rotate(-45deg);
  transition: transform 0.2s ease;
  margin-left: 8px;
  flex-shrink: 0;
}

.dashboard-sidebar__section[open] > .dashboard-sidebar__section-label::after {
  transform: rotate(45deg);
}

/* Submenu label (smaller, muted heading within a collapsible section) */
.dashboard-sidebar__submenu-label {
  padding: 8px 16px 2px;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.3);
}

/* Sub-items get a small left indent */
.dashboard-sidebar__link--sub {
  padding-left: 28px;
}

/* Collapsed sidebar: hide section labels, submenu labels, chevrons */
.collapsed .dashboard-sidebar__section-label {
  display: none;
}

.collapsed .dashboard-sidebar__submenu-label {
  display: none;
}

.collapsed .dashboard-sidebar__section {
  /* In collapsed mode, treat sections as flat — all items visible */
}

/* Force <details> to render as open block when sidebar is collapsed */
.collapsed details.dashboard-sidebar__section {
  display: block;
}

.collapsed details.dashboard-sidebar__section > summary {
  display: none;
}

.collapsed details.dashboard-sidebar__section > :not(summary) {
  display: block;
}

.collapsed .dashboard-sidebar__link--sub {
  padding-left: 16px;
}

.dashboard-sidebar__footer {
  padding: 12px 16px;
  border-top: 1px solid rgba(255,255,255,0.1);
  font-size: 0.8rem;
  color: rgba(255,255,255,0.5);
}

.collapsed .dashboard-sidebar__footer .dashboard-sidebar__footer-email {
  display: none;
}

/* Main content area */
.dashboard-content {
  flex: 1;
  min-width: 0;
  margin-left: 260px;
  padding: 0;
  transition: margin-left 0.2s ease;
  min-height: 100vh;
  background: var(--mis-cream, #faf7f2);
  /* Without this, a page whose content is wider than the viewport (a wide
     table with no .table-scroll wrapper, a long unbroken string, etc.)
     overflows past .dashboard-content's own box and becomes page-level
     horizontal scroll instead of staying contained here. Since
     .dashboard-sidebar is position:fixed (not part of this flex layout,
     so it never scrolls with the page), any such page-level scroll then
     visually hides that overflowing content underneath the sidebar
     instead of the sidebar scrolling out of the way with it — the
     "content is cut off behind the sidebar" bug. This clips overflow
     here instead, so any inner overflow-x:auto/.table-scroll wrapper
     becomes the only thing that actually scrolls, as intended.
     Deliberately `clip`, not `hidden`: `hidden` forces the UA to compute
     overflow-y as `auto` too (you can't set only one axis to a
     non-visible value per the CSS Overflow spec), which turns
     .dashboard-content into an actual scroll container — but it never
     itself scrolls (it grows with its content), so any position:sticky
     descendant (e.g. hr/hiring.php's sticky action bar) stops sticking,
     because sticky positioning resolves against the nearest scrolling
     ancestor, which would then be the wrong element. `clip` contains
     overflow the same way without creating a scroll container, so
     sticky descendants keep working. Trade-off: on the ~77 pages still
     missing a .table-scroll wrapper (see CLAUDE.md's Mobile-friendliness
     section), wide unwrapped content is now unreachable rather than
     reachable via page-level scroll under the sidebar — accepted until
     that retrofit happens. */
  overflow-x: clip;
}

.dashboard-content.expanded {
  margin-left: 64px;
}

/* Reserves space for #emergency-dock-column (the guru_admin-only docked
   emergency panel — see renderDashboardSidebar()/renderEmergencyBanner()
   in src/helpers.php and public/emergency-procedures/banner.js) while an
   emergency is active, so the fixed-position aside doesn't overlap page
   content. Toggled by banner.js's showBanner()/hideBanner() alongside the
   aside's own visibility — replaces the old per-page inline
   `style="margin-right:360px;"` that public/emergency-procedures/index.php
   used to compute at PHP render time. */
.dashboard-content.has-emergency-dock {
  margin-right: 360px;
}

.dashboard-content__header {
  background: #fff;
  border-bottom: 1px solid var(--mis-rule-soft);
  padding: 16px 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.dashboard-content__header h1 {
  font-family: var(--font-serif);
  font-size: 1.4rem;
  color: var(--mis-navy);
  margin: 0;
}

.dashboard-content__body {
  padding: 24px 32px;
}

/* Module cards for overview/dashboard pages */
.module-card {
  background: #fff;
  border: 1px solid var(--mis-rule-soft);
  border-radius: 12px;
  padding: 20px;
  transition: box-shadow 0.15s;
}

.module-card:hover {
  box-shadow: var(--mis-shadow-soft);
}

.module-card h3 {
  font-family: var(--font-serif);
  font-size: 1.1rem;
  margin: 0 0 8px;
  color: var(--mis-navy);
}

.module-card p {
  color: var(--mis-ink-muted);
  font-size: 0.88rem;
  margin: 0 0 12px;
}

/* Stat cards for dashboard overviews */
.stat-card {
  background: #fff;
  border: 1px solid var(--mis-rule-soft);
  border-radius: 12px;
  padding: 20px;
  text-align: center;
}

.stat-card__value {
  font-family: var(--font-serif);
  font-size: 2rem;
  font-weight: 700;
  color: var(--mis-navy);
  line-height: 1;
  margin-bottom: 4px;
}

.stat-card__label {
  font-size: 0.8rem;
  color: var(--mis-ink-muted);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Clickable stat cards on HR overview */
a.stat-card--link {
  text-decoration: none;
  color: inherit;
  transition: box-shadow 0.15s, transform 0.15s;
  cursor: pointer;
}
a.stat-card--link:hover {
  box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  transform: translateY(-2px);
}

/* Dashboard grid */
.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.dashboard-grid--stats {
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
}

/* Section header within dashboard content */
.section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

.section-header h2 {
  font-family: var(--font-serif);
  font-size: 1.15rem;
  color: var(--mis-navy);
  margin: 0;
}

/* Responsive dashboard */
@media (max-width: 768px) {
  .dashboard-sidebar {
    width: 64px;
  }
  /* The rail is icon-only on a phone, so every heading goes: the group headings
     ("My Office", "HR", "My Children") and the section headings with their
     chevrons would otherwise wrap into the 64px column. The search box goes too —
     a text input in a 64px rail is unusable — and the phone-only shortcut grid on
     the dashboards (see .home-quick) is the way to reach a module by name.
     The bell's label goes but its unread count stays, and the links carry
     aria-label so an icon-only link still has an accessible name.
     The search box is not dropped any more (Henko, 2026-10-26): the rail shows
     a search icon instead, and tapping it opens the sidebar at the full width
     of the phone with the box across it — see .search-open below. */
  .dashboard-sidebar__brand-text,
  .dashboard-sidebar__group-label,
  .dashboard-sidebar__section-label,
  .dashboard-sidebar__submenu-label,
  .dashboard-sidebar__link span:not(.material-symbols-outlined),
  .dashboard-sidebar__bell > span:not(.material-symbols-outlined):not(.dashboard-sidebar__bell-count),
  .dashboard-sidebar__footer-email {
    display: none;
  }
  /* The header holds nothing but the brand lockup, and that lockup now sits in the
     phone search bar at the top of the page content (see .mobile-search__brand) —
     two identical marks 70px apart read as a mistake. The whole header goes, not
     just the mark, so no empty bordered band is left at the top of the rail. */
  .dashboard-sidebar__header {
    display: none;
  }
  .dashboard-sidebar__search {
    display: none;
  }

  /* ── Phone search drawer ──────────────────────────────────────────────
     The search icon sits in the rail where the other icons are; pressing it
     puts .search-open on the sidebar, which stretches the sidebar across the
     whole phone width, shows the text input full width, and brings the link
     labels back so the filtered results are readable. Closing (×, Escape on
     an empty box, tapping outside, or choosing a result) puts the rail back. */
  .dashboard-sidebar__search-open {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin: 6px auto 2px;
    padding: 0;
    background: rgba(255,255,255,0.08);
    border: 1px solid rgba(255,255,255,0.12);
    border-radius: 8px;
    color: rgba(255,255,255,0.75);
    cursor: pointer;
  }
  .dashboard-sidebar__search-open:active {
    background: rgba(255,255,255,0.16);
  }
  .dashboard-sidebar.search-open {
    width: 100%;
    max-width: 100%;
    z-index: 1000;
    box-shadow: 0 0 0 100vmax rgba(0,0,0,0.35);
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__search-open {
    display: none;
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__search {
    display: flex;
    position: relative;
    margin: 10px 12px;
    padding: 0 6px 0 10px;
    min-height: 46px;
    background: #fff;
    border-color: #fff;
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__search .material-symbols-outlined {
    color: rgba(26,35,50,0.55);
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__search input {
    flex: 1;
    min-width: 0;
    width: auto;
    padding-right: 44px;
    color: var(--mis-navy, #1a2332);
    font-size: 1rem;
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__search input::placeholder {
    color: rgba(26,35,50,0.45);
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__search-close {
    display: flex;
    position: absolute;
    top: 50%;
    right: 4px;
    transform: translateY(-50%);
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: none;
    border: none;
    border-radius: 6px;
    color: rgba(26,35,50,0.6);
    font-size: 1.4rem;
    line-height: 1;
    cursor: pointer;
  }
  /* While searching, the labels come back — a list of bare icons is not a
     search result list. Left-aligned rows, one tap target per result. */
  .dashboard-sidebar.search-open .dashboard-sidebar__link,
  .dashboard-sidebar.search-open .dashboard-sidebar__link--sub {
    justify-content: flex-start;
    padding: 10px 16px;
    gap: 12px;
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__link span:not(.material-symbols-outlined),
  .dashboard-sidebar.search-open .dashboard-sidebar__group-label,
  .dashboard-sidebar.search-open .dashboard-sidebar__submenu-label {
    display: block;
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__nav details.dashboard-sidebar__section > summary {
    display: none;
  }
  .dashboard-sidebar.search-open .dashboard-sidebar__widgets-row,
  .dashboard-sidebar.search-open .dashboard-sidebar__aqi,
  .dashboard-sidebar.search-open .dashboard-sidebar__footer,
  .dashboard-sidebar.search-open .dashboard-sidebar__header {
    display: none;
  }
  /* Sections render flat: the summary (the heading and its chevron) is the only part
     that goes, the links stay put. These rules are styling only — they cannot reveal
     a CLOSED <details>, because a closed section keeps its content unreachable
     whatever `display` says (tried: display:block on the details and on its children,
     and content-visibility:visible — all three still render an empty rail in Chrome).
     So the sidebar script is what opens every section at this width; these rules just
     make an already-open section look right. */
  .dashboard-sidebar__nav details.dashboard-sidebar__section > summary { display: none; }
  /* With the headings gone, a hairline between sections is what still reads as
     "these icons are one group". Two layouts need it: the collapsible one
     (<details> sections, guru_admin and the admin roles) and the flat one
     (div.dashboard-sidebar__group-label + links, parents / staff / students), where
     the label itself is display:none so the line has to hang off the link after it —
     every group's first link except the nav's own first group. */
  .dashboard-sidebar__nav .dashboard-sidebar__section + .dashboard-sidebar__section,
  .dashboard-sidebar__nav > .dashboard-sidebar__group-label:not(:first-child) + .dashboard-sidebar__link {
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid rgba(255,255,255,0.12);
  }
  /* The icon is the only tap target here: 44px minimum, centred in the rail. The
     sub-items lose their 28px indent — there is nothing left to indent under. */
  .dashboard-sidebar__link,
  .dashboard-sidebar__link--sub {
    justify-content: center;
    padding: 10px 0;
    min-height: 44px;
  }
  .dashboard-sidebar__bell {
    justify-content: center;
    padding: 10px 0;
    min-height: 44px;
  }
  .dashboard-content {
    margin-left: 64px;
  }
  .dashboard-content__body {
    padding: 16px;
  }

  /* AQI / on-premises badges: the rail is only 64px wide, so a row of
     40px badges cannot fit — stack them in a column, like .collapsed does. */
  .dashboard-sidebar__widgets-row {
    flex-direction: column;
    align-items: center;
    margin: 8px;
  }
  /* Their popups open to the right of the rail, fixed to the viewport and
     above everything (an absolute panel inside the 64px rail is clipped and
     sits under the page). The on-premises popovers get their top from JS. */
  .dashboard-sidebar__widget-panel {
    position: fixed;
    left: 72px;
    top: 8px;
    margin: 0;
    width: min(240px, calc(100vw - 84px));
    z-index: 10002;
  }
  .onprem-popover {
    left: 72px !important;
    width: min(280px, calc(100vw - 84px));
    z-index: 10002;
  }
}

/* Phone menu search: the rail is icon-only, so the search lives as a full-width bar
   at the top of the page content (inserted by the sidebar script in helpers.php). */
.mobile-search { display: none; }
@media (max-width: 768px) {
  .mobile-search {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    position: sticky;
    top: 0;
    /* Below the sidebar's own z-index: 100, deliberately. The sidebar is a fixed
       stacking context, so everything inside it — including the AQI/on-premises
       popups that go position:fixed at this width — is capped at 100, whatever its
       own z-index says. A bar at 900 therefore painted over an open AQI popup and
       hid its top (reported by Henko, 2026-10-26). 90 keeps the bar above ordinary
       page content (any positioned z-index beats static content) while leaving the
       rail and its popups in front. Modals and menus (1000+) still cover both. */
    z-index: 90;
    padding: 8px 12px;
    background: #fff;
    border-bottom: 1px solid var(--mis-rule-soft);
  }
  .mobile-search__brand {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    height: 44px;
  }
  .mobile-search__brand img {
    display: block;
    height: 32px;
    width: auto;
  }
  .mobile-search__field {
    flex: 1 1 150px;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 12px;
    background: var(--mis-cream, #faf7f2);
    border: 1px solid var(--mis-rule-soft);
    border-radius: 999px;
  }
  .mobile-search__field:focus-within { border-color: var(--mis-navy); }
  .mobile-search__field .material-symbols-outlined { font-size: 20px; color: var(--mis-navy); flex-shrink: 0; }
  .mobile-search__field input {
    flex: 1;
    min-width: 0;
    min-height: 44px;
    border: none;
    outline: none;
    background: none;
    font: inherit;
    font-size: 1rem;
    color: inherit;
  }
  .mobile-search__results {
    flex: 1 1 100%;
    display: none;
    margin-top: 6px;
    max-height: 60vh;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--mis-rule-soft);
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0,0,0,0.12);
  }
  .mobile-search__results.show { display: block; }
  .mobile-search__results a {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    padding: 8px 14px;
    color: var(--mis-navy);
    text-decoration: none;
    border-bottom: 1px solid var(--mis-rule-soft);
  }
  .mobile-search__results a:last-child { border-bottom: none; }
  .mobile-search__empty { padding: 12px 14px; color: #6b7280; }
}

/* --- Notifications --- */
.dashboard-sidebar__bell {
  display: flex;
  align-items: center;
  gap: 8px;
  color: rgba(255,255,255,0.85);
  text-decoration: none;
  font-size: 0.85rem;
  padding: 8px 0;
}
.dashboard-sidebar__bell .material-symbols-outlined { font-size: 1.1rem; }
.dashboard-sidebar__bell-count {
  background: var(--mis-clay);
  color: #fff;
  border-radius: 999px;
  font-size: 0.7rem;
  padding: 1px 7px;
  font-weight: 700;
}

.notif-list { display: flex; flex-direction: column; gap: 10px; }
.notif-item {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  padding: 14px 16px;
  border: 1px solid var(--mis-rule-soft);
  border-radius: 8px;
  background: var(--mis-surface);
}
.notif-item--unread { border-left: 3px solid var(--mis-accent); background: var(--mis-wash); }
.notif-item__body p { margin: 4px 0 0; color: var(--mis-ink-muted); font-size: 0.85rem; }
.notif-item__meta { display: block; margin-top: 6px; font-size: 0.75rem; color: var(--mis-ink-muted); }
.notif-item__actions { display: flex; gap: 8px; flex-shrink: 0; }

/* --- Company Hub --- */
.announcement-card {
  border: 1px solid var(--mis-rule-soft);
  border-radius: 10px;
  padding: 18px 20px;
  margin-bottom: 16px;
  background: var(--mis-surface);
}
.announcement-card--pinned { border-left: 4px solid var(--mis-gold); }
.announcement-card h3 { margin: 0 0 4px; color: var(--mis-navy); }
.announcement-card__meta { font-size: 0.78rem; color: var(--mis-ink-muted); margin: 4px 0 12px; }
.comment-list {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--mis-rule-soft);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.comment-item { font-size: 0.85rem; }
.comment-item strong { color: var(--mis-navy); }

/* --- Simple CSS bar charts (no charting library) --- */
.bar-list { display: flex; flex-direction: column; gap: 10px; }
.bar-row { display: grid; grid-template-columns: 140px 1fr 32px; align-items: center; gap: 10px; font-size: 0.85rem; }
.bar-row__label { color: var(--mis-ink-muted); }
.bar-row__track { background: var(--mis-rule-soft); border-radius: 999px; height: 8px; overflow: hidden; }
.bar-row__fill { display: block; height: 100%; background: var(--mis-accent); border-radius: 999px; }
.bar-row__value { text-align: right; font-weight: 600; color: var(--mis-navy); }

/* --- Guru-admin portal home --- */
.portal-greeting { margin-bottom: 24px; }
.portal-greeting h1 { margin: 0 0 4px; font-size: 1.6rem; color: var(--mis-navy); }
.portal-greeting p { margin: 0; color: var(--mis-ink-muted); font-size: 0.9rem; }

/* --- Welcome card (universal dashboard landing page) --- */
.welcome-card {
  background: var(--mis-surface);
  border: 1px solid var(--mis-rule-soft);
  border-top: 3px solid var(--mis-gold);
  border-radius: 12px;
  padding: 24px 28px;
  margin-bottom: 28px;
  box-shadow: var(--mis-shadow-soft);
}
.welcome-card__header h1 { margin: 0 0 4px; font-size: 1.6rem; color: var(--mis-navy); }
.welcome-card__header p { margin: 0; color: var(--mis-ink-muted); font-size: 0.9rem; }

.welcome-card__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid var(--mis-rule-soft);
}

.welcome-card__panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.welcome-card__panel-header h3 {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-family: var(--font-serif);
  font-size: 1rem;
  color: var(--mis-navy);
}
.welcome-card__panel-header h3 .material-symbols-outlined { color: var(--mis-accent); font-size: 1.2rem; }
.welcome-card__panel-header a { font-size: 0.8rem; color: var(--mis-accent-ink); text-decoration: none; font-weight: 600; }
.welcome-card__panel-header a:hover { text-decoration: underline; }

.welcome-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.welcome-list__item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--mis-rule-soft);
  border-radius: 8px;
  background: var(--mis-wash);
}
.welcome-list__item--task { align-items: center; }
.welcome-list__icon { color: var(--mis-accent); font-size: 1.15rem; flex-shrink: 0; margin-top: 1px; }
.welcome-list__item--task .welcome-list__icon { color: var(--mis-ink-muted); }
.welcome-list__body { flex: 1; min-width: 0; }
.welcome-list__title { display: block; font-size: 0.88rem; font-weight: 600; color: var(--mis-ink); text-decoration: none; }
a.welcome-list__title:hover { color: var(--mis-accent-ink); text-decoration: underline; }
.welcome-list__title--done { text-decoration: line-through; color: var(--mis-ink-muted); font-weight: 500; }
.welcome-list__meta { margin: 3px 0 0; font-size: 0.8rem; color: var(--mis-ink-muted); }

.welcome-empty {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px;
  border-radius: 8px;
  background: var(--mis-wash);
  color: var(--mis-ink-muted);
  font-size: 0.85rem;
}
.welcome-empty .material-symbols-outlined { color: #1f7a3d; font-size: 1.1rem; }

.news-carousel { position: relative; min-height: 56px; overflow: hidden; }
.news-carousel__slide {
  position: absolute;
  top: 0; left: 0; width: 100%;
  display: flex; align-items: center; gap: 10px;
  opacity: 0;
  transform: translateX(-100%);
  transition: transform 0.5s ease, opacity 0.5s ease;
  pointer-events: none;
}
.news-carousel__slide--active {
  position: relative;
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}
.news-carousel__slide--exiting {
  opacity: 0;
  transform: translateX(100%);
}
.news-carousel__icon { color: var(--mis-accent); flex-shrink: 0; }
.news-carousel__text { flex: 1; margin: 0; font-size: 0.9rem; }
.news-carousel__dismiss {
  flex-shrink: 0;
  display: inline-flex; align-items: center; gap: 4px;
  background: none;
  border: 1px solid var(--mis-rule-soft);
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 0.8rem;
  color: var(--mis-ink-muted);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.news-carousel__dismiss:hover { background: var(--mis-wash); color: var(--mis-accent-ink); }
.news-carousel__dismiss .material-symbols-outlined { font-size: 1rem; }
.news-carousel__dots { display: flex; gap: 6px; justify-content: center; margin-top: 10px; }
.news-carousel__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--mis-rule-soft); transition: background 0.3s; }
.news-carousel__dot--active { background: var(--mis-accent); }

.badge--done { background: #e3f2e6; color: #1f7a3d; }
.badge--in_progress { background: #fef3c7; color: #b45309; }
.badge--arranged { background: #ede9fe; color: #6d28d9; }
.badge--confirmed { background: #d1fae5; color: #065f46; }
.badge--cancelled { background: #fee2e2; color: #991b1b; }
.badge--on_hold { background: #fef3c7; color: #92400e; }
.badge--postponed { background: #e0e7ff; color: #3730a3; }

.action-feed { display: flex; flex-direction: column; gap: 8px; margin-bottom: 28px; }
.action-feed__item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  border: 1px solid var(--mis-rule-soft);
  border-radius: 8px;
  background: var(--mis-surface);
  text-decoration: none;
  color: var(--mis-ink);
  transition: box-shadow 0.15s ease;
}
.action-feed__item:hover { box-shadow: var(--mis-shadow-soft); }
.action-feed__item .material-symbols-outlined { color: var(--mis-accent); }
.action-feed__label { flex: 1; font-size: 0.92rem; }
.action-feed__count {
  background: var(--mis-clay);
  color: #fff;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  padding: 2px 10px;
}
.action-feed__empty {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px;
  margin-bottom: 28px;
  background: var(--mis-wash);
  border-radius: 8px;
  color: var(--mis-accent-ink);
}

.glance-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 16px; margin-bottom: 28px; }
.glance-card { border: 1px solid var(--mis-rule-soft); border-radius: 10px; padding: 16px; background: var(--mis-surface); text-align: center; }

.pulse-widget { border: 1px solid var(--mis-rule-soft); border-radius: 10px; padding: 18px 20px; background: var(--mis-surface); margin-bottom: 28px; }

.module-tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin-bottom: 28px; }
.module-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 14px 10px;
  border: 1px solid var(--mis-rule-soft);
  border-radius: 8px;
  background: var(--mis-surface);
  text-decoration: none;
  color: var(--mis-ink);
  font-size: 0.8rem;
  text-align: center;
}
.module-tile:hover { box-shadow: var(--mis-shadow-soft); }
.module-tile .material-symbols-outlined { color: var(--mis-accent); font-size: 1.3rem; }

.module-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 18px; margin-bottom: 28px; align-items: start; }
.module-group-card {
  background: var(--mis-surface);
  border: 1px solid var(--mis-rule-soft);
  border-radius: 12px;
  padding: 20px 24px;
}
.module-group-card__title {
  margin: 0 0 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--mis-rule-soft);
  font-family: var(--font-serif);
  font-size: 1rem;
  color: var(--mis-navy);
}
.module-group-card .module-tile-grid { margin-bottom: 0; }

.kb-highlight-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.kb-highlight-list li { display: flex; justify-content: space-between; padding: 10px 14px; border: 1px solid var(--mis-rule-soft); border-radius: 8px; }
.kb-highlight-list a { color: var(--mis-accent-ink); text-decoration: none; font-weight: 600; }
.kb-highlight-list span { color: var(--mis-ink-muted); font-size: 0.78rem; }

.sortable-table-th { cursor: pointer; user-select: none; white-space: nowrap; }
.sortable-table-th:hover { color: var(--mis-accent); }
.sortable-table-arrow { font-size: 0.75em; opacity: 0.4; margin-left: 4px; }
.sortable-table-arrow.active { opacity: 1; }

/* --- AQI alert banner — full-width, fixed at viewport top, above sidebar --- */
.aqi-alert-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10001;
  border-bottom: 3px solid;
  font-family: var(--font-sans, system-ui, sans-serif);
}
.aqi-alert-banner--warning {
  background: #fff3e0;
  border-color: #ff9933;
  color: #7c4700;
}
.aqi-alert-banner--critical {
  background: #fce4ec;
  border-color: #7e0023;
  color: #7e0023;
}
.aqi-alert-banner__inner {
  display: flex;
  align-items: center;
  gap: 14px;
  max-width: 1200px;
  margin: 0 auto;
  padding: 12px 24px;
}
.aqi-alert-banner__icon {
  font-size: 1.8rem;
  flex-shrink: 0;
  line-height: 1;
}
.aqi-alert-banner__content {
  flex: 1;
  min-width: 0;
}
.aqi-alert-banner__content strong {
  display: block;
  font-size: 1rem;
  line-height: 1.3;
}
.aqi-alert-banner__content p {
  margin: 4px 0 0;
  font-size: 0.85rem;
  opacity: 0.85;
  line-height: 1.4;
}
.aqi-alert-banner__aqi {
  flex-shrink: 0;
  font-size: 0.82rem;
  font-weight: 600;
  white-space: nowrap;
  text-align: right;
}
/* Push sidebar and content below the banner when present */
body:has(.aqi-alert-banner) {
  --aqi-banner-offset: var(--aqi-banner-height, 0px);
  padding-top: var(--aqi-banner-offset);
}
body:has(.aqi-alert-banner) .dashboard-sidebar {
  top: var(--aqi-banner-offset);
}
/* Impersonation banner pushes everything further down */
body:has(.impersonation-banner) {
  --impersonation-offset: var(--impersonation-banner-height, 0px);
  padding-top: calc(var(--impersonation-offset, 0px) + var(--aqi-banner-offset, 0px));
}
body:has(.impersonation-banner) .dashboard-sidebar {
  top: calc(var(--impersonation-offset, 0px) + var(--aqi-banner-offset, 0px));
}
body:has(.impersonation-banner) .aqi-alert-banner {
  top: var(--impersonation-offset, 0px);
}
/* Responsive: stack vertically on small screens */
@media (max-width: 640px) {
  .aqi-alert-banner__inner {
    flex-direction: column;
    gap: 8px;
    text-align: center;
    padding: 10px 16px;
  }
  .aqi-alert-banner__icon {
    font-size: 1.5rem;
  }
  .aqi-alert-banner__aqi {
    text-align: center;
  }
}

/* Never printed — an internal "You are impersonating X" control has no
   place in a printed page or a saved PDF, on this page or any other. */
@media print {
  .impersonation-banner {
    display: none !important;
  }
}

/* ── Impersonation exit banner ────────────────────────────────────────────── */
.impersonation-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000002; /* above everything, incl. the emergency banner (99998) and lockdown overlay (999999), so Exit Impersonation is always reachable */
  background: #1a2233;
  color: #fff;
  font-size: 0.875rem;
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
.impersonation-banner__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  max-width: 1200px;
  margin: 0 auto;
  padding: 10px 24px;
}
.impersonation-banner__icon {
  font-size: 1.25rem;
  color: #fbbf24; /* amber warning color */
}
.impersonation-banner__text {
  font-size: 0.9rem;
  line-height: 1.4;
}
.impersonation-banner__text strong {
  color: #fbbf24;
}
.impersonation-banner__form {
  margin: 0;
  padding: 0;
}
.impersonation-banner__exit {
  background: #dc2626;
  color: #fff;
  border: none;
  border-radius: 4px;
  padding: 5px 14px;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s;
}
.impersonation-banner__exit:hover {
  background: #b91c1c;
}
.impersonation-banner__exit:focus {
  outline: 2px solid #fbbf24;
  outline-offset: 2px;
}

/* Responsive: stack on small screens */
@media (max-width: 640px) {
  .impersonation-banner__inner {
    flex-direction: column;
    gap: 8px;
    text-align: center;
    padding: 10px 16px;
  }
}

/* Prominent parent-facing call-to-action banner (e.g. "Order Meals") on
   the main dashboard — reuses the hero section's navy+gold gradient
   treatment for visual consistency with the rest of the site. */
.dashboard-cta {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap;
  background-image:
    radial-gradient(120% 130% at 100% 0px, rgba(234, 183, 42, 0.14) 0px, rgba(234, 183, 42, 0) 45%),
    linear-gradient(162deg, #243a73, #1a2a57 50%, #111d40);
  color: #f6f7f9; border-radius: 16px; padding: 1.75rem 2rem; margin-bottom: 1.5rem;
}
.dashboard-cta__icon { font-size: 2.75rem; flex-shrink: 0; }
.dashboard-cta__text { flex: 1; min-width: 200px; }
.dashboard-cta__text h3 { margin: 0 0 0.25rem; font-size: 1.35rem; color: #fff; }
.dashboard-cta__text p { margin: 0; color: rgba(255,255,255,0.85); }
.dashboard-cta .btn--primary { background: #fff; color: var(--mis-accent); white-space: nowrap; }
.dashboard-cta .btn--primary:hover { background: rgba(255,255,255,0.9); }

/* --- Payroll runs: list cards, Runway strip, tabs, banner, stage log --- */
.payroll-run-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.payroll-run-card { display: block; text-decoration: none; color: inherit; }
.payroll-run-card:hover { border-color: var(--mis-accent); }
.payroll-run-card__top { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 6px; }
.payroll-run-card__meta { font-size: 0.85rem; color: var(--mis-ink-muted); margin-bottom: 2px; }
.payroll-run-card__next { margin-top: 10px; font-size: 0.85rem; font-weight: 600; color: var(--mis-accent); }

/* Roles & controls: named staff chips (name + × to remove) beside each duty's role picker */
.payroll-actor-users { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; min-height: 4px; }
.payroll-actor-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 6px 3px 10px;
  border: 1px solid #d8dce6; border-radius: 999px; background: #f4f6fb; font-size: 0.85rem;
}
.payroll-actor-chip__x {
  border: 0; background: none; cursor: pointer; font-size: 1.05rem; line-height: 1;
  padding: 0 3px; color: var(--mis-ink-muted);
}
.payroll-actor-chip__x:hover, .payroll-actor-chip__x:focus-visible { color: #b42318; }

.badge--payroll-planning, .badge--payroll-returned { background: #e8e8e8; color: #555; }
.badge--payroll-collecting, .badge--payroll-calculating, .badge--payroll-in_review,
.badge--payroll-submitted, .badge--payroll-paying, .badge--payroll-closing { background: #fdf3d8; color: var(--mis-gold-ink); }
.badge--payroll-approved, .badge--payroll-paid, .badge--payroll-closed { background: #e3f2e6; color: #1f7a3d; }

.payroll-banner {
  background: var(--mis-clay-soft); color: var(--mis-clay-ink);
  border-radius: 8px; padding: 10px 14px; margin-bottom: 16px; font-size: 0.9rem; font-weight: 600;
}

.payroll-runway__caption { color: var(--mis-ink-muted); font-size: 0.85rem; margin: 0 0 8px; }
.payroll-runway {
  /* The eight runway cards share the whole page width (Henko, 2026-10-29), so each is wide and short instead of
     a narrow tall strip. On a tablet they wrap to two rows of four; on a phone the old sideways-scrolling row
     returns, with its scrollbar hidden (a bar drawn across the card row read as clutter, 2026-10-21). */
  display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 10px;
  padding-bottom: 8px; margin-bottom: 20px;
}
.payroll-stop {
  min-width: 0; display: flex; flex-direction: column; gap: 3px;
  padding: 12px; border: 1px solid var(--mis-rule-soft); border-radius: 10px; background: #fff;
  text-decoration: none; color: inherit; font-size: 0.8rem; min-height: 44px; overflow-wrap: anywhere;
}
/* Sized by the strip's own available width (the sidebar eats ~260px of the viewport, so a viewport breakpoint
   would misjudge it): eight across when each card keeps ~128px, two rows of four below that, a scrolling row
   on a phone. */
.payroll-runway-wrap { container-type: inline-size; }
@container (max-width: 1099px) {
  .payroll-runway { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@container (max-width: 639px) {
  .payroll-runway {
    display: flex; overflow-x: auto; -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity;
    scrollbar-width: none; -ms-overflow-style: none;
  }
  .payroll-runway::-webkit-scrollbar { width: 0; height: 0; display: none; }
  .payroll-stop { flex: 0 0 150px; scroll-snap-align: start; }
}
.payroll-stop:hover { border-color: var(--mis-accent); }
.payroll-stop__dot {
  width: 24px; height: 24px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  background: var(--mis-accent-soft); color: var(--mis-accent-ink); font-weight: 700; font-size: 0.75rem;
}
.payroll-stop__label { font-weight: 600; line-height: 1.25; }
.payroll-stop__date, .payroll-stop__owner { color: var(--mis-ink-muted); }
.payroll-stop__state { font-weight: 600; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; }
.payroll-stop--done { background: #f3faf4; border-color: #b9dfc1; }
.payroll-stop--done .payroll-stop__dot { background: #1f7a3d; color: #fff; }
.payroll-stop--done .payroll-stop__state { color: #1f7a3d; }
.payroll-stop--due { border-color: var(--mis-gold-ink); }
.payroll-stop--due .payroll-stop__state { color: var(--mis-gold-ink); }
.payroll-stop--overdue { background: var(--mis-clay-soft); border-color: var(--mis-clay); animation: payroll-pulse 1.8s ease-in-out infinite; }
.payroll-stop--overdue .payroll-stop__dot { background: var(--mis-clay); color: #fff; }
.payroll-stop--overdue .payroll-stop__state { color: var(--mis-clay-ink); }
@keyframes payroll-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(191, 40, 39, 0.35); }
  50% { box-shadow: 0 0 0 6px rgba(191, 40, 39, 0); }
}
@media (prefers-reduced-motion: reduce) { .payroll-stop--overdue { animation: none; } }
/* Waiting on an earlier month to close (steps 8-11): not this step's fault, so it neither pulses nor reads as overdue. */
.payroll-stop--blocked { background: #f4f5f7; border-color: #c4c8cf; border-style: dashed; }
.payroll-stop--blocked .payroll-stop__dot { background: #767c86; color: #fff; }
.payroll-stop--blocked .payroll-stop__state { color: #5b6270; }

.payroll-tabs { display: flex; gap: 4px; overflow-x: auto; border-bottom: 1px solid var(--mis-rule-soft); margin-bottom: 20px; }
.payroll-tabs__tab {
  padding: 10px 16px; text-decoration: none; color: var(--mis-ink-muted); font-weight: 600;
  border-bottom: 2px solid transparent; white-space: nowrap; min-height: 44px; box-sizing: border-box;
}
.payroll-tabs__tab.is-active { color: var(--mis-accent); border-bottom-color: var(--mis-accent); }
/* A tab worked by another payroll duty: still listed so the section is discoverable, faded so it
   reads as "not yours", and its page explains whose job it is instead of showing the content. */
.payroll-tabs__tab.is-locked { opacity: 0.55; }
.payroll-tabs__tab.is-locked.is-active { opacity: 1; color: var(--mis-ink-muted); border-bottom-color: var(--mis-rule-soft); }
.payroll-blocked { border-left: 4px solid var(--mis-accent); }
.payroll-blocked h2 { color: var(--mis-ink); }

.payroll-log { list-style: none; padding: 0; margin: 0; }
.payroll-log li { padding: 10px 0; border-bottom: 1px solid var(--mis-rule-soft); font-size: 0.9rem; }
.payroll-log li:last-child { border-bottom: none; }
.payroll-log__from, .payroll-log__meta { color: var(--mis-ink-muted); font-size: 0.82rem; margin-left: 6px; }
.payroll-log__note { margin-top: 4px; color: var(--mis-ink-soft); }

/* --- Payroll pay master (Task 2) --- */
.alert--success { background: #e3f2e6; color: #1f7a3d; }
.payroll-banner--soft { background: #fdf3d8; color: var(--mis-gold-ink); }
.chip { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 0.72rem; font-weight: 600; background: #e8e8e8; color: #555; margin: 1px 2px 1px 0; }
.chip--warn { background: #fdf3d8; color: var(--mis-gold-ink); }
.chip--ok { background: #e3f2e6; color: #1f7a3d; }
/* Destructive action button (offboard, delete, exit-impersonation). Referenced
   across several pages but never actually defined — it fell back to a bare .btn
   (no background, no padding). Kept before .btn--sm so a combined
   `btn btn--danger btn--sm` still gets the small padding. */
.btn--danger { background: var(--mis-clay); color: #fff; padding: 8.8px 18px; border-radius: 999px; }
.btn--danger:hover { background: var(--mis-clay-ink); }
.btn--sm { padding: 4px 10px; font-size: 0.8rem; min-height: 32px; }
.payroll-salary-input { width: 100%; min-width: 110px; max-width: 160px; text-align: right; }
.payroll-account { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 0.04em; }
.payroll-reject-form { display: flex; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
.payroll-reject-form input[type="text"] { flex: 1 1 140px; min-width: 120px; }

/* --- Payroll attendance + Conveyor board (Task 3) --- */
.chip--bad { background: var(--mis-clay-soft); color: var(--mis-clay-ink); }
.btn.is-active { border-color: var(--mis-accent); color: var(--mis-accent); font-weight: 700; }
.payroll-confirm-form { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.payroll-confirm-form__force { font-size: 0.8rem; color: var(--mis-ink-muted); display: inline-flex; gap: 6px; align-items: center; }

.payroll-lane { margin-bottom: 20px; }
.payroll-lane__title { font-size: 1rem; margin: 0 0 8px; }
.payroll-board { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; align-items: start; }
.payroll-col {
  background: var(--mis-surface); border: 1px solid var(--mis-rule-soft); border-radius: 10px;
  padding: 10px; min-width: 0;
}
.payroll-col__head { margin: 0 0 8px; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.03em; display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.payroll-col__count { background: var(--mis-rule-soft); color: var(--mis-ink-muted); border-radius: 999px; padding: 1px 9px; font-size: 0.75rem; font-weight: 700; }
.payroll-col__empty { color: var(--mis-ink-muted); font-size: 0.85rem; margin: 4px 0; }
.payroll-col--attention { border-top: 3px solid var(--mis-clay); }
.payroll-col--pay_setup { border-top: 3px solid var(--mis-gold); }
.payroll-col--waiting   { border-top: 3px solid var(--mis-rule-soft); }
.payroll-col--cleared   { border-top: 3px solid #1f7a3d; }
.payroll-card {
  background: var(--mis-surface); border: 1px solid var(--mis-rule-soft); border-radius: 8px;
  padding: 8px 10px; margin-bottom: 8px; overflow-wrap: anywhere;
}
.payroll-card__name { font-weight: 600; display: flex; justify-content: space-between; gap: 6px; }
.payroll-card__tick { color: #1f7a3d; font-weight: 700; }
.payroll-card__meta { color: var(--mis-ink-muted); font-size: 0.78rem; margin-top: 2px; }
.payroll-card__flags { margin-top: 6px; }

/* Narrow screens: the four columns become a horizontal scroll-snap strip. */
@media (max-width: 768px) {
  .payroll-board {
    display: flex; overflow-x: auto; gap: 10px; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch; padding-bottom: 8px;
  }
  .payroll-col { flex: 0 0 82%; scroll-snap-align: start; }
}

/* --- Payroll register + pay story (Task 4) --- */
.stat-card--money .stat-card__value { font-size: 1.3rem; overflow-wrap: anywhere; }
.payroll-register .num, .payroll-register th.num { text-align: right; white-space: nowrap; }
.payroll-register th[data-key] { user-select: none; white-space: nowrap; }
.payroll-register th[data-key]:hover { background: rgba(34, 51, 105, 0.06); }
.payroll-register .sortable-table-arrow { margin-left: 4px; font-size: 0.7em; opacity: 0.35; }
.payroll-register .sortable-table-arrow.active { opacity: 1; }
.roster-prorate { margin-top: 4px; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.payroll-register__person > tr:first-child > td { border-bottom: none; }
.payroll-register__story > td { padding-top: 0; }
.payroll-neg { color: var(--mis-clay-ink); }
.payroll-card__net { margin-top: 4px; font-size: 0.85rem; }
.payroll-board { grid-template-columns: repeat(var(--payroll-cols, 4), minmax(0, 1fr)); }
.payroll-col--calculated { border-top: 3px solid var(--mis-accent); }

.paystory > summary { cursor: pointer; color: var(--mis-accent); font-size: 0.85rem; font-weight: 600; min-height: 32px; display: flex; align-items: center; }
.paystory__panel { padding: 8px 0 12px; }
.paystory__row {
  display: grid; grid-template-columns: minmax(150px, 34%) 1fr minmax(90px, auto);
  gap: 10px; align-items: center; padding: 4px 0; font-size: 0.88rem;
}
.paystory__row--total { border-top: 1px solid var(--mis-rule-soft); margin-top: 4px; padding-top: 8px; font-weight: 700; }
.paystory__label { overflow-wrap: anywhere; }
.paystory__alt { display: block; color: var(--mis-ink-muted); font-size: 0.75rem; font-weight: 400; }
.paystory__src { font-size: 0.75rem; margin-left: 6px; }
.paystory__track { position: relative; height: 12px; background: var(--mis-surface); border-radius: 6px; }
.paystory__bar { position: absolute; top: 0; bottom: 0; border-radius: 6px; }
.paystory__bar--earn { background: #1f7a3d; }
.paystory__bar--ded { background: var(--mis-clay); }
.paystory__bar--net { background: var(--mis-accent); }
.paystory__amt { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 600px) {
  .paystory__row { grid-template-columns: 1fr auto; }
  .paystory__track { grid-column: 1 / -1; order: 3; }
}

/* --- Payroll Review tab + Gates (Task 5) --- */
.payroll-gates { display: grid; gap: 8px; margin-bottom: 16px; }
.payroll-gate { display: flex; gap: 12px; padding: 10px 12px; border: 1px solid var(--mis-rule-soft); border-left-width: 4px; border-radius: 8px; background: #fff; }
.payroll-gate--green { border-left-color: #1f7a3d; }
.payroll-gate--red { border-left-color: var(--mis-clay-ink); }
.payroll-gate--neutral { border-left-color: #b9b9b9; }
.payroll-gate__dot { flex: 0 0 26px; height: 26px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-weight: 700; background: #e8e8e8; color: #555; }
.payroll-gate--green .payroll-gate__dot { background: #e3f2e6; color: #1f7a3d; }
.payroll-gate--red .payroll-gate__dot { background: var(--mis-clay-soft); color: var(--mis-clay-ink); }
.payroll-gate__body { min-width: 0; flex: 1 1 auto; }
.payroll-gate__title { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.payroll-gate__lang { margin-left: 0; }
.payroll-gate__detail { margin-top: 2px; font-size: 0.9rem; overflow-wrap: anywhere; }
/* What to do: the action steps under a gate that is not green. */
.payroll-gate__action { margin-top: 6px; padding: 6px 0 6px 10px; border-left: 3px solid var(--mis-accent); font-size: 0.9rem; color: var(--mis-ink-muted); overflow-wrap: anywhere; }
.payroll-gate__action strong { color: var(--mis-ink); }
.payroll-gate__action .btn { margin-left: 8px; }
.payroll-gate__form { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.payroll-gate__form input[type="text"] { flex: 1 1 160px; min-width: 120px; max-width: 320px; }
.payroll-exc__head { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-bottom: 8px; }
.payroll-exc__links { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 8px; }
.payroll-spark { color: var(--mis-accent); vertical-align: middle; max-width: 100%; }
.payroll-spark-row th { font-weight: 400; }
.payroll-mom--current > td { background: #f6f3ea; }

/* --- Payroll Approval + approval pack (Task 6) --- */
.payroll-locked { background: #fdf3d8; color: var(--mis-gold-ink); }
/* Guru-only "start this run over from scratch" card: destructive, so it is framed like a warning, not a normal card. */
.payroll-danger { border: 1px solid #e0a4a0; background: #fffafa; }
.payroll-danger ul { padding-left: 18px; color: var(--mis-ink-muted); }
.payroll-danger .form-actions { margin-top: 4px; }
.approval-timeline { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-bottom: 8px; }
.approval-step { padding: 12px 14px; border: 1px solid var(--mis-rule-soft); border-top-width: 4px; border-top-color: #b9b9b9; border-radius: 8px; background: #fff; overflow-wrap: anywhere; }
.approval-step--done { border-top-color: #1f7a3d; }
.approval-step__title { font-weight: 700; margin-bottom: 4px; }
@media (max-width: 640px) { .approval-timeline { grid-template-columns: 1fr; } }

/* Signature capture (public/hr/_signature_pad.php) */
.sigpad { border: 1px solid var(--mis-rule-soft); border-radius: 8px; padding: 12px; margin: 0 0 8px; background: #fff; }
.sigpad legend { font-weight: 700; padding: 0 6px; }
.sigpad__tabs { display: flex; gap: 8px; margin-bottom: 10px; }
.sigpad__tab { min-height: 44px; padding: 0 16px; border: 1px solid var(--mis-rule-soft); border-radius: 8px; background: #f3f0e8; cursor: pointer; font: inherit; }
.sigpad__tab.is-active { background: var(--mis-accent, #1a2332); color: #fff; border-color: transparent; }
.sigpad__panel[hidden] { display: none; }
.sigpad__panel input[type="text"] { width: 100%; min-height: 44px; font-size: 1.05rem; }
.sigpad__canvas { display: block; width: 100%; max-width: 600px; aspect-ratio: 3 / 1; border: 1px dashed #999; border-radius: 6px; background: #fff; touch-action: none; cursor: crosshair; }
.sigpad__clear { min-height: 44px; margin-top: 8px; }

/* Approval pack page (public/hr/payroll-pack.php) */
.pack { max-width: 1000px; }
.pack h2 { font-size: 1.05rem; margin: 24px 0 8px; }
.pack-totals { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
.pack-totals__item { border: 1px solid var(--mis-rule-soft); border-radius: 8px; padding: 10px 12px; background: #fff; }
.pack-totals__value { font-size: 1.2rem; font-weight: 700; overflow-wrap: anywhere; }
.pack .num, .pack th.num { text-align: right; white-space: nowrap; }
.pack-sign { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; margin-top: 16px; }
.pack-sign__box { border-bottom: 1px solid #333; min-height: 64px; padding-bottom: 4px; display: flex; flex-direction: column; justify-content: flex-end; }
.pack-sign__img { max-height: 70px; max-width: 100%; object-fit: contain; }
@media (max-width: 640px) { .pack-sign { grid-template-columns: 1fr; } }
@media print {
  @page { size: A4; margin: 12mm; }
  .dashboard-sidebar, .pack-noprint, .dashboard-content__header .btn, .payroll-tabs { display: none !important; }
  .dashboard { display: block; }
  .dashboard-content { margin-left: 0 !important; background: #fff; min-height: 0; overflow: visible !important; }
  .dashboard-content__body { padding: 0 !important; }
  .pack { max-width: none; font-size: 10pt; }
  .pack .table-scroll { overflow: visible; }
  .pack table { font-size: 9pt; }
  .pack tr, .pack-sign, .pack-totals__item { break-inside: avoid; }
  .pack h2 { break-after: avoid; }
}

/* --- Meals menu item action menu (public/meals/manage.php) --- */
.action-menu { position: relative; }
.action-menu__trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--mis-rule);
  border-radius: 8px;
  background: var(--mis-surface);
  color: var(--mis-ink);
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
  list-style: none;
}
.action-menu__trigger::-webkit-details-marker { display: none; }
.action-menu__trigger:hover { background: var(--mis-accent-soft); }
.action-menu__list {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  padding: 6px 0;
  min-width: 190px;
  background: var(--mis-surface);
  border: 1px solid var(--mis-rule);
  border-radius: 8px;
  box-shadow: var(--mis-shadow-soft);
  z-index: 20;
}
.action-menu__list form { margin: 0; }
.action-menu__item {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 40px;
  padding: 0 14px;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: 0.85rem;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.action-menu__item:hover, .action-menu__item:focus { background: var(--mis-rule-soft); }
.action-menu__item--danger { color: var(--mis-clay-ink); }
/* The dropdown is not unclipped from CSS. Both .table-scroll (a scroll
   container: overflow-x:auto forces the computed overflow-y to auto as well)
   and .table (overflow hidden, so its 12px border-radius clips the header)
   would cut an absolutely-positioned panel off. A
   `.table-scroll:has(.action-menu[open]) { overflow: visible; }` rule was
   tried for this and is deliberately NOT used: on any viewport where the
   table really scrolls (every phone, narrow desktops) setting overflow:
   visible stops the element being a scroll container, which drops its
   scrollLeft back to 0 — opening the menu snapped the table to its left edge
   and pushed the open panel past the right edge, where .dashboard-content's
   overflow-x: clip made it unreachable. Do not re-add it. Instead a small
   script in public/meals/manage.php pins the open panel with position: fixed
   at viewport coordinates taken from its <summary>, which no ancestor's
   overflow can clip. */

/* Payroll Payment tab (Task 7) */
.pay-ribbon { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin-bottom: 8px; }
@media (max-width: 900px) { .pay-ribbon { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) { .pay-ribbon { grid-template-columns: 1fr; } }
.pay-lines td { vertical-align: top; }
.pay-act { margin-bottom: 4px; }
.pay-act > summary { cursor: pointer; font-size: 0.85rem; font-weight: 600; color: var(--mis-accent); }
.payroll-col--approved { border-top: 3px solid var(--mis-accent); }
.payroll-col--paid { border-top: 3px solid #1f7a3d; }

/* Payslips (Task 8b): my-payslips / payslip-sign / profile tabs / Payment tab column */
.payslip-table td { vertical-align: top; }
.payslip-row--voided td { color: var(--mis-ink-muted); background: #faf6f5; }
.payslip-confirm { display: inline-flex; align-items: center; min-height: 44px; margin: 0 8px 8px 0; }
.payslip-summary { margin: 8px 0 12px; }
.payslip-sign-card { max-width: 720px; }
.payslip-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin: 0 0 12px; }
.payslip-facts dt { font-size: 0.8rem; color: var(--mis-ink-muted); }
.payslip-facts dd { margin: 2px 0 0; font-weight: 600; }
.payslip-facts__net { font-size: 1.25rem; color: #1f7a3d; }
.payslip-confirm-check { display: flex; align-items: flex-start; gap: 12px; min-height: 44px; margin: 12px 0; padding: 12px; border: 1px solid var(--mis-rule-soft); border-radius: 8px; cursor: pointer; }
.payslip-confirm-check input { width: 24px; height: 24px; flex: 0 0 auto; margin-top: 2px; }
.payslip-submit { min-height: 48px; width: 100%; margin-top: 8px; }
@media (min-width: 640px) { .payslip-submit { width: auto; min-width: 220px; } }

/* Payroll Close tab (Task 10) */
.close-progress { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin: 8px 0; }
@media (max-width: 900px) { .close-progress { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.close-stat { text-align: center; padding: 12px; }
.close-stat__n { font-size: 1.5rem; font-weight: 700; line-height: 1.3; }
.close-stat__l { font-size: 0.8rem; color: var(--mis-ink-muted); }
.close-banner--closed { background: #e3f2e6; color: #1f7a3d; border-color: #b9dfc1; margin-bottom: 12px; }
.close-blockers { margin: 0 0 12px; padding-left: 20px; }
.close-blockers li { margin-bottom: 4px; }
.close-task--overdue td { background: var(--mis-clay-soft); }
.payroll-run-card__progress { margin: 6px 0; }

/* --- Home landing (public/index.php): warm linen, serif hero, rounded cards ---
   Everything is scoped under body.home-landing so no other dashboard page changes. */
body.home-landing { --home-linen: #ece7de; --home-card: #fbf9f5; --home-tint: #f3eee5; --home-rule: #ded7c8; }
body.home-landing .dashboard-content { background: var(--home-linen); }

.home-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
  padding: clamp(8px, 2vw, 28px) 0 clamp(28px, 4vw, 52px);
}
.home-hero__title {
  margin: 0 0 18px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(2rem, 4.2vw, 3.4rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
  color: var(--mis-accent-ink);
}
.home-hero__lede { margin: 0 0 4px; font-size: 1.05rem; line-height: 1.6; color: var(--mis-ink-soft); }
.home-hero__meta { margin: 0; font-size: 0.95rem; line-height: 1.6; color: var(--mis-ink-muted); }
.home-hero__school { display: block; }
/* Phones: the greeting is only a step up from the date line (1.05rem). */
@media (max-width: 768px) {
  .home-hero__title { font-size: 1.35rem; line-height: 1.2; margin-bottom: 10px; }
  /* The whole visual/logo block goes; the calendar board is right below the hero,
     so the "View calendar" pill is redundant on a phone. */
  /* (.home-hero prefix: the base .home-hero__visual / .home-pill rules sit later in the file.) */
  .home-hero .home-hero__visual { display: none; }
  .home-hero .home-pill--calendar { display: none; }
}
.home-hero__rule { display: block; width: 44px; height: 2px; margin: 22px 0; background: var(--mis-gold); }
.home-hero__actions { display: flex; flex-wrap: wrap; gap: 12px; }
.home-pill {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 0 28px; border-radius: 999px;
  border: 1.5px solid var(--mis-accent-ink); color: var(--mis-accent-ink);
  font-weight: 600; font-size: 0.95rem; text-decoration: none;
  transition: background .15s, color .15s;
}
.home-pill:hover { background: var(--home-tint); }
.home-pill--solid { background: var(--mis-accent-ink); color: #fff; }
.home-pill--solid:hover { background: var(--mis-accent); }
.home-pill:focus-visible { outline: 3px solid var(--mis-gold); outline-offset: 2px; }

.home-hero__visual {
  position: relative;
  min-height: clamp(260px, 32vw, 400px);
  border-radius: 28px;
  background: var(--mis-wash) center / cover no-repeat;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 28px; /* room for the stat card that overhangs the bottom edge */
}
.home-hero__mark { width: min(46%, 220px); height: auto; opacity: .9; }
.home-hero__logo {
  position: absolute; top: 18px; left: 18px;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 16px 8px 10px; border-radius: 999px;
  background: rgba(255,255,255,.92); box-shadow: 0 2px 10px rgba(22,34,74,.12);
  font-size: .85rem; font-weight: 600; color: var(--mis-accent-ink);
}
.home-hero__logo img { width: 36px; height: 36px; object-fit: contain; }
.home-hero__stat {
  position: absolute; left: clamp(-8px, -1vw, 0px); bottom: -28px;
  max-width: min(78%, 280px);
  padding: 18px 24px; border-radius: 18px;
  background: var(--mis-accent-ink); color: #fff;
  box-shadow: 0 10px 28px rgba(22,34,74,.28);
}
.home-hero__stat-value { font-family: var(--font-display); font-size: clamp(2rem, 3.4vw, 2.8rem); line-height: 1; font-weight: 500; }
.home-hero__stat-label { margin-top: 6px; font-size: .85rem; line-height: 1.4; color: rgba(255,255,255,.78); }

@media (max-width: 900px) {
  .home-hero { grid-template-columns: 1fr; }
  .home-hero__stat { left: 12px; }
}

/* Panels and launcher: soft rounded cards on the linen ground */
body.home-landing .welcome-card { background: none; border: 0; box-shadow: none; padding: 0; margin-bottom: 36px; }
body.home-landing .welcome-card__grid { margin: 0; padding: 0; border: 0; gap: 20px; }
body.home-landing .welcome-card__panel {
  background: var(--home-card); border-radius: 22px; padding: 22px 24px;
  box-shadow: 0 1px 2px rgba(60,48,30,.05), 0 8px 24px rgba(60,48,30,.06);
}
body.home-landing .welcome-card__panel-header h3 { font-family: var(--font-display); font-weight: 500; font-size: 1.15rem; }
body.home-landing .welcome-list__item,
body.home-landing .welcome-empty { background: var(--home-tint); border: 0; border-radius: 14px; }
body.home-landing .section-header h2 { font-family: var(--font-display); font-weight: 500; font-size: 1.5rem; letter-spacing: -0.01em; }
body.home-landing .action-feed__item,
body.home-landing .glance-card { background: var(--home-card); border: 0; border-radius: 18px; box-shadow: 0 1px 2px rgba(60,48,30,.05), 0 6px 18px rgba(60,48,30,.05); }
body.home-landing .module-group-card {
  background: var(--home-card); border: 0; border-radius: 22px;
  box-shadow: 0 1px 2px rgba(60,48,30,.05), 0 8px 24px rgba(60,48,30,.06);
}
body.home-landing .module-tile { background: var(--home-tint); border: 0; border-radius: 14px; transition: background .15s, box-shadow .15s; }
body.home-landing .module-tile:hover { background: #fff; box-shadow: 0 4px 14px rgba(60,48,30,.12); }
body.home-landing .dashboard-cta { border-radius: 22px; }

/* --- Home landing: connected board (calendar + agenda + to-dos share one selected day) --- */
.home-board { display: grid; grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); gap: 20px; margin-bottom: 36px; align-items: start; scroll-margin-top: 16px; }
.home-card {
  background: var(--home-card, #fbf9f5); border-radius: 22px; padding: 22px 24px;
  box-shadow: 0 1px 2px rgba(60,48,30,.05), 0 8px 24px rgba(60,48,30,.06);
}
.home-card__title { margin: 0; font-family: var(--font-display); font-weight: 500; font-size: 1.25rem; color: var(--mis-accent-ink); }
.home-card__link { display: inline-block; margin-top: 12px; font-size: .85rem; font-weight: 600; color: var(--mis-accent-ink); text-decoration: none; }
.home-card__link:hover { text-decoration: underline; }

.home-cal__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 14px; }
.home-icon-btn { display: inline-flex; width: 40px; height: 40px; align-items: center; justify-content: center; border: 0; border-radius: 50%; background: var(--home-tint, #f3eee5); color: var(--mis-accent-ink); cursor: pointer; }
.home-icon-btn:hover { background: #e9e2d3; }
.home-cal__dow, .home-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.home-cal__dow span { text-align: center; font-size: .75rem; color: var(--mis-ink-muted); padding-bottom: 6px; }
.home-cal__day {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: 46px; border: 0; border-radius: 14px; background: transparent; color: var(--mis-ink); cursor: pointer; font: inherit;
}
.home-cal__day b { font-weight: 500; font-size: .92rem; }
.home-cal__day span { display: flex; gap: 3px; height: 6px; }
.home-cal__day i { width: 5px; height: 5px; border-radius: 50%; display: block; }
.home-cal__day:hover { background: var(--home-tint, #f3eee5); }
.home-cal__day.is-out { color: var(--mis-ink-muted); opacity: .55; }
.home-cal__day.is-today b { color: var(--mis-clay); font-weight: 700; }
.home-cal__day.is-selected { background: var(--mis-accent-ink); color: #fff; }
.home-cal__day.is-selected b { color: #fff; }
.home-cal__day.is-selected i { outline: 1px solid rgba(255,255,255,.7); }
.home-cal__day:focus-visible, .home-check:focus-visible, .home-icon-btn:focus-visible { outline: 3px solid var(--mis-gold); outline-offset: 2px; }

.home-agenda__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.home-agenda__sub { margin: 18px 0 8px; font-size: .95rem; font-weight: 600; color: var(--mis-ink-soft); }
.home-agenda__sub-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.home-agenda__sub-row .home-card__link { margin-top: 0; }
.home-pill--small { min-height: 36px; padding: 0 18px; font-size: .85rem; background: transparent; cursor: pointer; }

.home-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.home-list__item { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: 14px; background: var(--home-tint, #f3eee5); border-left: 4px solid var(--dot, transparent); }
.home-list__item--task { border-left-color: transparent; padding-left: 6px; }
.home-list__time { flex: 0 0 auto; min-width: 64px; font-size: .8rem; color: var(--mis-ink-muted); }
.home-list__text { flex: 1; min-width: 0; font-size: .92rem; overflow-wrap: anywhere; }
.home-list__text.is-done { text-decoration: line-through; color: var(--mis-ink-muted); }
.home-empty { padding: 12px 14px; border-radius: 14px; background: var(--home-tint, #f3eee5); color: var(--mis-ink-muted); font-size: .88rem; }
.home-check { display: inline-flex; width: 40px; height: 40px; align-items: center; justify-content: center; border: 0; background: none; border-radius: 50%; cursor: pointer; color: var(--mis-ink-muted); }
.home-check.is-done { color: #1f7a3d; }
.home-check:hover:not(:disabled) { background: rgba(0,0,0,.05); }
.home-check:disabled { opacity: .5; cursor: progress; }

a.home-hero__stat { text-decoration: none; }
a.home-hero__stat:hover { background: var(--mis-accent); }

@media (max-width: 900px) { .home-board { grid-template-columns: 1fr; } }

/* Student Uniforms — status badges (see docs/superpowers/plans/2026-10-01-student-uniforms.md) */
.badge--uniform-requested { background: #fef3c7; color: #b45309; }
.badge--uniform-ordered   { background: #e0e7ff; color: #3730a3; }
.badge--uniform-issued    { background: #e3f2e6; color: #1f7a3d; }
.badge--uniform-cancelled { background: #fee2e2; color: #991b1b; }

/* Shopping List sortable headers (public/assets/supply-checkout.php). Each sortable <th> holds a
   <button> so the header is keyboard-reachable; the button is made to look exactly like the plain
   header text it replaced, and the direction glyph is CSS-only, so an unsorted header row is
   unchanged. The th's own padding/size/uppercase styling is untouched — nothing here widens the
   table inside its .table-scroll wrapper. */
.pl-sort-btn {
  display: inline;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
  text-align: inherit;
}
.pl-sort-btn:hover { color: var(--mis-accent); }
.pl-sort-btn:focus-visible { outline: 2px solid var(--mis-accent); outline-offset: 2px; border-radius: 3px; }
/* The indicator only exists once a column is hovered or active: an empty ::after has zero width, so
   an unsorted header row measures exactly the same as it did before and cannot widen the table. */
.pl-sort-ind::after { content: ''; font-size: 0.8em; }
.pl-sort-btn:hover .pl-sort-ind::after { content: '↕'; opacity: 0.45; margin-left: 4px; }
.pl-sort-btn[data-dir="asc"] .pl-sort-ind::after { content: '↑'; opacity: 1; margin-left: 4px; }
.pl-sort-btn[data-dir="desc"] .pl-sort-ind::after { content: '↓'; opacity: 1; margin-left: 4px; }

/* --- Sidebar Emergency button (pinned in the footer, outside the scrolling nav) + overlay --- */
.dashboard-sidebar__emergency {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; margin: 8px 0 4px; min-height: 44px; padding: 8px 12px;
  background: #b91c1c; color: #fff; border: 2px solid #fecaca; border-radius: 8px;
  font: inherit; font-weight: 700; cursor: pointer; letter-spacing: .03em;
}
.dashboard-sidebar__emergency:hover, .dashboard-sidebar__emergency:focus-visible { background: #991b1b; }
.collapsed .dashboard-sidebar__emergency span:not(.material-symbols-outlined) { display: none; }
.emg-overlay {
  position: fixed; inset: 0; z-index: 2147483000; background: rgba(60,0,0,.78);
  display: flex; align-items: center; justify-content: center; padding: 12px; overflow-y: auto;
}
.emg-overlay[hidden] { display: none; }
.emg-panel { background: #fff; border: 4px solid #b91c1c; border-radius: 12px; width: min(760px, 100%); max-height: 100%; overflow-y: auto; padding: 16px; }
.emg-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.emg-head h2 { margin: 0; color: #b91c1c; font-size: 1.2rem; display: flex; align-items: center; gap: 8px; }
.emg-close { min-width: 44px; min-height: 44px; font-size: 1.8rem; line-height: 1; background: #f3f4f6; border: 0; border-radius: 8px; cursor: pointer; }
.emg-hint { margin: 6px 0 12px; color: #444; }
.emg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.emg-card { display: flex; flex-direction: column; align-items: center; gap: 4px; min-height: 84px; padding: 10px 6px; background: #fff5f5; border: 2px solid #fca5a5; border-radius: 8px; color: #7f1d1d; font: inherit; cursor: pointer; text-align: center; }
.emg-card .material-symbols-outlined { font-size: 1.8rem; }
.emg-card__title { font-weight: 700; }
.emg-card__resp { font-size: .75rem; opacity: .8; }
.emg-card.armed { background: #b91c1c; color: #fff; border-color: #7f1d1d; }
.emg-confirm { margin-top: 14px; padding-top: 12px; border-top: 2px dashed #b91c1c; display: flex; flex-direction: column; gap: 8px; }
.emg-confirm[hidden] { display: none; }
.emg-activate { min-height: 60px; background: #b91c1c; color: #fff; border: 0; border-radius: 8px; font: inherit; font-size: 1.1rem; font-weight: 800; cursor: pointer; }
.emg-activate:disabled { background: #9ca3af; cursor: not-allowed; }
.emg-cancel { min-height: 48px; background: #f3f4f6; border: 1px solid #d1d5db; border-radius: 8px; font: inherit; cursor: pointer; }
@media (max-width: 768px) {
  .dashboard-sidebar__emergency { width: 44px; margin: 8px auto 4px; padding: 0; }
  .dashboard-sidebar__emergency span:not(.material-symbols-outlined) { display: none; }
}
.dashboard-sidebar__footer { flex-shrink: 0; }
.dashboard-sidebar__nav { min-height: 0; }

/* Phone-only home shortcuts (landing page): hidden on desktop, shown <=768px. */
.home-quick, .home-phone-wide { display: none; }
@media (max-width: 768px) {
  .home-quick { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin: 0 0 14px; padding: 6px 0; }
  .home-quick__btn {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    min-width: 0; min-height: 92px; padding: 12px 8px; box-sizing: border-box;
    border: 1px solid var(--mis-border, #d9d9d9); border-radius: 10px; background: #fff;
    color: var(--mis-accent-ink); text-decoration: none; text-align: center;
  }
  .home-quick__btn:focus-visible { outline: 3px solid var(--mis-gold); outline-offset: 2px; }
  .home-quick__btn .material-symbols-outlined { font-size: 28px; }
  .home-quick__label { font-size: .62rem; line-height: 1.2; font-weight: 600; max-width: 100%; padding: 0 2px; overflow-wrap: anywhere; hyphens: auto; }
  .home-phone-wide {
    display: flex; align-items: center; justify-content: center; gap: 8px; box-sizing: border-box;
    width: 100%; min-height: 48px; padding: 10px 16px; margin: 14px 0 0;
    border-radius: 12px; background: var(--mis-accent-ink); color: #fff;
    font-weight: 600; font-size: .95rem; text-align: center; text-decoration: none;
  }
  .home-phone-wide:focus-visible { outline: 3px solid var(--mis-gold); outline-offset: 2px; }
  .home-hero .home-phone-wide { margin: 12px 0 0; }
  .home-phone-wide--projects { background: #fff; color: var(--mis-accent-ink); border: 1px solid var(--mis-accent-ink); }
  .home-phone-wide--students { margin: 0 0 16px; }
  /* Phones show English + Chinese only on the landing shortcuts. */
  .home-quick .i18n-th, .home-hero__actions .home-pill .i18n-th, .home-phone-wide .i18n-th { display: none; }
}

/* Horizontal tab bars (renderPeopleTabs and other .tab-nav pages): on narrow screens the tabs scroll sideways
   instead of being cut off (.dashboard-content clips horizontal overflow). Each page defines its own base
   .tab-nav look inline; this only adds the scrolling. */
@media (max-width: 900px) {
  .tab-nav {
    overflow-x: auto; overflow-y: hidden; flex-wrap: nowrap;
    padding-bottom: 2px;                       /* keeps the active underline inside the scroll box */
    -webkit-overflow-scrolling: touch; scrollbar-width: thin; overscroll-behavior-x: contain;
  }
  .tab-nav > a { flex: 0 0 auto; white-space: nowrap; }
}

/* Settings pages: a grouped block of related fields with a status line, and a panel shown only for the chosen option */
.settings-group { border: 1px solid var(--mis-rule); border-radius: 12px; padding: 16px 18px; margin-top: 20px; background: var(--mis-surface); }
.settings-group h3 { margin: 0 0 6px; font-size: 1.05rem; }
.settings-status { margin: 0 0 14px; padding: 8px 12px; border-radius: 8px; background: var(--mis-wash, #eef3f8); font-size: .92rem; }
.settings-panel { margin: 0 0 16px; padding: 12px 14px; border-left: 3px solid var(--mis-accent); background: var(--mis-cream, #faf7f2); border-radius: 0 8px 8px 0; font-size: .92rem; }
.settings-panel[hidden] { display: none; }
.settings-panel p { margin: 0 0 8px; }
.settings-panel ol { margin: 0 0 8px; padding-left: 20px; }
.settings-panel li { margin-bottom: 4px; }
.settings-panel code { background: #fff; border: 1px solid var(--mis-rule); border-radius: 4px; padding: 1px 6px; }
.settings-check { display: flex; gap: 8px; align-items: center; margin: 8px 0 0; font-weight: 400; }

/* ── Generic modal dialog (native <dialog>): Offboarding template edit, reusable elsewhere ── */
.mis-dialog { border: 0; border-radius: 14px; padding: 0; width: min(560px, 94vw); box-shadow: 0 20px 60px rgba(0,0,0,0.3); color: var(--mis-ink, #1c2540); }
.mis-dialog::backdrop { background: rgba(20,24,40,0.5); }
.mis-dialog__head { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--mis-border, #e5e7eb); }
.mis-dialog__head h2 { margin: 0; font-size: 1.1rem; }
.mis-dialog__x { background: none; border: 0; font-size: 1.6rem; line-height: 1; cursor: pointer; color: var(--mis-ink-muted, #6b7280); min-width: 44px; min-height: 44px; }
.mis-dialog__body { padding: 20px; }

/* ── Expense Payment Request form (public/hr/_expense_form.php) ── */
.exp-section { border: 1px solid var(--mis-rule); border-radius: 10px; padding: 14px 16px; margin: 14px 0; background: var(--mis-surface); }
.exp-section > h3 { margin: 0 0 10px; font-size: 1rem; }
.exp-line { border: 1px solid var(--mis-rule); border-radius: 8px; padding: 12px; margin-bottom: 10px; background: #fff; }
.exp-line[hidden] { display: none; }
.exp-line__no { font-weight: 600; margin: 0 0 8px; }
.exp-total { font-size: 1.1rem; font-weight: 700; margin: 8px 0 0; text-align: right; }
.exp-choice { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 4px 0; }
.exp-choice label { display: flex; align-items: center; gap: 6px; font-weight: 400; min-height: 32px; }
.exp-readonly { margin: 0; padding: 8px 10px; background: var(--mis-wash, #eef3f8); border-radius: 6px; min-height: 20px; }
.field-error { color: #b91c1c; font-size: .85rem; margin: 4px 0 0; }
.exp-checklist { margin: 6px 0 0 18px; padding: 0; font-size: .85rem; color: #b91c1c; }
@media (max-width: 768px) { .exp-total { text-align: left; } }

/* ── Expense Payment Request: the "View Request" popup (public/hr/expenses.php) ──
   Modifiers / new classes only — the base .mis-dialog rules above are shared with offboarding.php. */
.mis-dialog--wide { width: min(960px, 96vw); max-height: min(90vh, 900px); }
.mis-dialog--wide[open] { display: flex; flex-direction: column; overflow: hidden; }
.mis-dialog--wide .mis-dialog__body { overflow-y: auto; min-height: 0; }

.exp-view-heading { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 12px; }
.exp-view-title { margin: 0; font-size: 1.15rem; }
.exp-view-h3 { margin: 18px 0 8px; font-size: 1rem; }
.exp-view-grid { display: grid; grid-template-columns: minmax(140px, 200px) 1fr; gap: 6px 16px; margin: 0; }
.exp-view-row { display: contents; }
.exp-view-label { color: var(--mis-ink-muted, #6b7280); font-size: .85rem; }
.exp-view-value { white-space: pre-wrap; word-break: break-word; }
.exp-view-amt { text-align: right; white-space: nowrap; }
.exp-view-total td { font-weight: 700; }
.exp-view-total-label { text-align: right; }
.exp-view-docs > div { margin: 2px 0; }
.exp-view-tick { font-weight: 700; }
.exp-view-receipt { margin: 10px 0 0; }
.exp-view-decl { margin: 14px 0 0; font-size: .9rem; }
.exp-view-missing-head { margin: 14px 0 0; font-weight: 600; }
.exp-view-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--mis-rule, #e5e7eb); }

/* Reject-with-a-reason + the amend/resubmit loop (round 2). */
.exp-view-reject-alert { margin: 0 0 8px; }
.exp-view-note { margin: 6px 0 12px; font-size: .88rem; color: var(--mis-ink-muted, #6b7280); }
.exp-view-actform { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.exp-view-reject-box { flex-basis: 100%; width: 100%; margin-top: 8px; padding: 10px 12px; background: var(--mis-wash, #eef3f8); border-radius: 6px; }
.exp-view-reject-box[hidden] { display: none; }
.exp-view-reject-box > label { display: block; font-weight: 600; font-size: .9rem; margin-bottom: 6px; }
.exp-view-reject-box textarea { width: 100%; box-sizing: border-box; }
.exp-view-reject-box .form-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.exp-view-history { margin: 0; padding-left: 18px; font-size: .9rem; }
.exp-view-hist-item { margin: 4px 0; }
.exp-view-hist-action { font-weight: 600; }
.exp-view-hist-approved { color: var(--mis-success, #15803d); }
.exp-view-hist-rejected { color: #b91c1c; }
.exp-view-hist-advised { color: #b45309; }
.exp-view-hist-meta { color: var(--mis-ink-muted, #6b7280); font-size: .85rem; }

/* The inline two-step "Reject" on public/hr/my-approvals.php. */
.exp-reject-details > summary { list-style: none; display: inline-block; }
.exp-reject-details > summary::-webkit-details-marker { display: none; }

@media (max-width: 768px) {
  /* Full-bleed on a phone, like the duty grid dialog (public/styles/duty.css). */
  .mis-dialog--wide[open] { width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; }
  .exp-view-grid { grid-template-columns: 1fr; gap: 0; }
  .exp-view-row { display: block; margin-bottom: 8px; }
  .exp-view-label { display: block; font-size: .8rem; }
}

/* --- Staff birthdays (2026-10-14) --- */
/* Screen-reader-only: keeps the day-of birthday cue available to a viewer who
   gets none of the colour, glow or cake (the cake is aria-hidden). Same technique
   as the standard sr-only utility — never `display:none`, which removes it from
   the accessibility tree as well. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.birthday-name { font-weight: 700; color: var(--mis-gold-ink); }
/* The base background is what a reduced-motion viewer sees: with `animation: none`
   the keyframes stop supplying it, and today's date cell would otherwise carry no
   visible cue at all. While the animation runs it overrides this declaration, so
   the animated look is unchanged. */
.birthday-name--today { animation: birthday-glow 2.4s ease-in-out infinite; border-radius: 4px; padding: 0 2px; background: rgba(234, 183, 42, 0.10); }
@keyframes birthday-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(234, 183, 42, 0.45); background: rgba(234, 183, 42, 0.10); }
  50%      { box-shadow: 0 0 0 6px rgba(234, 183, 42, 0); background: rgba(234, 183, 42, 0.22); }
}
@media (prefers-reduced-motion: reduce) { .birthday-name--today { animation: none; } }
.birthday-name__cake { margin-left: 4px; }

/* --- Masked pay figures (2026-10-15) --- */
/* A salary on a staff profile rests as asterisks and is revealed by clicking them.
   The reveal is a POST that is logged (HrPayrollMaster::revealSalary), so the
   asterisks are a real button; it is styled to read as the value it hides rather
   than as a control — the dashed underline is the whole affordance, and it goes
   solid once the amount is showing. */
.pay-reveal {
  font: inherit;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.14em;
  color: var(--mis-ink);
  background: none;
  border: 0;
  border-bottom: 1px dashed var(--mis-ink-muted);
  padding: 0;
  cursor: pointer;
}
.pay-reveal:hover { color: var(--mis-accent); border-bottom-color: var(--mis-accent); }
.pay-reveal:focus-visible { outline: 2px solid var(--mis-accent); outline-offset: 2px; border-radius: 3px; }
.pay-reveal--shown { letter-spacing: normal; border-bottom-style: solid; }
.pay-reveal__form { display: inline; margin: 0; }
.pay-reveal__hide { margin-left: 10px; font-size: 0.85rem; color: var(--mis-ink-muted); }
.pay-reveal__hide:hover { color: var(--mis-accent); }

/* ── Payroll run Overview: readiness-check list, with the stage-transition action under it ── */
.payroll-checks__action { margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--mis-border, #e5e7eb); }
.payroll-checks__item a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.payroll-checks__item a:hover { text-decoration-thickness: 2px; }
/* A readiness item is a button (it opens that check's popup), styled as a link. */
.payroll-checks__link { background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  text-decoration: underline; text-underline-offset: 2px; }
.payroll-checks__link:hover { text-decoration-thickness: 2px; }
.payroll-checks__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.payroll-checks__item { display: flex; gap: 8px; align-items: flex-start; font-size: 0.92rem; line-height: 1.3; }
.payroll-checks__item .material-symbols-outlined { font-size: 20px; flex-shrink: 0; }
.payroll-checks__item--ok .material-symbols-outlined { color: #1a7f37; }
.payroll-checks__item--bad .material-symbols-outlined { color: #c62828; }
.payroll-checks__item--bad { color: #8a1c1c; }
.payroll-checks__item--neutral .material-symbols-outlined { color: #94a3b8; }
.payroll-checks__sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* Readiness groups: what is needed now, then the phases that come later (folded). */
.payroll-checks__group { margin-top: 16px; }
.payroll-checks__group--now { border-left: 3px solid var(--mis-accent); padding-left: 12px; }
.payroll-checks__group-title { display: inline-flex; align-items: center; gap: 8px; margin: 0;
  font-size: 0.82rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--mis-ink-soft); }
.payroll-checks__group-note { margin: 3px 0 8px; font-size: 0.85rem; }
.payroll-checks__group > summary { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  cursor: pointer; list-style: none; padding: 10px 0; border-top: 1px solid var(--mis-rule); }
.payroll-checks__group > summary::-webkit-details-marker { display: none; }
.payroll-checks__group > summary::marker { content: ''; }
.payroll-checks__group > summary::after { content: '\25B8'; margin-left: auto; color: var(--mis-ink-muted); }
.payroll-checks__group[open] > summary::after { content: '\25BE'; }
.payroll-checks__group-count { font-size: 0.82rem; font-weight: 400; }

/* Payroll Review tab: the calendar dates a "Payroll calendar confirmed" tick covers. */
.payroll-gate__dates { display: grid; grid-template-columns: max-content 1fr; gap: 2px 14px; margin: 8px 0; font-size: 0.9rem; }
.payroll-gate__dates dt { color: var(--mis-ink-muted, #6b7280); }
.payroll-gate__dates dd { margin: 0; font-weight: 600; }

/* Payroll roster: sortable headers + the "this payroll only / permanent" dialog */
#roster-table th.roster-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
#roster-table th.roster-sortable:hover { background: rgba(34, 51, 105, 0.06); }
#roster-table .sortable-table-arrow { margin-left: 4px; font-size: 0.7em; opacity: 0.35; }
#roster-table .sortable-table-arrow.active { opacity: 1; }
/* Roster group heading — Staff / School aides / Other (Henko, 2026-10-21). A band across the table,
   not a person row: no hover, no sort, and it always stays at the top of its own group. */
.roster-group td { background: var(--mis-surface, #f4f5f9); font-weight: 700; font-size: 0.8rem; letter-spacing: .05em; text-transform: uppercase; color: var(--mis-navy, #223369); border-top: 2px solid var(--mis-rule, #d7dbe6); padding-top: 10px; padding-bottom: 10px; }
.roster-group:hover td { background: var(--mis-surface, #f4f5f9); }
.roster-group__count { font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--mis-ink-muted, #6b7280); }
.roster-scope-dialog { border: 1px solid var(--mis-border, #d7dbe6); border-radius: 12px; padding: 20px 22px; max-width: 520px; width: calc(100% - 32px); box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25); }
.roster-scope-dialog::backdrop { background: rgba(20, 28, 55, 0.45); }
.roster-scope-dialog [hidden] { display: none !important; }
.roster-scope-dialog .rsd-scope { border: 0; padding: 0; margin: 0 0 12px; display: grid; gap: 8px; }
.roster-scope-dialog .rsd-scope legend { font-weight: 600; margin-bottom: 6px; padding: 0; }
.roster-scope-dialog .rsd-scope label { display: block; }
.roster-ov { font-size: 0.72rem; white-space: nowrap; }

/* Collapsed groups on the payroll Review tab */
.payroll-collapse { margin: 12px 0; }
.payroll-collapse > summary { cursor: pointer; font-weight: 600; color: var(--mis-navy); padding: 10px 14px; background: #fff; border: 1px solid var(--mis-rule); border-radius: 10px; list-style-position: inside; }
.payroll-collapse[open] > summary { margin-bottom: 12px; }

/* "Next step" bar on every payroll run tab */
.payroll-next { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin: 0 0 16px; padding: 14px 18px; background: #fff; border: 1px solid var(--mis-rule); border-left: 6px solid var(--mis-navy, #223369); border-radius: 10px; }
.payroll-next--wait { border-left-color: #b8860b; }
.payroll-next--done { border-left-color: #2f7d46; }
.payroll-next__text { flex: 1 1 320px; line-height: 1.45; }
.payroll-next__label { display: inline-block; margin-right: 8px; font-size: 0.72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--mis-navy, #223369); }
.payroll-next__warn { margin-top: 6px; color: #8a1f1f; font-size: 0.9rem; }
.payroll-next__form { margin: 0; }

/* Overview "Readiness checks": still-to-do items spelled out */
.payroll-todo { border: 1px solid var(--mis-rule); border-left: 5px solid #b3382c; border-radius: 8px; padding: 12px 14px; margin: 10px 0; background: #fff; }
.payroll-todo__title { font-weight: 700; color: var(--mis-navy); }
.payroll-todo__why { color: var(--mis-ink-muted); margin: 2px 0 6px; }
.payroll-todo__meta { font-size: 0.85rem; color: var(--mis-ink-muted); margin-top: 4px; }
.payroll-todo__buttons { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.payroll-checks__clear { color: #2f7d46; font-weight: 600; margin: 6px 0 10px; }
.payroll-checks__done { margin-top: 8px; }
.payroll-checks__done > summary { cursor: pointer; color: var(--mis-ink-muted); }

.payroll-checks__nextup { font-size: 0.72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--mis-navy); margin-top: 8px; }
.payroll-checks__after { margin: 8px 0 4px; color: var(--mis-ink-muted); font-size: 0.9rem; }

/* Approval pack: tabs, one-glance summary, check cards. All panels print. */
.pack-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--mis-rule); margin: 18px 0 16px; flex-wrap: wrap; }
.pack-tabs__tab { background: none; border: 0; border-bottom: 3px solid transparent; padding: 10px 16px; font: inherit; font-weight: 600; color: var(--mis-ink-muted); cursor: pointer; }
.pack-tabs__tab.is-active { color: var(--mis-navy); border-bottom-color: var(--mis-navy); }
.pack-tabpanel[hidden] { display: none; }
.pack-print-title { display: none; }
.pack-glance { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; margin: 0 0 16px; }
.pack-glance__item { background: #fff; border: 1px solid var(--mis-rule); border-left: 5px solid var(--mis-rule); border-radius: 8px; padding: 10px 14px; }
.pack-glance__item strong { font-size: 1.15rem; margin-right: 4px; }
.pack-glance__item span { display: block; font-size: 0.8rem; color: var(--mis-ink-muted); }
.pack-glance__item--ok { border-left-color: #2f7d46; }
.pack-glance__item--bad { border-left-color: #b3382c; }
.pack-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 14px; align-items: start; }
@media (max-width: 560px) { .pack-grid { grid-template-columns: 1fr; } }
.pack-card { margin: 0; }
.pack-card__title { margin: 0 0 10px; font-size: 1.05rem; }
@media print {
  .pack-tabpanel[hidden] { display: block !important; }
  .pack-print-title { display: block; }
  .pack-glance, .pack-grid { display: block; }
  .pack-card { break-inside: avoid; margin-bottom: 10px; box-shadow: none; }
}

/* Approval pack: sign-off and A4 printing */
.pack-signcard { margin: 0 0 16px; }
.pack-print-foot { display: none; margin-top: 14px; }
@media print {
  .pack-sign-title { break-before: auto; break-after: avoid; }
  .pack-sign { break-inside: avoid; page-break-inside: avoid; margin-top: 18px; }
  .pack-sign__box { min-height: 22mm; }
  .pack-print-foot { display: block; }
  .pack table { width: 100%; table-layout: auto; }
  .pack th, .pack td { padding: 3px 6px !important; }
  .pack h2 { font-size: 12pt; margin: 12px 0 6px; }
  .pack-totals { grid-template-columns: repeat(3, 1fr) !important; }
  .pack-card { border: 1px solid #ccc; }
  .pack-glance__item { border: 1px solid #ccc; }
  .chip { border: 1px solid #999; background: #fff !important; color: #000 !important; }
}

.pay-signcell { min-width: 140px; border-bottom: 1px solid #777 !important; }
.pay-tabs { margin-top: 16px; }

.pay-cash-form { display: grid; gap: 6px; margin-top: 6px; }
.pay-cash-form__opt { display: flex; gap: 8px; align-items: center; cursor: pointer; }

/* The design system pads every <section>; payment/pack tab panels must not add that extra gap under their tab bar. */
.pack-tabpanel { padding-block: 0; }
/* Envelope sheet (printed before staff collect their cash) */
.envelope-sheet th, .envelope-sheet td { vertical-align: middle; }
.envelope-sheet tbody td { height: 13mm; border-bottom: 1px solid #bbb; }
.envelope-sheet__n { width: 8mm; text-align: center; }
.envelope-sheet__chk { width: 22mm; text-align: center; font-size: 1.2rem; }
.envelope-sheet__sig { width: 55mm; border-left: 1px solid #ddd; }
.envelope-sheet__date { width: 24mm; border-left: 1px solid #ddd; }
@media print { .envelope-sheet tbody tr { break-inside: avoid; } .envelope-sheet tfoot td { border-top: 2px solid #000; } }

.envelope-head { text-align: center; margin-bottom: 14px; }
.envelope-head__logo { height: 56px; width: auto; margin: 0 auto 8px; display: block; }
.envelope-head__title { margin: 0; font-size: 1.5rem; color: var(--mis-navy); }
.envelope-head__sub { margin: 4px 0 2px; }
.envelope-head__count { margin: 0; }

.help-btn { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; margin-left: 6px; border-radius: 50%; border: 1px solid var(--mis-navy, #223369); background: #fff; color: var(--mis-navy, #223369); font: inherit; font-size: 0.8rem; font-weight: 700; line-height: 1; cursor: pointer; vertical-align: middle; }
.help-btn:hover { background: var(--mis-navy, #223369); color: #fff; }

.payroll-stop__who { display: block; margin-top: 2px; font-size: 0.78rem; font-weight: 600; color: var(--mis-navy, #223369); overflow-wrap: anywhere; }
.payroll-stop__who--none { color: #8a1f1f; font-weight: 600; }

/* Run page top zone: Next step bar (and notices) in the left column, the "What to do" help box in the right one. */
.payroll-top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; align-items: start; margin: 0 0 16px; }
.payroll-top--single { grid-template-columns: minmax(0, 1fr); }
.payroll-top__main > * { margin: 0 0 12px; }
.payroll-top__main > *:last-child { margin-bottom: 0; }
.payroll-top__help .payroll-banner { margin: 0; }
@media (max-width: 900px) { .payroll-top { grid-template-columns: minmax(0, 1fr); } }

/* Changes tab: Submit a change (2/3) beside Deductions confirmed (1/3) */
.payroll-split { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 20px; align-items: start; margin-bottom: 24px; }
.payroll-split .card { margin-bottom: 0 !important; }
@media (max-width: 900px) { .payroll-split { grid-template-columns: minmax(0, 1fr); } }

/* Tabs the signed-in user can work with their duty: a raised, ringed pill so they stand out */
.payroll-tabs { padding: 6px 4px 8px; }
.payroll-tabs__tab.is-mine {
  color: var(--mis-navy, #223369); background: #fff; border: 2px solid var(--mis-navy, #223369); border-radius: 999px;
  box-shadow: 0 3px 0 rgba(34, 51, 105, 0.35), 0 8px 14px rgba(34, 51, 105, 0.18); transform: translateY(-2px); margin: 0 4px;
}
.payroll-tabs__tab.is-mine::before { content: '\25CF'; margin-right: 6px; font-size: 0.6em; vertical-align: middle; color: #c0392b; }
.payroll-tabs__tab.is-mine.is-active { background: var(--mis-navy, #223369); color: #fff; }
.payroll-tabs__legend { margin: -12px 0 16px; font-size: 0.8rem; color: var(--mis-ink-muted); }

.pay-bank-open { background: none; border: 0; padding: 0; font: inherit; color: var(--mis-accent); text-decoration: underline; cursor: pointer; }
.pay-bank-open--missing { color: #b3382c; font-weight: 600; }

.payroll-tabs__tab.is-waiting { opacity: 0.5; cursor: not-allowed; background: transparent; border: 2px dashed #9aa3b8; border-radius: 999px; margin: 0 4px; color: var(--mis-ink-muted); }
.payroll-top__main .payroll-next__paras p { margin: 6px 0 0; }
.payroll-next__paras p { margin: 6px 0 0; font-size: 0.92rem; }
.payroll-next__paras .payroll-next__mine { color: var(--mis-navy, #223369); }
.payroll-next__paras .payroll-next__need { color: #8a1f1f; }

/* Attendance tab: the action buttons in one tidy row, in the order you work through them */
.att-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--mis-rule-soft); }
.att-actions form { margin: 0; }
.att-actions .btn { min-height: 44px; white-space: nowrap; }
.att-actions__confirm { margin-left: auto !important; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: flex-end; }
.att-actions__confirm .payroll-confirm-form__force { margin: 0; font-size: 0.85rem; }

/* A finished action: shown as a calm "done" badge, not clickable */
.btn--done, .btn--done:hover, .btn--done:disabled { background: #e3f2e6; color: #1f7a3d; border: 1px solid #b9dcc3; cursor: default; pointer-events: none; opacity: 1; box-shadow: none; transform: none; }

/* Register: while a person's pay story is long, their row stays just under the column headers */
.payroll-register__person > tr:first-child > td { position: sticky; top: var(--reg-th-h, 46px); z-index: 1; }
.paystory__adj { margin-left: 8px; background: none; border: 1px solid var(--mis-accent); color: var(--mis-accent); border-radius: 999px; padding: 0 10px; font: inherit; font-size: 0.72rem; font-weight: 600; cursor: pointer; line-height: 1.6; }
.paystory__adj:hover { background: var(--mis-accent); color: #fff; }

/* Register: every other person is shaded, so where one person ends and the next begins is obvious (no divider lines) */
.payroll-register__person > tr > td { background: #fff; border-bottom: 0; }
.payroll-register__person:nth-of-type(odd) > tr > td { background: #eef1f9; }

/* "Mark all N as paid" progress: a bar and a time-left estimate under the form (Henko, 2026-10-21). */
.pay-progress { margin: 12px 0 0; padding: 14px 16px; background: var(--mis-surface, #fff); border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 12px; }
.pay-progress__track { height: 12px; margin: 10px 0 8px; background: var(--mis-rule-soft, #eef0f4); border-radius: 999px; overflow: hidden; }
.pay-progress__bar { width: 0; height: 100%; background: var(--mis-accent, #223369); border-radius: 999px; transition: width .4s ease; background-image: linear-gradient(90deg, rgba(255,255,255,.18) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.18) 50%, rgba(255,255,255,.18) 75%, transparent 75%); background-size: 24px 24px; animation: pay-progress-stripes 1s linear infinite; }
@keyframes pay-progress-stripes { to { background-position: 24px 0; } }
.pay-progress--error { border-color: var(--mis-clay, #bf2827); }
@media (prefers-reduced-motion: reduce) { .pay-progress__bar { animation: none; } }

/* ── Venue and Asset Bookings (public/bookings/) ─────────────────────────────────────────────── */
.vab-tabs { display: flex; gap: 4px; flex-wrap: wrap; border-bottom: 1px solid var(--mis-rule); margin-bottom: 16px; }
.vab-tabs a { padding: 8px 14px; text-decoration: none; color: var(--mis-ink-muted); font-weight: 600; font-size: 0.9rem; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.vab-tabs a:hover { color: var(--mis-ink); }
.vab-tabs a.is-active { color: var(--mis-accent, #223369); border-bottom-color: var(--mis-accent, #223369); }
.vab-count { display: inline-block; min-width: 20px; padding: 0 6px; margin-left: 4px; border-radius: 999px; background: var(--mis-clay, #bf2827); color: #fff; font-size: 0.72rem; text-align: center; }
.vab-nav { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.vab-nav .input { width: auto; }
.vab-section-title { font-size: 1rem; margin: 20px 0 8px; color: var(--mis-ink); }
.vab-book-card { margin-bottom: 20px; }
.vab-legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 0.8rem; color: var(--mis-ink-muted); margin: 6px 0 12px; }
.vab-legend i { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.vab-agrid td, .vab-agrid th { vertical-align: top; font-size: 0.82rem; }
.vab-acell { min-width: 120px; }
.vab-acell a { text-decoration: none; }
.vab-chip { display: block; margin: 0 0 3px; padding: 2px 6px; border-radius: 4px; background: #4d7c0f; color: #fff; font-size: 0.74rem; line-height: 1.25; }
.vab-chip--pending { background: #94a3b8; }
.vab-free { color: var(--mis-ink-muted); font-size: 0.78rem; }
.vab-suggest { margin: 12px 0 0; padding: 12px 14px; border: 1px solid var(--mis-rule); border-radius: 8px; background: var(--mis-surface-soft, #f6f7f9); }
.vab-suggest h4 { margin: 10px 0 6px; font-size: 0.9rem; }
.vab-suggest h4:first-child { margin-top: 0; }
.vab-suggest form { display: inline-block; margin: 0 6px 6px 0; }
.vab-actions { display: flex; gap: 6px; flex-wrap: wrap; align-items: flex-start; }
.vab-actions form { margin: 0; }
.vab-actions details { position: relative; }
.vab-actions details > summary { list-style: none; cursor: pointer; }
.vab-actions details > summary::-webkit-details-marker { display: none; }
.vab-actions details[open] > form { margin-top: 6px; display: grid; gap: 6px; min-width: 220px; }
.vab-kv { display: grid; grid-template-columns: 150px 1fr; gap: 6px 14px; margin: 0 0 16px; }
.vab-kv dt { color: var(--mis-ink-muted); font-weight: 600; font-size: 0.85rem; }
.vab-kv dd { margin: 0; }
/* Everything shows without JavaScript; with it the form hides the fields that do not apply to the chosen item. */
.vab-form.vab-js:not(.vab-form--asset) .vab-only-asset { display: none; }
.vab-form.vab-js.vab-form--asset .vab-only-venue { display: none; }
.vab-radio { display: inline-flex; align-items: center; gap: 6px; margin-right: 16px; font-weight: 400; }
@media (max-width: 768px) {
  .vab-kv { grid-template-columns: 1fr; }
}

/* Asset edit: details card + Service History side by side; one column under 768px */
.asset-edit-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; align-items: start; }
.asset-edit-layout > .card { max-width: none; margin: 0; }
@media (max-width: 768px) { .asset-edit-layout { grid-template-columns: minmax(0, 1fr); } }
.service-entry { border-top: 1px solid var(--mis-border, #e5e7eb); padding: 12px 0; }
.service-entry__head { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 4px; }
.service-entry__meta { font-size: 0.85rem; color: var(--mis-ink-muted, #6b7280); margin: 2px 0 0; }
.service-entry p { margin: 4px 0; white-space: pre-wrap; }
.card-head-row { display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; justify-content: space-between; margin: 0 0 12px; }
.asset-edit-side { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.asset-edit-side > .card { max-width: none; margin: 0; }

/* ── Asset / venue record header: QR + photo + responsible staff (public/assets/_item_header.php) ── */
.item-header { display: flex; flex-wrap: wrap; gap: 20px; align-items: stretch; margin-bottom: 16px; }
.item-header > * { flex: 1 1 240px; min-width: 0; }
.item-header .qr-box { margin-bottom: 0; }
.item-header__block { padding: 16px; background: #f9fafb; border: 1px solid var(--mis-border, #e5e7eb); border-radius: 8px; }
.item-header__block h3 { font-size: 1rem; margin: 0 0 12px; color: var(--mis-ink); }
.pic-stage { width: 100%; max-width: 220px; aspect-ratio: 4 / 3; border-radius: 8px; overflow: hidden; background: #e5e7eb; display: flex; align-items: center; justify-content: center; margin-bottom: 12px; }
.pic-stage img { width: 100%; height: 100%; object-fit: cover; }
.pic-stage img[hidden], .pic-placeholder[hidden] { display: none; }
.pic-placeholder { color: var(--mis-ink-muted, #6b7280); font-size: 0.85rem; text-align: center; padding: 8px; }
.pic-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.pic-btn { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; padding: 8px 14px; border: 1.5px solid #d1d5db; border-radius: 8px; background: #fff; font-size: 14px; font-weight: 600; color: #374151; cursor: pointer; }
.pic-btn:hover { border-color: var(--mis-accent); }
.pic-btn input { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.pic-btn:focus-within { outline: 3px solid rgba(99, 102, 241, 0.35); }
.pic-msg { font-size: 13px; color: #b91c1c; margin: 6px 0; }
.pic-msg:empty { display: none; }
.pic-msg--info { color: var(--mis-ink-muted, #6b7280); }
/* Multi-photo mode (data-multiple): one thumbnail per accepted photo, each with a remove button. */
.pic-list { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
.pic-list:empty { display: none; }
.pic-thumb { position: relative; width: 120px; border: 1px solid var(--mis-border, #e5e7eb); border-radius: 8px; overflow: hidden; background: #fff; }
.pic-thumb img { display: block; width: 100%; height: 90px; object-fit: cover; }
.pic-thumb__name { display: block; padding: 4px 6px; font-size: 11px; line-height: 1.3; color: var(--mis-ink-muted, #6b7280); word-break: break-word; }
.pic-thumb__x { position: absolute; top: 4px; right: 4px; width: 28px; height: 28px; border: 0; border-radius: 50%; background: rgba(17, 24, 39, 0.75); color: #fff; font-size: 18px; line-height: 1; cursor: pointer; }
.pic-thumb__x:hover { background: #b91c1c; }
/* Incident report attachments: the read view's list of photos/diagrams and their inline previews. */
.ir-attachment-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 16px; }
.ir-attachment-list li { max-width: 220px; font-size: 0.9rem; }
.ir-attachment-thumb { display: block; margin-top: 6px; max-width: 200px; max-height: 160px; border: 1px solid var(--mis-border, #e5e7eb); border-radius: 6px; }
.staff-chips { display: flex; flex-wrap: wrap; gap: 12px; }
.staff-chip { display: flex; align-items: center; gap: 10px; }
.staff-chip__avatar { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; flex: 0 0 48px; background: #e0e7ff; }
.staff-chip__initials { display: flex; align-items: center; justify-content: center; font-weight: 700; color: #3730a3; }

/* ── Asset print pages (public/assets/assets-print.php): A4 register + QR label sheet ── */
.print-sheet { background: #fff; color: #111; margin: 0; padding: 10mm; font-family: Arial, sans-serif; }
.print-toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }
.print-head { display: flex; gap: 12px; align-items: center; border-bottom: 2px solid #223369; padding-bottom: 8px; margin-bottom: 10px; }
.print-head__logo { height: 14mm; width: auto; }
.print-head h1 { margin: 0; font-size: 18pt; color: #223369; }
.print-head p { margin: 2px 0 0; font-size: 9pt; color: #555; }
.print-table { width: 100%; border-collapse: collapse; font-size: 8.5pt; }
.print-table th, .print-table td { border: 1px solid #c8ccd8; padding: 3px 5px; text-align: left; vertical-align: top; }
.print-table th { background: #eef0f6; }
.print-table thead { display: table-header-group; }
.print-table tr { page-break-inside: avoid; }
.lbl-grid { display: grid; gap: 0; }
.lbl-grid--2 { grid-template-columns: repeat(2, 1fr); --lbl-h: 50mm; --lbl-qr: 34mm; }
.lbl-grid--3 { grid-template-columns: repeat(3, 1fr); --lbl-h: 38mm; --lbl-qr: 26mm; }
.lbl-grid--4 { grid-template-columns: repeat(4, 1fr); --lbl-h: 38mm; --lbl-qr: 22mm; }
.lbl { height: var(--lbl-h); box-sizing: border-box; border: 1px dashed #9aa1b5; padding: 2mm; display: flex; gap: 2mm; align-items: center; overflow: hidden; break-inside: avoid; page-break-inside: avoid; }
.lbl__qr { width: var(--lbl-qr); height: var(--lbl-qr); flex: 0 0 var(--lbl-qr); }
.lbl__text { min-width: 0; line-height: 1.15; }
.lbl__code { font-size: 12pt; font-weight: 800; color: #223369; font-family: monospace; }
.lbl__name { font-size: 8.5pt; font-weight: 700; }
.lbl__meta { font-size: 6.5pt; color: #444; }
.lbl__scan { font-size: 6.5pt; font-weight: 700; margin-top: 1mm; }
@media print {
  .no-print { display: none !important; }
  .print-sheet { padding: 0; }
}

/* Assets list: Add Asset + PDF/Print side by side */
.asset-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; margin-bottom: 24px; }
.asset-actions__add[open] { flex: 1 0 100%; order: 2; }
.asset-actions__print { position: relative; }
.asset-actions__print summary { cursor: pointer; list-style: none; }
.asset-actions__menu { position: absolute; z-index: 20; top: 100%; left: 0; margin-top: 4px; min-width: 220px; background: #fff; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); }
.asset-actions__menu a { display: block; padding: 10px 16px; color: var(--mis-ink, #1a2233); text-decoration: none; font-size: 0.9rem; }
.asset-actions__menu a + a { border-top: 1px solid var(--mis-rule, #e2e5ec); }

/* QR landing page (public/assets/view.php), signed-in overview */
.av-photo { width: 100%; max-height: 240px; object-fit: cover; border-radius: 10px; margin: 0 0 12px; }
.av-h { font-size: 1rem; margin: 18px 0 6px; color: var(--mis-ink, #1e1b4b); border-top: 1px solid #e5e7eb; padding-top: 12px; }
.av-entry { padding: 8px 0; border-bottom: 1px solid #f0f0f0; font-size: 0.9rem; }
.av-entry p { margin: 2px 0; }
.av-actions { margin-top: 16px; display: flex; flex-direction: column; }
.av-actions .btn { min-height: 48px; justify-content: center; }

/* Venue week schedule print (public/assets/venue-week-print.php) */
.wk { display: grid; grid-template-columns: 16mm repeat(var(--wk-days), 1fr); font-size: 12pt; --wk-row: 5.2mm; }
.wk__corner, .wk__dayhead { border-bottom: 2px solid #223369; padding: 1mm 4px; height: 9mm; box-sizing: border-box; font-size: 15pt; font-weight: 700; text-align: center; background: #eef0f6; }
.wk__times { position: relative; height: calc(var(--wk-row) * var(--wk-rows)); }
.wk__time { position: absolute; right: 2px; font-size: 11.5pt; font-weight: 600; color: #444; transform: translateY(-50%); }
.wk__col { position: relative; height: calc(var(--wk-row) * var(--wk-rows)); border-left: 1px solid #c8ccd8;
  background-image: repeating-linear-gradient(to bottom, #e4e7ef 0, #e4e7ef 0.2mm, transparent 0.2mm, transparent calc(var(--wk-row) * 2)); }
.wk__col:last-child { border-right: 1px solid #c8ccd8; }
.wk__block { position: absolute; box-sizing: border-box; overflow: hidden; padding: 0.4mm 1.2mm; border-radius: 2px; border: 0.3mm solid #0b5f73; background: #0e7490; color: #fff; line-height: 1.15;
  display: -webkit-box; -webkit-box-orient: vertical; text-overflow: ellipsis; word-break: break-word;
  -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.wk__block--pending { background: repeating-linear-gradient(45deg, #d6dbe6, #d6dbe6 1.2mm, #fff 1.2mm, #fff 2.4mm); color: #222; border: 0.3mm dashed #667; }
.wk__time-range { font-weight: 700; }
.wk__block--one { display: block; white-space: nowrap; text-overflow: ellipsis; }
.wk-legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 10pt; margin: 1.5mm 0; height: 4mm; align-items: center; }
.wk-legend i { display: inline-block; width: 5mm; height: 3mm; margin-right: 4px; vertical-align: middle; border-radius: 1px; }
.print-sheet--landscape { padding: 6mm; }
.print-sheet--landscape .print-head h1 { font-size: 20pt; }
.print-sheet--landscape .print-head p { font-size: 10.5pt; }
.print-sheet--landscape .print-head { margin-bottom: 2mm; padding-bottom: 2mm; }
@media print { .print-sheet--landscape { padding: 0; } }
/* venues list: per-row actions menu (fixed-position so .table-scroll cannot clip it) + bookable icon */
.row-menu summary { cursor: pointer; list-style: none; }
.row-menu summary::-webkit-details-marker { display: none; }
.row-menu summary { white-space: nowrap; }
.row-menu__list { position: fixed; z-index: 1000; min-width: 220px; background: #fff; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 6px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); }
.row-menu__list a, .row-menu__list button { display: block; width: 100%; box-sizing: border-box; padding: 10px 16px; border: 0; background: none; text-align: left; font: inherit; font-size: 0.9rem; color: var(--mis-ink, #1a2233); text-decoration: none; cursor: pointer; }
.row-menu__list a:hover, .row-menu__list button:hover, .row-menu__list a:focus, .row-menu__list button:focus { background: var(--mis-wash, #eef3f8); }
.row-menu__list .row-menu__danger { color: var(--mis-error, #c00); }
.row-menu__list form { margin: 0; }
.row-menu__list > * + * { border-top: 1px solid var(--mis-rule, #e2e5ec); }
.venue-bookable-icon { font-size: 1.1rem; vertical-align: -4px; color: var(--mis-accent, #4f46e5); margin-left: 4px; }

/* Record header: right-hand column stacks Responsible staff, then (venues) the bookings card */
.item-header__side { flex: 2 1 420px; display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.item-header__side > .card { max-width: none; margin: 0; }

/* Venue edit: clean two-column record layout (independent columns, stacks under 768px) */
.rec-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; align-items: start; }
.rec-col { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.rec-col > .card, .rec-col > .item-header__block { max-width: none; margin: 0; }
.rec-col > h2 { margin: 4px 0 0 !important; }
@media (max-width: 768px) { .rec-cols { grid-template-columns: minmax(0, 1fr); } }
.rec-col { overflow-x: auto; }

/* Bookings: venue day grid uses the asset week table (.vab-agrid); booking dialog */
.vab-vgrid .vab-acell { min-width: 64px; padding: 4px 6px; }
.vab-vgrid th { white-space: nowrap; }
.vab-chip--venue { background: #0e7490; }
.vab-chip--venue.vab-chip--pending { background: #94a3b8; }
.vab-chip--mine { box-shadow: 0 0 0 2px #f59e0b; }
.vab-free:hover { color: var(--mis-accent, #223369); text-decoration: underline; }
.mis-dialog--form { width: min(720px, 96vw); max-height: 92vh; overflow-y: auto; }

/* Venue Responsible staff card */
.staff-rules { margin: 0 0 8px; padding-left: 18px; }
.staff-row-actions { display: inline-block; margin: 0 4px 0 0; }
.staff-add-toggle { margin-top: 14px; }
.staff-add-toggle > summary { cursor: pointer; list-style: none; display: inline-block; }
.staff-add-toggle > summary::-webkit-details-marker { display: none; }
.staff-add-toggle[open] > summary { margin-bottom: 4px; }
.staff-add { margin-top: 14px; border-top: 1px solid var(--mis-border, #e5e7eb); padding-top: 12px; }

/* Chrome-less embed (new-asset form inside the venue page's dialog iframe) */
.embed-body { background: #fff; margin: 0; }
.embed-wrap { padding: 12px 16px; }
.embed-title { font-size: 1.1rem; margin: 0 0 12px; }
.mis-dialog--tall { width: min(980px, 96vw); height: min(90vh, 900px); }
.mis-dialog--tall[open] { display: flex; flex-direction: column; overflow: hidden; }
.mis-dialog--tall iframe { flex: 1 1 auto; width: 100%; border: 0; min-height: 0; }

/* Venue Bookings card header: the PDF/Print/CSV menu sits beside "Book this venue", its list right-aligned so it stays on screen */
.card-head-row__actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; justify-content: flex-end; }
.asset-actions__print--right .asset-actions__menu { left: auto; right: 0; }

/* ==========================================================================
   .meals-planner — Meal Planner (table view), public/meals/planner.php
   One table per week; rows = dates / meal options / combos; columns = picture,
   date+name+prices (one first column), one per person, messages. On a desktop
   the picture + date columns and the header row are sticky inside the
   .table-scroll wrapper; below 820px each row is a CARD instead (see the block
   at the end of this section). Sticky summary bar at the bottom. A picture
   grows to screen size on click / tap (.mp-preview), one animation.
   Tokens only (--mis-*).
   ========================================================================== */
.meals-planner .mp-topbar { margin: 0 0 12px; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.meals-planner .mp-help { margin: 0 0 16px; max-width: 70ch; }
/* The picture column's width in the desktop/tablet-landscape TABLE (> 820px only — below that the
   rows are cards, see the "phones and tablet portrait" block at the end of this section). */
.meals-planner { --mp-pic-w: 150px; }
/* A week with a combo shows the weekly menu poster: a wide picture column, so the poster is seen in full width as well as full height (Henko, 2026-10-26). */
.meals-planner .mp-table--poster { --mp-pic-w: clamp(200px, 36vw, 480px); }
.meals-planner .mp-week { margin: 0 0 16px; border: 1px solid var(--mis-rule); border-radius: 8px; background: var(--mis-surface); overflow: hidden; }   /* hidden: the first column's pictures run into the card's rounded corners */
.meals-planner .mp-week > summary { cursor: pointer; padding: 12px 16px; color: var(--mis-accent); list-style-position: inside; min-height: 44px; display: flex; align-items: center; gap: 12px; }
.meals-planner .mp-week__count { margin-left: auto; font-size: 0.8rem; color: var(--mis-ink-muted); }
.meals-planner .mp-table { min-width: 860px; table-layout: auto; }
.meals-planner .mp-table th,
.meals-planner .mp-table td { vertical-align: top; }
.meals-planner .mp-table thead th { position: sticky; top: 0; z-index: 2; background: var(--mis-surface); white-space: nowrap; }
.meals-planner .mp-col-date { position: sticky; left: var(--mp-pic-w); z-index: 1; min-width: 240px; max-width: 340px; background: var(--mis-surface); box-shadow: 1px 0 0 var(--mis-rule); text-align: left; }
.meals-planner .mp-table thead .mp-col-date { z-index: 3; }
.meals-planner .mp-zebra-1 > td,
.meals-planner .mp-zebra-1 > th { background: var(--mis-wash); }
.meals-planner .mp-row--combo > td,
.meals-planner .mp-row--combo > th { background: var(--mis-accent-soft, var(--mis-wash)); }
.meals-planner .mp-col-pic { width: var(--mp-pic-w); min-width: var(--mp-pic-w); max-width: var(--mp-pic-w); padding: 0; border: 0; position: sticky; left: 0; z-index: 1; background: var(--mis-surface); box-shadow: 1px 0 0 var(--mis-rule); }
.meals-planner .mp-table thead .mp-col-pic { z-index: 3; background: transparent; box-shadow: none; }
/* The first picture of each week also covers the header row above it: header row + first meal row, top corner to bottom (Henko, 2026-10-26).
   --mp-head-h is the header's height, set by a small script in planner.php. */
.meals-planner .mp-table tbody tr:first-child .mp-col-pic { z-index: 4; }
.meals-planner .mp-table tbody tr:first-child .mp-photo { top: calc(-1 * var(--mp-head-h, 0px)); }
/* A combo's weekly menu poster is shown whole - full width AND top to bottom: it is laid out in the cell at its own shape (the row
   grows to fit it) instead of being cropped to the row. When it is the week's first row it still reaches up over the header row. */
.meals-planner .mp-row--combo .mp-photo { position: static; inset: auto; width: 100%; }
.meals-planner .mp-row--combo .mp-thumb { width: 100%; height: auto; object-fit: contain; }
.meals-planner .mp-table tbody tr.mp-row--combo:first-child .mp-photo { margin-top: calc(-1 * var(--mp-head-h, 0px)); }
/* The picture fills its cell top to bottom — as tall as the row/card it sits in (Henko, 2026-10-26). */
.meals-planner .mp-photo { position: absolute; inset: 0; display: block; cursor: zoom-in; overflow: hidden; }
.meals-planner .mp-thumb { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Hover / tap preview: the full picture, much bigger than the cell (Henko, 2026-10-26). */
.mp-preview { position: fixed; inset: 0; z-index: 1200; display: flex; align-items: center; justify-content: center; padding: 12px; background: rgba(15, 23, 42, 0.86); }
.mp-preview[hidden] { display: none; }
.mp-preview__img { display: block; max-width: calc(100vw - 24px); max-height: calc(100vh - 24px); max-width: calc(100dvw - 24px); max-height: calc(100dvh - 24px); border-radius: 10px; background: #fff; box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5); will-change: transform; }
.mp-preview__close { position: absolute; top: 12px; right: 12px; min-width: 44px; min-height: 44px; border: 0; border-radius: 999px; background: rgba(255, 255, 255, 0.92); color: #111; font-size: 1.4rem; line-height: 1; cursor: pointer; }
.meals-planner .mp-name { font-weight: 600; }
.meals-planner .mp-desc { color: var(--mis-ink-muted); font-size: 0.85rem; margin-top: 2px; }
.meals-planner .mp-col-person { text-align: center; min-width: 96px; }
.meals-planner .mp-col-msg { min-width: 200px; font-size: 0.85rem; }
.meals-planner .mp-sub { display: block; font-size: 0.75rem; font-weight: 400; color: var(--mis-ink-muted); }
.meals-planner .mp-combo-tag { display: block; width: max-content; max-width: 100%; margin-bottom: 4px; padding: 1px 8px; border-radius: 999px; font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; background: var(--mis-accent); color: #fff; }
.meals-planner .mp-pick { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-width: 44px; min-height: 44px; cursor: pointer; }
.meals-planner .mp-pick input { width: 22px; height: 22px; cursor: pointer; }
.meals-planner .mp-pick__amt { font-size: 0.75rem; color: var(--mis-ink-muted); }
.meals-planner .mp-muted { color: var(--mis-ink-muted); font-size: 0.8rem; }
.meals-planner .mp-muted--err { color: var(--mis-clay-ink); }
.meals-planner .mp-cell--covered .mp-pick { opacity: 0.4; }
.meals-planner .mp-cancel { display: block; margin: 4px auto 0; min-height: 36px; }
.meals-planner .mp-stray { margin-top: 8px; padding-top: 6px; border-top: 1px dashed var(--mis-line, #d6d3c8); text-align: center; }
.meals-planner .mp-stray small { display: block; color: var(--mis-error, #b3261e); }
.meals-planner .mp-line { margin-top: 6px; }
.meals-planner .mp-msg { margin: 0 0 4px; }
.meals-planner .mp-msg--ok { color: var(--mis-accent-ink); }
.meals-planner .mp-msg--warn { color: var(--mis-gold-ink); }
.meals-planner .mp-msg--err { color: var(--mis-clay-ink); font-weight: 600; }
.meals-planner .mp-msg--info { color: var(--mis-ink-muted); }
.meals-planner .mp-summary { position: sticky; bottom: 0; z-index: 5; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; margin-top: 16px; padding: 12px 16px; background: var(--mis-surface); border: 1px solid var(--mis-rule); border-radius: 8px; box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.08); }
.meals-planner .mp-summary__people { display: flex; flex-wrap: wrap; gap: 8px; flex: 1 1 280px; }
.meals-planner .mp-chip { padding: 4px 10px; border-radius: 999px; border: 1px solid var(--mis-rule); font-size: 0.8rem; }
.meals-planner .mp-chip--on { background: var(--mis-wash); border-color: var(--mis-accent); }
.meals-planner .mp-summary__total { font-size: 1rem; }
/* Ordered previously (saved) vs Selected now (not yet saved) */
.meals-planner .mp-badge--prev { display: inline-block; padding: 4px 10px; border-radius: 999px; font-size: 0.78rem; font-weight: 700; background: var(--mis-accent-soft, #e3f1e6); color: var(--mis-accent-ink); border: 1px solid var(--mis-accent); }
.meals-planner .mp-pick--on { background: var(--mis-gold-soft, #fff6dc); outline: 2px dashed var(--mis-gold-ink); outline-offset: 1px; border-radius: 8px; padding: 4px 6px; }
.meals-planner .mp-pick__now { font-size: 0.7rem; font-weight: 600; line-height: 1.2; color: var(--mis-gold-ink); max-width: 14ch; }
.meals-planner .mp-pick__now[hidden] { display: none; }
.meals-planner .mp-rownote { margin: 6px 0 0; font-size: 0.8rem; font-weight: 400; }
.meals-planner .mp-rownote__done { color: var(--mis-accent-ink); }
.meals-planner .mp-rownote__todo { color: var(--mis-gold-ink); font-weight: 600; }
.meals-planner .mp-row--partial > .mp-col-date { box-shadow: inset 4px 0 0 var(--mis-gold-ink), 1px 0 0 var(--mis-rule); }
.meals-planner .mp-summary__group { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; flex: 1 1 300px; min-width: 0; }
.meals-planner .mp-summary__title { flex: 1 1 100%; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--mis-ink-muted); }
.meals-planner .mp-summary__group .mp-summary__people { flex: 1 1 auto; }
.meals-planner .mp-chip--prev { background: var(--mis-accent-soft, #e3f1e6); border-color: var(--mis-accent); }
.meals-planner .mp-summary .btn { min-height: 44px; }
/* Two columns when something was ordered before: left = already ordered, right = this round (chips, total and the Place orders button together). */
.meals-planner .mp-summary--split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr); gap: 12px 28px; align-items: start; }
.meals-planner .mp-summary--split .mp-summary__group--now { padding-left: 24px; border-left: 1px solid var(--mis-rule); }
.meals-planner .mp-summary__group--now .btn { margin-left: auto; flex: 0 0 auto; }
/* keep the fixed "How do I…" launcher (right 16px, ~170px wide) clear of the Place orders button */
.meals-planner .mp-summary { padding-right: 200px; }

/* Prices live under the combo's date (first column) or a single meal's description - there is no Price column any more. */
.meals-planner .mp-datecell-prices { margin-top: 10px; font-size: 0.85rem; font-weight: 400; color: var(--mis-ink); }
.meals-planner .mp-datecell-prices .mp-line { margin-top: 6px; font-weight: 600; }

/* Tablet landscape / small laptop: still the table, but the two sticky columns are
   narrowed so the person columns get most of the width before it has to scroll. */
@media (min-width: 821px) and (max-width: 1100px) {
  .meals-planner { --mp-pic-w: 110px; }
  .meals-planner .mp-table--poster { --mp-pic-w: clamp(180px, 26vw, 340px); }
  .meals-planner .mp-col-date { min-width: 200px; max-width: 260px; }
}

/* ── Phones and tablet portrait: the table becomes a stack of cards ───────────
   Below 820px the table's 860px min-width is wider than the screen, and its two
   sticky columns (thumbnail + date) alone fill a phone — so the person columns
   that actually carry the ticks could never be reached. One card per row
   instead: picture + name/description/prices on the first band, one cell per
   linked person underneath (each named above its tick), messages last. Nothing
   scrolls sideways and nothing is sticky except the summary bar, which is where
   the button is. The thead is clipped rather than display:none so the column
   headings stay in the accessibility tree (each checkbox also has its own
   aria-label). A combo's weekly poster still shows whole, across the full width
   of the card (Henko, 2026-10-26). */
@media (max-width: 820px) {
  .meals-planner { --mp-thumb: clamp(96px, 16vw, 132px); }
  .meals-planner .table-scroll { overflow: visible; }
  .meals-planner .mp-table { display: block; min-width: 0; border: 0; border-radius: 0; }
  .meals-planner .mp-table tbody { display: block; }
  .meals-planner .mp-table thead {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
  .meals-planner .mp-row { display: flex; flex-wrap: wrap; border-top: 1px solid var(--mis-rule); }
  .meals-planner .mp-row:first-child { border-top: 0; }
  /* Undo the table-cell + sticky-column treatment on every cell of the row. */
  .meals-planner .mp-row > th,
  .meals-planner .mp-row > td {
    display: block; position: static; width: auto; min-width: 0; max-width: none;
    border-bottom: 0; box-shadow: none;
  }
  /* First band: the thumbnail fills the band's height, exactly as the desktop column does. */
  .meals-planner .mp-row > .mp-col-pic { flex: 0 0 var(--mp-thumb); position: relative; min-height: 96px; }
  .meals-planner .mp-row > .mp-col-pic--empty { display: none; }
  /* The date cell takes the rest of the band (its min-width is what pushes the
     person cells onto the next line), so the picture and the text sit side by side. */
  .meals-planner .mp-row > .mp-col-date {
    flex: 1 1 0; min-width: calc(100% - var(--mp-thumb) - 1px); padding: 10px 12px;
  }
  .meals-planner .mp-datecell-prices { margin-top: 6px; }
  /* A combo's poster is shown whole, across the full width of the card; its text block
     then takes the whole line below it (min-width: 100%) so no person cell squeezes in
     beside the description. */
  .meals-planner .mp-row--combo > .mp-col-pic { flex: 1 1 100%; min-height: 0; }
  .meals-planner .mp-row--combo > .mp-col-date { min-width: 100%; }
  .meals-planner .mp-row--combo .mp-thumb { max-height: 70vh; }
  /* One cell per linked person: the name above, the tick filling the cell. */
  .meals-planner .mp-row > .mp-col-person {
    flex: 1 1 88px; padding: 8px 6px 10px; border-top: 1px solid var(--mis-rule-soft);
  }
  .meals-planner .mp-row > .mp-col-person::before {
    content: attr(data-label); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    margin-bottom: 2px; overflow: hidden; font-size: 0.72rem; font-weight: 600; line-height: 1.2;
    color: var(--mis-ink-muted);
  }
  .meals-planner .mp-row > .mp-col-person .mp-pick { width: 100%; }
  .meals-planner .mp-row > .mp-col-person .mp-cancel { min-height: 44px; }
  .meals-planner .mp-row > .mp-col-msg { flex: 1 1 100%; padding: 6px 12px 12px; }
  /* The summary bar: its chips scroll sideways on one line, then the total and the
     button share the next one instead of the button taking a whole row. */
  .meals-planner .mp-summary { padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px)); gap: 8px 12px; }
  .meals-planner .mp-summary { padding-right: 188px; }
  .meals-planner .mp-summary__people { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 2px; }
  .meals-planner .mp-summary__group { flex: 1 1 100%; gap: 4px 10px; }
  .meals-planner .mp-summary__title { font-size: 0.66rem; }
  .meals-planner .mp-summary--split { display: flex; }
  .meals-planner .mp-summary--split .mp-summary__group--now { padding-left: 0; border-left: 0; }
  .meals-planner .mp-summary__group--prev .mp-summary__people { display: none; }  /* phone: previous orders collapse to the one-line total */
  .meals-planner .mp-summary__group--prev .mp-summary__title { display: none; }       /* the one-line total below already says "Ordered previously" */
  .meals-planner .mp-summary__group--prev .mp-summary__total { font-size: 0.85rem; }
  .meals-planner .mp-summary__group--now .mp-summary__total { font-size: 0.9rem; flex: 1 1 auto; }
  .meals-planner .mp-summary__group .i18n-cn,
  .meals-planner .mp-summary__group .i18n-th { display: none; }                       /* phone: English only inside the bar so it stays two short lines */
  .meals-planner .mp-row > .mp-col-person .mp-badge--prev { white-space: normal; }
  .meals-planner .mp-row > .mp-col-person .mp-pick__now { max-width: none; }
  .meals-planner .mp-chip { white-space: nowrap; }
  .meals-planner .mp-summary__total { flex: 1 1 auto; }
  .meals-planner .mp-summary .btn { width: auto; flex: 0 0 auto; }
}

/* ---- AgentTTT "How do I..." helper (public/scripts/howdoi.js) ---- */
/* z-index stays below the emergency banner (99998) and lockdown overlay (999999), above sidebar/modals (<= 10001). */
.howdoi-launcher { position: fixed; right: 16px; bottom: 16px; z-index: 90000; display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px; border: 0; border-radius: 999px; background: var(--mis-navy, #223369); color: #fff; font: inherit; font-weight: 600; cursor: pointer; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25); }
.howdoi-launcher:hover, .howdoi-launcher:focus-visible { background: #1a2852; }
.howdoi-launcher__icon { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 50%; background: #fff; color: var(--mis-navy, #223369); font-weight: 700; }
.howdoi-panel { position: fixed; right: 16px; bottom: 72px; z-index: 90001; width: 380px; max-width: calc(100vw - 32px); max-height: 70vh; display: flex; flex-direction: column; background: #fff; color: var(--mis-ink, #1f2937); border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); }
.howdoi-panel__head { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--mis-rule, #e2e5ec); }
.howdoi-panel__title { flex: 1 1 auto; color: var(--mis-navy, #223369); }
.howdoi-panel__body { padding: 12px; overflow-y: auto; }
.howdoi-btn { min-height: 44px; min-width: 44px; }
.howdoi-item { display: flex; flex-direction: column; gap: 4px; width: 100%; min-height: 44px; margin-bottom: 8px; padding: 10px 12px; text-align: left; font: inherit; background: #fff; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 8px; cursor: pointer; }
.howdoi-item:hover, .howdoi-item:focus-visible { border-color: var(--mis-navy, #223369); }
.howdoi-muted { color: var(--mis-ink-muted, #6b7280); font-size: 0.875rem; }
.howdoi-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.howdoi-h { margin: 16px 0 6px; font-size: 1rem; }
.howdoi-list { margin: 0 0 8px 18px; padding: 0; }
.howdoi-faq { margin-bottom: 6px; }
.howdoi-faq summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; font-weight: 600; }
.howdoi-overlay { position: fixed; inset: 0; z-index: 90002; pointer-events: auto; }
.howdoi-overlay--dim { background: rgba(15, 23, 42, 0.6); }
.howdoi-ring { position: fixed; border-radius: 8px; box-shadow: 0 0 0 9999px rgba(15, 23, 42, 0.6), 0 0 0 3px #fff; pointer-events: none; transition: left .2s, top .2s, width .2s, height .2s; }
.howdoi-card { position: fixed; width: 340px; max-width: calc(100vw - 16px); max-height: calc(100vh - 16px); overflow-y: auto; box-sizing: border-box; padding: 14px 16px; background: #fff; color: var(--mis-ink, #1f2937); border-radius: 12px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35); outline: none; }
.howdoi-card__count { color: var(--mis-navy, #223369); font-weight: 700; font-size: 0.8125rem; text-transform: uppercase; letter-spacing: .04em; }
.howdoi-card__text { margin: 6px 0; }
.howdoi-card__tip { margin: 6px 0; padding: 8px 10px; background: #eef1fa; border-radius: 8px; font-size: 0.9rem; }
.howdoi-options { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.howdoi-opt { text-align: left; justify-content: flex-start; }
.howdoi-opt--right { background: #e6f4ea !important; border-color: #2e7d32 !important; }
.howdoi-opt--wrong { background: #fdecea !important; border-color: #c62828 !important; }
@media (prefers-reduced-motion: reduce) { .howdoi-ring { transition: none; } }
@media (max-width: 768px) {
  .howdoi-launcher { right: 12px; bottom: 12px; }
  .howdoi-panel { right: 0; left: 0; bottom: 0; width: auto; max-width: none; max-height: 75vh; border-radius: 16px 16px 0 0; }
  .howdoi-card { width: calc(100vw - 16px); }
}

/* ── MISOS Articles (AgentTTT management pages: /admin/misos-articles.php, misos-article.php) ───────────── */
.arts-intro { max-width: 820px; margin: 0 0 16px; }
.arts-banner { border: 1px solid #e0b100; background: #fff8dc; color: #4a3a00; border-radius: 10px; padding: 12px 16px; margin: 0 0 16px; max-width: 920px; }
.arts-banner p { margin: 0; }
.arts-tabs { display: flex; flex-wrap: wrap; gap: 4px; border-bottom: 2px solid var(--mis-rule); margin: 0 0 20px; }
.arts-tabs a { padding: 10px 14px; text-decoration: none; color: var(--mis-navy, #223369); border-bottom: 3px solid transparent; margin-bottom: -2px; font-weight: 600; white-space: nowrap; }
.arts-tabs a:hover { background: var(--mis-wash, #eef3f8); }
.arts-tabs a.is-active { border-bottom-color: var(--mis-navy, #223369); }
.arts-head { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 0 0 14px; }
.arts-head h2 { margin: 0; }
.arts-chip { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: .78rem; border: 1px solid var(--mis-rule); color: #6b7280; background: #fff; margin-right: 4px; }
.arts-chip.is-on { background: #e4f4e8; border-color: #8cc9a0; color: #1d5b32; }
.arts-badge { display: inline-block; padding: 2px 9px; border-radius: 6px; font-size: .78rem; font-weight: 600; background: var(--mis-wash, #eef3f8); color: #223369; }
.arts-badge--ok { background: #e4f4e8; color: #1d5b32; }
.arts-badge--warn { background: #fff1d6; color: #7a4b00; }
.arts-badge--bad { background: #fde3e3; color: #9b1c1c; }
.arts-card { border: 1px solid var(--mis-rule); border-radius: 12px; padding: 16px 18px; margin: 0 0 16px; background: var(--mis-surface, #fff); max-width: 1100px; }
.arts-card > h3, .arts-card > h2 { margin-top: 0; }
.arts-card__head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; margin-bottom: 10px; }
.arts-langs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.arts-langs label { display: block; font-size: .8rem; font-weight: 600; color: #4b5563; margin-bottom: 2px; }
.arts-langs textarea, .arts-langs input { width: 100%; box-sizing: border-box; }
.arts-count { font-weight: 400; color: #6b7280; margin-left: 6px; }
.arts-step { display: grid; grid-template-columns: minmax(0, 1fr) 190px; gap: 16px; align-items: start; }
.arts-step__shot img { width: 100%; height: auto; border: 1px solid var(--mis-rule); border-radius: 8px; display: block; }
.arts-step__opts { display: flex; flex-wrap: wrap; gap: 8px 22px; margin: 6px 0 10px; }
.arts-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 12px; }
.arts-checks { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 6px 14px; }
.arts-checks label { display: flex; gap: 8px; align-items: center; }
.arts-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; margin-bottom: 16px; }
.arts-tile { border: 1px solid var(--mis-rule); border-radius: 12px; padding: 12px 14px; background: var(--mis-surface, #fff); }
.arts-tile strong { display: block; font-size: 1.6rem; color: #223369; line-height: 1.1; }
.arts-tile span { font-size: .82rem; color: #6b7280; }
.arts-frame { width: 100%; max-width: 760px; height: 640px; border: 1px solid var(--mis-rule); border-radius: 10px; background: #fff; display: block; }
.arts-frame--pdf { height: 720px; }
.arts-pre { white-space: pre-wrap; word-break: break-word; background: var(--mis-wash, #eef3f8); border-radius: 8px; padding: 12px 14px; max-height: 420px; overflow: auto; font-size: .85rem; margin: 0; }
.arts-shots { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.arts-shots .arts-card { margin: 0; }
.arts-shots img { width: 100%; height: auto; border: 1px solid var(--mis-rule); border-radius: 8px; display: block; margin-bottom: 8px; }
.arts-sub { margin: 18px 0 8px; font-size: 1.02rem; }
.arts-mini { font-size: .85rem; color: #6b7280; }
.arts-people { max-height: 300px; overflow: auto; border: 1px solid var(--mis-rule); border-radius: 8px; padding: 8px 12px; }
.arts-people label { display: flex; gap: 8px; align-items: center; padding: 2px 0; }
.arts-mono { font-family: ui-monospace, Menlo, monospace; font-size: .85rem; }
@media (max-width: 900px) {
  .arts-tabs { flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; scrollbar-width: thin; }
  .arts-langs { grid-template-columns: 1fr; }
  .arts-step { grid-template-columns: 1fr; }
  .arts-step__shot { max-width: 260px; }
  .arts-frame { height: 520px; }
}
.arts-sr { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.arts-note { max-width: 560px; }
.arts-checks { margin-bottom: 14px; }

/* MISOS Articles + How-do-I: supervisor part, button rows, full-width previews (2026-10-26 b) */
.arts-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.arts-frame--wide { max-width: none; width: 100%; height: 80vh; min-height: 600px; }
.arts-langrows { display: grid; gap: 8px; margin: 0 0 14px; }
.arts-langrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.arts-langrow__label { display: inline-block; min-width: 84px; font-weight: 600; color: #223369; }
.arts-langrows__title { margin: 12px 0 8px; }
.arts-sup { border: 2px solid #f0b429; background: #fffaf0; }
.arts-sup__h { color: #7a4b00; }
.howdoi-suptag { display: inline-block; margin: 0 0 6px; padding: 3px 10px; border-radius: 6px; background: #fabe28; color: #46280a; font-size: .8125rem; font-weight: 700; }
.howdoi-card--sup { border-top: 6px solid #f0b429; }
.howdoi-actions--sup { margin-top: 14px; padding-top: 12px; border-top: 1px dashed #f0b429; }
.howdoi-btn--sup { border-color: #f0b429; background: #fff6dc; color: #7a4b00; }
@media (max-width: 768px) { .arts-frame--wide { height: 70vh; min-height: 420px; } .arts-langrow__label { min-width: 100%; } }

/* AgentTTT: language review page + the Languages & review tab (2026-10-26 c) */
.rv-intro { max-width: 1100px; margin: 0 0 18px; padding: 14px 18px; border: 1px solid var(--mis-rule); border-radius: 12px; background: var(--mis-wash, #eef3f8); }
.rv-intro ul { margin: 8px 0 12px; padding-left: 20px; }
.rv-previews { display: flex; flex-wrap: wrap; gap: 8px; }
.rv-group { max-width: 1100px; margin: 0 0 22px; padding: 0; min-height: 0; }
.rv-group > h2 { font-size: 1.15rem; color: #223369; margin: 0 0 10px; padding-bottom: 6px; border-bottom: 2px solid var(--mis-rule); }
.rv-field { border: 1px solid var(--mis-rule); border-radius: 12px; padding: 12px 14px; margin: 0 0 12px; background: var(--mis-surface, #fff); }
.rv-field__label { font-size: .85rem; font-weight: 700; color: #223369; margin: 0 0 8px; }
.rv-field__cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; align-items: start; }
.rv-en { color: #5b6680; }
.rv-tag { display: inline-block; font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; margin-bottom: 4px; }
.rv-en__text { white-space: normal; word-break: break-word; background: #f6f7fa; border-radius: 8px; padding: 8px 10px; }
.rv-shot { display: block; max-width: 240px; width: 100%; height: auto; margin-top: 8px; border: 1px solid var(--mis-rule); border-radius: 8px; }
.rv-edit { margin: 0; }
.rv-edit textarea { width: 100%; box-sizing: border-box; }
.rv-bar { position: sticky; bottom: 0; background: var(--mis-surface, #fff); padding: 10px 0; border-top: 1px solid var(--mis-rule); max-width: 1100px; }
.rv-finish { max-width: 1100px; margin: 26px 0 30px; padding: 16px 18px; border: 2px solid #223369; border-radius: 12px; }
.rv-finish h2 { margin-top: 0; }
@media (max-width: 768px) { .rv-field__cols { grid-template-columns: 1fr; } }
.lng-table td, .lng-table th { vertical-align: middle; }
.lng-copy { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.lng-copy input { flex: 1 1 320px; min-width: 0; }
.lng-copied { color: #1d5b32; font-weight: 700; }
.lng-hint { background: #fff1d6; border: 1px solid #f0b429; border-radius: 8px; padding: 8px 12px; margin: 8px 0; color: #7a4b00; }
.arts-tag-off { display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 4px; font-size: .7rem; font-weight: 700; background: #f3f4f6; color: #6b7280; }
.arts-chip--sub { background: #fff1d6; border-color: #f0b429; color: #7a4b00; }

/* Pick-many field (public/js/pick-chips.js): chosen people as chips, a select to add one more. Used by
   the Assignment card on /assets/asset-edit.php. Built from the same variables as the payroll actor chips. */
.pick-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.pick-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 6px 3px 10px;
  border: 1px solid #d8dce6; border-radius: 999px; background: #f4f6fb; font-size: 0.85rem;
}
.pick-chip__x {
  border: 0; background: none; cursor: pointer; font-size: 1.05rem; line-height: 1;
  padding: 0 3px; color: var(--mis-ink-muted);
}
.pick-chip__x:hover, .pick-chip__x:focus-visible { color: #b42318; }
.pick-add { width: auto; min-width: 14rem; max-width: 100%; }

/* --- Asset bundle badge on the asset list (2026-10-26) --- */
/* The icon matches .venue-bookable-icon (same size / baseline) but in the bundle teal, so "in a bundle" and
   "bookable" read as two different facts. The card is position:fixed and moved by public/js/bundle-tip.js, because
   .table-scroll and .dashboard-content would clip an absolutely positioned one; display:none while hidden also keeps
   its "Open bundle" link out of the tab order until the badge is opened. */
.bundle-tip { display: inline; }
.bundle-tip__icon { color: #0e7490; }
.bundle-tip__link { display: inline-block; text-decoration: none; border-radius: 4px; }
.bundle-tip__link:hover .bundle-tip__icon, .bundle-tip__link:focus-visible .bundle-tip__icon { color: #155e75; }
.bundle-tip__link:focus-visible { outline: 2px solid #0e7490; outline-offset: 1px; }
.bundle-tip__card {
  display: none; position: fixed; z-index: 1100; width: 280px; max-width: calc(100vw - 16px); box-sizing: border-box;
  padding: 10px 12px; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 8px;
  background: var(--mis-surface, #fff); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.16);
  font-size: 0.85rem; line-height: 1.35; color: var(--mis-ink, #1a2233); text-align: left;
}
.bundle-tip__card.is-open { display: block; }
.bundle-tip__head { display: block; font-weight: 700; color: #223369; margin-bottom: 4px; }
.bundle-tip__code { font-weight: 400; color: var(--mis-ink-muted, #5b6680); font-family: monospace; font-size: 0.8rem; }
.bundle-tip__line { display: block; color: var(--mis-ink-muted, #5b6680); margin-top: 2px; }
.bundle-tip__open { display: inline-block; margin-top: 8px; font-weight: 700; color: #0e7490; text-decoration: none; }
.bundle-tip__open:hover, .bundle-tip__open:focus-visible { text-decoration: underline; }

/* ---- Asset week roster (card on asset-edit.php, print sheet asset-week-print.php) ---- */
.aroster-pick { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin: 8px 0; }
.aroster-pick .form-row { margin: 0; }
.aroster-pick__btns, .aroster-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.aroster-actions { margin-top: 12px; }
.aroster-list { margin: 6px 0; padding-left: 18px; font-size: 0.9rem; }
.aroster-list li { margin-bottom: 3px; overflow-wrap: anywhere; }
.wk__block--bundle { background: #5b3fa0; border-color: #45307c; }
.wk__block--bundle.wk__block--pending { background: repeating-linear-gradient(45deg, #d9d0ee, #d9d0ee 1.2mm, #fff 1.2mm, #fff 2.4mm); color: #222; border: 0.3mm dashed #5b3fa0; }
.aroster-table { width: 100%; border-collapse: collapse; font-size: 9pt; margin-top: 4mm; }
.aroster-table th, .aroster-table td { border: 1px solid #c8ccd8; padding: 1mm 2mm; text-align: left; vertical-align: top; }
.aroster-table th { background: #eef0f6; color: #223369; }
.aroster-table tr { break-inside: avoid; }
.aroster-table thead { display: table-header-group; }

/* Non-Teaching: "＋ Add a new role…" dialog on /school/non-teaching.php */
.nt-role-dialog .form-actions { justify-content: flex-end; }
.nt-role-dialog .alert[hidden] { display: none; }

/* ===== THRIVE student page (public/thrive.php) ===== */
.thrive-body { margin: 0; background: var(--mis-bg, #f3f5fa); color: var(--mis-ink, #1c2540); }
.thrive-wrap { max-width: 760px; margin: 0 auto; padding: 16px 14px 120px; box-sizing: border-box; }
.thrive-logo { display: block; height: 2.5rem; width: auto; max-width: 100%; margin: 4px 0 14px; }
.thrive-card { background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.07); padding: 18px; margin: 0 0 16px; overflow-wrap: anywhere; }
.thrive-card--notice { text-align: center; padding: 28px 18px; margin-top: 10vh; }
/* A review ("test") link: the banner above the questionnaire itself (migration 0331). */
.thrive-card--review { border-left: 4px solid var(--mis-accent, #223369); background: var(--mis-accent-soft, #dde3f0); }
.thrive-card--review h1 { font-size: 1.15rem; }
.thrive-card--review p { margin: 4px 0; }
.thrive-card h1, .thrive-card h2, .thrive-card h3, .thrive-card h4 { margin: 0 0 8px; color: var(--mis-accent, #223369); }
.thrive-card h1 { font-size: 1.4rem; }
.thrive-part { margin: 22px 0 10px; color: var(--mis-accent, #223369); font-size: 1.2rem; }
.thrive-en, .thrive-zh { display: block; }
.thrive-zh { color: var(--mis-ink-muted, #4b5563); }
.thrive-who { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin: 12px 0 16px; }
.thrive-who div { background: var(--mis-accent-soft, #dde3f0); border-radius: 8px; padding: 8px 10px; }
.thrive-who dt { font-size: 0.75rem; color: var(--mis-ink-muted, #4b5563); }
.thrive-who dd { margin: 0; font-weight: 600; }
.thrive-legend summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; font-weight: 600; }
.thrive-legend ul { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 10px; }
.thrive-domain { display: flex; gap: 12px; align-items: center; margin-bottom: 10px; }
.thrive-letter { flex: 0 0 auto; width: 48px; height: 48px; border-radius: 50%; background: var(--mis-accent, #223369); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 1.5rem; font-weight: 700; }
.thrive-sub { margin: 0; color: var(--mis-ink-muted, #4b5563); }
.thrive-subarea { margin: 14px 0 4px; font-size: 1rem; }
.thrive-item { border: 0; border-top: 1px solid var(--mis-border, #e5e7eb); margin: 0; padding: 12px 0 4px; min-width: 0; }
.thrive-item__text { padding: 0; margin-bottom: 8px; font-weight: 600; width: 100%; }
.thrive-item__text .thrive-zh { font-weight: 400; }
.thrive-num { float: left; margin-right: 8px; color: var(--mis-accent, #223369); }
.thrive-scale { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
/* Yes/No questions: two wide answers instead of four. */
.thrive-scale--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* Single-choice questions: the counsellor's own options, one per line, read left-to-right. */
.thrive-scale--list { grid-template-columns: 1fr; }
.thrive-scale--list .thrive-opt__box { flex-direction: row; align-items: center; justify-content: flex-start; gap: 10px; min-height: 48px; padding: 8px 12px; text-align: left; }
.thrive-opt { position: relative; display: block; margin: 0; }
.thrive-opt input { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.thrive-opt__box { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 2px; min-height: 64px; padding: 8px 4px; border: 2px solid var(--mis-border, #d1d5db); border-radius: 10px; background: #fff; font-size: 0.85rem; box-sizing: border-box; }
.thrive-opt__box b { font-size: 1.1rem; }
.thrive-opt input:checked + .thrive-opt__box { border-color: var(--mis-accent, #223369); background: var(--mis-accent-soft, #dde3f0); }
.thrive-opt input:focus-visible + .thrive-opt__box { outline: 3px solid var(--mis-accent, #223369); outline-offset: 2px; }
.thrive-prompt { margin: 0 0 10px; }
.thrive-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.thrive-chip { position: relative; display: block; margin: 0; }
.thrive-chip input { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.thrive-chip > span { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; min-height: 44px; padding: 6px 12px; border: 2px solid var(--mis-border, #d1d5db); border-radius: 22px; background: #fff; box-sizing: border-box; font-size: 0.85rem; }
.thrive-chip .thrive-en, .thrive-chip .thrive-zh { display: inline; }
.thrive-chip input:checked + span { border-color: var(--mis-accent, #223369); background: var(--mis-accent-soft, #dde3f0); }
.thrive-chip input:focus-visible + span { outline: 3px solid var(--mis-accent, #223369); outline-offset: 2px; }
.thrive-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.thrive-card textarea { width: 100%; box-sizing: border-box; min-height: 96px; }
.thrive-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 14px; padding: 10px 14px; background: #fff; border-top: 1px solid var(--mis-border, #e5e7eb); box-shadow: 0 -2px 10px rgba(0,0,0,0.08); box-sizing: border-box; }
.thrive-progress { margin: 0; font-weight: 600; }
.thrive-progress .thrive-en, .thrive-progress .thrive-zh { display: inline; margin-left: 4px; }
.thrive-bar__btns { display: flex; gap: 8px; flex-wrap: wrap; }
.thrive-bar .btn, .thrive-dialog__body .btn { min-height: 44px; }
.thrive-bar .btn .thrive-en, .thrive-bar .btn .thrive-zh, .thrive-dialog__body .btn .thrive-en, .thrive-dialog__body .btn .thrive-zh { display: inline; }
.thrive-bar .btn .thrive-zh::before, .thrive-dialog__body .btn .thrive-zh::before { content: " "; }
.thrive-dialog__body { padding: 16px 20px 20px; }
.thrive-missing { color: #8a4b00; font-weight: 600; }
.thrive-support { margin-top: 18px; padding: 12px; border-radius: 8px; background: var(--mis-accent-soft, #dde3f0); text-align: left; }

/* --- Progress bar (always shown, paged or single page) --- */
.thrive-bar__progress { display: flex; align-items: center; gap: 10px; flex: 1 1 220px; min-width: 0; }
.thrive-progressbar { -webkit-appearance: none; appearance: none; flex: 1 1 120px; min-width: 72px; height: 10px; border: 0; border-radius: 6px; background: #e8ebf3; overflow: hidden; }
.thrive-progressbar::-webkit-progress-bar { background: #e8ebf3; border-radius: 6px; }
.thrive-progressbar::-webkit-progress-value { background: var(--mis-accent, #223369); border-radius: 6px; }
.thrive-progressbar::-moz-progress-bar { background: var(--mis-accent, #223369); border-radius: 6px; }
.thrive-pct { margin: 0; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }
.thrive-pct .thrive-en, .thrive-pct .thrive-zh { display: inline; margin-left: 4px; }

/* --- One card at a time (the counsellor's "one_card" setting) ---
   The script adds .thrive-paged to <body> (the intro header is outside the form and pages too).
   With the setting off, or with no JavaScript, none of this
   applies and every card shows: the single scrolling questionnaire, unchanged. Steps are hidden with a
   class so they stay in the DOM (and in the form post) while hidden. */
.thrive-paged .thrive-step, .thrive-paged .thrive-step-hide, .thrive-paged .thrive-remember { display: none; }
.thrive-paged .thrive-step.is-current, .thrive-paged .thrive-remember.is-current { display: block; }
.thrive-paged [data-thrive-intro]:not(.is-current) { display: none; }
.thrive-step:focus { outline: none; }
.thrive-nav { background: #fff; border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.07); padding: 12px 16px; margin: 0 0 16px; }
.thrive-nav__hint { margin: 0 0 10px; color: #8a4b00; font-weight: 600; }
.thrive-nav__btns { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.thrive-nav__btns .btn { min-height: 44px; flex: 1 1 auto; }
.thrive-nav__count { font-weight: 600; color: var(--mis-ink-muted, #4b5563); white-space: nowrap; }
.thrive-nav__btns .btn .thrive-en, .thrive-nav__btns .btn .thrive-zh { display: inline; }
.thrive-nav__btns .btn .thrive-zh::before { content: " "; }

@media (max-width: 600px) {
  .thrive-wrap { padding-bottom: 160px; }   /* the fixed bar gained the progress row */
  .thrive-who { grid-template-columns: 1fr; }
  .thrive-scale { grid-template-columns: 1fr; }
  .thrive-opt__box { flex-direction: row; justify-content: flex-start; gap: 10px; min-height: 48px; padding: 8px 12px; text-align: left; }
  .thrive-opt__box .thrive-en, .thrive-opt__box .thrive-zh { display: inline; }
  .thrive-bar__btns { width: 100%; }
  .thrive-bar__btns .btn { flex: 1 1 0; }
}

/* ===== THRIVE counsellor pages (public/students/thrive*.php) ===== */
.thrive-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 16px; }
.thrive-panel { background: #fff; border: 1px solid var(--mis-rule, #e5e7eb); border-radius: 10px; padding: 16px; margin: 0 0 16px; overflow-wrap: anywhere; }
.thrive-panel > h2, .thrive-panel > h3 { margin-top: 0; }
/* The "Try it first — review link" card on /students/thrive.php. */
.thrive-review { border: 1px solid var(--mis-rule, #e5e7eb); border-left: 4px solid var(--mis-accent, #223369); background: #f8faff; border-radius: 8px; padding: 12px 14px; margin: 12px 0 18px; overflow-wrap: anywhere; }
.thrive-review > h3 { margin: 0 0 6px; }
.thrive-review .form-actions { margin-top: 10px; }
.thrive-conf { background: #fef2f2; border: 1px solid #fecaca; color: #991b1b; border-radius: 8px; padding: 8px 12px; font-size: 0.85rem; margin: 0 0 16px; }
.thrive-read-soon { background: #fff7ed; border: 1px solid #fdba74; color: #9a3412; border-radius: 8px; padding: 10px 14px; margin: 0 0 16px; font-weight: 600; }
.thrive-link-box { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.thrive-link-box .input { flex: 1 1 260px; min-width: 0; }
.thrive-checks { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 4px 0; }
.thrive-checks label { display: inline-flex; gap: 6px; align-items: center; font-weight: 400; min-height: 32px; }
/* A deep-dive area's checkbox beside its "(+N questions)" button (never a button inside the label). */
.thrive-check { display: inline-flex; flex-wrap: wrap; gap: 4px 10px; align-items: center; }
.thrive-row-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.thrive-row-actions form { margin: 0; }
.thrive-meter { display: block; width: 100%; max-width: 220px; height: 10px; background: #e8ebf3; border-radius: 6px; overflow: hidden; }
.thrive-meter > span { display: block; height: 100%; background: var(--mis-accent, #223369); }
.thrive-meter--e > span { background: #8b95b5; }
.thrive-val { display: inline-block; min-width: 1.6em; text-align: center; font-weight: 600; }
.thrive-val--low::after { content: "\00b7"; color: #b45309; margin-left: 2px; }
.thrive-grid td, .thrive-grid th { vertical-align: top; }
.thrive-quote { white-space: pre-wrap; background: #f8fafc; border-left: 3px solid var(--mis-rule, #cbd5e1); padding: 8px 12px; border-radius: 4px; margin: 4px 0 10px; }
.thrive-note { border-top: 1px solid var(--mis-rule, #e5e7eb); padding: 8px 0; }
.thrive-heat { text-align: center; font-variant-numeric: tabular-nums; }
.thrive-heat--1 { background: #eef1f9; }
.thrive-heat--2 { background: #d9e0f2; }
.thrive-heat--3 { background: #b9c5e6; }
.thrive-heat--4 { background: #8fa1d6; }
.thrive-heat--sup { color: #6b7280; background: #f3f4f6; }
.thrive-print-list td, .thrive-print-list th { font-size: 0.9rem; }
.thrive-link-text { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.8rem; word-break: break-all; }
@media (max-width: 768px) { .thrive-row-actions .btn { min-height: 44px; } }
@media print {
  .thrive-print-hide, .dashboard-sidebar, .dashboard-content__header { display: none !important; }
  .dashboard-content, .dashboard-content__body { margin: 0 !important; padding: 0 !important; }
}

/* ===== Student profile link cards (public/students/profile.php) =====
   The Wellbeing Profile / Counsellor Record / THRIVE cards are one family (Henko, 2026-10-28):
   identical heading, identical description, identical white-text action button, and one shared
   gap between them on every width. The gap lives on the wrapper (flex `gap`), not on each card,
   so no card can drift out of step with its neighbours — the cards used to be spaced by a
   per-card inline margin-bottom and the THRIVE card had none at all. */
.student-link-cards { display: flex; flex-direction: column; gap: 16px; margin: 0 0 16px; }
.student-link-cards > .card { margin: 0; }
.student-link-cards__title { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; font-size: 1.15rem; }
.student-link-cards__title .material-symbols-outlined { font-size: 1.2rem; color: var(--mis-accent, #1a56db); }
.student-link-cards__desc { margin: 0 0 12px; font-size: 0.9rem; color: var(--mis-ink-muted, #6b7280); }
.student-link-cards__actions { display: flex; flex-wrap: wrap; gap: 8px; }
/* Filled MISOS button, white label, on every action in these cards — a filled button's text is
   white by design (mis-design-system.css .btn--primary); stated here so a future secondary
   variant dropped into this block can never render navy-on-white and break the family. */
.student-link-cards__actions .btn { color: #fff; }
.student-link-cards__actions .btn .material-symbols-outlined { font-size: 1rem; }
@media (max-width: 768px) { .student-link-cards { gap: 16px; } .student-link-cards__actions .btn { min-height: 44px; } }

/* ── Benefits: enrolment popup + responsive Enrolments table (public/hr/benefits.php) ── */
.benefit-dialog-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.benefit-dialog-actions .btn { min-height: 44px; }
.benefit-confirm[hidden] { display: none; }
.benefit-confirm p { margin: 0 0 12px; }
.benefit-row-actions { white-space: nowrap; }
.benefit-row-actions .btn { min-height: 44px; }
@media (max-width: 640px) {
  .benefit-dialog-actions .btn { flex: 1 1 100%; }
}

/* THRIVE rounds page: the deep-dive block sits in its own card with room around it. */
.thrive-deep-card { margin: 32px 0; padding: 28px 32px; }
.thrive-deep-card h3 { margin: 0 0 14px; }
.thrive-deep-card p { margin: 0 0 16px; }
.thrive-deep-card .thrive-checks { margin: 20px 0 22px; }
.thrive-deep-card > :last-child { margin-bottom: 0; }
@media (max-width: 640px) {
  .thrive-deep-card { margin: 24px 0; padding: 20px 16px; }
}

/* The THRIVE banner at the top of every home page: big, full content width, scrolls with the page. */
.thrive-banner { margin: 0 0 28px; padding: 0; border-radius: 14px; overflow: hidden; box-shadow: 0 6px 20px rgba(34, 51, 105, 0.18); line-height: 0; }
.thrive-banner img { display: block; width: 100%; height: auto; }
@media (max-width: 640px) {
  .thrive-banner { margin-bottom: 20px; border-radius: 10px; }
}


/* A directory's email link: shortened with an ellipsis so a long address cannot stretch the row, with the
   full address in the title (hover) and one click opening the mail client. */
.email-cell { display: inline-block; max-width: 20ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

/* Receipt control by device (the claim form): a touch device gets the camera buttons, a desktop gets the
   plain file picker. `is-touch` is set on <html> as the form paints. */
html.is-touch .receipt-file-row { display: none; }
html:not(.is-touch) .receipt-photo-field { display: none; }

/* ── Row actions menu (Expense Payment Requests; append an item to add an option) ── */
.row-actions { display: inline-block; position: relative; }
.row-actions__toggle { min-height: 44px; }
.row-actions__menu { position: fixed; z-index: 1000; min-width: 190px; max-width: calc(100vw - 8px); background: var(--mis-surface, #fff); border: 1px solid var(--mis-rule, #d9dde8); border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,0.18); padding: 4px; display: flex; flex-direction: column; }
.row-actions__menu[hidden] { display: none; }
.row-actions__item { display: flex; align-items: center; min-height: 44px; padding: 0 12px; border: 0; border-radius: 8px; background: transparent; color: var(--mis-ink, #1c2540); font: inherit; font-size: 0.9rem; text-align: left; text-decoration: none; cursor: pointer; width: 100%; box-sizing: border-box; }
.row-actions__item:hover, .row-actions__item:focus-visible { background: var(--mis-surface-alt, #eef1f8); outline: none; }
.row-actions__item[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
/* Reimbursement no. autosave: the Save button stays only as the no-JS fallback */
.rn-form--auto .rn-form__save { display: none; }
.rn-form__status { font-size: 0.75rem; min-width: 5.5em; }
.rn-form__status--error { color: var(--mis-danger, #b3261e); }

/* ── Expense claims: History tab ── */
.expense-tabs { margin-bottom: 1rem; display: flex; flex-wrap: wrap; gap: 8px; }
.expense-ranges { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.expense-chip { min-height: 44px; display: inline-flex; align-items: center; }
.expense-filter { margin-bottom: 16px; }
.expense-filter .form-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.expense-filter .form-actions .btn { min-height: 44px; display: inline-flex; align-items: center; }
.expense-summary { margin: 12px 0; }
.expense-empty { text-align: center; padding: 24px 16px; }
.expense-amount { text-align: right; white-space: nowrap; }
.expense-pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px; margin: 16px 0; }
.expense-pager .btn { min-height: 44px; display: inline-flex; align-items: center; }

/* ── Expense payouts (public/hr/expense-payouts.php) ── */
.xp-export { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.xp-export .btn { min-height: 44px; }
.xp-export__sel { font-size: 0.85rem; display: flex; align-items: center; gap: 6px; min-height: 44px; }
.xp-summary { font-size: 1.05rem; margin: 0 0 16px; }
.xp-filter { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin-bottom: 16px; }
.xp-filter .form-row { margin: 0; min-width: 220px; }
.xp-filter .form-actions { margin: 0; }
.xp-table .xp-check { width: 44px; text-align: center; }
.xp-table .xp-check input { width: 22px; height: 22px; }
.xp-pickbox { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; cursor: pointer; }
.xp-table .xp-amt { text-align: right; white-space: nowrap; }
.xp-table .xp-desc { min-width: 180px; max-width: 320px; }
.xp-bar { position: sticky; bottom: 0; z-index: 20; display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; padding: 12px 16px; margin-top: 12px; background: var(--mis-surface, #fff); border: 1px solid var(--mis-rule, #d9dde8); border-radius: 10px; box-shadow: 0 -4px 18px rgba(0,0,0,0.12); }
.xp-bar[hidden] { display: none; }
.xp-bar .btn { min-height: 44px; }
@media (max-width: 820px) {
  .xp-table, .xp-recent { display: block; }
  .xp-table thead, .xp-recent thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .xp-table tbody, .xp-recent tbody { display: block; }
  .xp-table tr, .xp-recent tr { display: block; border: 1px solid var(--mis-rule, #d9dde8); border-radius: 10px; margin-bottom: 12px; padding: 8px 12px; background: var(--mis-surface, #fff); }
  .xp-table td, .xp-recent td { display: flex; justify-content: space-between; gap: 12px; border: 0; padding: 4px 0; text-align: right; }
  .xp-table td[data-label]::before, .xp-recent td[data-label]::before { content: attr(data-label); font-weight: 600; text-align: left; color: var(--mis-ink-muted, #6b7280); flex: 0 0 38%; }
  .xp-table td.xp-check { width: auto; justify-content: flex-start; }
  .xp-table td.xp-check input { width: 28px; height: 28px; }
  .xp-table .xp-amt { white-space: normal; }
  .xp-table .row-actions__toggle { min-height: 44px; }
  .xp-filter .form-row { min-width: 100%; }
  .xp-export { flex-basis: 100%; }
  .xp-filter .btn, .xp-export .btn { min-height: 44px; }
}

/* Salary change waiting for approval: the amber line under a person's salary on the payroll roster and Pay setup. */
.roster-pending { text-align: right; }
.payroll-pending-help { font-size: 0.85rem; margin: 4px 0 8px; }
.payroll-pending-chip { display: block; margin-top: 4px; padding: 4px 8px; border-radius: 8px; background: #fdf3d8; color: var(--mis-gold-ink); border: 1px solid #ecd48a; font-size: 0.78rem; line-height: 1.35; text-align: left; white-space: normal; overflow-wrap: anywhere; max-width: 100%; box-sizing: border-box; }
.payroll-pending-chip__main { font-weight: 600; }
.payroll-pending-chip__more { font-weight: 600; }
.payroll-pending-chip__note { display: block; font-weight: 400; color: var(--mis-ink-muted, #555); }
.payroll-pending-chip__link { display: inline-block; margin-top: 2px; font-weight: 600; }

/* Expenses History: the Filters card is collapsed behind a button until asked for (it opens itself when a
   filter is applied). */
.expense-filter-details { margin-bottom: 1rem; }
.expense-filter-details > summary { display: inline-block; cursor: pointer; }
.expense-filter-details > summary::marker { content: ''; }
.expense-filter-details > .expense-filter { margin-top: 10px; }

/* The Payment Request Form fills the content width (Henko, 2026-10-29) — the shared .form-card--wide caps at
   720px, which left the expense form squeezed into the middle of a wide screen. */
.expense-form-card { width: 100%; max-width: none; }

/* My Office hub: the Google connection line/card above the launch tiles (Henko, 2026-10-29). */
.office-connect { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin: 0 0 16px; padding: 10px 14px; border-radius: 10px; background: var(--mis-wash, #eef3f8); font-size: 0.92rem; }
.office-connect .material-symbols-outlined { font-size: 20px; color: var(--mis-accent); }
.office-connect__mail { color: var(--mis-ink-muted, #6b7280); overflow-wrap: anywhere; }
.office-connect--note { background: #fffbea; }
.office-connect-card { border: 1px solid var(--mis-rule, #e2e5ec); border-left: 4px solid var(--mis-accent, #223369); border-radius: 10px; background: #fff; padding: 14px 16px; margin-bottom: 18px; }
.office-connect-card h2 { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; font-size: 1.05rem; }
.office-connect-card h2 .material-symbols-outlined { color: var(--mis-accent, #223369); }
.office-connect-card__actions { margin: 12px 0 0; }
.office-connect-card__actions .btn { min-height: 44px; }

/* ============================================================================================
   Student Onboarding Checklist (Henko, 2026-10-29)
   public/students/onboarding.php (overview), _onboarding_tab.php (the checklist body) and
   onboarding-student.php. Built from the same --mis-* tokens as the rest of app.css.
   Every tappable control is at least 44px tall on a phone; under 820px the overview table becomes
   a stack of cards instead of a sideways-scrolling table (the .dashboard-content clip makes
   anything wider unreachable, not merely inconvenient).
   ============================================================================================ */

.onb-zh { font-size: 0.82em; color: var(--mis-ink-muted, #6b7280); font-weight: 500; }

/* Overview ---------------------------------------------------------------------------------- */
.onb-stats { margin-bottom: 16px; }
.onb-filters { margin-bottom: 16px; }
.onb-filters .form-actions { margin-top: 4px; }
.onb-empty { text-align: center; }

.onb-head { padding: 16px 18px; }
.onb-head__top { display: flex; flex-wrap: wrap; gap: 12px 20px; align-items: flex-start; justify-content: space-between; }
.onb-head__actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.onb-head__actions form { margin: 0; }

.onb-progress { margin-top: 14px; }
.onb-progress__bar { height: 8px; border-radius: 4px; background: var(--mis-surface, #eef0f4); overflow: hidden; }
.onb-progress__bar > span { display: block; height: 100%; border-radius: 4px; background: var(--mis-accent, #223369); transition: width 0.3s ease; }
.onb-progress__text { margin: 8px 0 0; font-size: 0.9rem; }

.onb-mini-bar { height: 6px; width: 100%; min-width: 90px; max-width: 160px; border-radius: 3px; background: var(--mis-surface, #eef0f4); overflow: hidden; margin-bottom: 4px; }
.onb-mini-bar > span { display: block; height: 100%; border-radius: 3px; background: var(--mis-accent, #223369); }

/* The checklist body ------------------------------------------------------------------------ */
.onb-section { padding: 16px 18px; margin-bottom: 16px; }
.onb-section__title { margin: 0 0 12px; font-size: 1.05rem; display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; }

.onb-row { display: flex; align-items: flex-start; gap: 12px; padding: 12px 0; border-top: 1px solid var(--mis-rule, #e2e5ec); }
.onb-row:first-of-type { border-top: 0; }
.onb-row--closed .onb-label { color: var(--mis-ink-muted, #6b7280); }
.onb-row--na { opacity: 0.85; }
.onb-main { flex: 1 1 auto; min-width: 0; }
.onb-label { font-weight: 600; line-height: 1.35; }
.onb-label .onb-zh { display: block; margin-top: 2px; }

.onb-meta { display: flex; flex-wrap: wrap; gap: 4px 6px; align-items: center; margin-top: 6px; }
.onb-chip { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 0.72rem; font-weight: 600; background: #eceef2; color: #4b5563; }
.onb-chip--done { background: #e3f2e6; color: #1f7a3d; }
.onb-chip--pending { background: #fdf3d8; color: #8a5a00; }
.onb-chip--na { background: #e8e8f4; color: #4c3f86; }
.onb-chip--overdue { background: #fee2e2; color: #991b1b; }
.onb-chip--quiet { background: transparent; color: var(--mis-ink-muted, #6b7280); font-weight: 500; }
.onb-chip--link { background: var(--mis-accent, #223369); color: #fff; text-decoration: none; }
.onb-chip--link:hover { text-decoration: underline; }

.onb-note { margin: 8px 0 0; font-size: 0.9rem; white-space: pre-wrap; }
.onb-overdue { color: #991b1b; font-weight: 700; }

.onb-tick { flex: 0 0 auto; margin: 0; }
.onb-tick-btn { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 10px; background: transparent; color: var(--mis-accent, #223369); cursor: pointer; }
.onb-tick-btn:hover { background: var(--mis-surface, #eef0f4); }
.onb-tick-btn[disabled] { cursor: default; opacity: 0.9; }
.onb-tick-btn--static { pointer-events: none; color: var(--mis-ink-muted, #6b7280); }

.onb-more { flex: 0 0 auto; width: 44px; height: 44px; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 10px; background: #fff; color: var(--mis-ink, #1c2540); font-size: 1.2rem; line-height: 1; cursor: pointer; }
.onb-more:hover { background: var(--mis-surface, #eef0f4); }

.onb-na-group { margin-top: 12px; border-top: 1px dashed var(--mis-rule, #e2e5ec); padding-top: 10px; }
.onb-na-group > summary { cursor: pointer; font-size: 0.9rem; color: var(--mis-ink-muted, #6b7280); }

.onb-settings > details > summary { cursor: pointer; font-weight: 600; }
.onb-settings code { background: #eceef2; border-radius: 4px; padding: 0 4px; font-size: 0.8rem; }

/* "Looks done — confirm" chip: a suggestion, pressed by a human, so it reads as an action rather
   than a status. Same pill shape as the other chips, with a dashed edge to say "not yet a fact". */
.onb-suggest { display: inline; margin: 0; }
.onb-chip--suggest { border: 1px dashed #b45309; background: #fffbeb; color: #7a4b00; cursor: pointer; font-family: inherit; }
.onb-chip--suggest:hover { background: #fdf3d8; }

.onb-welcome-btn { flex: 0 0 auto; }

/* Phone layout: the overview table becomes cards, because .dashboard-content clips anything
   wider rather than letting the page scroll (see CLAUDE.md, "Mobile-friendliness"). */
@media (max-width: 820px) {
  .onb-table thead { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .onb-table, .onb-table tbody, .onb-table tr, .onb-table td { display: block; width: 100%; }
  .onb-table tr { border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 12px; padding: 10px 12px; margin-bottom: 12px; background: #fff; }
  .onb-table td { border: 0; padding: 4px 0; }
  .onb-table td[data-label]:not([data-label=""])::before { content: attr(data-label); display: block; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--mis-ink-muted, #6b7280); }
  .onb-table td[data-label=""] { padding-top: 8px; }
  .onb-head__actions .btn, .onb-filters .btn { min-height: 44px; display: inline-flex; align-items: center; }
  .onb-more, .onb-tick-btn { min-width: 44px; min-height: 44px; }
}

/* ============================================================================
   MEALS — Normal / Small portion controls (added 2026-10-30)
   Delimited block: only classes introduced by the meal-portion change.
   ========================================================================== */
.mp-portion { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 6px; font-size: 0.8rem; }
.mp-portion label { display: inline-flex; align-items: center; gap: 4px; font-weight: 400; margin: 0; }
.mp-portion--combo { margin: 6px 0 4px; font-size: 0.85rem; }
.mp-portion__label { color: var(--mis-ink-muted, #6b7280); }
/* The Normal / Small pair is one left-aligned column (radios line up on the same edge), the block itself centred under the tick. */
.mp-col-person .mp-portion { flex-direction: column; align-items: flex-start; gap: 2px; width: max-content; max-width: 100%; margin-left: auto; margin-right: auto; }
@media (max-width: 820px) {
  /* Planner phone cards: the portion choice sits above a full-width 44px tick row. */
  .mp-col-person .mp-portion { flex-direction: column; align-items: flex-start; gap: 0; min-height: 32px; font-size: 0.7rem; max-width: 100%; }
  .mp-portion label { display: flex; align-items: flex-start; min-height: 32px; max-width: 100%; min-width: 0; line-height: 1.25; padding-top: 3px; }
  .mp-portion input { flex: none; margin-top: 2px; }
}

/* ============================================================================
   BENEFITS MATRIX — /hr/benefits-matrix.php (added 2026-10-30)
   Delimited block: only classes introduced by the benefits matrix page.
   The header row and the first column are frozen inside the scroll container,
   which is what keeps both of them reachable on a phone: .dashboard-content
   clips horizontal overflow, so the grid must scroll inside its own box.
   ========================================================================== */
.bm-page-head { flex-wrap: wrap; gap: 12px; }
.bm-intro { margin: 0 0 10px; max-width: 70ch; color: var(--mis-ink-muted, #6b7280); }
.bm-legend { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 0 0 14px; font-size: 0.82rem; color: var(--mis-ink-muted, #6b7280); }
.bm-legend__item { display: inline-flex; align-items: center; gap: 6px; }
.bm-legend .bm-state { display: inline; font-weight: 700; }

.bm-form { margin: 0; }
.bm-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; margin-bottom: 10px; }
.bm-toolbar__info { margin: 0; font-size: 0.9rem; color: var(--mis-ink-muted, #6b7280); }
.bm-toolbar__info strong { color: var(--mis-ink, #1c2540); }
.bm-toolbar__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.bm-toolbar__actions .btn { min-height: 40px; }
.bm-status { font-size: 0.85rem; color: var(--mis-ink-muted, #6b7280); }
.bm-status--ok { color: #1f7a3d; }
.bm-status--error { color: #991b1b; font-weight: 600; }
.bm-status--busy { color: var(--mis-accent, #223369); }

/* The scroll container: both directions, a bounded height so the page itself does not have to
   scroll the grid, and a solid background on every sticky cell. */
/* The grid scrolls inside its own box (horizontal scrolling has nowhere else to go —
   .dashboard-content clips overflow), and the box itself is STICKY: as the page scrolls past
   the grid's top, the box pins to the top of the window, so the header row stays in view exactly
   when the reader reaches the table (Henko, 2026-10-31: "1st row freeze when reach the top of the
   page"). The first column stays put inside the box while scrolling sideways. */
/* 2026-10-31 (replaces the sticky inner-scroll box, which did not pin inside .dashboard-content): the grid scrolls sideways in its
   own box and the PAGE scrolls vertically; public/js/sticky-table-head.js (data-sticky-head on the wrapper) shows a fixed copy of the
   header row, with the Staff member column pinned, whenever the real one has scrolled above the top of the window. */
.benefits-matrix { overflow-x: auto; overflow-y: visible; position: relative; z-index: 1; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 10px; background: #fff; }
.benefits-matrix:focus-visible { outline: 2px solid var(--mis-accent, #223369); outline-offset: 2px; }

.bm-table { border-collapse: separate; border-spacing: 0; width: auto; min-width: 100%; margin: 0; font-size: 0.9rem; }
.bm-table th, .bm-table td { border-bottom: 1px solid var(--mis-rule-soft, #edf0f4); border-right: 1px solid var(--mis-rule-soft, #edf0f4); padding: 6px 10px; vertical-align: middle; }
.bm-table thead th { position: sticky; top: 0; z-index: 3; background: var(--mis-wash, #eef3f8); }
.bm-table thead th.bm-corner { left: 0; z-index: 5; }
.bm-table tbody th.bm-row-head { position: sticky; left: 0; z-index: 2; background: #fff; }

.bm-corner { min-width: 210px; max-width: 260px; text-align: left; }
.bm-col-head { min-width: 112px; width: 112px; padding: 0; text-align: left; }
.bm-sort-link { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 8px 10px; color: inherit; text-decoration: none; font-weight: 600; line-height: 1.2; }
.bm-sort-link:hover .bm-sort-name, .bm-sort-link:focus-visible .bm-sort-name { text-decoration: underline; }
.bm-sort-link:focus-visible { outline: 2px solid var(--mis-accent, #223369); outline-offset: -2px; }
.bm-sort-name { font-size: 0.8rem; overflow-wrap: anywhere; }
.bm-corner .bm-sort-name { font-size: 0.95rem; }
.bm-col-type { font-size: 0.68rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--mis-ink-muted, #6b7280); }
.bm-col-count { font-size: 0.68rem; font-weight: 400; color: var(--mis-ink-muted, #6b7280); }
.bm-sort-mark { font-size: 0.7rem; line-height: 1; color: var(--mis-accent, #223369); }

.bm-row-head { min-width: 210px; max-width: 260px; text-align: left; }
.bm-person { display: block; font-weight: 600; color: var(--mis-ink, #1c2540); overflow-wrap: anywhere; }
.bm-dept { display: block; font-size: 0.72rem; font-weight: 400; color: var(--mis-ink-muted, #6b7280); }

.bm-cell { text-align: center; }
.bm-tick { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; cursor: pointer; }
.bm-tick input[type="checkbox"] { width: 20px; height: 20px; margin: 0; accent-color: var(--mis-accent, #223369); cursor: pointer; }
.bm-tick input[type="checkbox"]:disabled { cursor: progress; opacity: 0.6; }
.bm-state { display: block; font-size: 0.64rem; text-transform: uppercase; letter-spacing: 0.03em; }
.bm-state[hidden] { display: none; }
.bm-state--pending { color: #8a5a00; }
.bm-state--opted_out { color: #6b7280; }

@media (max-width: 820px) {
  /* Phone: keep the frozen first column narrow enough to leave the ticks reachable, and make
     the tap targets full 44px. The benefit names wrap; nothing is squeezed to one character. */
  .bm-toolbar__actions { width: 100%; }
  .bm-toolbar__actions .btn { flex: 1 1 auto; min-height: 44px; }
  .bm-corner, .bm-row-head { min-width: 150px; max-width: 170px; }
  .bm-col-head { min-width: 96px; width: 96px; }
}

/* ============================================================================
   Student Onboarding — the filter card starts collapsed (Henko, 2026-10-30).
   Same shape as .expense-filter-details: a summary that looks like a button,
   no disclosure marker, and the card inside only when it is open.
   ========================================================================== */
.onb-filters-details { margin-bottom: 1rem; }
.onb-filters-details > summary { display: inline-block; cursor: pointer; list-style: none; }
.onb-filters-details > summary::-webkit-details-marker { display: none; }
.onb-filters-details > summary::marker { content: ''; }
.onb-filters-details[open] > summary { margin-bottom: 10px; }
.onb-filters-details > .onb-filters { margin-top: 0; }

/* Student edit: the parent/guardian contact card sits to the right of the form while the student is in an intake status. */
.intake-split { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr); align-items: start; }
.intake-split--on { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.intake-split--on > .card { max-width: 720px; }
@media (max-width: 900px) { .intake-split--on { grid-template-columns: minmax(0, 1fr); } }
.intake-col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.intake-col > .card { margin: 0; }

/* Student photo, compact: the avatar sits in the top-right corner of the Student Information card; the crop tool floats. */
.student-photo-corner { position: absolute; top: 16px; right: 16px; width: 120px; text-align: center; z-index: 2; }
.student-photo-corner .form-actions { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.student-photo-corner .student-photo-crop { position: fixed; top: 6vh; left: 50%; transform: translateX(-50%); width: min(92vw, 520px); max-height: 88vh; overflow: auto; background: #fff; padding: 16px; border-radius: 12px; box-shadow: 0 12px 48px rgba(0, 0, 0, .35); z-index: 1000; text-align: left; }
@media (max-width: 480px) { .student-photo-corner { position: static; margin: 0 0 12px; } }

/* ============================================================================
   Bookings — items that are due back or overdue (Henko, 2026-10-31).
   Shown above the tabs on every tab, because an asset still in someone's hands
   is the one thing on this page that must not be buried in a table.
   ========================================================================== */
.vab-due { margin:0 0 18px; padding:16px 18px; border:1px solid #f0c36d; border-left:6px solid #d97706; border-radius:12px; background:#fffbeb; }
.vab-due h2 { display:flex; align-items:center; gap:8px; margin:0 0 12px; font-size:1.05rem; color:#7c2d12; }
.vab-due h2 .material-symbols-outlined { font-size:22px; }
.vab-due__row { display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:12px; padding:12px 0; border-top:1px solid #f3e3b8; }
.vab-due__row:first-of-type { border-top:0; }
.vab-due__row--overdue { background:#fef2f2; margin:0 -8px; padding:12px 8px; border-radius:8px; }
.vab-due__what { display:flex; flex-direction:column; gap:2px; font-size:0.95rem; }
.vab-due__what strong { font-size:1.05rem; color:var(--mis-ink, #1c2540); }
.vab-due__who { color:var(--mis-ink-muted, #6b7280); font-size:0.85rem; }
.vab-due__when { font-size:0.85rem; color:#92400e; }
.vab-due__row--overdue .vab-due__when { color:#b91c1c; font-weight:600; }
.vab-due__btn { min-height:44px; font-size:1rem; padding:10px 22px; white-space:nowrap; }
.vab-due__note { margin:10px 0 0; font-size:0.8rem; color:var(--mis-ink-muted, #6b7280); }
@media (max-width: 640px) {
  .vab-due__row { flex-direction:column; align-items:stretch; }
  .vab-due__btn { width:100%; }
}

/* The sidebar's "Search menu" box (and its phone icon) never belongs on paper or in a saved PDF (Henko, 2026-10-31). */
@media print { .dashboard-sidebar__search, .dashboard-sidebar__search-open, .mobile-search { display: none !important; } }

/* ============================================================================
   Expense status history — hover (or focus) a status badge (Henko, 2026-10-31).
   Rendered into one shared popup at page level so the .table-scroll box cannot
   clip it; the same lines are the badge's native title when JavaScript is off.
   ========================================================================== */
.exp-status { display: inline-block; border-bottom: 1px dotted var(--mis-ink-muted, #6b7280); }
.exp-hist-pop { position: absolute; z-index: 4000; max-width: 380px; padding: 12px 14px; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 10px; background: #fff; box-shadow: 0 10px 30px rgba(17, 24, 39, 0.18); font-size: 0.82rem; line-height: 1.5; color: var(--mis-ink, #1c2540); }
.exp-hist-pop__title { display: block; margin-bottom: 6px; font-size: 0.75rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--mis-ink-muted, #6b7280); }
.exp-hist-pop__list { margin: 0; padding-left: 16px; }
.exp-hist-pop__list li { margin-bottom: 6px; }
.exp-hist-pop__at { display: block; font-size: 0.72rem; color: var(--mis-ink-muted, #6b7280); }

/* ============================================================================
   School fees page (Henko, 2026-10-31): a real gap between the cards, the
   ledger filter collapsed behind "Open filter", and the record popup wider.
   ========================================================================== */
.finance-page > .card { margin-bottom: 28px; }
.finance-page > .card:last-child { margin-bottom: 0; }
.fee-filter-details { margin: 0 0 16px; }
.fee-filter-details > summary { display: inline-block; cursor: pointer; list-style: none; }
.fee-filter-details > summary::-webkit-details-marker { display: none; }
.fee-filter-details > summary::marker { content: ''; }
.fee-filter-details[open] > summary { margin-bottom: 12px; }
.fee-record-dialog { max-width: 880px; width: 92vw; }
.fee-ext-row { padding: 10px 12px; border-left: 3px solid var(--mis-accent, #223369); background: var(--mis-wash, #eef3f8); border-radius: 6px; }
.fee-ext-row > label { margin-bottom: 4px; display: block; }

/* ============================================================================
   Buttons: a red (clay) button always carries white text (Henko, 2026-10-31).
   The default for .btn--primary and .btn--danger, in every state, and it has to
   beat a card's own link colour — `.form-card a { color: accent }` was turning
   the two application-form buttons on /hr/hiring.php into navy text on red.
   ========================================================================== */
.btn--primary, .btn--danger,
a.btn--primary, a.btn--danger,
a.btn--primary:visited, a.btn--danger:visited,
a.btn--primary:hover, a.btn--danger:hover,
a.btn--primary:focus, a.btn--danger:focus,
a.btn--primary:active, a.btn--danger:active,
.btn--primary:hover, .btn--danger:hover { color: #fff; }

/* ===== Venue booking calendar (public/scripts/vab-calendar.js): month grid + day ruler ===== */
.vab-cal { max-width: 100%; min-width: 0; }
.vab-cal__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.vab-cal__title { font-weight: 600; text-align: center; flex: 1; }
.vab-cal__nav { min-width: 44px; min-height: 44px; border: 1px solid #d5d9e3; background: #fff; border-radius: 8px; font-size: 1.3rem; line-height: 1; cursor: pointer; }
.vab-cal__row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; margin-bottom: 3px; }
.vab-cal__dow { text-align: center; font-size: .75rem; color: #5b6478; padding: 2px 0; }
.vab-cal__cell { text-align: center; padding: 8px 0; border-radius: 6px; font-size: .9rem; background: #f3f5f9; border: 2px solid transparent; min-width: 0; }
.vab-cal__cell--pad { background: transparent; }
.vab-cal__cell--free { background: #e3f4e6; }
.vab-cal__cell--part { background: #fff1c9; }
.vab-cal__cell--busy { background: #f6d2d2; }
.vab-cal__cell.is-chosen { border-color: #223369; font-weight: 700; }
.vab-cal__legend { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: .8rem; margin: 8px 0 0; }
.vab-cal__swatch { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: -1px; }
.vab-cal__swatch--free { background: #e3f4e6; }
.vab-cal__swatch--part { background: #fff1c9; }
.vab-cal__swatch--busy { background: #f6d2d2; }
.vab-cal__note, .vab-cal__summary { font-size: .85rem; margin: 6px 0; overflow-wrap: anywhere; }
.vab-cal__note:empty, .vab-cal__summary:empty { display: none; }
.vab-cal__summary.is-clash { color: #a02020; font-weight: 600; }
.vab-cal__dayhead { font-weight: 600; margin-top: 12px; }
.vab-cal__ruler { position: relative; height: 220px; margin: 6px 0 0 30px; border-left: 1px solid #c4cad8; background: repeating-linear-gradient(#fff, #fff 19px, #eef0f5 20px); }
.vab-cal__tick { position: absolute; left: -30px; width: 24px; text-align: right; font-size: .7rem; color: #5b6478; transform: translateY(-50%); }
.vab-cal__block { position: absolute; left: 4px; right: 4px; background: #c9606a; opacity: .85; border-radius: 4px; }
.vab-cal__mine { position: absolute; left: 14px; right: 0; border: 2px dashed #223369; background: rgba(34, 51, 105, .12); border-radius: 4px; box-sizing: border-box; }
.vab-cal__mine.is-clash { border-color: #a02020; background: rgba(160, 32, 32, .25); }

/* ============================================================================
   The booking dialog, two columns (Henko, 2026-10-31): every field keeps its
   place on the left, the availability calendar sits beside it. The calendar's
   own styles are a separate .vab-cal* block; this is only the shell.
   Under 900px the columns stack — a two-column dialog at phone width is unusable.
   ========================================================================== */
.mis-dialog--form:has(.vab-book-cols) { max-width: 980px; width: 96vw; }
.vab-book-cols { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 380px); gap: 24px; align-items: start; }
.vab-book-cols__form { min-width: 0; }
.vab-book-cols__cal { min-width: 0; position: sticky; top: 0; }
.vab-book-cols__cal .vab-cal__hint { margin: 0 0 10px; font-size: 0.85rem; }
.vab-book-cols__cal .vab-cal__hint[hidden] { display: none; }
/* The two switches now stack on their own (see .vab-checkstack), so the old phone-only nudge for
   the indented "Full day" label is gone; at phone width they simply keep the same left edge. */
@media (max-width: 560px) {
  .vab-checkstack > label { align-items: flex-start; }
}
@media (max-width: 900px) {
  .vab-book-cols { grid-template-columns: 1fr; gap: 16px; }
  .vab-book-cols__cal { position: static; }
  .mis-dialog--form:has(.vab-book-cols) { width: 100vw; max-width: 100vw; }
}

/* ============================================================================
   Venue approvers as chips (Henko, 2026-10-31): the chosen people show as names
   with an x that removes them; "Add a staff member" puts one back. The native
   multi-select keeps the value and is only hidden once the chips are drawn.
   ========================================================================== */
.approver-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 10px; }
.approver-chips:empty { display: none; }
.approver-chip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 6px 5px 12px; border: 1px solid var(--mis-accent, #223369); border-radius: 999px; background: var(--mis-wash, #eef3f8); font-size: 0.9rem; color: var(--mis-ink, #1c2540); }
.approver-chip__x { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 50%; background: rgba(34, 51, 105, 0.12); color: var(--mis-accent, #223369); font-size: 15px; line-height: 1; cursor: pointer; }
.approver-chip__x:hover, .approver-chip__x:focus-visible { background: #b91c1c; color: #fff; }
.approver-add { max-width: 360px; }
.approver-add label { display: block; margin-bottom: 4px; font-size: 0.85rem; }

/* The venue's Responsible staff, shown beside the approver picker (Henko, 2026-10-31). */
.approver-resp { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 10px; font-size: 0.88rem; }
.approver-chip--resp { background: transparent; border-style: dashed; padding: 3px 10px; }
.approver-resp .btn { min-height: 32px; }

/* The two switches of a venue booking, stacked on one left edge (Henko, 2026-10-31):
   "Full day" was indented under "Multi Days" and its label hung oddly. */
.vab-checkstack { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin: 10px 0 0; }
.vab-checkstack > label { display: flex; align-items: center; gap: 8px; margin: 0; font-weight: 400; }
.vab-checkstack > label > input[type="checkbox"] { margin: 0; }
.vab-till-help { margin: -6px 0 10px; }
.vab-till-help[hidden] { display: none; }

/* Weekly repeat: the later occurrences of the series are chosen days with a dashed outline (the first day keeps the solid one). */
.vab-cal__cell.is-repeat { border-style: dashed; }

/* The month-calendar icon beside a venue's name on the booking grid (Henko, 2026-10-31). */
.vab-venue-name { display: inline-flex; align-items: center; gap: 6px; }
.vab-calbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; border: 1px solid var(--mis-accent, #223369); border-radius: 6px; background: #fff; color: var(--mis-accent, #223369); cursor: pointer; }
.vab-calbtn:hover, .vab-calbtn:focus-visible { background: var(--mis-accent, #223369); color: #fff; }
.vab-calbtn .material-symbols-outlined { font-size: 18px; }

/* The calendar's hover card (Henko, 2026-10-31): time first, then who it is for and whether it is confirmed.
   Positioned inside the calendar root so a dialog cannot clip it. */
.vab-cal { position: relative; }
.vab-cal__tip { position: absolute; z-index: 5; max-width: 260px; padding: 8px 10px; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 8px; background: #fff; box-shadow: 0 6px 18px rgba(17, 24, 39, 0.16); font-size: 0.78rem; line-height: 1.45; color: var(--mis-ink, #1c2540); pointer-events: none; }
.vab-cal__tip[hidden] { display: none; }
.vab-cal__tip-main { font-weight: 700; margin-bottom: 2px; }
.vab-cal__block { cursor: help; }

/* The day whose hours the ruler is showing (Henko, 2026-10-31): a ring that is distinct from the
   "chosen" days the form marks, so a clicked day never reads as a booking choice. */
.vab-cal__cell.is-viewday { box-shadow: inset 0 0 0 2px var(--mis-accent, #223369); }

/* The booking written on the ruler's block, so a day reads without hovering (Henko, 2026-11-01). */
.vab-cal__block { overflow: hidden; padding: 2px 4px; box-sizing: border-box; }
.vab-cal__block-time { display: block; font-size: 0.68rem; font-weight: 700; color: #fff; line-height: 1.2; }
.vab-cal__block-name { display: block; font-size: 0.68rem; color: #fff; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vab-cal__block-purpose { display: block; font-size: 0.62rem; color: rgba(255,255,255,0.88); line-height: 1.2; overflow: hidden; text-overflow: ellipsis; }
.vab-cal__block-status { display: block; font-size: 0.6rem; color: #fef3c7; line-height: 1.2; text-transform: uppercase; letter-spacing: 0.03em; }

/* The venue calendar's head actions ("Book this venue" beside the close x, Henko 2026-11-01). */
.vab-venuecal-actions { display: inline-flex; align-items: center; gap: 10px; }

/* What the room needs, inside the booking popup (Henko, 2026-11-01). */
.vab-needs { margin: 14px 0 0; padding: 12px 14px; border: 1px solid var(--mis-rule, #e2e5ec); border-radius: 10px; }
.vab-needs > legend { padding: 0 6px; font-size: 0.85rem; font-weight: 700; color: var(--mis-ink, #1c2540); }
.vab-needs__checks { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin: 8px 0 0; }
.vab-needs__checks > label { display: flex; align-items: center; gap: 8px; margin: 0; font-weight: 400; }
.vab-needs__checks > label > input[type="checkbox"] { margin: 0; }
.vab-needs #vab_catering_row { margin-top: 10px; }
