:root {
  --bg: #f4f5f7;
  --panel: #ffffff;
  --ink: #0a0a0a;
  --ink-soft: #2a2a2a;
  --muted: #6b6b6b;
  --line: #e2e4e8;
  --line-strong: #c8ccd2;
  --shadow: 0 1px 2px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.05);

  /* Status palette — mirrors the old sheet */
  --c-active:    #2e7d32;  --c-active-bg:    #e2f3e4;
  --c-debtor:    #c62828;  --c-debtor-bg:    #fde2e2;
  --c-newcomer:  #1565c0;  --c-newcomer-bg:  #e1ecfb;
  --c-frozen:    #0277bd;  --c-frozen-bg:    #dbeefb;
  --c-left:      #424242;  --c-left-bg:      #e8e8e8;
  --c-vip:       #546e7a;  --c-vip-bg:       #eceff1;

  /* Lesson-type palette for the schedule grid.
     Headway levels use the book-cover colours: Beginner green, Elementary red,
     Pre-Intermediate teal, Intermediate blue, Upper-Intermediate purple, Advanced orange. */
  --lt-kids:                #fff59d;
  --lt-beginner:            #86c98a;   /* Headway green  */
  --lt-elementary:          #ef9a9a;   /* Headway red    */
  --lt-pre-intermediate:    #7fd0c8;   /* Headway teal   */
  --lt-intermediate:        #90caf9;   /* Headway blue   */
  --lt-upper-intermediate:  #b39ddb;   /* Headway purple */
  --lt-advanced:            #ffb74d;   /* Headway orange */
  --lt-ielts:          #ffccbc;
  --lt-speaking:       #f8bbd0;
  --lt-writing:        #f0e68c;
  --lt-individual:     #cfd8dc;
  --lt-teachers:       #b0bec5;
  --lt-other:          #eceff1;

  /* Reference / lead source palette */
  --ref-instagram: #e1306c;
  --ref-telegram:  #0088cc;
  --ref-call:      #4caf50;
  --ref-billboard: #ff9800;
  --ref-myschool:  #6a1b9a;

  /* ===== Design-system foundation tokens (additive — only used by new/standardized rules below). ===== */
  /* Spacing scale */
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px; --space-6: 32px;
  /* Radius tokens (match current hardcoded usage so nothing shifts) */
  --radius-sm: 6px; --radius: 10px; --radius-lg: 12px;
  /* Motion tokens (match the existing ~.14-.16s feel) */
  --ease: cubic-bezier(.2,.6,.2,1); --t-fast: .14s; --t: .2s;
  /* Table row-height hint for content-visibility sizing — shrinks in compact density. */
  --row-h: 38px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: 'Google Sans', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  color: var(--ink); background: var(--bg); min-height: 100vh;
}

/* ============ TOPBAR ============ */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 28px;
  background: linear-gradient(180deg, #0a0a0a, #1a1a1a);
  color: #fff; border-bottom: 1px solid #000;
}
.brand {
  display: flex; align-items: center; gap: 14px;
  cursor: pointer; border-radius: 10px; padding: 4px 8px; margin: -4px -8px;
  transition: background var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.brand:hover { background: rgba(255,255,255,0.06); transform: translateY(-1px); }
.brand:active { transform: translateY(0); }
.brand:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(255,255,255,0.35); }
.logo {
  width: 42px; height: 42px; border-radius: 9px;
  background: #fff; color: #0a0a0a;
  display: grid; place-items: center; font-weight: 700; letter-spacing: 1px;
  box-shadow: 0 0 0 3px rgba(255,255,255,0.08);
}
.brand-title { font-size: 16px; font-weight: 500; }
.brand-sub { font-size: 12px; color: #b8b8b8; }
.topbar-meta { font-size: 13px; color: #c8c8c8; }

/* ===== Sticky app header (dark topbar + grouped nav as one unit) =====
   Wraps .topbar + .tabs so the whole top header stays pinned and full-width on
   scroll. --app-header-h (set from JS to the measured height) is the offset every
   page-scrolled sticky header below it uses, so nothing tucks behind the header. */
.app-header { position: sticky; top: 0; z-index: 50; }
/* Page-scrolled data-table headers stick just below the app header (not at top:0,
   where they'd hide behind it). Scoped to .panel so modal/grid-internal scroll
   headers keep their own offset. */
.panel .table-wrap thead { top: var(--app-header-h, 132px); }

/* ============ TABS ============ */
.tabs {
  display: flex; align-items: flex-end; gap: 0;
  padding: 0 20px;
  background: #fff; border-bottom: 1px solid var(--line);
  position: relative; z-index: 1;
  box-shadow: 0 1px 2px rgba(0,0,0,0.03);
}
/* Two-tier grouping: a small uppercase caption above each group's row of tabs. */
.tab-group { display: flex; flex-direction: column; }
.tab-group.hidden { display: none !important; }
.tab-group-label {
  font-size: 10px; line-height: 1; text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted); font-weight: 500; white-space: nowrap; user-select: none;
  padding: var(--space-2) var(--space-3) var(--space-1);
}
.tab-group-row { display: flex; }
/* Subtle 1px vertical rule between groups; collapsed at the bar's ends. */
.tab-divider {
  align-self: stretch; width: 1px; flex: 0 0 1px;
  background: var(--line); margin: var(--space-3) var(--space-1);
}
.tab-divider:first-child, .tab-divider:last-child { display: none; }
.tab-group.hidden + .tab-divider,
.tab-divider + .tab-divider { display: none; }
/* A divider immediately followed by a hidden group would dangle — hide it too. */
.tab-divider:has(+ .tab-group.hidden) { display: none; }
.tab {
  border: 0; background: transparent;
  padding: 12px 16px; font-family: inherit; font-size: 14px;
  color: var(--muted); cursor: pointer;
  border-bottom: 3px solid transparent;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.tab.hidden { display: none !important; }
.tab:hover { color: var(--ink); background: #fafafa; }
.tab.active { color: var(--ink); border-bottom-color: var(--ink); font-weight: 500; }

/* ============ PANELS ============ */
main { padding: 20px 28px 60px; }
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 20px; box-shadow: var(--shadow); animation: panelIn var(--t) var(--ease); }
.panel.hidden { display: none; }
.hidden { display: none !important; }
/* Calm panel entrance — runs each time a panel becomes visible via switchTab.
   .hidden's display:none keeps hidden panels hidden (and pauses the animation). */
@keyframes panelIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .panel { animation: none; } }
.panel-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; gap: 12px; flex-wrap: wrap; }
.panel-header h2 { margin: 0; font-size: 20px; font-weight: 500; }
.panel-actions { display: flex; gap: 8px; align-items: center; }

/* ============ BUTTONS / INPUTS ============ */
.btn {
  font-family: inherit; font-size: 13px; font-weight: 500;
  padding: 8px 14px; border-radius: 6px;
  border: 1px solid var(--line-strong); background: #fff; color: var(--ink);
  cursor: pointer; transition: background .15s, border-color .15s, transform .05s;
}
.btn:hover { background: #f4f4f4; }
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--ink); color: #fff; border-color: var(--ink); }
.btn-primary:hover { background: #222; }
.btn-danger { color: var(--c-debtor); border-color: var(--c-debtor); background: #fff; }
.btn-danger:hover { background: var(--c-debtor-bg); }
.btn-sm { padding: 5px 10px; font-size: 12px; }
/* Disabled buttons: dim, no pointer, no hover background. */
.btn:disabled, .btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn:disabled:hover, .btn[disabled]:hover { background: #fff; }
.btn-primary:disabled:hover, .btn-primary[disabled]:hover { background: var(--ink); }

/* ===== Accessible focus rings (keyboard-only via :focus-visible — no change for mouse users). ===== */
.btn:focus-visible,
.tab:focus-visible,
.ctx-item:focus-visible,
.ctx-back:focus-visible,
.day-switch button:focus-visible {
  outline: none; box-shadow: 0 0 0 3px rgba(0,0,0,0.14);
}
/* Dark-topbar segmented control mirrors the .profile-btn ring. */
.lang-switch button:focus-visible {
  outline: none; box-shadow: 0 0 0 3px rgba(255,255,255,0.35);
}
input[type=text], input[type=number], input[type=search], input[type=date], select, textarea {
  font-family: inherit; font-size: 14px;
  padding: 9px 12px; border: 1px solid var(--line-strong); border-radius: 6px;
  background: #fff; color: var(--ink); width: 100%;
}
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--ink); box-shadow: 0 0 0 3px rgba(0,0,0,0.06); }
label { display: block; font-size: 13px; color: var(--ink-soft); margin-bottom: 10px; }
label input, label select, label textarea { margin-top: 4px; }
.search-box { min-width: 240px; }

/* ============ TABLES ============ */
.table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: 8px; background: #fff; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead { background: #fafbfc; position: sticky; top: 0; }
th { font-weight: 500; color: var(--ink-soft); text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--line); white-space: nowrap; }
td { padding: 10px 12px; border-bottom: 1px solid var(--line); }
tbody tr { content-visibility: auto; contain-intrinsic-size: 0 var(--row-h); }
tbody tr:hover { background: #fafafa; }
tbody tr:last-child td { border-bottom: 0; }
/* Virtualized Table view: the two spacer rows reserve the off-window scroll
   height with a single full-width <td>. They must not inherit the row-height
   hint (which would add --row-h on top), the hover tint, or a border, and their
   lone <td> must stay non-sticky so it never trips the frozen #/Name columns. */
.virt-spacer { content-visibility: visible; contain-intrinsic-size: auto; }
.virt-spacer:hover { background: transparent; }
#activeListTable tr.virt-spacer > td { position: static; background: transparent; box-shadow: none; left: auto; }
.col-num { text-align: right; font-variant-numeric: tabular-nums; }
.col-name { white-space: nowrap; }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; align-items: center; white-space: nowrap; }
.row-actions .btn-sm { display: inline-flex; align-items: center; }
.row-actions .btn svg { width: 14px; height: 14px; display: block; }
.btn-pay { color: var(--c-active); border-color: var(--c-active); background: #fff; }
.btn-pay:hover { background: var(--c-active-bg); }
.btn-attend { color: #1565c0; border-color: #1565c0; background: #fff; }  /* blue: matches the ATTEND badge */
.btn-attend:hover { background: #d6e9fb; }
.btn-edit { color: var(--ink-soft); border-color: var(--line-strong); background: #fff; }
.btn-edit:hover { color: var(--ink); border-color: var(--ink); }

/* ===== Frozen first two columns (Active "Table" sub-view only) =====
   Scoped to #activeListTable so no other .table-wrap table is affected. The two
   leftmost columns (# row-number, 48px fixed; and Name) pin during horizontal
   scroll. Stacking order, lowest -> highest:
     normal cells (auto) < sticky body cells (3) < sticky header row (thead, 4)
     < sticky header corner cells (5). */
#activeListTable td:nth-child(1),
#activeListTable td:nth-child(2) { position: sticky; background: #fff; z-index: 3; }
#activeListTable th:nth-child(1),
#activeListTable th:nth-child(2) { position: sticky; background: #fafbfc; z-index: 5; }
#activeListTable th:nth-child(1), #activeListTable td:nth-child(1) { left: 0; }
#activeListTable th:nth-child(2), #activeListTable td:nth-child(2) { left: 48px; }
/* The thead is already sticky-top; its corner cells must also stick left and out-rank
   everything. The body sticky cells sit above normal cells but below the header row. */
#activeListTable thead { z-index: 4; }
/* Sticky body cells follow the row hover so scrolled-under content doesn't bleed through. */
#activeListTable tbody tr:hover td:nth-child(1),
#activeListTable tbody tr:hover td:nth-child(2) { background: #fafafa; }
/* Calm freeze-edge cue on the column-2 boundary (between Name and the scrolling cells). */
#activeListTable th:nth-child(2),
#activeListTable td:nth-child(2) { box-shadow: inset -1px 0 0 var(--line); }

/* ===== Comfortable / Compact density (body.dense) =====
   Scoped to .table-wrap tables only, so the schedule grid, attendance month grid,
   and any non-.table-wrap tables keep their own sizing. */
body.dense { --row-h: 28px; }
body.dense .table-wrap table { font-size: 12px; }
body.dense .table-wrap table th,
body.dense .table-wrap table td { padding: 5px 8px; }

/* Click-to-call phone links — look like plain text, hint green on hover. */
.tel-link { color: inherit; text-decoration: none; white-space: nowrap; cursor: pointer; }
.tel-link:hover { color: var(--c-active); text-decoration: underline; text-underline-offset: 2px; }

/* ============ STUDENT CONTEXT MENU (change group / edit / delete) ============ */
.student-name { cursor: pointer; }
.student-name:hover { text-decoration: underline; text-underline-offset: 2px; }

.ctx-menu {
  position: fixed; z-index: 200; min-width: 224px; max-width: 300px;
  background: #fff; border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: 0 8px 34px rgba(0,0,0,0.18); padding: 6px;
  animation: ctxPop .14s ease;
}
.ctx-menu.hidden { display: none; }
@keyframes ctxPop { from { opacity: 0; transform: scale(.96) translateY(-4px); } to { opacity: 1; transform: none; } }

.ctx-head { font-weight: 600; font-size: 13px; color: var(--ink); padding: 6px 10px 8px;
  border-bottom: 1px solid var(--line); margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.ctx-item, .ctx-back {
  display: flex; align-items: center; gap: 9px; width: 100%;
  border: 0; background: none; cursor: pointer; font-family: inherit; font-size: 13px;
  color: var(--ink); text-align: left; padding: 9px 10px; border-radius: 7px;
  animation: ctxItemIn .16s ease both;
}
.ctx-item svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--ink-soft); }
.ctx-item:hover:not(:disabled), .ctx-back:hover { background: #f4f4f5; }
.ctx-item:disabled { opacity: .6; cursor: default; }
/* While a Google-Sheets sync is in flight, spin the refresh icon. */
.ctx-item.syncing svg { animation: spin .9s linear infinite; transform-origin: 50% 50%; }
@keyframes spin { to { transform: rotate(360deg); } }
.ctx-item > span:first-of-type { flex: 1; }
.ctx-arrow { margin-left: auto; display: inline-flex; }
.ctx-arrow svg { width: 14px; height: 14px; color: var(--line-strong); }
.ctx-meta { font-size: 11px; color: var(--ink-soft); }
.ctx-danger, .ctx-danger svg { color: #c62828; }
.ctx-item.ctx-left, .ctx-item.ctx-left svg { color: #fff; }
.ctx-item.ctx-left { background: #757575; }
.ctx-item.ctx-left:hover:not(:disabled) { background: #616161; }

.ctx-back { font-weight: 600; color: var(--ink-soft); border-bottom: 1px solid var(--line);
  border-radius: 0; margin-bottom: 4px; padding-left: 4px; }
.ctx-back svg { width: 16px; height: 16px; }

.ctx-group { gap: 8px; }
.ctx-grp-day { font-weight: 600; min-width: 48px; }
.ctx-grp-time { color: var(--ink-soft); }
.ctx-group .ctx-meta { margin-left: auto; }
.ctx-current { cursor: default; }
.ctx-cur-tag { margin-left: 6px; font-size: 10px; text-transform: uppercase; letter-spacing: .4px; color: var(--c-active); }
.ctx-empty { padding: 12px 10px; font-size: 12px; color: var(--ink-soft); }
@keyframes ctxItemIn { from { opacity: 0; transform: translateX(8px); } to { opacity: 1; transform: none; } }

/* Move-to-group: source row fades/slides out, destination row "lands" in its new
   group with a settling green border (no background tint — border only). */
.row-leaving td { animation: rowLeave .26s ease forwards; }
@keyframes rowLeave { to { opacity: .12; } }

/* Green border ring that wraps the whole row and settles (mirrors .vk-card-land).
   Drawn on an overlay so border-collapse doesn't swallow the box-shadow; the ring
   is `inset` so the pill's overflow:hidden can't clip it at the row edges. */
.row-arriving { position: relative; z-index: 1; }
.row-arriving::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 8px; pointer-events: none;
  animation: rowLand 1.2s cubic-bezier(.2,.7,.3,1);
}
@keyframes rowLand {
  0%   { box-shadow: inset 0 0 0 2px var(--c-active), 0 6px 18px color-mix(in srgb, var(--c-active) 30%, transparent); }
  30%  { box-shadow: inset 0 0 0 2px var(--c-active), 0 4px 14px color-mix(in srgb, var(--c-active) 26%, transparent); }
  75%  { box-shadow: inset 0 0 0 2px var(--c-active), 0 2px 8px color-mix(in srgb, var(--c-active) 18%, transparent); }
  100% { box-shadow: inset 0 0 0 0 transparent, 0 1px 2px rgba(0,0,0,.04); }
}

/* Lift-and-fly clone: a fixed-position copy of the row that hovers in the air
   while the view scrolls to the destination, then flies straight into the new
   slot. White like a normal row, with just a green border ring. */
.row-fly {
  position: fixed; z-index: 300; pointer-events: none;
  border-radius: 10px; overflow: hidden;
  background: #fff;
  box-shadow: 0 18px 40px rgba(0,0,0,.28), 0 0 0 2px var(--c-active);
  transform: scale(1.03);
  transition: transform .5s cubic-bezier(.2,.7,.3,1);
  will-change: transform;
}
/* Neutralize the wrapper pill so only the row (with its real column widths and
   cell styling) shows on the white clone. */
.row-fly .group-pill {
  border: 0; border-radius: 0; box-shadow: none;
  background: transparent; content-visibility: visible;
}
.row-fly .group-table,
.row-fly .group-table tbody tr td { background: transparent; }

/* Take-payment modal */
.pay-student { font-size: 18px; font-weight: 700; color: var(--ink); }
.pay-student-sub { font-size: 12px; margin: 2px 0 14px; }

/* By-classes block in the pay modal — the money amount is the focal point,
   with the coverage date as supporting context beside it. */
.pay-sub { margin-bottom: 14px; }

/* Two-up hero: amount leads (primary), the covered-until date supports it. */
.pay-hero {
  display: grid; grid-template-columns: 1.4fr 1fr; align-items: stretch;
  border: 1px solid var(--c-active); border-radius: 12px; overflow: hidden;
  margin-bottom: 14px;
}
.pay-hero-cell { padding: 13px 16px; min-width: 0; }
.pay-hero-amount { background: linear-gradient(180deg, var(--c-active-bg), #fff); }
.pay-hero-until {
  border-left: 1px solid var(--line);
  display: flex; flex-direction: column; justify-content: center;
}
.pay-hero-label { font-size: 11px; text-transform: uppercase; letter-spacing: .8px; font-weight: 600; }
.pay-hero-amount .pay-hero-label { color: var(--c-active); }
.pay-hero-until  .pay-hero-label { color: var(--muted); }
.pay-hero-val {
  font-size: 28px; font-weight: 800; color: var(--ink); line-height: 1.1;
  margin-top: 4px; word-break: break-word;
}
.pay-hero-unit { font-size: 15px; font-weight: 600; color: var(--ink-soft); margin-left: 6px; }
.pay-hero-date { font-size: 19px; font-weight: 700; color: var(--ink); line-height: 1.2; margin-top: 4px; }
.pay-hero-meta { font-size: 12px; margin-top: 5px; }
.pay-hero-meta.is-overdue { color: var(--c-debtor); font-weight: 600; }

/* Class count: stepper + presets on one row. */
.pay-cls-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.pay-stepper { display: inline-flex; align-items: center; border: 1px solid var(--line-strong); border-radius: 8px; overflow: hidden; }
.pay-step {
  border: 0; background: #fafafa; width: 34px; height: 38px; font-size: 20px; line-height: 1;
  color: var(--ink); cursor: pointer; font-family: inherit;
}
.pay-step:hover { background: var(--c-active-bg); color: var(--c-active); }
.pay-stepper input {
  width: 56px; text-align: center; border: 0; border-left: 1px solid var(--line);
  border-right: 1px solid var(--line); border-radius: 0; font-size: 16px; font-weight: 600; height: 38px;
  -moz-appearance: textfield;
}
.pay-stepper input::-webkit-outer-spin-button, .pay-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.pay-cls-unit { font-size: 13px; color: var(--ink-soft); margin-right: auto; }
.pay-modes { display: flex; gap: 8px; }
.pay-mode {
  padding: 8px 12px; border: 1px solid var(--line-strong); border-radius: 7px;
  background: #fff; color: var(--ink-soft); font-family: inherit; font-size: 13px; cursor: pointer; white-space: nowrap;
}
.pay-mode:hover { border-color: var(--ink); color: var(--ink); }
.pay-mode.active { background: var(--c-active-bg); border-color: var(--c-active); color: var(--c-active); font-weight: 600; }

/* Label used by the partial-payment "Paid now" row. */
.pay-amount-lbl { font-size: 13px; color: var(--ink-soft); }

.pay-bycls { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-soft); margin-top: 10px; cursor: pointer; }
.pay-bycls input { width: auto; }

/* "Paid until" cell states in the active-students table */
.pay-overdue { color: #c62828; font-weight: 600; }
.pay-ok { color: var(--c-active); }

/* ============ BADGES (statuses, etc.) ============ */
.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 600; letter-spacing: .3px; text-transform: uppercase; }
.b-active   { background: var(--c-active-bg);   color: var(--c-active); }
.b-debtor   { background: var(--c-debtor-bg);   color: var(--c-debtor); }
.b-newcomer { background: var(--c-newcomer-bg); color: var(--c-newcomer); }
.b-frozen   { background: var(--c-frozen-bg);   color: var(--c-frozen); }
.b-left     { background: var(--c-left-bg);     color: var(--c-left); }
.b-vip      { background: var(--c-vip-bg);      color: var(--c-vip); }
.b-attend   { background: #d6e9fb; color: #1565c0; }  /* blue: matches Newcomers funnel ATTEND accent */
.b-coming   { background: #ffe3c2; color: #e65100; }  /* orange */
.b-waiting  { background: #ffd5d5; color: #d32f2f; }  /* red */
.b-recall   { background: #ffd6d6; color: #b91c1c; }
.b-no       { background: #ececec; color: #555; }
.b-yes      { background: #cce4ff; color: #1565c0; }
.b-muted    { background: #ececec; color: var(--muted); }

/* ============ REPORT / KPI TILES (mimics old Report sheet) ============ */
.report-banner {
  display: grid; grid-template-columns: 1.2fr 1.2fr 1fr 1fr 1fr 1fr 1fr 1fr;
  gap: 10px; margin-bottom: 14px;
}
/* Active Students summary row: 5 equal tiles that wrap responsively, without
   touching the fixed-template Finance / Dashboard banners. */
#activeStats { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 900px) { #activeStats { grid-template-columns: repeat(2, 1fr); } }
.tile {
  border-radius: 10px; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 4px;
  color: #fff; box-shadow: var(--shadow);
  min-height: 86px; justify-content: center;
}
.tile .tlabel { font-size: 11px; letter-spacing: .5px; text-transform: uppercase; opacity: .9; font-weight: 500; }
.tile .tvalue { font-size: 26px; font-weight: 700; line-height: 1.1; }
.tile .tsub   { font-size: 11px; opacity: .85; }

.tile-mosque    { background: #b39863; }                  /* صلى‌الله corner */
.tile-revenue   { background: linear-gradient(135deg,#1f6f3a,#2e9c54); }
.tile-expected  { background: linear-gradient(135deg,#374151,#5b6473); }
.tile-total     { background: linear-gradient(135deg,#f0c419,#f9a825); color: #2c2200; }
.tile-vip       { background: linear-gradient(135deg,#9c27b0,#c158d6); }
.tile-active    { background: linear-gradient(135deg,#2e7d32,#43a047); }
.tile-debtor    { background: linear-gradient(135deg,#c62828,#e53935); }
.tile-attend    { background: linear-gradient(135deg,#0097a7,#26c6da); }
.tile-frozen    { background: linear-gradient(135deg,#37474f,#607d8b); }
.tile-left      { background: linear-gradient(135deg,#212121,#424242); }
.tile-newcomer  { background: linear-gradient(135deg,#1565c0,#42a5f5); }
.tile-money-soft{ background: linear-gradient(135deg,#5d4037,#8d6e63); }

/* Active-Students summary tiles: soft-tinted treatment (light card, faint
   status tint, colored left accent + number). Scoped to #activeStats so the
   shared Finance/Dashboard tiles keep their solid fills. */
#activeStats .tile {
  color: #1f2430;
  border: 1px solid #e6e8ee;
  border-left: 3px solid var(--tile-accent, #cbd2dc);
  background: var(--tile-bg, #fff);
  box-shadow: 0 1px 2px rgba(16, 24, 40, .05);
}
#activeStats .tile .tlabel { color: #6b7280; opacity: 1; font-weight: 600; }
#activeStats .tile .tvalue { color: var(--tile-accent, #1f2430); }
#activeStats .tile .tsub   { color: #9aa1ab; opacity: 1; }

#activeStats .tile-total  { --tile-accent: #a8740d; --tile-bg: #fcf7e8; }
#activeStats .tile-active { --tile-accent: #1f7a39; --tile-bg: #ecf7ef; }
#activeStats .tile-debtor { --tile-accent: #b42626; --tile-bg: #fcebeb; }
#activeStats .tile-frozen { --tile-accent: #0277bd; --tile-bg: #e6f1fb; }
#activeStats .tile-vip    { --tile-accent: #546e7a; --tile-bg: #eef1f4; }

.report-secondary {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px; margin-bottom: 20px;
}
.mini-tile {
  background: #fff; border: 1px solid var(--line); border-radius: 8px;
  padding: 12px 14px; display: flex; flex-direction: column; gap: 3px;
  border-left: 4px solid var(--line-strong);
}
.mini-tile .mlabel { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
.mini-tile .mvalue { font-size: 20px; font-weight: 700; }
.mini-tile.mt-attend  { border-left-color: #26c6da; }
.mini-tile.mt-coming  { border-left-color: #f9a825; }
.mini-tile.mt-waiting { border-left-color: #ff9800; }
.mini-tile.mt-recall  { border-left-color: #e53935; }
.mini-tile.mt-no      { border-left-color: #9e9e9e; }
.mini-tile.mt-yes     { border-left-color: #1565c0; }

.report-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 14px; margin-top: 18px; }
.report-card { background: #fff; border: 1px solid var(--line); border-radius: 10px; padding: 16px; }
.report-card h3 { margin: 0 0 14px; font-size: 14px; font-weight: 500; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .4px; }
.bars { display: flex; flex-direction: column; gap: 8px; }
.bar-row { display: grid; grid-template-columns: 150px 1fr 50px; gap: 10px; align-items: center; font-size: 13px; }
.bar-row .label { color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar-row .track { height: 10px; background: #eef0f3; border-radius: 999px; overflow: hidden; }
.bar-row .fill { height: 100%; background: linear-gradient(90deg,#1565c0,#42a5f5); border-radius: 999px; }
.bar-row .num { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); }

/* ---- Dashboard hub (period bar + switchable views) ---- */
.rep-toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.rep-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.rep-views { flex-wrap: wrap; }
.rep-period-label { font-size: 14px; font-weight: 600; color: var(--ink-soft); }
.rep-proj { color: var(--c-newcomer); font-weight: 700; text-transform: uppercase; font-size: 11px; letter-spacing: .4px; }
.rep-grid-2 { grid-template-columns: 1.5fr 1fr; }
@media (max-width: 1000px) { .rep-grid-2 { grid-template-columns: 1fr; } }

/* Extra accent colors for the shared .fin-card used across the dashboard. */
.fin-card-blue::before { background: var(--c-newcomer); }
.fin-card-teal::before { background: #00838f; }

.rep-delta { font-size: 11px; font-weight: 700; white-space: nowrap; }
.rep-delta.up   { color: var(--c-active); }
.rep-delta.down { color: var(--c-debtor); }
.rep-delta.flat { color: var(--muted); }

.rep-statusbar { height: 16px; }

/* 12-month income/expense trend — fixed-height columns so % bars resolve. */
.rep-chart { display: flex; align-items: flex-end; gap: 6px; }
.rep-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 0; padding-top: 4px; border-radius: 6px; }
.rep-col-bars { height: 150px; width: 100%; display: flex; align-items: flex-end; justify-content: center; gap: 3px; }
.rep-bar { width: 42%; max-width: 16px; min-height: 2px; border-radius: 3px 3px 0 0; }
.rep-bar.in { background: var(--c-active); }
.rep-bar.ex { background: var(--c-debtor); }
.rep-col-x { font-size: 10px; color: var(--muted); }
.rep-col.is-sel { background: var(--c-active-bg); }
.rep-col.is-sel .rep-col-x { color: var(--ink); font-weight: 700; }

.rep-progress { height: 12px; background: #eef0f3; border-radius: 999px; overflow: hidden; }
.rep-progress-fill { height: 100%; background: linear-gradient(90deg, var(--c-active), #43a047); border-radius: 999px; }
.rep-progress-meta { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; margin-top: 8px; }
.rep-kv { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 18px; }
.rep-kv > div { display: flex; flex-direction: column; gap: 3px; font-size: 12px; }
.rep-kv strong { font-size: 16px; color: var(--ink); }

.rep-note { background: #fff8e1; border: 1px solid #ffe0a3; color: #8a6a00; padding: 10px 14px; border-radius: 10px; font-size: 13px; margin: 0 0 14px; }

.rep-funnel { display: flex; flex-direction: column; gap: 10px; }
.rep-funnel-row { display: grid; grid-template-columns: 130px 1fr 44px; gap: 10px; align-items: center; font-size: 13px; }
.rep-funnel-label { color: var(--ink-soft); }
.rep-funnel-track { height: 22px; background: #eef0f3; border-radius: 6px; overflow: hidden; }
.rep-funnel-fill { height: 100%; border-radius: 6px; min-width: 2px; transition: width .25s ease; }
.rep-funnel-num { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }

/* ============ SCHEDULE GRID (mimics old ROOMS sheet) ============ */
.schedule-meta { display: flex; gap: 16px; margin-bottom: 12px; font-size: 13px; color: var(--muted); }
.schedule-legend { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.legend-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--ink-soft); padding: 3px 8px; border-radius: 4px; border: 1px solid var(--line); background: #fff; }
.legend-swatch { width: 12px; height: 12px; border-radius: 3px; }
.day-switch { display: inline-flex; flex-shrink: 0; border: 1px solid var(--line-strong); border-radius: 6px; overflow: hidden; }
.day-switch button { border: 0; padding: 7px 14px; background: #fff; cursor: pointer; font-family: inherit; font-size: 13px; color: var(--ink-soft); white-space: nowrap; flex-shrink: 0; }
.day-switch button.active { background: var(--ink); color: #fff; font-weight: 500; }
/* The newcomers "Register" CTA matches the view-switch buttons: same height and
   pill shape, dark fill, and never wraps — so the header row reads as one set. */
#openAddStudent { padding: 7px 14px; white-space: nowrap; flex-shrink: 0; }

/* Standalone panel-action buttons (Clear filters / Export CSV) match the view-toggle size */
#clearFilters, #exportCsv { padding: 7px 14px; font-size: 13px; }

.schedule-stack { display: grid !important; grid-template-columns: 1fr 1fr !important; gap: 16px; align-items: start; }
.schedule-block { background: #fff; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; box-shadow: var(--shadow); min-width: 0; }
.schedule-block .slot-cell { min-width: 0; }
.schedule-block .schedule-grid th.time-col,
.schedule-block .schedule-grid td.time-col { min-width: 70px; }
.schedule-block-title {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; background: #fafbfc; border-bottom: 1px solid var(--line);
}
.sb-tag {
  font-size: 12px; font-weight: 600; letter-spacing: .4px;
  padding: 4px 10px; border-radius: 999px; color: #fff;
}
.sb-mwf { background: #1565c0; }
.sb-tts { background: #2e7d32; }
.sb-count { font-size: 12px; color: var(--muted); }

/* Floor plan */
.floor-wrap {
  background: #fafbfc; border: 1px solid var(--line); border-radius: 12px;
  padding: 20px; overflow: auto;
}
#floorPlan { width: 100%; height: auto; max-width: 1240px; display: block; margin: 0 auto; }

/* 3D viewer canvas */
.floor-3d-wrap {
  background: linear-gradient(180deg, #e9ecf2, #f4f5f7);
  border: 1px solid var(--line); border-radius: 12px;
  width: 100%; max-width: 1240px; margin: 0 auto;
  height: 70vh; position: relative; overflow: hidden;
}
#floorCanvas3D { display: block; width: 100%; height: 100%; cursor: grab; }
#floorCanvas3D:active { cursor: grabbing; }
.floor-3d-hint {
  position: absolute; left: 12px; bottom: 10px; font-size: 11px;
  color: var(--muted); background: rgba(255,255,255,.7);
  padding: 3px 8px; border-radius: 6px; pointer-events: none;
}

/* Stage holds the floor view (2D or 3D) plus the time roller on the right. */
.floor-stage { display: flex; align-items: stretch; gap: 14px; }
.floor-stage > .floor-wrap,
.floor-stage > .floor-3d-wrap { flex: 1 1 auto; min-width: 0; }

/* Vertical time roller + day switch, pinned to the right of the floor. */
.floor-time-control {
  flex: 0 0 96px; align-self: stretch;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  background: #fafbfc; border: 1px solid var(--line); border-radius: 12px;
  padding: 14px 8px;
}
.floor-time-control.hidden { display: none; }
.ftc-days { flex-direction: column; width: 100%; }
.ftc-days button { width: 100%; }
.ftc-readout { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.ftc-time {
  font-family: 'Google Sans', system-ui, sans-serif;
  font-size: 22px; font-weight: 600; color: #1565c0; font-variant-numeric: tabular-nums;
}
.ftc-occ { font-size: 11px; text-align: center; }
.ftc-roller-wrap { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; }
/* Make the range input run vertically (top = earliest, bottom = latest).
   writing-mode drives this in current Chrome; slider-vertical is the legacy
   fallback for older engines. */
.ftc-roller {
  writing-mode: vertical-lr;
  -webkit-appearance: slider-vertical; appearance: slider-vertical;
  width: 28px; height: 100%; min-height: 260px; cursor: pointer; accent-color: #1565c0;
}
.fp-room rect { transition: fill .15s, stroke .15s; }
.fp-room:hover rect { fill: #eef3ff; stroke: #1565c0; cursor: default; }
.fp-room--filled:hover rect { fill: #6e7177; }
.fp-label {
  font-family: 'Google Sans', system-ui, sans-serif;
  font-size: 24px; font-weight: 600; fill: #2a2a2a; letter-spacing: .5px;
}
.fp-label--on-dark { fill: #ffffff; }
.fp-label--sm { font-size: 14px; fill: #6e7177; letter-spacing: 1px; }
.floor-legend { margin-top: 10px; text-align: center; font-size: 12px; }

/* Floor plan editor */
.floor-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.floor-edit-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; flex: 1; }
.floor-edit-tools .spacer { flex: 1; min-width: 8px; }
#floorHint { font-size: 12px; color: var(--muted); }
#floorPlan.is-editing .fp-shape { cursor: move; }
#floorPlan.is-editing .fp-shape:hover rect { stroke: #1565c0; }
.fp-selring { fill: none; stroke: #1565c0; stroke-width: 2; stroke-dasharray: 4 3; pointer-events: none; }
.fp-handle { fill: #1565c0; stroke: #fff; stroke-width: 2; cursor: nwse-resize; }

/* Tables, chairs, seat badge */
/* Tables: cool light neutral, modern office vibe (not brown) */
.fp-table { fill: #e8ebf0; stroke: #9ea5b1; stroke-width: 1.5; }
.fp-table--desk { fill: #dde2eb; stroke: #8a93a1; stroke-width: 1; }
/* Chairs: warm dark slate — clear contrast on light tables */
.fp-chair { fill: #4a5563; stroke: #2a313b; stroke-width: 1; }
/* A seated student: the chair underneath stays as-is; a green person sits on it. */
.fp-person circle, .fp-person path { fill: #2e7d32; stroke: #ffffff; stroke-width: .6; }
.fp-seats-badge rect { fill: #1565c0; stroke: #0d4a8a; stroke-width: 1; }
.fp-seats-badge text { fill: #fff; font-size: 11px; font-weight: 600; font-family: 'Google Sans', sans-serif; }
/* Badge turns green when the room has people, red when over capacity. */
.fp-seats-badge.is-occupied rect { fill: #2e7d32; stroke: #1b5e20; }
.fp-seats-badge.is-over rect { fill: #c62828; stroke: #8e1f1f; }
.fp-person-icon circle, .fp-person-icon path { fill: #fff; stroke: none; }
.fp-table-handle { fill: #2e7d32; stroke: #fff; stroke-width: 2; cursor: nwse-resize; }

/* Room walls — chunky like an AutoCAD floor plan (visible wall thickness,
   not a thin line). Darken blend keeps overlapping walls merging into one. */
.fp-wall {
  fill: none; stroke: #3d4350; stroke-width: 7; stroke-linecap: butt;
  pointer-events: none;
  mix-blend-mode: darken;
  shape-rendering: crispEdges;
}
.fp-shape--room.is-selected .fp-wall { stroke: #1f2329; }

/* Architectural door symbol: leaf line + quarter-circle swing arc */
.fp-door-symbol { fill: none; stroke: #4a5563; stroke-width: 1.4; stroke-linecap: round; pointer-events: none; }
/* Architectural window symbol: two parallel thin lines across the wall gap */
.fp-window { stroke: #1565c0; stroke-width: 1.5; pointer-events: none; }

/* Stairs walls: left + bottom + right only — the top edge is open since the
   stairs connect to the room. mix-blend + crispEdges merges with neighboring
   walls just like the room walls. */
.fp-stairs-wall {
  fill: none;
  stroke: #3d4350;
  stroke-width: 7;
  stroke-linecap: butt;
  stroke-linejoin: miter;
  pointer-events: none;
  mix-blend-mode: darken;
  shape-rendering: crispEdges;
}

/* Stairs: minimal — just parallel tread lines. */
.fp-stairs-icon line { stroke: #3d4350; stroke-width: 1.4; pointer-events: none; }

/* Room names rendered outside the building — bold with a halo so they read on the dotted ground */
.fp-room-name-ext { font-weight: 700; font-size: 14px; fill: #1f2329; letter-spacing: .5px; paint-order: stroke; stroke: #f4f5f7; stroke-width: 3; }

/* Door drag-handle (visible only in edit mode when room is selected) */
.fp-door-handle rect { fill: rgba(21, 101, 192, 0.18); stroke: #1565c0; stroke-width: 1.5; stroke-dasharray: 4 3; cursor: move; }
.fp-door-handle:hover rect { fill: rgba(21, 101, 192, 0.32); }

/* Inline seat controls in toolbar */
.floor-room-props {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border: 1px solid var(--line-strong);
  border-radius: 999px; background: #fff; font-size: 12px;
  margin-left: 6px;
}
.floor-room-props #floorSeatLabel { min-width: 56px; text-align: center; font-weight: 600; }
.floor-layout-switch {
  display: inline-flex; gap: 0; margin-left: 8px;
  border: 1px solid var(--line-strong); border-radius: 999px; overflow: hidden;
  background: #fafafa;
}
.floor-layout-switch button {
  border: 0; background: transparent; padding: 4px 12px; font-size: 11px;
  color: var(--ink-soft); cursor: pointer; border-radius: 0;
}
.floor-layout-switch button.active { background: var(--ink); color: #fff; }

.floor-wb-switch {
  display: inline-flex; gap: 0; margin-left: 8px;
  border: 1px solid var(--line-strong); border-radius: 999px; overflow: hidden;
  background: #fafafa; align-items: center;
}
.floor-wb-switch .floor-wb-label { padding: 0 8px; font-size: 11px; color: var(--muted); }
.floor-wb-switch button {
  border: 0; background: transparent; padding: 4px 8px; font-size: 12px;
  color: var(--ink-soft); cursor: pointer; border-radius: 0; min-width: 22px;
}
.floor-wb-switch button.active { background: #2a2f36; color: #fff; }

/* Stairs ascent direction picker (mirrors the WB picker style) */
.floor-stairs-props {
  display: inline-flex; gap: 0; margin-left: 8px;
  border: 1px solid var(--line-strong); border-radius: 999px; overflow: hidden;
  background: #fafafa; align-items: center;
}
.floor-stairs-props .floor-wb-label { padding: 0 8px; font-size: 11px; color: var(--muted); }
.floor-stairs-props button {
  border: 0; background: transparent; padding: 4px 8px; font-size: 12px;
  color: var(--ink-soft); cursor: pointer; border-radius: 0; min-width: 22px;
}
.floor-stairs-props button.active { background: #2a2f36; color: #fff; }

/* Door toggle pill */
.floor-door-switch {
  display: inline-flex; gap: 0; margin-left: 8px;
  border: 1px solid var(--line-strong); border-radius: 999px; overflow: hidden;
  background: #fafafa; align-items: center;
}
.floor-door-switch .floor-wb-label { padding: 0 8px; font-size: 11px; color: var(--muted); }
.floor-door-switch button {
  border: 0; background: transparent; padding: 4px 12px; font-size: 11px;
  color: var(--ink-soft); cursor: pointer; border-radius: 0;
}
.floor-door-switch button.active { background: #1565c0; color: #fff; }

.floor-door-style {
  display: inline-flex; gap: 0; margin-left: 8px;
  border: 1px solid var(--line-strong); border-radius: 999px; overflow: hidden;
  background: #fafafa; align-items: center;
}
.floor-door-style .floor-wb-label { padding: 0 8px; font-size: 11px; color: var(--muted); }
.floor-door-style button {
  border: 0; background: transparent; padding: 4px 9px; font-size: 13px;
  color: var(--ink-soft); cursor: pointer; border-radius: 0;
}
.floor-door-style button.active { background: #1565c0; color: #fff; }

/* Color swatch pickers */
.floor-color-picker {
  display: inline-flex; align-items: center; gap: 6px; margin-left: 8px;
  padding: 3px 8px; border: 1px solid var(--line-strong); border-radius: 999px;
  background: #fafafa;
}
.floor-color-picker .cp-title { font-size: 11px; color: var(--muted); }
.cp-swatches { display: inline-flex; gap: 3px; }
.cp-swatch {
  width: 16px; height: 16px; border-radius: 50%;
  border: 1px solid var(--line-strong); cursor: pointer; padding: 0;
  font-size: 10px; line-height: 14px; color: var(--muted); display: inline-flex;
  align-items: center; justify-content: center;
}
.cp-swatch:hover { transform: scale(1.12); }
.cp-swatch.active { outline: 2px solid var(--ink); outline-offset: 1px; }

/* Whiteboard: actual white with a dark frame (real-life whiteboard look) */
.fp-whiteboard { fill: #fcfcfd; stroke: #2a2f36; stroke-width: 2.4; }

.fp-grid { display: none; }
#floorPlan.is-editing .fp-grid { display: block; }

.schedule-block .grid-wrap { border: 0; border-radius: 0; max-height: 60vh; }
.grid-wrap { overflow: auto; border: 1px solid var(--line); border-radius: 8px; background: #fff; max-height: 70vh; }
.schedule-grid { border-collapse: collapse; width: 100%; font-size: 11px; }
.schedule-grid th, .schedule-grid td {
  border: 1px solid #e0e0e0; padding: 4px 6px; vertical-align: middle;
}
.schedule-grid thead th {
  background: #1a1a1a; color: #fff; font-weight: 500; text-align: center;
  position: sticky; top: 0; z-index: 2; font-size: 12px; padding: 8px 6px;
}
.schedule-grid th.time-col, .schedule-grid td.time-col {
  background: #fafbfc; font-weight: 600; color: var(--ink-soft);
  text-align: center; white-space: nowrap; min-width: 90px;
  position: sticky; left: 0; z-index: 1;
}
.schedule-grid thead th.time-col { z-index: 3; }
.slot-cell { min-width: 110px; height: 38px; text-align: center; line-height: 1.2; vertical-align: top; padding: 0; }
.slot-cell .slot-inner {
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  gap: 2px; padding: 6px 6px; height: 100%; min-height: 32px;
}
.slot-cell .slot-note { font-weight: 600; font-size: 11px; color: #1a1a1a; line-height: 1.15; overflow-wrap: anywhere; }
.slot-cell .slot-teacher { font-size: 10px; color: #333; opacity: .9; line-height: 1.1; }
.slot-cell .slot-meta { font-size: 9.5px; color: #555; opacity: .8; font-variant-numeric: tabular-nums; }
.slot-cell.lt-kids          { background: var(--lt-kids); }
.slot-cell.lt-beginner      { background: var(--lt-beginner); }
.slot-cell.lt-elementary    { background: var(--lt-elementary); }
.slot-cell.lt-pre-intermediate { background: var(--lt-pre-intermediate); }
.slot-cell.lt-intermediate  { background: var(--lt-intermediate); }
.slot-cell.lt-upper-intermediate { background: var(--lt-upper-intermediate); }
.slot-cell.lt-advanced      { background: var(--lt-advanced); }
.slot-cell.lt-ielts         { background: var(--lt-ielts); }
.slot-cell.lt-speaking      { background: var(--lt-speaking); }
.slot-cell.lt-writing       { background: var(--lt-writing); }
.slot-cell.lt-individual    { background: var(--lt-individual); }
.slot-cell.lt-teachers      { background: var(--lt-teachers); color: #fff; }
.slot-cell.lt-other         { background: var(--lt-other); }
.slot-cell.empty            { background: #ffffff; }

/* ============ SCHEDULE (combined weekly grid) ============ */
.sch-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.sch-counts { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--muted); flex-wrap: wrap; }
.sch-counts .sch-count { font-variant-numeric: tabular-nums; }
.sch-counts .sch-dot { color: var(--line-strong); margin: 0 2px; }
.sch-tag { font-size: 11px; font-weight: 600; letter-spacing: .4px; padding: 3px 10px; border-radius: 999px; color: #e9edf3; background: #2b303a; }
.sch-tag.sch-tts, .sch-tag.sch-mwf { background: #2b303a; }

/* Filter bars (level legend + teachers) */
.sch-filters { display: flex; flex-direction: column; gap: 7px; margin-bottom: 12px; }
.sch-filter-row { display: flex; align-items: flex-start; gap: 8px; }
.sch-filter-label { flex: 0 0 52px; font-size: 11px; font-weight: 600; color: var(--muted); padding-top: 4px; }
.schedule-legend, .sch-teacher-filter { display: flex; flex-wrap: wrap; gap: 6px; flex: 1; }
.schedule-legend.hidden { display: none; }
.legend-chip, .tch-chip {
  display: inline-flex; align-items: center; gap: 5px; font-family: inherit; font-size: 10.5px;
  color: var(--ink-soft); padding: 3px 9px; border-radius: 999px; border: 1px solid var(--line);
  background: #fff; cursor: pointer; line-height: 1.3; transition: border-color .12s, box-shadow .12s, background .12s;
}
.legend-chip:hover, .tch-chip:hover { border-color: var(--line-strong); }
.legend-chip.active { border-color: var(--ink); box-shadow: 0 0 0 1.5px var(--ink) inset; font-weight: 600; color: var(--ink); }
.tch-chip.active { background: var(--ink); border-color: var(--ink); color: #fff; font-weight: 600; }
.legend-swatch { width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0; }

/* dimmed (filtered-out) lessons */
.sch-grid.is-filtering .slot-cell.sch-dim .slot-inner { opacity: .12; filter: grayscale(.5); }
.sch-grid.is-filtering .slot-cell:not(.sch-dim):not(.empty) .slot-inner { box-shadow: 0 0 0 1.5px rgba(21,101,192,.35); }

.sch-wrap {
  overflow: auto; border: 1px solid var(--line); border-radius: 12px; background: #fff;
  max-height: 76vh; box-shadow: 0 4px 16px -8px rgba(23,32,53,.18);
}
/* Fixed layout + 100% width => all columns share the screen, no horizontal scroll. */
.sch-grid { border-collapse: separate; border-spacing: 0; table-layout: fixed; width: 100%; font-size: 10px; }
.sch-grid th, .sch-grid td { border-right: 1px dashed #dfe3e9; border-bottom: 1px dashed #dfe3e9; overflow: hidden; }

/* sticky two-row header + sticky time column */
.sch-grid thead th { position: sticky; z-index: 2; background: #fff; }
.sch-grouphead .day-group {
  top: 0; height: 32px; color: #e9edf3; font-weight: 600; letter-spacing: 2px;
  font-size: 11.5px; text-align: center; border-bottom: 0; background: #2b303a;
}
.sch-roomhead .room-head {
  top: 32px; background: #f6f8fb; text-align: center; padding: 6px 3px 7px; vertical-align: middle;
}
.room-head .rh-name { display: block; font-weight: 700; font-size: 13px; color: var(--ink); letter-spacing: .5px; }
.room-head .rh-cap {
  display: inline-flex; align-items: center; gap: 3px; margin-top: 4px;
  font-size: 10px; font-weight: 600; color: #51606f; font-variant-numeric: tabular-nums;
  padding: 1px 8px; background: #e7edf4; border: 1px solid #dbe3ec; border-radius: 999px;
}
.sch-pic { width: 11px; height: 11px; flex-shrink: 0; }

.sch-grid .time-col {
  position: sticky; left: 0; z-index: 1; background: #f6f8fb; font-weight: 600; color: var(--ink-soft);
  text-align: center; white-space: nowrap; width: 46px; padding: 5px 3px; font-variant-numeric: tabular-nums;
}
.sch-grid thead th.time-col { top: 0; z-index: 5; background: #eef1f5; }

/* fixed row height => every N-slot group is exactly N rows tall, regardless of text */
.sch-grid tbody tr { height: 40px; }

/* lesson cells — the coloured group is a rounded card floating inside the white cell */
.sch-grid .slot-cell { text-align: center; vertical-align: middle; padding: 3px; background: #fff; }
.sch-grid .slot-inner {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 5px 4px; box-sizing: border-box; border-radius: 8px; overflow: hidden; transition: opacity .12s, filter .12s, box-shadow .12s;
}
.sch-grid .slot-type { font-weight: 700; font-size: 11.5px; letter-spacing: .2px; color: #0f2740; line-height: 1.12; overflow-wrap: anywhere; }
.sch-grid .slot-teacher {
  font-size: 11px; color: #1f2d3a; line-height: 1.15; opacity: 1; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.sch-grid .slot-meta { font-size: 8.5px; color: #44505d; opacity: .85; font-variant-numeric: tabular-nums; }
.sch-grid .slot-cell.empty { background: #fff; }
.sch-grid .group-start { border-left: 2px solid var(--line-strong); }
/* hover a group => fade every OTHER level to ~50%, keeping this level full */
.sch-grid.is-lvlhover .slot-cell:not(.lvl-match):not(.empty) .slot-inner { opacity: .15; }

/* coloured group cards (level palette applied to the inner card) */
.sch-grid .slot-inner.lt-kids               { background: var(--lt-kids); }
.sch-grid .slot-inner.lt-beginner           { background: var(--lt-beginner); }
.sch-grid .slot-inner.lt-elementary         { background: var(--lt-elementary); }
.sch-grid .slot-inner.lt-pre-intermediate   { background: var(--lt-pre-intermediate); }
.sch-grid .slot-inner.lt-intermediate       { background: var(--lt-intermediate); }
.sch-grid .slot-inner.lt-upper-intermediate { background: var(--lt-upper-intermediate); }
.sch-grid .slot-inner.lt-advanced           { background: var(--lt-advanced); }
.sch-grid .slot-inner.lt-ielts              { background: var(--lt-ielts); }
.sch-grid .slot-inner.lt-speaking           { background: var(--lt-speaking); }
.sch-grid .slot-inner.lt-writing            { background: var(--lt-writing); }
.sch-grid .slot-inner.lt-individual         { background: var(--lt-individual); }
.sch-grid .slot-inner.lt-teachers           { background: var(--lt-teachers); color: #fff; }
.sch-grid .slot-inner.lt-teachers .slot-type,
.sch-grid .slot-inner.lt-teachers .slot-teacher,
.sch-grid .slot-inner.lt-teachers .slot-meta { color: #fff; }
.sch-grid .slot-inner.lt-other              { background: var(--lt-other); }

/* unit badge (which lesson unit a group is on) */
.sch-grid .slot-unit { font-size: 8.5px; line-height: 1.1; cursor: pointer; margin-top: 1px; }
.sch-grid .slot-unit .su-on { font-weight: 700; color: #0f2740; background: rgba(255,255,255,.62); padding: 0 5px; border-radius: 5px; }
.sch-grid .slot-unit .su-set { color: #46566a; opacity: .55; font-style: italic; }
.sch-grid .slot-unit:hover .su-set { opacity: 1; text-decoration: underline; }
.sch-grid .slot-inner.lt-teachers .su-on { color: #fff; background: rgba(0,0,0,.28); }

/* schedule edit mode: drag a group block to a new room / day / time */
.sch-edit-hint { font-size: 11px; }
.sch-grid.sch-editing .sch-group { cursor: grab; }
.sch-grid.sch-editing .sch-group .slot-inner { outline: 1px dashed rgba(15,39,64,.45); outline-offset: -2px; }
.sch-grid.sch-editing .sch-group:active { cursor: grabbing; }
.sch-grid .sch-group.sch-dragging { opacity: .45; }
.sch-grid.sch-editing .slot-cell.sch-drop-ok { outline: 2px solid #1565c0; outline-offset: -2px; background: rgba(21,101,192,.08); }

/* ---- Rooms tab design polish (minimalist) ---- */
#roomsHeading { letter-spacing: .2px; }
.sch-wrap { border-color: #e6e9ef; box-shadow: 0 6px 22px -14px rgba(23,32,53,.22); }
.sch-grid .slot-inner { box-shadow: inset 0 0 0 1px rgba(255,255,255,.22); }

/* ============ MODALS ============ */
.modal { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: grid; place-items: center; z-index: 100; padding: 20px; }
.modal.hidden { display: none; }
.modal-content { background: #fff; border-radius: 12px; padding: 24px; width: 100%; max-width: 480px; box-shadow: 0 20px 60px rgba(0,0,0,0.25); max-height: 90vh; overflow: auto; }
/* Gentle entrance (restrained, like ctxPop). The parent's .modal.hidden sets
   display:none, so this only animates when the modal is actually shown. */
.modal:not(.hidden) .modal-content { animation: modalIn var(--t) var(--ease); }
@keyframes modalIn { from { opacity: 0; transform: scale(.98) translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .modal:not(.hidden) .modal-content { animation: none; } }
.modal-content h3 { margin: 0 0 16px; font-weight: 500; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
.muted { color: var(--muted); font-size: 13px; }

/* ============ TOAST ============ */
.toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); background: var(--ink); color: #fff; padding: 12px 18px; border-radius: 8px; font-size: 14px; z-index: 200; box-shadow: var(--shadow); }
.toast.hidden { display: none; }
.toast.error { background: var(--c-debtor); }

.empty { padding: 32px; text-align: center; color: var(--muted); font-size: 14px; }

/* ===== Reusable empty + loading states (ready for a later wiring slice). ===== */
.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-3); padding: var(--space-6) var(--space-4);
  text-align: center; color: var(--muted); font-size: 14px;
}
.empty-state svg { width: 40px; height: 40px; color: var(--line-strong); }
.empty-state .empty-msg { max-width: 36ch; }

/* Skeleton shimmer for loading placeholders. */
@keyframes shimmer { from { background-position: -180% 0; } to { background-position: 180% 0; } }
.skeleton {
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--line) 25%, #eef0f3 50%, var(--line) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.4s var(--ease) infinite;
}
.skeleton-row { height: 14px; margin: var(--space-2) 0; }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

/* ============ FINANCE STYLING ============ */
.tile-income  { background: linear-gradient(135deg,#1f6f3a,#2e9c54); }
.tile-expense { background: linear-gradient(135deg,#c62828,#e53935); }
.tile-net     { background: linear-gradient(135deg,#0a0a0a,#37474f); }

.amount-income  { color: var(--c-active); font-weight: 600; }
.amount-expense { color: var(--c-debtor); font-weight: 600; }

/* ---- Finance tab: toolbar, summary cards, insights, ledger ---- */
.fin-toolbar { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.fin-toolbar-left, .fin-toolbar-right { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.fin-range { display: flex; align-items: center; gap: 8px; }
.fin-range input[type=date] { padding: 6px 8px; width: auto; }
.fin-search { min-width: 230px; }

.fin-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 14px; }
.fin-card {
  position: relative; overflow: hidden; background: #fff; border: 1px solid var(--line);
  border-radius: 12px; padding: 14px 16px 14px 18px; display: flex; flex-direction: column; gap: 3px;
  box-shadow: var(--shadow);
}
.fin-card::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--line-strong); }
.fin-card-income::before  { background: var(--c-active); }
.fin-card-expense::before { background: var(--c-debtor); }
.fin-card-net::before     { background: var(--ink); }
.fin-card-out::before     { background: #f9a825; }
.fin-card-exp::before     { background: #5b6473; }
.fin-card-label { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); font-weight: 600; }
.fin-card-val { font-size: 23px; font-weight: 800; color: var(--ink); line-height: 1.1; }
.fin-card-income  .fin-card-val { color: var(--c-active); }
.fin-card-expense .fin-card-val { color: var(--c-debtor); }
.fin-card-net.is-pos .fin-card-val { color: var(--c-active); }
.fin-card-net.is-neg .fin-card-val { color: var(--c-debtor); }
.fin-card-sub { font-size: 11px; color: var(--muted); }

.fin-insights { display: grid; grid-template-columns: 1.6fr 1fr; gap: 12px; margin-bottom: 16px; }
.fin-panel { background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; box-shadow: var(--shadow); }
.fin-panel-title { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); font-weight: 600; margin-bottom: 12px; }
.fin-bar { display: flex; height: 14px; border-radius: 7px; overflow: hidden; background: #eef0f3; }
.fin-bar .seg-income  { background: var(--c-active); }
.fin-bar .seg-expense { background: var(--c-debtor); }
.fin-bar-legend { display: flex; gap: 18px; margin-top: 12px; font-size: 13px; flex-wrap: wrap; color: var(--ink-soft); }
.fin-legend-item { display: flex; align-items: center; gap: 6px; }
.fin-dot { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.fin-legend-amt { font-weight: 700; color: var(--ink); }
.fin-cats-list { display: flex; flex-direction: column; gap: 9px; }
.fin-cat { display: grid; grid-template-columns: 1fr auto; column-gap: 10px; row-gap: 5px; align-items: baseline; font-size: 13px; }
.fin-cat-name { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fin-cat-amt { font-weight: 600; font-variant-numeric: tabular-nums; }
.fin-cat-bar { grid-column: 1 / -1; height: 5px; border-radius: 3px; background: #eef0f3; overflow: hidden; }
.fin-cat-bar > i { display: block; height: 100%; border-radius: 3px; }

.fin-table tfoot td { background: #fafbfc; font-weight: 700; border-top: 2px solid var(--line-strong); padding: 11px 12px; }
.fin-foot-label { color: var(--muted); font-weight: 500; }
tr.fin-day td { background: #f7f8fa; border-top: 1px solid var(--line); padding-top: 8px; padding-bottom: 8px; }
.fin-day-label { font-weight: 700; color: var(--ink); font-size: 12px; text-transform: uppercase; letter-spacing: .4px; }
.fin-dir-cell { text-align: center; }
.fin-dir { display: inline-flex; width: 26px; height: 26px; border-radius: 7px; align-items: center; justify-content: center; }
.fin-dir svg { width: 15px; height: 15px; }
.fin-dir.in  { background: var(--c-active-bg); color: var(--c-active); }
.fin-dir.out { background: var(--c-debtor-bg); color: var(--c-debtor); }
.fin-desc { color: var(--ink-soft); max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 900px) { .fin-insights { grid-template-columns: 1fr; } }

/* small helpers */
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.spacer { flex: 1; }
.chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px; background: #eef0f3; border-radius: 999px; font-size: 12px; color: var(--ink-soft); }

/* ============ MERGED GROUP CELLS (List view) ============ */
td.group-cell {
  vertical-align: middle;
  font-weight: 500;
  text-align: center;
  white-space: nowrap;
  font-size: 13px;
  padding: 8px 10px;
}
/* ============ Groups view — one pill-card per group ============ */
.group-pill-stack { display: flex; flex-direction: column; gap: 18px; }   /* breathing room between pills */

/* Single shared header pinned above the stack */
.group-sticky-header {
  position: sticky;
  top: var(--app-header-h, 132px);  /* sticks just below the sticky .app-header (topbar + nav) */
  z-index: 8;
  background: var(--bg);
  margin-bottom: 12px;
  border-radius: 16px;
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  overflow: hidden;
  background: #fff;
}
.group-sticky-header .group-table { width: 100%; table-layout: fixed; }
.group-sticky-header thead th {
  background: #fafbfc;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .3px;
  font-size: 11px;
  color: var(--ink-soft);
}

.group-pill {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow);
  overflow: hidden;                /* clips child table to the rounded edges */
  /* Native browser virtualization: off-screen pills are skipped entirely
     (no layout, no paint). `--pill-h` is set inline based on student count
     so the scrollbar stays accurate while pills are still off-screen. */
  content-visibility: auto;
  contain-intrinsic-size: 0 var(--pill-h, 380px);
}
.group-pill.unassigned { background: #fbfbfd; }

/* Header strip on top of each pill — Room | Day | Time | Teacher | count.
   No truncation here: every value renders in full. A post-render JS pass
   equalizes the width of each field (Room / Day / Time / Teacher) across
   all pills so the columns line up visually. */
.group-pill-header {
  display: flex;
  align-items: stretch;
  background: transparent;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: #fff;
}
.group-pill-header .gph-room,
.group-pill-header .gph-item,
.group-pill-header .gph-count {
  white-space: nowrap;
  overflow: visible;
  text-overflow: clip;
  box-sizing: border-box;
}
.group-pill-header .gph-room {
  display: flex; align-items: center; justify-content: center;
  background: #0a0a0a; color: #fff;
  font-weight: 700; letter-spacing: .4px;
  padding: 12px 22px;
  min-width: 96px;
  width: var(--gph-room-w, auto);
  border-right: 1px solid #2a2a2a;
}
.group-pill-header .gph-item {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 12px 18px;
  background: #0a0a0a;
  border-right: 1px solid #2a2a2a;
  color: #fff;
}
.group-pill-header .gph-day     { width: var(--gph-day-w, auto); }
.group-pill-header .gph-time    { width: var(--gph-time-w, auto); }
.group-pill-header .gph-teacher { width: var(--gph-teacher-w, auto); }
.group-pill-header .gph-val {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: #fff;
  flex: 0 0 auto;
}
.group-pill-header .gph-teacher .gph-val { font-weight: 500; }
.group-pill-header .gph-count {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 12px 18px;
  background: #0a0a0a; color: #fff;
  font-size: 13px; font-weight: 600;
}
.group-pill-header .gph-count .gph-person {
  width: 14px; height: 14px;
  fill: currentColor;
  flex: 0 0 auto;
}
.group-pill-header .gph-count .gph-num {
  font-variant-numeric: tabular-nums;
}
.group-pill-header .gph-count-edit { cursor: pointer; }
.group-pill-header .gph-count-edit:hover { background: #1f1f1f; }
/* empty "available seat" placeholder rows: faint, dashed, italic */
.group-pill .group-table tr.seat-empty-row td { background: #fafbfc; color: var(--muted); border-top: 1px dashed #dfe3e8; }
.group-pill .group-table tr.seat-empty-row td.seat-empty-label { font-style: italic; letter-spacing: .2px; }
.group-pill.unassigned .group-pill-header .gph-teacher .gph-val {
  color: #b8b8b8; font-style: italic;
}

/* All pills share an identical column layout so values align vertically
   across cards. table-layout: fixed enforces the widths declared in <colgroup>. */
.group-pill .group-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
}

/* Single-line cells, never clipped */
.group-pill .group-table td,
.group-pill .group-table th {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
  padding: 6px 8px;          /* squeezed from 10px 12px to free room for the comment column */
  line-height: 1.3;
}

/* Explicit width for every column — identical across all pills */
.group-pill .group-table col.cg-group     { width: 84px; }    /* Room / Day / Time / Teacher */
.group-pill .group-table col.cg-num       { width: 40px; }    /* # */
.group-pill .group-table col.cg-name       { width: 16%; }     /* Name (flexes) */
.group-pill .group-table col.cg-age        { width: 52px; }
.group-pill .group-table col.cg-status     { width: 92px; }
.group-pill .group-table col.cg-level      { width: 8%;  }
.group-pill .group-table col.cg-phone      { width: 10%; }     /* Private + Parents share */
.group-pill .group-table col.cg-date       { width: 92px; }
.group-pill .group-table col.cg-price      { width: 88px; }
.group-pill .group-table col.cg-due         { width: 104px; }  /* Due this month */
.group-pill .group-table col.cg-last        { width: 92px; }
.group-pill .group-table col.cg-attendance  { width: 240px; }  /* repurposed: operator comment (col W) */
.group-pill .group-table col.cg-act         { width: 184px; }  /* room for incoming-row "Attend"/"Not came"; enrolled rows just right-align their icons */

/* Groups (List) view: show full names & data instead of crushing the columns.
   Two problems are fixed here:
   1. The column widths above only apply to the pill tables, so the sticky header
      table (.group-sticky-header) used auto layout and never lined up. We give it
      table-layout:fixed and the SAME widths so header and body align.
   2. Too many wide fixed columns left almost no room for Name/Level/Phone, so
      they collapsed to "...". The attendance column is trimmed and the whole view
      is given a floor width (min-width). When the viewport is narrower than that
      floor the page scrolls left-to-right (the sticky column header stays pinned)
      instead of squeezing the names away.
   Scoped to #activeGroupsView so the group-detail modal (#gdBody) is unaffected. */
#activeGroupsView .group-sticky-header .group-table,
#activeGroupsView .group-pill .group-table { table-layout: fixed; }
#activeGroupsView .group-table col.cg-num        { width: 40px; }
#activeGroupsView .group-table col.cg-name       { width: 16%; }
#activeGroupsView .group-table col.cg-age        { width: 52px; }
#activeGroupsView .group-table col.cg-status     { width: 92px; }
#activeGroupsView .group-table col.cg-level      { width: 9%;  }
#activeGroupsView .group-table col.cg-phone      { width: 10%; }
#activeGroupsView .group-table col.cg-date       { width: 92px; }
#activeGroupsView .group-table col.cg-price      { width: 88px; }
#activeGroupsView .group-table col.cg-due        { width: 104px; }
#activeGroupsView .group-table col.cg-last       { width: 92px; }
#activeGroupsView .group-table col.cg-attendance { width: 240px; }  /* repurposed: comment */
#activeGroupsView .group-table col.cg-act        { width: 184px; }  /* fits incoming-row "Attend" + "Not came" + edit */
#activeGroupsView .group-sticky-header,
#activeGroupsView .group-pill-stack { min-width: 1540px; }

/* Attendance — every session collapses into one continuous, rounded-square
   gradient bar per student. State colors blend smoothly into each other at
   cell boundaries (set inline via linear-gradient in JS). */
.col-attendance { padding: 6px 10px !important; vertical-align: middle; }
/* Operator comment shown in place of the attendance column. Same text size as
   every other cell; clamped to exactly two lines with an ellipsis. The fixed
   two-line height is what keeps EVERY row the same height — a long comment can
   never push one row taller than the rest, and rows with no comment reserve the
   same space. */
.col-comment { white-space: normal; vertical-align: middle; }
.col-comment .cmt {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: normal;
  word-break: break-word;
  line-height: 1.3;
  max-height: 2.6em;        /* never more than two lines */
}
/* Lock every body row to one height so a two-line comment never makes a row
   taller than its neighbours; the clamped comment fits, shorter cells center. */
.group-pill .group-table tbody tr { height: 46px; }
.att-strip-wrap {
  display: inline-flex; align-items: center; gap: 10px;
  width: 100%;
}
.att-bar {
  flex: 1 1 auto;
  height: 20px;
  border-radius: 6px;
  min-width: 0;
}
.att-pct {
  font-size: 11px; font-weight: 600;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  min-width: 30px;
  text-align: right;
}
/* Placeholder shown until a pill scrolls into view and its strip is built. */
.att-strip-pending .att-bar { background: #ececec; }

/* Header */
.group-pill .group-table thead th { background: #fafbfc; }
.group-pill .group-table th.group-head {
  background: #f7f9fc;
  text-align: center;
  font-weight: 600;
  color: var(--ink-soft);
  border-right: 1px solid var(--line);
}
.group-pill .group-table th.group-head + th:not(.group-head) { border-left: 2px solid #98a2b3; }
.group-pill .group-table td.group-cell-teacher { border-right: 2px solid #98a2b3; }

/* Group-block (Room/Day/Time/Teacher) merged cells */
.group-pill .group-table td.group-cell {
  text-align: center;
  font-weight: 500;
  font-size: 13px;
}
/* Group block — neutral black & white palette */
.group-pill .group-table td.group-cell-room    { background: #0a0a0a; color: #ffffff; font-weight: 700; letter-spacing: .3px; }
.group-pill .group-table td.group-cell-day     { background: #f4f5f7; color: var(--ink); }
.group-pill .group-table td.group-cell-time    { background: #ffffff; color: var(--ink); font-variant-numeric: tabular-nums; font-weight: 600; }
.group-pill .group-table td.group-cell-teacher { background: #f4f5f7; color: var(--ink); font-weight: 500; }

/* No per-student row dividers inside the pill */
.group-pill .group-table tbody tr td { border-bottom: none; }
.group-pill .group-table tbody tr:hover td:not(.group-cell) { background: #f4f7fb; }
.group-pill.unassigned .group-table td.group-cell-teacher { color: var(--muted); font-style: italic; }

.group-table tbody.group-block tr:hover td:not(.group-cell) { background: #f4f7fb; }
.group-table tbody.group-block.unassigned td.group-cell-teacher { color: var(--muted); font-style: italic; }

/* "Attendance details" button — anchored to the top-right of each group pill.
   Lives in the white area to the right of the black cells, so it uses a
   solid dark style to stay visible against the pill background. */
.group-pill-header .gph-details {
  margin-left: auto;
  margin-right: 12px;
  padding: 6px 14px;
  font-family: inherit;
  font-size: 12px; font-weight: 600;
  background: var(--ink);
  color: #fff;
  border: 1px solid var(--ink);
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
  align-self: center;
}
.group-pill-header .gph-details:hover {
  background: #222;
  border-color: #222;
}

/* "+N incoming" chip — matched newcomers about to join this group. */
.group-pill-header .gph-incoming {
  margin-left: 10px;
  padding: 3px 10px;
  font-size: 11px; font-weight: 700;
  color: var(--c-newcomer);
  background: var(--c-newcomer-bg);
  border: 1px solid color-mix(in srgb, var(--c-newcomer) 30%, transparent);
  border-radius: 999px;
  white-space: nowrap;
  align-self: center;
}

/* ===== Incoming (prospective newcomer) rows inside a group pill ===== */
/* Divider that separates the enrolled roster from matched newcomers. */
.group-pill .group-table tr.prospect-divider td {
  padding: 7px 12px 5px;
  background: var(--c-newcomer-bg);
  border-top: 1px dashed color-mix(in srgb, var(--c-newcomer) 45%, transparent);
}
.prospect-divider .pd-label {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  color: var(--c-newcomer);
}
.prospect-divider .pd-sub {
  margin-left: 8px;
  font-size: 11px; font-style: italic; color: var(--muted);
}
/* The newcomer rows themselves — muted, tinted, clearly "not yet enrolled". */
.group-pill .group-table tr.prospect-row td {
  background: color-mix(in srgb, var(--c-newcomer-bg) 45%, #fff);
  color: var(--ink-soft);
}
.group-pill .group-table tr.prospect-row:hover td { background: var(--c-newcomer-bg); }
/* Incoming rows carry up to three buttons ("Attend" + "Not came" + edit) in the
   actions column, vs. enrolled rows' icons. Keep them compact and let them wrap
   rather than clip, so none gets hidden by the column edge. */
.prospect-row .row-actions { flex-wrap: wrap; gap: 5px; white-space: normal; justify-content: flex-end; }
.prospect-row .row-actions .btn-sm { padding: 4px 9px; font-size: 11px; line-height: 1.2; }
.prospect-row .prospect-when {
  display: inline-block;
  padding: 1px 8px;
  font-size: 11px; font-weight: 600;
  color: var(--c-coming, #f9a825);
  background: color-mix(in srgb, #f9a825 16%, #fff);
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}

/* ===== Attendance details modal ===== */
.modal-content-wide {
  max-width: min(96vw, 1500px) !important;
  width: 96vw;
}

/* Group-detail modal (opened from the General view) reuses the Groups (List)
   layout. Give the roster a comfortable min-width so the 12 columns — including
   the edit/pay/delete actions — render at full size instead of being squished by
   table-layout:fixed; the modal-content scrolls horizontally when narrower. The
   sticky column header pins to the modal's own top, not the page tabs bar. */
#gdBody .group-sticky-header,
#gdBody .group-pill-stack { min-width: 1080px; }
#gdBody .group-sticky-header {
  top: 0;
  margin-bottom: 12px;
  box-shadow: none;
}
.am-header {
  display: flex; align-items: center; gap: 16px;
  margin-bottom: 14px;
}
.am-titles { flex: 1; min-width: 0; }
.am-titles h3 { margin: 0 0 4px; font-size: 16px; }
.am-titles .muted { font-size: 13px; }
.am-nav {
  display: inline-flex; align-items: center; gap: 8px;
  background: #f4f5f7; border-radius: 8px; padding: 4px 6px;
}
.am-month-label {
  font-weight: 600; font-size: 13px;
  min-width: 130px; text-align: center;
}
.am-body { overflow: auto; max-height: 70vh; }
.am-scroll { overflow-x: auto; }
.am-table {
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 12px;
}
.am-table th, .am-table td {
  padding: 4px 4px;
  text-align: center;
  vertical-align: middle;
  width: 30px;                              /* roomier day columns */
  border-right: 1px solid var(--line);
}
.am-table thead th {
  background: #fafbfc;
  font-weight: 600;
  color: var(--ink);
  line-height: 1;
}
/* Both header rows get identical vertical space so weekday letters
   sit on equal footing with the date numbers — centered, breathing room. */
.am-table thead th {
  height: 28px;
  padding: 6px 4px;
  vertical-align: middle;
  line-height: 1;
  border-bottom: 1px solid var(--line);
}
.am-table .am-th-date { font-size: 12px; font-variant-numeric: tabular-nums; }
.am-table .am-th-day  { font-size: 12px; color: var(--muted); text-transform: uppercase; font-weight: 700; }
.am-table .am-weekend { color: #b0bec5; }

/* End-of-week separator — thick line between Sun and the next Mon column */
.am-table .am-eow { border-right: 3px solid #c8ccd2 !important; }

.am-table .am-num     { width: 36px; color: var(--muted); }
.am-table .am-name    {
  width: 220px;
  text-align: left;
  padding-left: 12px; padding-right: 12px;
  font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  position: sticky; left: 0;
  background: #fff;
  z-index: 2;
}
.am-table thead .am-name { background: #fafbfc; z-index: 3; }
.am-table .am-pct     {
  width: 56px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right; padding-right: 10px;
  background: #fafbfc;
  position: sticky; right: 0;
}
.am-table tbody tr { height: 40px; }                /* roomier rows */
.am-table tbody tr:nth-child(even) td:not(.am-cell) { background: #fafafa; }
.am-table tbody tr:hover td:not(.am-cell) { background: #f4f7fb; }

/* Day cells — colored bg with a white SVG icon centered for at-a-glance state */
.am-table .am-cell {
  padding: 0;
  border: 1px solid #fff;
  color: #fff;
  text-align: center;
  vertical-align: middle;
  line-height: 0;
}
.am-table .am-cell svg {
  width: 16px; height: 16px;
  vertical-align: middle;
  display: inline-block;
}
.am-table .am-cell.am-none           { background: #eef0f2; color: transparent; }
.am-table .am-cell.am-unmarked       { background: repeating-linear-gradient(45deg, #f3f5f8, #f3f5f8 4px, #e9edf2 4px, #e9edf2 8px); color: transparent; }  /* scheduled, not marked */
.am-table .am-cell.am-present        { background: #4caf50; }   /* vivid green  */
.am-table .am-cell.am-absent         { background: #e53935; }   /* vivid red    */
.am-table .am-cell.am-late           { background: #ff9800; }   /* vivid orange */
.am-table .am-cell.am-frozen         { background: #29b6f6; }   /* vivid blue   */
.am-table .am-cell.am-excused        { background: #7e57c2; }   /* purple       */
.am-table .am-cell.am-teacher-absent { background: #90a4ae; }   /* mid gray     */
.am-table .am-cell.am-substitute     { background: #4caf50; }   /* vivid green  */

.am-legend {
  display: flex; gap: 16px; flex-wrap: wrap;
  margin-top: 14px;
  font-size: 12px; color: var(--ink-soft);
}
.am-legend > span { display: inline-flex; align-items: center; gap: 6px; }
.am-swatch {
  width: 14px; height: 14px; border-radius: 3px;
  display: inline-block;
  border: 1px solid rgba(0,0,0,0.06);
}

/* ============ GENERAL VIEW (teacher × day-pattern rows × 1.5-hour time-slot columns) ============ */
.gen-grid {
  display: grid;
  grid-template-columns: 156px 60px repeat(var(--slot-count, 9), minmax(84px, 1fr));
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
  overflow: auto;
}
.gen-corner,
.gen-slot-head {
  background: #fafbfc;
  font-weight: 700; font-size: 11px;
  text-align: center;
  padding: 12px 6px;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: .3px;
  position: sticky; top: 0;
  z-index: 2;
}
.gen-slot-head:last-of-type { border-right: none; }
.gen-corner { z-index: 3; }
.gen-corner-teacher { left: 0; }
.gen-corner-day { left: 156px; }

.gen-teacher-cell {
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 4px;
  justify-content: center;
  background: #fff;
  position: sticky; left: 0;
  z-index: 1;
}

/* Day-pattern column — one labelled sub-row per weekday set. Single compact
   line (full weekday names only) so the row stays short. */
.gen-day-cell {
  padding: 6px 6px;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  display: flex; align-items: center;
  background: #fff;
  position: sticky; left: 156px;
  z-index: 1;
}
.gen-day-cell .gen-day-full {
  font-size: 11px; color: var(--ink-soft); font-weight: 600;
}
.gen-day-cell.is-other .gen-day-full { color: var(--muted); }
.gen-teacher-cell .gt-name {
  font-weight: 700; font-size: 14px; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.gen-teacher-cell .gt-stats {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--ink-soft);
}
.gen-teacher-cell .gt-stats b { font-weight: 700; color: var(--ink); }
.gen-teacher-cell .gt-stat-sep { color: var(--muted); }

.gen-slot-cell {
  padding: 6px;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column; gap: 6px;
  min-height: 44px;
}
.gen-slot-cell:last-of-type { border-right: none; }
.gen-slot-cell.is-empty { background: #fbfcfd; }

.gen-cell {
  display: inline-flex; align-items: center; gap: 6px;
  background: #0a0a0a;
  color: #fff;
  border: 1px solid #0a0a0a;
  border-radius: 6px;
  padding: 4px 6px;
  cursor: pointer;
  font-family: inherit;
  transition: background .12s, border-color .12s, transform .04s;
  width: 100%;
  text-align: left;
}
.gen-cell:hover { background: #1f1f1f; border-color: #1f1f1f; }
.gen-cell:active { transform: translateY(1px); }
.gen-cell .gen-room {
  background: #fff; color: #0a0a0a;
  font-weight: 700; letter-spacing: .3px;
  padding: 3px 5px;
  border-radius: 4px;
  min-width: 28px; text-align: center;
  font-size: 10px;
}
.gen-cell .gen-mid {
  display: inline-flex; flex-direction: column; gap: 1px;
  min-width: 0;
}
.gen-cell .gen-time { font-size: 11px; color: #fff; font-weight: 700; font-variant-numeric: tabular-nums; }
.gen-cell .gen-count {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 3px;
  color: #fff;
  font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.gen-cell .gen-count svg {
  width: 11px; height: 11px;
  fill: currentColor;
}
.gen-cell .gen-total { color: #b8b8b8; font-weight: 500; }

/* ============ SORTABLE / FILTERABLE COLUMN HEADERS ============ */
th.col-head {
  user-select: none; position: relative;
  white-space: nowrap;
}
th.col-head .col-head-inner {
  display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer; padding: 2px 4px; border-radius: 4px;
}
th.col-head .col-head-inner:hover { background: #eef0f3; }
th.col-head .sort-ind {
  font-size: 10px; color: var(--muted); width: 10px; display: inline-block; text-align: center;
}
th.col-head.sorted .sort-ind { color: var(--ink); font-weight: 700; }
th.col-head .filter-btn {
  border: 0; background: transparent; cursor: pointer; color: var(--muted);
  padding: 2px 4px; border-radius: 4px; font-size: 11px; line-height: 1;
}
th.col-head .filter-btn:hover { background: #eef0f3; color: var(--ink); }
th.col-head.filtered .filter-btn { color: var(--c-newcomer); background: var(--c-newcomer-bg); }

.col-filter-pop {
  position: absolute; z-index: 50;
  background: #fff; border: 1px solid var(--line-strong); border-radius: 8px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.18);
  width: 240px; padding: 10px; font-size: 13px; color: var(--ink);
}
.col-filter-pop input[type=search] { padding: 6px 9px; font-size: 13px; margin-bottom: 8px; }
.col-filter-pop .cf-section { margin-bottom: 10px; }
.col-filter-pop .cf-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin-bottom: 6px; }
.col-filter-pop .cf-op { width: 100%; padding: 6px 8px; font-size: 13px; margin-bottom: 6px; }
.col-filter-pop .cf-inputs { display: flex; gap: 6px; }
.col-filter-pop .cf-inputs input { flex: 1; min-width: 0; padding: 6px 8px; font-size: 13px; margin-bottom: 0; }
.col-filter-pop .cf-values { border-top: 1px solid var(--line); padding-top: 8px; }
.col-filter-pop .cf-list {
  max-height: 220px; overflow: auto; border: 1px solid var(--line); border-radius: 6px; padding: 4px;
}
.col-filter-pop .cf-row {
  display: flex; align-items: center; gap: 8px; padding: 4px 6px; border-radius: 4px;
}
.col-filter-pop .cf-row:hover { background: #f4f5f7; }
.col-filter-pop .cf-row input { width: auto; }
.col-filter-pop .cf-row .cf-count { margin-left: auto; color: var(--muted); font-size: 11px; }
.col-filter-pop .cf-actions { display: flex; gap: 6px; margin-top: 8px; }
.col-filter-pop .cf-actions button { flex: 1; }
.col-filter-pop .cf-toggle { display: flex; gap: 6px; margin-bottom: 6px; }
.col-filter-pop .cf-toggle button { flex: 1; padding: 4px 8px; font-size: 11px; }

/* ============ ROOMS — stacked M/W/F + T/T/S layout ============ */
.schedule-stack { display: flex; flex-direction: column; gap: 18px; }
.schedule-block-title {
  display: flex; align-items: center; gap: 12px; margin-bottom: 8px;
}
.sb-tag {
  display: inline-block; padding: 6px 14px; border-radius: 8px;
  font-weight: 700; letter-spacing: .5px; font-size: 13px; color: #fff;
}
.sb-mwf { background: linear-gradient(135deg,#1565c0,#42a5f5); }
.sb-tts { background: linear-gradient(135deg,#c62828,#e53935); }
.sb-count { color: var(--muted); font-size: 12px; }

/* ============ GROUPED VIEW (Active Students) ============ */
.group-card {
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  margin-bottom: 16px; overflow: hidden; box-shadow: var(--shadow);
}
.group-header {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 16px;
  background: linear-gradient(180deg, #1a1a1a, #2a2a2a); color: #fff;
}
.group-header .gh-title {
  font-size: 14px; font-weight: 600; letter-spacing: .3px;
  display: flex; align-items: center; gap: 10px;
}
.group-header .gh-meta { display: flex; gap: 8px; flex-wrap: wrap; }
.group-header .gh-chip {
  background: rgba(255,255,255,0.12); color: #fff;
  padding: 3px 10px; border-radius: 999px; font-size: 11px; font-weight: 500;
}
.group-header .gh-chip.room  { background: #1565c0; }
.group-header .gh-chip.day   { background: #2e7d32; }
.group-header .gh-chip.time  { background: #f9a825; color: #2c2200; }
.group-header .gh-chip.teacher { background: #9c27b0; }
.group-header .gh-count {
  margin-left: auto; background: #fff; color: #0a0a0a;
  padding: 4px 12px; border-radius: 999px; font-size: 12px; font-weight: 600;
}
.group-card table { width: 100%; }
.group-card thead { background: #fafbfc; }
.group-card.unassigned .group-header {
  background: linear-gradient(180deg, #6b6b6b, #8a8a8a);
}

/* status filter pills (active students tab) */
.filter-pills { display: flex; gap: 6px; flex-wrap: wrap; }
.pill {
  font-family: inherit; font-size: 12px; font-weight: 500; padding: 6px 12px;
  border-radius: 999px; border: 1px solid var(--line-strong); background: #fff;
  cursor: pointer; color: var(--ink-soft);
}
.pill.active { background: var(--ink); color: #fff; border-color: var(--ink); }

/* ============ VIRTUALIZED GRID (TanStack Virtual) ============ */
.vgrid {
  border: 1px solid var(--line); border-radius: 8px; background: #fff; overflow: hidden;
  --vgrid-cols: 48px 90px minmax(160px, 1.4fr) 56px 130px 130px 110px 110px 90px 90px 130px 90px 130px 110px 110px minmax(140px, 1.2fr) 48px;
}
.vgrid-head, .vgrid-row {
  display: grid; grid-template-columns: var(--vgrid-cols); font-size: 13px; align-items: center;
}
.vgrid-head {
  background: #fafbfc; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 2;
}
.vgrid-head > div {
  padding: 10px 12px; font-weight: 500; color: var(--ink-soft); white-space: nowrap;
  border-right: 1px solid var(--line);
}
.vgrid-head > div:last-child { border-right: 0; }
.vgrid-scroll {
  position: relative; overflow: auto; max-height: 65vh; min-height: 200px;
}
.vgrid-spacer { width: 100%; }
.vgrid-rows { position: absolute; top: 0; left: 0; right: 0; pointer-events: none; }
.vgrid-row {
  position: absolute; left: 0; right: 0;
  border-bottom: 1px solid var(--line);
  contain: layout paint style;
  pointer-events: auto;
}
.vgrid-row:hover { background: #fafafa; }
.vgrid-row > div {
  padding: 8px 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-right: 1px solid var(--line);
}
.vgrid-row > div:last-child { border-right: 0; }
.vgrid-row .muted { color: var(--muted); font-size: 12px; }
.vgrid-empty { padding: 32px; text-align: center; color: var(--muted); font-size: 14px; }

/* ============ PAGER ============ */
.pager {
  display: flex; align-items: center; gap: 10px; margin-top: 12px;
  font-size: 13px; color: var(--ink-soft);
}
.pager .pager-info { color: var(--muted); }
.pager .pager-size { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; margin-bottom: 0; }
.pager .pager-size select { width: auto; padding: 4px 8px; }
.pager .btn:disabled { opacity: .4; cursor: not-allowed; }

/* ============ VORONKA (newcomers kanban) ============ */
.voronka-board {
  display: grid; gap: 14px; align-items: stretch;
  /* Single row, always: grid-auto-flow:column lays every column on one line.
     Columns share the width evenly (1fr) but never shrink below 220px — when
     they no longer fit (e.g. zoomed in) the board scrolls horizontally instead
     of wrapping to a second row. align-items:stretch makes every column as tall
     as the fullest one, so a card can be dropped into the empty space of a short
     column. The board is its own scroll viewport (both axes) so the column
     headers can stay frozen via position:sticky while scrolling a long column. */
  grid-auto-flow: column;
  grid-auto-columns: minmax(220px, 1fr);
  overflow: auto;
  max-height: calc(100vh - var(--app-header-h, 132px) - 150px);
  min-height: 320px;
}

.vk-col {
  background: #f7f8fa; border: 1px solid var(--line); border-radius: 10px;
  display: flex; flex-direction: column;
}
.vk-col-head {
  position: sticky; top: 0; z-index: 4;
  display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  border-bottom: 1px solid var(--line); border-top-left-radius: 10px; border-top-right-radius: 10px;
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .4px;
  /* Opaque, lightly tinted with the column's own color so a frozen header still
     reads as "which column is which" once cards scroll underneath it. */
  background: #eef1f5;
  background: color-mix(in srgb, var(--vk-col-color, #8895a7) 16%, #fff);
  box-shadow: 0 1px 2px rgba(0,0,0,.05);
}
.vk-col-head .vk-count {
  margin-left: auto; background: #fff; color: var(--ink-soft);
  padding: 2px 9px; border-radius: 999px; font-size: 11px; font-weight: 700;
  border: 1px solid var(--line);
}
.vk-col-body { padding: 10px; display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; min-height: 0; }
.vk-empty { padding: 16px 8px; text-align: center; color: var(--muted); font-size: 12px; font-style: italic; }

.vk-card {
  background: #fff; border: 1px solid var(--line); border-radius: 8px;
  padding: 10px 12px; box-shadow: 0 1px 2px rgba(0,0,0,0.04);
  display: flex; flex-direction: column; gap: 4px;
}
.vk-card .vk-name { font-weight: 600; font-size: 13px; color: var(--ink); }
.vk-card .vk-meta { font-size: 11px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 4px 10px; }
.vk-card .vk-meta strong { color: var(--ink-soft); font-weight: 500; }
.vk-card .vk-comment { font-size: 11px; color: var(--ink-soft); border-left: 2px solid var(--line); padding-left: 6px; margin-top: 2px; }

/* Funnel journey — the colored path a student took through the Voronka, shown in
   the client card. Equal-width segments left-to-right; the current (last) stage is
   emphasized. Each segment's color comes from --fj (set inline per stage). */
.fj-bar { display: flex; align-items: center; gap: 2px; width: 100%; }
.fj-seg {
  flex: 1 1 0; min-width: 4px; height: 8px; border-radius: 2px;
  background: var(--fj, #9e9e9e); opacity: .9;
}
.fj-seg.fj-cur { opacity: 1; height: 10px; box-shadow: 0 0 0 1.5px rgba(0,0,0,.12); }

/* Client-card journey timeline (bar + labeled, dated steps) */
.cc-journey { margin-bottom: 14px; }
.cc-journey:empty { display: none; }
.cc-journey-title { font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); margin-bottom: 6px; }
.cc-journey .fj-bar { margin: 0 0 10px; }
.fj-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 6px 16px; }
.fj-step { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-soft); }
.fj-step .fj-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--fj, #9e9e9e); flex: none; }
.fj-step-cur { font-weight: 600; color: var(--ink); }
.fj-step-when { font-size: 11px; }

/* Column-head accents tied to the same colors used by newcomerStateBadge */
.vk-col-attend  { border-top: 3px solid #1e88e5; }
.vk-col-coming  { border-top: 3px solid #f9a825; }
.vk-col-waiting { border-top: 3px solid #ff9800; }
.vk-col-recall  { border-top: 3px solid #e53935; }
.vk-col-yes     { border-top: 3px solid #1565c0; }
.vk-col-no      { border-top: 3px solid #9e9e9e; }
.vk-col-notcame { border-top: 3px solid #795548; }
.vk-col-unset   { border-top: 3px solid var(--line-strong); }

.vk-toolbar { display: flex; gap: 8px; margin-bottom: 10px; }
.vk-toolbar .btn-primary { background: var(--ink); color: #fff; border-color: var(--ink); }
.vk-icon-btn {
  border: 0; background: transparent; cursor: pointer; padding: 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 4px; color: var(--muted);
}
.vk-icon-btn:hover { background: rgba(0,0,0,0.06); color: var(--ink); }
.vk-icon-btn svg { width: 14px; height: 14px; display: block; }
.vk-label-input {
  flex: 1; min-width: 0;
  font-family: inherit; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .4px;
  padding: 4px 6px; border: 1px solid var(--line-strong); border-radius: 4px;
  background: #fff; color: var(--ink);
}
.vk-add-col {
  border: 2px dashed var(--line-strong); border-radius: 10px; background: transparent;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; padding: 24px 12px; color: var(--muted); font-size: 13px;
  cursor: pointer; min-height: 120px; font-family: inherit;
}
.vk-add-col:hover { border-color: var(--ink); color: var(--ink); }
.vk-add-col svg { width: 24px; height: 24px; }
.vk-meta-label { color: var(--muted); font-weight: 500; }

/* ============ CGM branching chart (SVG, n8n-style workflow look) ============ */
.vk-chart-wrap {
  display: flex;
  justify-content: center;
  padding-bottom: 14px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
}
.vk-chart {
  display: inline-block;
  padding: 14px 22px;
  background:
    radial-gradient(circle at 10% 0%, rgba(124,77,255,0.04), transparent 40%),
    radial-gradient(circle at 90% 100%, rgba(21,101,192,0.04), transparent 45%),
    #fbfbfd;
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.03), 0 4px 16px rgba(0,0,0,0.04);
  overflow-x: auto;
  max-width: 100%;
}
.vk-chart svg { display: block; }

/* Funnel chart now lives in a modal — let it scroll inside instead of
   overflowing. Scoped so the (now removed) inline-flow rules above are untouched. */
#funnelModal .vk-chart-wrap {
  margin-bottom: 0;
  border-bottom: none;
  overflow: auto;
  max-height: 70vh;
}

/* Dots feel alive — gentle staggered pulse + soft drop shadow for depth */
.vk-chart svg .vk-chart-dot {
  transform-box: fill-box;
  transform-origin: center;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.15));
  animation: vk-chart-pulse 2.6s ease-in-out infinite;
}
@keyframes vk-chart-pulse {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(1.15); opacity: 0.85; }
}

/* drag & drop */
/* No static will-change here: the Yes/Left columns can hold thousands of cards and
   promoting every one to its own compositor layer thrashes the GPU. The FLIP code in
   vkInsertPlaceholder sets will-change only on the handful of cards it's animating. */
.vk-card { cursor: grab; user-select: none; }
.vk-card:active { cursor: grabbing; }
.vk-card.dragging { display: none; }   /* removed from layout so source column closes the gap */

.vk-color-input {
  width: 22px; height: 22px; padding: 0; border: 1px solid var(--line-strong); border-radius: 4px;
  background: transparent; cursor: pointer; flex-shrink: 0;
}
.vk-color-input::-webkit-color-swatch-wrapper { padding: 0; }
.vk-color-input::-webkit-color-swatch { border: 0; border-radius: 3px; }

/* Column drag (edit mode) — columns shift left/right live as you drag (FLIP). */
.vk-col { position: relative; will-change: transform; }
.vk-col[draggable="true"] { cursor: grab; }
.vk-col[draggable="true"]:active { cursor: grabbing; }
.vk-col[draggable="true"] input,
.vk-col[draggable="true"] button { cursor: auto; }
.vk-col[draggable="true"] .vk-icon-btn { cursor: pointer; }
.vk-col.vk-col-dragging { opacity: .4; }
/* Touch drag-and-drop (voronka): floating clone + scroll lock while a card is lifted.
   These only take effect on touch (the clone/lock are added by JS; mouse uses native DnD). */
.vk-card-clone { box-shadow: 0 12px 30px rgba(0,0,0,.28); opacity: .96; transform: rotate(1.5deg); pointer-events: none; }
body.vk-drag-lock { overflow: hidden; touch-action: none; }
body.vk-drag-lock .voronka-board { scroll-snap-type: none !important; touch-action: none; }

.vk-card-placeholder {
  background: rgba(21, 101, 192, 0.06);
  border: 2px dashed var(--c-newcomer);
  border-radius: 8px;
  min-height: 56px;
  animation: vk-placeholder-in 140ms cubic-bezier(.2,.7,.3,1);
}
@keyframes vk-placeholder-in {
  from { opacity: 0; transform: scale(.96); }
  to   { opacity: 1; transform: scale(1); }
}

/* When a card lands in a column, wash its background with that column's colour, hold it
   for ~1s, then fade back to the card's base #fff. Colour comes from the destination column
   via --vk-land-color, set inline on the card right before the animation starts; it ends
   exactly on the resting style (#fff + base shadow) so there's no flicker when it clears. */
.vk-just-landed { --vk-land-color: var(--c-active); }
@keyframes vk-card-land {
  0%   { background-color: color-mix(in srgb, var(--vk-land-color) 45%, #fff);
         box-shadow: 0 0 0 2px color-mix(in srgb, var(--vk-land-color) 55%, transparent),
                     0 4px 14px color-mix(in srgb, var(--vk-land-color) 28%, transparent); }
  65%  { background-color: color-mix(in srgb, var(--vk-land-color) 42%, #fff);
         box-shadow: 0 0 0 2px color-mix(in srgb, var(--vk-land-color) 48%, transparent),
                     0 3px 12px color-mix(in srgb, var(--vk-land-color) 24%, transparent); }
  100% { background-color: #fff;
         box-shadow: 0 1px 2px rgba(0,0,0,.04); }
}
.vk-just-landed { animation: vk-card-land 1800ms ease; }
@media (prefers-reduced-motion: reduce) { .vk-just-landed { animation: none; } }

/* ============================================================
   ATTENDANCE TAB + ROLES + acting-as indicator (mobile + desktop)
   ============================================================ */

/* topbar right cluster + acting indicator */
.topbar-right { display: flex; align-items: center; gap: 14px; }

/* profile button + dropdown */
.profile { position: relative; display: inline-flex; }
.profile-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 35px; height: 35px; border-radius: 999px; cursor: pointer;
  color: #fff; background: rgba(255,255,255,0.09);
  border: 1px solid rgba(255,255,255,0.14);
  transition: background .15s, box-shadow .15s;
}
.profile-btn:hover { background: rgba(255,255,255,0.12); }
.profile-btn:active { transform: translateY(.5px); }
.profile-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(255,255,255,0.35); }
.profile-btn svg { width: 18px; height: 18px; }

.profile-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 300;
  min-width: 200px;
  background: #fff; border: 1px solid var(--line-strong); border-radius: 10px;
  box-shadow: 0 8px 34px rgba(0,0,0,0.18); padding: 6px;
  animation: ctxPop .14s ease;
}
.profile-menu.hidden { display: none; }
.profile-head { display: flex; flex-direction: column; gap: 2px; }
.profile-name { font-weight: 600; font-size: 13px; color: var(--ink); }
.profile-role { font-weight: 400; font-size: 11px; color: var(--ink-soft); }
.topbar-user { font-size: 12px; }
/* Language switch (UZ / RU / EN) + integrated "translate terms" toggle.
   A single rounded segmented pill on the dark topbar. */
.lang-switch {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px; border-radius: 9px;
  background: rgba(255,255,255,0.09);
  border: 1px solid rgba(255,255,255,0.14);
}
.lang-switch button {
  border: 0; background: transparent; color: #c8cdd6; cursor: pointer;
  font-family: inherit; font-size: 12px; font-weight: 600; letter-spacing: .4px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px; transition: background .15s, color .15s, box-shadow .15s;
}
.lang-switch .lang-opt { padding: 5px 9px; }
.lang-switch button:hover { color: #fff; background: rgba(255,255,255,0.12); }
.lang-switch button:active { transform: translateY(.5px); }
.lang-switch button.active {
  background: #fff; color: #0a0a0a; box-shadow: 0 1px 3px rgba(0,0,0,.28);
}
/* thin divider between the language options and the terms toggle */
.lang-sep { width: 1px; align-self: stretch; margin: 2px 3px; background: rgba(255,255,255,0.16); }
/* terms toggle — icon-only segment that highlights when on */
.lang-switch .lang-term { padding: 5px 7px; }
.lang-switch .lang-term svg { width: 15px; height: 15px; display: block; }
.lang-switch .lang-term.active {
  background: #fff; color: #0a0a0a; box-shadow: 0 1px 3px rgba(0,0,0,.28);
}
/* 3D people-model picker bar */
.people-picker { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 12px; }
.people-picker.hidden { display: none; }
.people-picker .pp-label { font-size: 13px; }
.people-picker .pp-btns { display: flex; gap: 6px; flex-wrap: wrap; }
.people-picker .pp-btn.active { background: var(--ink); color: #fff; border-color: var(--ink); }
.people-picker #peopleCompare.active { background: #1565c0; color: #fff; border-color: #1565c0; }
.people-picker .pp-spacer { flex: 1; min-width: 6px; }
.people-picker #vizToggle.active { background: #c62828; border-color: #c62828; }
/* Hour readout overlaid on the 3D view during the day visualization */
.viz-clock {
  position: absolute; top: 14px; left: 50%; transform: translateX(-50%);
  background: rgba(20, 26, 38, 0.82); color: #fff; font-family: 'Google Sans', sans-serif;
  font-size: 30px; font-weight: 700; letter-spacing: 1px; padding: 8px 22px; border-radius: 12px;
  box-shadow: 0 6px 20px rgba(0,0,0,.28); pointer-events: none; font-variant-numeric: tabular-nums;
  animation: vizClockIn .35s ease;
}
.viz-clock.hidden { display: none; }
@keyframes vizClockIn { from { opacity: 0; transform: translate(-50%, -8px); } to { opacity: 1; transform: translate(-50%, 0); } }
.acting-indicator {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--c-newcomer-bg); color: var(--c-newcomer);
  border: 1px solid #b9d4f5; border-radius: 999px; padding: 4px 6px 4px 12px;
  font-size: 13px; font-weight: 500;
}
.acting-indicator .btn { padding: 3px 10px; }

/* tabs: let the grouped bar scroll horizontally on narrow screens (groups + dividers
   stay on one row; the hidden scrollbar keeps the dark/light chrome clean) */
.tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tab-group, .tab-divider { flex: none; }

/* --- attendance header / date bar --- */
.att-header { flex-wrap: wrap; gap: 12px; align-items: center; }
.att-head-left { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.att-teacher-label { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
.att-teacher-select {
  font-family: inherit; font-size: 14px; padding: 7px 10px;
  border: 1px solid var(--line-strong); border-radius: 6px; background: #fff; color: var(--ink);
}
.att-teacher-fixed {
  font-size: 15px; font-weight: 600; color: var(--ink);
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: 6px 12px;
}
.att-datebar { display: inline-flex; align-items: center; gap: 6px; }
.att-date-input {
  font-family: inherit; font-size: 14px; padding: 6px 10px;
  border: 1px solid var(--line-strong); border-radius: 6px; background: #fff; color: var(--ink);
}
.att-daylabel { margin: 4px 0 16px; font-size: 14px; }

/* --- group card --- */
.att-card {
  border: 1px solid var(--line); border-radius: 12px; background: #fff;
  margin-bottom: 16px; overflow: hidden; box-shadow: var(--shadow);
}
.att-card-head {
  display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 14px 16px; background: var(--bg); border-bottom: 1px solid var(--line);
}
.att-card-title { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.att-card-time { font-size: 18px; font-weight: 700; color: var(--ink); }
.att-card-meta { font-size: 13px; color: var(--muted); }
.att-card-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.att-card-summary { font-size: 13px; color: var(--ink-soft); font-weight: 500; }
.att-noclass { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-soft); cursor: pointer; user-select: none; }
.att-noclass input { width: 16px; height: 16px; accent-color: var(--c-debtor); }

.att-card-cancelled .att-card-body { opacity: .45; pointer-events: none; filter: grayscale(.5); }
.att-card-cancelled .att-card-head { background: var(--c-left-bg); }

/* --- student rows --- */
.att-card-body { padding: 6px 0; }
.att-row {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 16px; border-bottom: 1px solid var(--line);
}
.att-row:last-child { border-bottom: 0; }
.att-row-num { width: 26px; text-align: right; color: var(--muted); font-size: 13px; flex-shrink: 0; }
.att-row-name { flex: 1; min-width: 0; font-weight: 500; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-row-unmarked { background: repeating-linear-gradient(45deg, #fff, #fff 8px, #fbfbfc 8px, #fbfbfc 16px); }
.att-row-states { display: inline-flex; gap: 6px; flex-shrink: 0; }

.att-status { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px; padding: 1px 6px; border-radius: 4px; vertical-align: middle; }
.att-status-debtor { background: var(--c-debtor-bg); color: var(--c-debtor); }
.att-status-frozen { background: var(--c-frozen-bg); color: var(--c-frozen); }

/* segmented state buttons — icon above a text label */
.att-st {
  min-width: 60px; padding: 6px 8px; border-radius: 8px; cursor: pointer;
  border: 1.5px solid var(--line-strong); background: #fff; color: var(--muted);
  font-family: inherit; font-size: 11px; font-weight: 600;
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  transition: transform .05s ease, background .12s ease, color .12s ease, border-color .12s ease;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.att-st .att-st-ico { display: inline-flex; }
.att-st .att-st-ico svg { width: 18px; height: 18px; display: block; }
.att-st-lbl { line-height: 1; white-space: nowrap; }
.att-st:hover { border-color: var(--ink-soft); color: var(--ink); }
.att-st:active { transform: scale(.94); }
.att-st.active { color: #fff; border-color: transparent; }
.att-st-P.active { background: #4caf50; }
.att-st-L.active { background: #ff9800; }
.att-st-A.active { background: #e53935; }
.att-st-F.active { background: #29b6f6; }
.att-st-E.active { background: #7e57c2; }

/* --- sticky save bar --- */
.att-savebar {
  position: sticky; bottom: 0; z-index: 5;
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  margin-top: 8px; padding: 12px 16px;
  background: #fff; border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 -2px 14px rgba(0,0,0,.08);
}
.att-save-info { font-size: 14px; color: var(--c-debtor); font-weight: 500; }
.att-savebar-actions { display: flex; gap: 8px; }

/* --- roles tab --- */
.roles-intro { max-width: 640px; margin: 0 0 18px; line-height: 1.5; }
.roles-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
.role-card {
  display: flex; align-items: center; gap: 14px;
  border: 1px solid var(--line); border-radius: 12px; background: #fff; padding: 14px 16px;
  box-shadow: var(--shadow);
}
.role-card-active { border-color: var(--c-newcomer); box-shadow: 0 0 0 2px var(--c-newcomer-bg); }
.role-avatar {
  width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: #fff; font-weight: 700; font-size: 16px;
}
.role-info { flex: 1; min-width: 0; }
.role-name { font-weight: 600; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.role-sub { font-size: 12px; }

/* ---- attendance drill-down (topbar / tiles / mark screen) ---- */
.att-topbar { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.att-crumbs { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.att-crumbs h2 { margin: 0; font-size: 20px; }
.att-crumb-hint { font-size: 13px; color: var(--muted); }
.att-loading { padding: 24px 4px; }

/* tappable list of teachers / groups */
.att-list { display: flex; flex-direction: column; gap: 10px; }
.att-tile {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  border: 1px solid var(--line); border-radius: 12px; background: #fff; padding: 14px 16px;
  font-family: inherit; cursor: pointer; box-shadow: var(--shadow);
  transition: border-color .12s ease, transform .04s ease, background .12s ease;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
}
.att-tile:hover { border-color: var(--line-strong); background: #fcfcfd; }
.att-tile:active { transform: scale(.995); }
.att-tile-avatar {
  width: 42px; height: 42px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: #fff; font-weight: 700; font-size: 15px;
}
.att-tile-time {
  flex-shrink: 0; min-width: 64px; font-size: 18px; font-weight: 700; color: var(--ink);
}
.att-tile-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.att-tile-title { font-weight: 600; font-size: 15px; }
.att-tile-sub { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.att-tile-chev { flex-shrink: 0; font-size: 22px; color: var(--line-strong); line-height: 1; }

/* mark screen (single group) */
.att-mark { border: 1px solid var(--line); border-radius: 12px; background: #fff; overflow: hidden; box-shadow: var(--shadow); }
.att-mark-head {
  display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 14px 16px; background: var(--bg); border-bottom: 1px solid var(--line);
}
.att-mark-headline { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
.att-mark-date { font-size: 15px; font-weight: 600; color: var(--ink); }
.att-mark-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.att-mark-body { padding: 6px 0; }
.att-mark.att-card-cancelled .att-mark-body { opacity: .45; pointer-events: none; filter: grayscale(.5); }
.att-mark.att-card-cancelled .att-mark-head { background: var(--c-left-bg); }

/* summary as a subtle pill */
.att-card-summary {
  font-size: 12px; font-weight: 600; color: var(--ink-soft);
  background: #eef0f3; border-radius: 999px; padding: 3px 10px;
}
/* icon inside header buttons */
.att-btn-ico { display: inline-flex; vertical-align: middle; margin-right: 4px; }
.att-btn-ico svg { width: 15px; height: 15px; display: block; }
.att-allpresent-btn { display: inline-flex; align-items: center; }
.att-allpresent-btn .att-btn-ico { color: var(--c-active); }

/* "No class today" toggle button */
.att-noclass-btn {
  display: inline-flex; align-items: center; gap: 2px; cursor: pointer;
  font-family: inherit; font-size: 13px; font-weight: 600; color: var(--ink-soft);
  background: #fff; border: 1.5px solid var(--line-strong); border-radius: 8px; padding: 6px 12px;
  -webkit-tap-highlight-color: transparent; touch-action: manipulation;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.att-noclass-btn:hover { border-color: var(--ink-soft); color: var(--ink); }
.att-noclass-btn.active { background: var(--c-debtor); border-color: var(--c-debtor); color: #fff; }
.att-noclass-btn.active .att-btn-ico { color: #fff; }

/* note shown when a session is cancelled */
.att-cancel-note {
  padding: 10px 16px; font-size: 13px; color: var(--c-left);
  background: var(--c-left-bg); border-bottom: 1px solid var(--line);
}

/* mark/history sub-switch + the date/month control row */
.att-subswitch { flex-shrink: 0; }
.att-datebar-row { margin-bottom: 14px; }
.att-month-label { font-size: 14px; font-weight: 600; min-width: 130px; text-align: center; }
.att-hist-legend { margin-top: 14px; }
/* history grid cells are clickable to jump to that day's mark screen */
.am-table .am-cell[data-att-histday] { cursor: pointer; }
.am-table .am-cell[data-att-histday]:hover { outline: 2px solid var(--ink); outline-offset: -2px; }

/* ---- My Students (read-only roster) ---- */
.ms-group { border: 1px solid var(--line); border-radius: 12px; background: #fff; box-shadow: var(--shadow); margin-bottom: 14px; overflow: hidden; }
.ms-group-head { display: flex; align-items: baseline; gap: 10px; padding: 12px 16px; background: var(--bg); border-bottom: 1px solid var(--line); }
.ms-time { font-size: 16px; font-weight: 700; }
.ms-row { display: flex; align-items: center; gap: 12px; padding: 9px 16px; border-bottom: 1px solid var(--line); }
.ms-row:last-child { border-bottom: 0; }
.ms-num { width: 24px; text-align: right; color: var(--muted); font-size: 13px; flex-shrink: 0; }
.ms-name { font-weight: 500; flex: 0 0 auto; min-width: 180px; }
.ms-meta { color: var(--muted); font-size: 13px; flex: 1; min-width: 0; }
.ms-phone { color: var(--ink-soft); font-size: 13px; white-space: nowrap; }

/* ---- My Timetable (read-only) ---- */
.tt-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.tt-col { border: 1px solid var(--line); border-radius: 12px; background: #fff; box-shadow: var(--shadow); overflow: hidden; }
.tt-col-head { padding: 10px 14px; background: var(--ink); color: #fff; font-weight: 600; font-size: 14px; }
.tt-slot { display: flex; gap: 12px; padding: 11px 14px; border-bottom: 1px solid var(--line); }
.tt-slot:last-child { border-bottom: 0; }
.tt-time { font-size: 16px; font-weight: 700; min-width: 56px; flex-shrink: 0; }
.tt-info { font-size: 13px; line-height: 1.45; }

/* ============ MOBILE (phones / small tablets) ============ */
@media (max-width: 720px) {
  /* tighter panel so the roster uses the full screen width */
  #panel-attendance { padding: 14px 12px; }

  /* topbar: breadcrumb on top, full-width Mark/History switch below it */
  .att-topbar { flex-direction: column; align-items: stretch; gap: 10px; margin-bottom: 12px; }
  .att-crumbs { gap: 6px 10px; }
  .att-crumbs h2 { font-size: 17px; }
  .att-subswitch { display: flex; width: 100%; }
  .att-subswitch button { flex: 1; padding: 9px 0; }

  /* teacher / group tiles */
  .att-tile { padding: 15px 14px; }
  .att-tile-time { min-width: 54px; font-size: 17px; }
  .att-tile-chev { font-size: 26px; }

  /* date / month control rows span the width with even, tappable buttons */
  .att-datebar { width: 100%; gap: 8px; }
  .att-datebar .btn { padding: 9px 12px; }
  .att-date-input { flex: 1; min-width: 0; font-size: 16px; padding: 9px 10px; } /* 16px avoids iOS focus-zoom */
  .att-month-label { flex: 1; min-width: 0; }

  /* mark header stacks: date + summary, then the two action buttons side by side */
  .att-mark-head { flex-direction: column; align-items: stretch; gap: 10px; }
  .att-mark-headline { justify-content: space-between; align-items: center; width: 100%; }
  .att-mark-date { font-size: 16px; }
  .att-mark-actions { width: 100%; gap: 8px; }
  .att-mark-actions .att-allpresent-btn, .att-mark-actions .att-noclass-btn { flex: 1; justify-content: center; }

  /* student rows: name (with number) on top, big segmented states below */
  .att-row { flex-wrap: wrap; gap: 8px 10px; padding: 12px 14px; }
  .att-row-num { order: 0; }
  .att-row-name { order: 1; flex: 1 1 auto; white-space: normal; font-size: 16px; }
  .att-row-states { order: 2; width: 100%; gap: 6px; }
  .att-st { flex: 1; min-width: 0; padding: 9px 2px; font-size: 11px; border-radius: 10px; }
  .att-st .att-st-ico svg { width: 20px; height: 20px; }

  /* sticky save bar — full-bleed to the panel edges, prominent buttons */
  .att-savebar { margin: 10px -12px -14px; padding: 12px; border-radius: 0; border-left: 0; border-right: 0; border-bottom: 0; }
  .att-savebar-actions { gap: 8px; }
  .att-savebar-actions .btn { padding: 11px 16px; }

  /* history month grid scrolls sideways; legend wraps */
  .am-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .att-hist-legend { gap: 8px 12px; flex-wrap: wrap; font-size: 12px; }

  .roles-grid { grid-template-columns: 1fr; }

  /* My Students rows stack on phones */
  .ms-row { flex-wrap: wrap; gap: 4px 10px; }
  .ms-name { flex: 1 1 100%; min-width: 0; }
  .ms-meta { flex: 1 1 100%; }
}

/* ===== General view: teacher separator + disabled-availability blocks ===== */
.gen-row-sep {
  grid-column: 1 / -1;
  height: 10px;
  background: var(--bg);
}
/* Disabled (teacher unavailable) cells — hatched red. Each cell is an
   independent toggle; in Edit mode every empty/disabled cell is clickable. */
.gen-slot-cell.gen-disabled { position: relative; }
.gen-slot-cell.gen-disabled::before {
  content: ""; position: absolute; inset: 4px;
  background: repeating-linear-gradient(135deg, #f1d6d6 0 6px, #f8e6e6 6px 12px);
  border: 1.5px solid #f0a8a8; border-radius: 6px;
}
.gen-editing .gen-disabled { cursor: pointer; }
.gen-editing .gen-slot-cell.gen-disabled:hover::before { border-color: #d9534f; }
.gen-editing .gen-slot-open { cursor: pointer; }
.gen-editing .gen-slot-open:hover {
  background: #f3e3e3;
  box-shadow: inset 0 0 0 1px #d98a8a;
}

/* ===== General view: mode switch + forming-groups cells ===== */
.gen-modebar { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.gen-mode-hint { font-size: 12px; }
.gen-forming-cell {
  position: relative;
  flex-direction: row; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 8px;
  --gf-fill: 0;   /* 0..1 headcount ratio, set inline per cell */
}
/* Solid green fill whose richness tracks --gf-fill: pale for a near-empty
   forming group, deep green for a full one. The inset ring and outer glow
   intensify with it too, so fuller groups visually pop. */
.gen-forming-cell::before {
  content: ""; position: absolute; inset: 4px; z-index: 0;
  border-radius: 7px;
  background: color-mix(in srgb, #2e9e54 calc(16% + var(--gf-fill) * 64%), #f3fbf5);
  box-shadow:
    inset 0 0 0 2px color-mix(in srgb, #2e9e54 calc(40% + var(--gf-fill) * 55%), transparent),
    inset 0 0 9px rgba(46,158,84, calc(0.22 + var(--gf-fill) * 0.35)),
    0 0 calc(4px + var(--gf-fill) * 8px) rgba(46,158,84, calc(0.2 + var(--gf-fill) * 0.4));
}
.gen-forming-cell > * { position: relative; z-index: 1; }
.gen-forming-cell .gf-total {
  font-weight: 700; font-size: 13px; color: #1b5e20;
  background: #c8e6c9; border-radius: 6px; padding: 1px 7px;
  font-variant-numeric: tabular-nums;
}
.gen-forming-cell .gf-chips { display: inline-flex; gap: 3px; flex-wrap: wrap; }
.gen-forming-cell .gf-chip {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10px; font-weight: 700;
  padding: 1px 6px; border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
.gen-forming-cell .gf-chip svg { width: 16px; height: 16px; display: block; }
.gen-forming-cell .gf-n { line-height: 1; }

/* Forming-group chip colors by newcomer type (icon + count). */
.gen-forming-cell .gf-chip { border: 1px solid rgba(0,0,0,0.07); }
.gen-forming-cell .gf-chip.gf-waiting { background: #fde2e2; color: #c62828; }  /* red */
.gen-forming-cell .gf-chip.gf-coming  { background: #ffe8d4; color: #fb8c00; }  /* orange */
.gen-forming-cell .gf-chip.gf-recall  { background: #ffded0; color: #d84315; }  /* dark orange */
.gen-forming-cell .gf-chip.gf-attend  { background: #e1ecfb; color: #1565c0; }  /* blue */
.gen-forming-cell .gf-chip.gf-yes     { background: #cdebd0; color: #2e7d32; }  /* green */

.gen-forming-cell { cursor: pointer; }
/* Forming-group hover tooltip */
.gen-tip {
  position: fixed; z-index: 1000; pointer-events: none;
  background: #fff; border: 1px solid var(--line-strong);
  border-radius: 10px; box-shadow: var(--shadow);
  padding: 6px; display: flex; flex-direction: column; gap: 4px;
}
.gen-tip.hidden { display: none; }
.gen-tip-row {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 9px; border-radius: 7px; font-size: 12px; font-weight: 600;
  white-space: nowrap; border: 1px solid rgba(0,0,0,0.06);
}
.gen-tip-row svg { width: 16px; height: 16px; }
.gen-tip-row.gf-waiting { background: #fde2e2; color: #c62828; }
.gen-tip-row.gf-coming  { background: #ffe8d4; color: #fb8c00; }
.gen-tip-row.gf-recall  { background: #ffded0; color: #d84315; }
.gen-tip-row.gf-attend  { background: #e1ecfb; color: #1565c0; }
.gen-tip-row.gf-yes     { background: #cdebd0; color: #2e7d32; }

/* ============ CLIENT CARD (newcomers: profile + notes chat) ============ */
.nc-row { cursor: pointer; }
.nc-row:hover { background: #f3f6fb; }

.cc-modal {
  width: min(980px, 95vw); max-width: 980px; height: min(84vh, 780px);
  display: flex; flex-direction: column; padding: 0; overflow: hidden;
}
.cc-header {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 15px 20px; border-bottom: 1px solid var(--line);
}
.cc-titles h3 { margin: 0 0 4px; }
.cc-body { display: flex; flex: 1; min-height: 0; }
.cc-pane { display: flex; flex-direction: column; min-height: 0; }
.cc-left { flex: 1 1 56%; padding: 18px 20px; overflow: auto; }
.cc-left #ccForm { display: flex; flex-direction: column; gap: 12px; }
.cc-left .row { display: flex; gap: 12px; }
.cc-left label { display: block; font-size: 12px; font-weight: 500; color: var(--ink); }
.cc-left label input, .cc-left label select, .cc-left label textarea {
  width: 100%; box-sizing: border-box; margin-top: 5px; padding: 8px 10px;
  border: 1px solid var(--line-strong); border-radius: 8px; font-family: inherit; font-size: 13px;
}
.cc-left label textarea { resize: vertical; }
.cc-form-actions { display: flex; align-items: center; gap: 10px; margin-top: 18px; }
.cc-form-actions .spacer { flex: 1; }

.cc-right { flex: 1 1 44%; max-width: 410px; border-left: 1px solid var(--line); background: #f5f6f9; }
.cc-chat-head { padding: 12px 16px; font-weight: 600; font-size: 13px; border-bottom: 1px solid var(--line); }
.cc-chat { flex: 1; overflow: auto; padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }
.cc-note {
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  padding: 9px 11px; box-shadow: 0 1px 2px rgba(0,0,0,.04);
}
.cc-note-body { font-size: 13px; line-height: 1.45; word-break: break-word; }
.cc-note-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 6px; font-size: 11px; color: var(--muted);
}
.cc-note-del { border: 0; background: transparent; color: var(--muted); cursor: pointer; padding: 2px; border-radius: 4px; opacity: 0; transition: opacity .15s, color .15s; }
.cc-note:hover .cc-note-del { opacity: 1; }
.cc-note-del:hover { color: #c62828; }
.cc-note-del svg { width: 13px; height: 13px; display: block; }
.cc-chat-empty, .cc-chat-loading { text-align: center; padding: 22px 0; font-size: 13px; }
.cc-compose { display: flex; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--line); background: #fff; }
.cc-compose textarea {
  flex: 1; resize: none; font-family: inherit; font-size: 13px;
  padding: 8px 10px; border: 1px solid var(--line-strong); border-radius: 8px;
}
@media (max-width: 760px) {
  .cc-body { flex-direction: column; }
  .cc-right { max-width: none; border-left: 0; border-top: 1px solid var(--line); min-height: 280px; }
  .cc-modal { height: 92vh; }
}

/* Voronka card position context (Left-column gate checkbox removed — plain DnD) */
.vk-card { position: relative; }

/* ============================================================
   BOTTOM NAV + MORE SHEET — base rules (desktop: hidden)
   Phones (<= 640px) override below.
   ============================================================ */
.bottom-nav { display: none; }
.more-sheet  { display: none; }

/* ============================================================
   RESPONSIVE GAP-FILL — phone/tablet rules for topbar, nav,
   stat-tile banners, and page padding. These are additive and
   deliberately avoid the already-tuned selectors in the
   max-width:720px / 760px / 900px blocks above (attendance,
   .ms-row, Claude-chat modal, #activeStats, .fin-insights, .tt-cols).
   Desktop (>900px) appearance is unchanged.
   ============================================================ */

/* --- Stat-tile banners wrap instead of squeezing into 8 fixed cols.
   Scoped to NOT touch #activeStats (it keeps its own 2-col rule). --- */
@media (max-width: 900px) {
  .report-banner:not(#activeStats) {
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  }
}
@media (max-width: 560px) {
  .report-banner:not(#activeStats) {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* --- Phone topbar / nav / page padding (<= 640px) --- */
@media (max-width: 640px) {
  /* Topbar: trim horizontal padding, allow the right cluster to wrap so
     lang-switch + profile (+ acting pill) never push off-screen. */
  .topbar { padding: 10px 12px; gap: 8px; }
  .topbar-right { gap: 8px; flex-wrap: wrap; justify-content: flex-end; row-gap: 6px; }

  /* Hide the long live date and the brand subtitle to reclaim width.
     The .logo (home button) stays fully tappable. */
  #topbarMeta, .topbar-meta { display: none; }
  .brand-sub { display: none; }
  .brand { gap: 10px; }
  .logo { width: 40px; height: 40px; }

  /* Acting-as pill shrinks and is allowed to wrap to its own line. */
  .acting-indicator { font-size: 12px; padding: 3px 5px 3px 10px; gap: 6px; max-width: 100%; }
  .acting-indicator .acting-text { white-space: normal; }

  /* Keep targets tappable. */
  .profile-btn { width: 36px; height: 36px; }
  .lang-switch .lang-opt { padding: 6px 9px; }
  .lang-switch .lang-term { padding: 6px 7px; }

  /* Page + panels use the full width on phones. (#panel-attendance is
     intentionally left to the 720px block, which already sets it.) */
  main { padding: 14px 12px calc(64px + env(safe-area-inset-bottom)); }
  .panel:not(#panel-attendance) { padding: 14px; }

  /* Nav: slightly tighter so more fits before horizontal scroll kicks in.
     Sticky + overflow-x scroll behavior from the base rules is preserved. */
  .tab { padding: 11px 12px; font-size: 13px; }
  .tab-group-label { font-size: 9px; padding: 6px 10px 3px; }

  /* --- Bottom nav replaces the top tab bar on phones --- */
  .tabs { display: none; }

  :root { --bottom-nav-h: 56px; }

  /* Bottom nav shell */
  .bottom-nav {
    display: flex;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    background: #fff;
    border-top: 1px solid var(--line);
    padding-bottom: env(safe-area-inset-bottom);
    box-shadow: 0 -2px 12px rgba(0,0,0,.06);
  }
  .bn-item {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; min-height: 56px; padding: 6px 4px 4px;
    border: 0; background: transparent; cursor: pointer;
    color: var(--muted); font-family: inherit;
    -webkit-tap-highlight-color: transparent; touch-action: manipulation;
    transition: color var(--t-fast) var(--ease);
  }
  .bn-item.active { color: var(--ink); }
  .bn-ico { display: inline-flex; width: 24px; height: 24px; flex-shrink: 0; }
  .bn-ico svg { width: 24px; height: 24px; display: block; }
  .bn-label { font-size: 10px; font-weight: 500; line-height: 1; white-space: nowrap; }

  /* Attendance sticky save bar must clear the bottom nav */
  .att-savebar {
    bottom: calc(var(--bottom-nav-h) + env(safe-area-inset-bottom));
  }

  /* More sheet (bottom sheet) */
  .more-sheet { display: block; }
  .more-sheet.hidden { display: none; }
  .more-backdrop {
    position: fixed; inset: 0; background: rgba(0,0,0,.4); z-index: 60;
  }
  .more-panel {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 61;
    background: #fff;
    border-radius: 16px 16px 0 0;
    padding: 12px 0 env(safe-area-inset-bottom);
    max-height: 70vh;
    overflow-y: auto;
    box-shadow: 0 -4px 24px rgba(0,0,0,.12);
  }
  .bn-more-item {
    display: flex; align-items: center; gap: 14px; width: 100%;
    min-height: 48px; padding: 10px 20px;
    border: 0; background: transparent; cursor: pointer; font-family: inherit;
    font-size: 15px; color: var(--ink); text-align: left;
    -webkit-tap-highlight-color: transparent; touch-action: manipulation;
    transition: background var(--t-fast) var(--ease);
  }
  .bn-more-item:hover, .bn-more-item:active { background: #f4f5f7; }
  .bn-more-item .bn-ico { width: 22px; height: 22px; color: var(--muted); }
  .bn-more-item .bn-ico svg { width: 22px; height: 22px; }
}

/* On very narrow phones, drop the brand title too but keep the logo. */
@media (max-width: 420px) {
  .brand-title { display: none; }
}

/* ============================================================
   MOBILE CONTENT RESPONSIVENESS
   All rules below are additive and scoped to phone breakpoints.
   Desktop (>900px) appearance is unchanged.
   Primary phone: max-width:640px. Small phone: max-width:420px.
   Tablet tweaks: max-width:900px (some already exist above).
   ============================================================ */

/* ------------------------------------------------------------------
   1. Panel headers / actions / search — stack on phones
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  .panel-header {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .panel-header h2 { font-size: 18px; }
  .panel-actions {
    flex-wrap: wrap;
    gap: 8px;
  }
  /* Search box fills the row */
  .search-box { min-width: 0; width: 100%; }
  /* Segmented day/view/density switches go full-width */
  .day-switch { width: 100%; }
  .day-switch button { flex: 1; }
  #viewSwitch, #densitySwitch { width: 100%; }
  #viewSwitch button, #densitySwitch button { flex: 1; }
}

/* ------------------------------------------------------------------
   2. Data tables — edge-to-edge horizontal scroll with touch hint
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  .table-wrap {
    border-left: 0;
    border-right: 0;
    border-radius: 0;
    margin-left: -14px;
    margin-right: -14px;
    -webkit-overflow-scrolling: touch;
  }
  /* Subtle right-edge gradient to hint scroll affordance */
  .table-wrap::after {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: 20px;
    background: linear-gradient(to left, rgba(255,255,255,.8), transparent);
    pointer-events: none;
    border-radius: 0 8px 8px 0;
  }
  .table-wrap { position: relative; }
}

/* ------------------------------------------------------------------
   3. Schedule grid — horizontal scroll, sticky time col
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  .sch-wrap {
    -webkit-overflow-scrolling: touch;
    max-height: 80vh;
  }
  .sch-grid tbody tr { height: 48px; }
  .sch-grid .time-col { min-width: 36px; font-size: 9px; padding: 4px 2px; }
  .grid-wrap { -webkit-overflow-scrolling: touch; }
  .schedule-block .grid-wrap { max-height: 50vh; }
  /* Room schedule blocks: single column on phones */
  .schedule-stack {
    grid-template-columns: 1fr !important;
  }
}

/* ------------------------------------------------------------------
   4. Dashboard / report tiles + charts + breakdown grids
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  /* Main stat tiles: 2 per row */
  .report-banner {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 8px;
  }
  /* Report secondary row: 2 per row */
  .report-secondary {
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
  }
  /* Report cards stack to 1 col */
  .report-grid { grid-template-columns: 1fr; gap: 10px; }
  /* Bar chart label column: narrow */
  .bar-row { grid-template-columns: 100px 1fr 44px; }
  /* SVG/chart: never overflow container */
  svg { max-width: 100%; }
  /* CGM voronka chart */
  .vk-chart { padding: 10px 12px; }
  .vk-chart svg { width: 100% !important; height: auto !important; }
}

/* ------------------------------------------------------------------
   5. Finance — form fields stack, totals wrap
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  .fin-toolbar {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .fin-toolbar-left, .fin-toolbar-right {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }
  .fin-range { flex-wrap: wrap; }
  .fin-range input[type=date] { flex: 1; min-width: 0; }
  .fin-search { min-width: 0; width: 100%; }
  .fin-cards { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .fin-card-val { font-size: 18px; }
}

/* ------------------------------------------------------------------
   6. Voronka kanban — horizontal scroll-snap, each col ~78vw
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  .voronka-board {
    display: flex !important;
    flex-direction: row;
    max-height: none; min-height: 0;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: 10px;
    padding-bottom: 8px;
    /* Allow the board to extend outside the panel padding */
    margin-left: -14px;
    margin-right: -14px;
    padding-left: 14px;
    padding-right: 14px;
  }
  .vk-col {
    flex: 0 0 78vw;
    min-width: 78vw;
    scroll-snap-align: start;
    max-height: 70vh;
  }
  .vk-add-col {
    flex: 0 0 60vw;
    min-width: 60vw;
    scroll-snap-align: start;
  }
}

/* ------------------------------------------------------------------
   7. Groups / General / My Students / My Timetable
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  /* Groups: pill min-width removed on phone — horizontal scroll handles it */
  #activeGroupsView .group-sticky-header,
  #activeGroupsView .group-pill-stack { min-width: 900px; }

  /* General grid: horizontal scroll */
  .gen-grid { -webkit-overflow-scrolling: touch; }

  /* My Timetable columns: single col on very narrow phones */
  .tt-cols { grid-template-columns: 1fr; }

  /* My Students: already handled by 720px block; tighten font */
  .ms-name { font-size: 14px; }
  .ms-time { font-size: 15px; }
}

/* ------------------------------------------------------------------
   8. Modals — near-full-screen on phones using 100dvh
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  .modal { padding: 0; align-items: flex-end; }
  .modal-content {
    width: 100vw;
    max-width: 100vw;
    border-radius: 16px 16px 0 0;
    max-height: 94dvh;
    height: auto;
    padding: 20px 16px env(safe-area-inset-bottom);
    overflow-y: auto;
  }
  /* Wide modals (attendance detail etc) */
  .modal-content-wide {
    max-width: 100vw !important;
    width: 100vw;
    border-radius: 16px 16px 0 0;
    max-height: 94dvh !important;
    height: auto;
  }
  /* Client card modal becomes full screen */
  .cc-modal {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    border-radius: 0;
  }
  /* Modal action bars pin to bottom */
  .modal-actions {
    position: sticky;
    bottom: 0;
    background: #fff;
    padding-top: 12px;
    margin-top: 12px;
    border-top: 1px solid var(--line);
  }
}

/* ------------------------------------------------------------------
   9. Forms everywhere — 16px font-size prevents iOS focus zoom
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  input[type=text],
  input[type=number],
  input[type=search],
  input[type=date],
  input[type=email],
  input[type=password],
  select,
  textarea {
    font-size: 16px;
    padding: 10px 12px;
    width: 100%;
  }
  /* Pay modal stepper: keep the input 16px */
  .pay-stepper input { font-size: 16px; }
  /* Label+input combos are already full-width via the label/input base rules */
  label { margin-bottom: 12px; }
  .modal-content label { display: flex; flex-direction: column; }
  .modal-content .row { flex-direction: column; gap: 0; }
  /* Finance add-entry form rows */
  .fin-toolbar .row { flex-direction: column; gap: 8px; }
}

/* ------------------------------------------------------------------
   10. Floor plan — fit to viewport, toolbar wraps
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  .floor-stage {
    flex-direction: column;
    gap: 12px;
  }
  .floor-3d-wrap {
    height: 50vw;
    min-height: 200px;
    max-width: 100%;
  }
  .floor-wrap { padding: 10px; overflow: auto; }
  #floorPlan { width: 100%; height: auto; touch-action: pan-x pan-y; }
  #floorCanvas3D { touch-action: none; }
  .floor-toolbar { gap: 6px; }
  .floor-time-control {
    flex-direction: row;
    flex: 0 0 auto;
    width: 100%;
    height: auto;
    padding: 8px 12px;
    gap: 10px;
  }
  .ftc-roller-wrap { flex: 1; }
  .ftc-roller {
    writing-mode: horizontal-tb;
    -webkit-appearance: auto;
    appearance: auto;
    width: 100%;
    height: 28px;
    min-height: 0;
  }
}

/* ------------------------------------------------------------------
   11. Topbar verification — bottom nav must not overlap topbar
       (topbar phone rules already exist in the 640px block above;
        just ensure z-index ordering is sane)
   ------------------------------------------------------------------ */
@media (max-width: 640px) {
  .topbar { position: relative; z-index: 20; }
}

/* ------------------------------------------------------------------
   Small phone (max-width: 420px) — tighter tile grid
   ------------------------------------------------------------------ */
@media (max-width: 420px) {
  .report-banner { grid-template-columns: 1fr 1fr !important; gap: 6px; }
  .report-secondary { grid-template-columns: 1fr; }
  .fin-cards { grid-template-columns: 1fr; }
  .tile .tvalue { font-size: 22px; }
  .modal-content { padding: 16px 12px env(safe-area-inset-bottom); }
  .vk-col { flex: 0 0 88vw; min-width: 88vw; }
}