/* ==== Kalimati — नेपाली (देवनागरी) अक्षरका लागि मात्र ====
   सर्वर/फोन मा फन्ट नभए पनि चल्न fonts/Kalimati.ttf (वा .woff2) यही फोल्डरमा राख्नुस्।
   unicode-range ले अङ्ग्रेजी/अङ्कलाई Inter/Poppins मै राख्छ। */
@font-face {
  font-family: "Kalimati";
  src: local("Kalimati"), local("Kalimati Regular"), url("../fonts/Kalimati.woff2") format("woff2"), url("../fonts/Kalimati.ttf") format("truetype");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0900-097F, U+1CD0-1CFF, U+A8E0-A8FF, U+200C-200D;
}
/* ==========================================================================
   Shree Khadgakali Secondary School — Marks Entry App
   Design tokens: deep indigo (#1B2A4A) + marigold accent (#E8A33D)
   on warm cream (#FAF7F2). Display: Poppins. Body: Inter. Data: Roboto Mono.
   ========================================================================== */

/* Fonts are intentionally 100% system/native — no @import, no @font-face,
   no CDN of any kind. Every font-family stack below names "Kalimati" and
   "Nirmala UI" (Windows' own Nepali/Devanagari system fonts) ahead of
   "Noto Sans Devanagari" (the default on Android/ChromeOS/most Linux) and
   a generic sans-serif/monospace tail (macOS/iOS auto-substitute Kohinoor
   Devanagari for Devanagari codepoints even under a plain "sans-serif"
   request). Nothing here is fetched over the network, so a page can never
   render Devanagari text in one font while it loads and a different one
   after — the same markup looks the same everywhere, on the first paint,
   including offline or on a blocked/slow connection. Latin display text
   (previously Poppins/Inter/Roboto Mono via Google Fonts) now falls
   through to the browser's own default UI sans-serif/monospace font. */

:root {
  --ink: #1b2a4a;
  --ink-light: #2f4270;
  --gold: #e8a33d;
  --gold-dark: #c8811f;
  --cream: #faf7f2;
  --card: #ffffff;
  --text: #2b2b2b;
  --muted: #6b7280;
  --success: #3f7a5c;
  --error: #c1443c;
  --border: #e6e0d4;
  /* Mark-type color coding — used across the admin print ledger AND the
     marks-entry number-entry table/print view (see .mk-* and the
     data-field selectors under "Mark-type coloring" below). */
  --external: #1f6b3a;   /* dark green — external exam marks */
  --internal: #1a3d7c;   /* dark blue  — internal/formative marks */
  --total-mark: #cc1f1f; /* red        — computed totals */
}

* { box-sizing: border-box; }

/* ---- Digit-substitution guard ------------------------------------------
   Some Devanagari system fonts (Windows' "Nirmala UI"/"Kalimati" in
   particular) carry an OpenType "locl" feature that silently swaps plain
   ASCII 0-9 for Devanagari numeral glyphs whenever that font is the one
   actually doing the rendering — which happens more often than intended
   here, since none of "Inter"/"Poppins"/"Roboto Mono" above are loaded
   via @font-face (see the file banner above); they're only present if a
   visitor's OS happens to have them, and Kalimati/Nirmala UI is usually
   what's left on a Nepali-locale Windows machine. The DOM still holds a
   real "0".."9" the whole time — only the drawn glyph changes — but the
   effect looks exactly like "my API key/EMIS code/date turned into
   Nepali digits". Disabling the feature site-wide fixes every occurrence
   of that at once and is fully safe: it only turns off locale-conditional
   numeral shaping, so normal Devanagari letters render exactly as before,
   and it has zero effect on the calendar's own BS day numbers, which are
   already real ०१२३ Unicode characters (see toDevanagariDigits() in
   js/utils.js) rather than a font substitution. */
html, body, input, textarea, select, button {
  font-feature-settings: "locl" 0;
  font-variant-numeric: normal;
}

body {
  background: var(--cream);
  color: var(--text);
  font-family: "Kalimati", "Inter", "Nirmala UI", "Noto Sans Devanagari", system-ui, sans-serif;
  -webkit-tap-highlight-color: transparent;
}

h1, h2, h3, .display {
  font-family: "Kalimati", "Poppins", "Nirmala UI", "Noto Sans Devanagari", sans-serif;
}

.font-mono-data {
  font-family: "Kalimati", "Roboto Mono", "Nirmala UI", "Noto Sans Devanagari", monospace;
}

/* ---- Header / brand bar ---- */
.brand-header {
  background: linear-gradient(135deg, var(--ink) 0%, var(--ink-light) 100%);
  position: relative;
}
.brand-header::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--gold-dark), var(--gold), var(--gold-dark));
}

/* ---- Cards ---- */
.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 1px 3px rgba(27, 42, 74, 0.06);
}

/* ---- Buttons ---- */
.btn-primary {
  background: var(--ink);
  color: #fff;
  font-weight: 600;
  border-radius: 12px;
  transition: transform 0.12s ease, background 0.12s ease;
}
.btn-primary:hover { background: var(--ink-light); }
.btn-primary:active { transform: scale(0.98); }
.btn-primary:disabled { opacity: 0.5; }

.btn-gold {
  background: var(--gold);
  color: var(--ink);
  font-weight: 700;
  border-radius: 12px;
  transition: transform 0.12s ease, background 0.12s ease;
}
.btn-gold:hover { background: var(--gold-dark); }
.btn-gold:active { transform: scale(0.98); }

/* ---- "खाली फाराम" (blank/manual print) buttons — Inventory tab toolbars ----
   These print an empty form for someone to fill in by hand; they're used far
   less often than the real, data-populated print/report buttons (which use
   .btn-gold — see annualStatementBtn/printLandRegisterBtn in inventory.html),
   so they're kept deliberately small and muted to not compete for attention.
   Applied alongside .btn-cancel; declared after it so these sizing/color
   rules win regardless of any Tailwind utility classes still on the element. */
.btn-blank-print {
  padding: 0.3rem 0.6rem;
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--muted);
  border-color: var(--border);
  border-radius: 8px;
  opacity: 0.8;
}
.btn-blank-print:hover { opacity: 1; background: var(--cream, #fbf9f4); border-color: var(--gold); color: var(--ink); }
.btn-blank-print i { font-size: 0.65rem; }

/* ---- Inputs ---- */
.input-field {
  border: 1.5px solid var(--border);
  border-radius: 10px;
  padding: 0.65rem 0.85rem;
  font-size: 1rem;
  background: #fff;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
  width: 100%;
}
.input-field:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(232, 163, 61, 0.25);
}
.input-field.invalid {
  border-color: var(--error);
  box-shadow: 0 0 0 3px rgba(193, 68, 60, 0.15);
}

:focus-visible {
  outline: 2px solid var(--gold-dark);
  outline-offset: 2px;
}

/* ---- Ledger-style marks table (the app's signature element) ---- */
.ledger {
  border-collapse: separate;
  border-spacing: 0;
  width: 100%;
}
.ledger thead th {
  background: var(--ink);
  color: #f3ede0;
  font-family: "Kalimati", "Poppins", "Nirmala UI", "Noto Sans Devanagari", sans-serif;
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 0.6rem 0.5rem;
  position: sticky;
  top: 0;
  z-index: 5;
  border: 1px solid var(--gold-dark);
  border-bottom: 2px solid var(--gold);
  white-space: nowrap;
}
/* Allotted-marks note shown under a column label, e.g. "Written (50)" —
   same small, tight-width bracket convention everywhere a column has a
   fixed full-marks value: Nursery/KG, Breakdown (classes 6-10), the LO
   ledger's Full Marks column, and the matching headers on the Marks
   Entry page and its print/preview. Deliberately lighter and smaller
   than the label above it, and never wraps onto its own second line. */
.fm-note {
  display: inline-block;
  font-weight: 400;
  font-size: 0.85em;
  letter-spacing: normal;
  text-transform: none;
  opacity: 0.7;
  white-space: nowrap;
}
.ledger tbody tr {
  background: #fff;
  border-bottom: 1px solid var(--border);
}
.ledger tbody tr:nth-child(even) { background: #fbf9f4; }
.ledger tbody tr:hover { background: #fdf3e2; }
.ledger td {
  padding: 0.5rem;
  vertical-align: middle;
  border: 1px solid var(--border);
}
/* Centered by default everywhere in the ledger — high enough
   specificity to beat Tailwind's .text-left utility used on a few
   header/data cells. Student-name cells are the one exception, set
   to left-aligned via .ledger-name-col below — photo + name read
   left-to-right like any other name column, which is what keeps
   these tables looking clean on print. */
.ledger th,
.ledger td {
  text-align: center;
}
.ledger td.ledger-name-col {
  text-align: left;
}
/* Manage Students / Manage Teachers now show a plain-text, read-only
   summary row (editing happens in the dedicated Edit modal — see
   .record-edit-* below and js/admin-students.js / js/admin-teachers.js),
   but the ledger's default table-layout would still happily let Name or
   Student ID/Email get squeezed down to just a couple of characters when
   several columns compete for space — .table-scroll would gladly let the
   table scroll horizontally if only it knew these columns needed more
   room. A concrete min-width on the columns people actually need to read
   fixes this at the source. Any input/select still dropped directly into
   a ledger cell elsewhere (e.g. the Marks Entry table) keeps its own
   floor below. */
.ledger td.ledger-name-col {
  min-width: 11rem;
}
.ledger td input.input-field,
.ledger td select.input-field {
  min-width: 8rem;
}
/* Plain-text Student ID cell (Manage Students) — same treatment so it
   stays clearly readable rather than depending on its neighbors. */
.ledger td.ledger-id-col {
  min-width: 8rem;
  white-space: nowrap;
}
/* Principal Desk — प्रमाणपत्र (Certificate) record table. This table used
   to pin exact percentage-based column widths via <colgroup> +
   table-layout:fixed (see pdCertRenderPanelShell_() in
   js/principal-desk.js), which meant a narrow phone screen had no
   choice but to squeeze every column — student name and address
   included — down to an unreadably thin sliver instead of letting
   .table-scroll's horizontal scroll take over. Giving each column a
   real min-width here instead (table-layout back to the default auto)
   keeps every row readable in one line, and .table-scroll shows a
   horizontal scrollbar once that full width no longer fits the
   screen — the same approach Manage Students/Manage Teachers already
   use above. */
.ledger td.pd-cert-photo-col,
.ledger th.pd-cert-photo-col { min-width: 2.75rem; }
.ledger td.pd-cert-class-col,
.ledger th.pd-cert-class-col { min-width: 4rem; }
.ledger td.pd-cert-address-col,
.ledger th.pd-cert-address-col { min-width: 9rem; }
.ledger td.pd-cert-address-col { text-align: left; }
.ledger td.pd-cert-person-col,
.ledger th.pd-cert-person-col { min-width: 6rem; }
.ledger td.pd-cert-relation-col,
.ledger th.pd-cert-relation-col { min-width: 4.5rem; }
.ledger td.pd-cert-certno-col,
.ledger th.pd-cert-certno-col { min-width: 6rem; }
.ledger td.pd-cert-date-col,
.ledger th.pd-cert-date-col { min-width: 6.5rem; }
.ledger td.pd-cert-action-col,
.ledger th.pd-cert-action-col { min-width: 6rem; }
/* Manage Teachers / Manage Students / Uploaded Media — these plain-text
   listing tables mix cells with no size class, text-xs, and text-sm,
   so rows look uneven. Force one small, consistent size on every cell —
   higher specificity (class + element) beats any single Tailwind
   text-xs/text-sm utility already on the td. Opt-in via .ledger-compact
   on the <table> so the Grade Ledger / Marks Entry / print ledgers
   (which already have their own deliberate sizing) are unaffected. */
.ledger-compact td {
  font-size: 0.8rem;
}
.ledger .mark-input {
  width: 100%;
  min-width: 3.5rem;
  text-align: center;
  font-family: "Kalimati", "Roboto Mono", "Nirmala UI", "Noto Sans Devanagari", monospace;
  font-weight: 600;
  padding: 0.4rem 0.3rem;
  border: 1.5px solid var(--border);
  border-radius: 8px;
}
.ledger .mark-input:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(232, 163, 61, 0.25);
}
.ledger .mark-input.invalid { border-color: var(--error); }
.ledger .row-total {
  font-family: "Kalimati", "Roboto Mono", "Nirmala UI", "Noto Sans Devanagari", monospace;
  font-weight: 700;
  color: var(--ink);
}

/* ---- Mark-type coloring (marks-entry number-entry table) ----
   Internal/formative fields -> dark blue, the external-exam field ->
   dark green, computed totals -> red. Selected by the same data-field
   attributes marks-entry.js already puts on each input, so no extra
   markup is needed here. */
.ledger .mark-input[data-field="participation"],
.ledger .mark-input[data-field="practical"],
.ledger .mark-input[data-field="firstTerm"],
.ledger .mark-input[data-field="written"],
.ledger .mark-input[data-field="oral"],
.ledger .mark-input[data-field="obtainedLO"] {
  color: var(--internal);
}
.ledger .mark-input[data-field="external"] {
  color: var(--external);
}
.ledger .row-total,
.ledger td.mk-total {
  color: var(--total-mark) !important;
}
.ledger td.mk-internal { color: var(--internal) !important; }
.ledger td.mk-external { color: var(--external) !important; }

/* Grade Ledger — NG subject cells get a soft red background so a failed
   subject stands out at a glance; the GPA column is bold so it reads as
   the row's headline number. */
.ledger td.grade-ng {
  background: #fbe4e2;
  color: var(--error) !important;
  font-weight: 600;
}
.ledger td.gpa-cell {
  font-weight: 700;
}

.table-scroll {
  overflow-x: auto;
  border-radius: 16px;
  border: 1px solid var(--border);
}
/* Vertical scroll box for long lists (Letters / Registers / Notices): the list
   scrolls inside its own frame — the header row stays pinned (.ledger thead th
   is sticky) — so a long list never pushes the rest of the page far down,
   especially on a phone. */
.table-scroll.table-scroll-y {
  max-height: min(70vh, 34rem);
  overflow: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
@media (max-width: 640px) {
  .table-scroll.table-scroll-y { max-height: 58vh; }
}
/* क्र.सं. (serial no.) column */
.ledger th.sn-col,
.ledger td.sn-col {
  width: 2.75rem;
  min-width: 2.75rem;
  text-align: center;
  white-space: nowrap;
}

/* ---- Audit trail ---- */
.audit-line {
  font-size: 0.72rem;
  color: var(--muted);
  font-family: "Kalimati", "Roboto Mono", "Nirmala UI", "Noto Sans Devanagari", monospace;
}

/* ---- Sticky save bar (thumb-reach on mobile) ---- */
.save-bar {
  position: sticky;
  bottom: 0;
  background: rgba(250, 247, 242, 0.92);
  backdrop-filter: blur(6px);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom);
}

/* ---- Tab pills (in-page tabs: Print Ledger, Settings) ---- */
.admin-nav {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  padding-bottom: 0.25rem;
  -ms-overflow-style: none;
  scrollbar-width: none;
}
.admin-nav::-webkit-scrollbar { display: none; }
.admin-nav-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.55rem 1rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  background: #fff;
  border: 1.5px solid var(--border);
  color: var(--ink);
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
  flex-shrink: 0;
}
.admin-nav-pill:hover { background: var(--cream); border-color: var(--gold); }
.admin-nav-pill[aria-current="page"] {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}

/* ---- Mobile admin menu: hamburger opens a full left-side drawer (not a
   floating button widget) so the whole nav is reachable in one place, same
   as the always-visible desktop sidebar below. ---- */
.admin-menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 0.6rem;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #fff;
  font-size: 1.2rem;
  line-height: 1;
  flex-shrink: 0;
  transition: background 0.12s ease;
}
.admin-menu-toggle svg { width: 1.15rem; height: 1.15rem; display: block; }
.admin-menu-toggle:hover { background: rgba(255, 255, 255, 0.18); }
.admin-menu-toggle[aria-expanded="true"] { background: var(--gold); border-color: var(--gold); color: var(--ink); }

/* Dimmed backdrop behind the open drawer — click to close. */
.admin-drawer-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 20, 35, 0.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  z-index: 70;
}
.admin-drawer-overlay.open { opacity: 1; pointer-events: auto; }

/* The drawer itself — full-height panel pinned to the left edge, slides in
   over the page instead of a small button-style dropdown. */
.admin-drawer {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: min(80vw, 300px);
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, var(--ink) 0%, var(--ink-light) 100%);
  transform: translateX(-105%);
  transition: transform 0.25s ease;
  z-index: 71;
  box-shadow: 10px 0 30px rgba(10, 14, 28, 0.35);
}
.admin-drawer.open { transform: translateX(0); }
.admin-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 1.1rem 1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  flex-shrink: 0;
}
.admin-drawer-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 0.5rem;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: #fff;
  flex-shrink: 0;
}
.admin-drawer-close svg { width: 1rem; height: 1rem; display: block; }
.admin-drawer-close:hover { background: rgba(255, 255, 255, 0.18); }
.admin-drawer-nav {
  flex: 1;
  overflow-y: auto;
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

/* ---- Desktop admin sidebar — always visible, full nav list, not a
   collapsed dropdown of action buttons. ---- */
.admin-sidebar {
  background: linear-gradient(180deg, var(--ink) 0%, var(--ink-light) 100%);
}
.admin-sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.65rem 0.85rem;
  border-radius: 10px;
  font-size: 0.85rem;
  font-weight: 600;
  color: rgba(255,255,255,0.75);
  transition: background 0.12s ease, color 0.12s ease;
}
.sidebar-link:hover { background: rgba(255,255,255,0.08); color: #fff; }
.sidebar-link[aria-current="page"] {
  background: var(--gold);
  color: var(--ink);
}
.sidebar-link .admin-menu-icon { font-size: 1rem; width: 1.4rem; text-align: center; flex-shrink: 0; }

/* ---- Sidebar "Child Menu" groups (e.g. Accounting, Manage Exam) — a
   header link that expands/collapses its own nested list of links. See
   navGroupHtml()/wireSidebarGroupToggles() in js/utils.js. Deliberately
   generic so any future grouped section just works by adding another
   `children` entry — no CSS changes needed per group. ---- */
.sidebar-group-toggle {
  width: 100%;
  border: none;
  background: none;
  cursor: pointer;
  font-family: inherit;
}
/* "This section is open" accent for the group header — deliberately NOT
   the same full-gold pill a plain link/active child gets (that's
   .sidebar-link[aria-current="page"]), so the header and the children
   panel below it (its own distinct background — see
   .sidebar-group-children below) read as two visually separate tiers
   rather than merging into one solid block. */
.sidebar-group-toggle-active { background: rgba(255, 255, 255, 0.08); color: #fff; }
.sidebar-group-toggle-active .admin-menu-icon i { color: var(--gold); }
.sidebar-group-toggle .sidebar-group-chevron {
  margin-left: auto;
  font-size: 0.7rem;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.sidebar-group.open > .sidebar-group-toggle .sidebar-group-chevron { transform: rotate(180deg); }
.sidebar-group-children {
  display: grid;
  /* minmax(0, …) — not a plain 0fr/1fr — is what actually lets the row
     collapse all the way to 0px. A bare fr track still respects its
     content's automatic min-size (min-content), so the padded/backed
     inner div below kept forcing a sliver of height (and its background
     colour) to show through even while "collapsed". Wrapping the row in
     minmax(0, …) overrides that automatic minimum with an explicit 0. */
  grid-template-rows: minmax(0, 0fr);
  overflow: hidden;
  transition: grid-template-rows 0.18s ease;
}
.sidebar-group.open > .sidebar-group-children { grid-template-rows: minmax(0, 1fr); }
/* Background/padding/margin all live on this INNER div, not on
   .sidebar-group-children itself — so when the row above collapses to
   0px, this whole div (and its background/border-radius) is clipped away
   completely by the row's overflow:hidden, instead of leaking a thin
   coloured line while "closed". Distinct background from both the
   sidebar and the group header above it, so an opened sub-menu clearly
   reads as its own nested panel rather than blending into the parent. */
.sidebar-group-children > div {
  overflow: hidden;
  min-height: 0;
  background: rgba(0, 0, 0, 0.18);
  border-radius: 10px;
  margin-top: 0.2rem;
  padding: 0.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.sidebar-group-children .sidebar-link { padding-left: 2rem; font-size: 0.8rem; }

/* Sidebar icon transitions (colour itself now comes from the site-wide
   meaningful icon-colour map below, keyed by icon shape rather than
   list position — see "Meaningful icon colours" further down). */
.admin-sidebar-nav .sidebar-link .admin-menu-icon i,
.admin-drawer-nav .sidebar-link .admin-menu-icon i { transition: color 0.12s ease; }
.admin-sidebar-nav .sidebar-link[aria-current="page"] .admin-menu-icon i,
.admin-drawer-nav .sidebar-link[aria-current="page"] .admin-menu-icon i { color: var(--ink); }

/* ==========================================================================
   Meaningful icon colours (site-wide)

   Every Font Awesome icon on the site is coloured by what it means, not by
   where it happens to sit — the same glyph is always the same colour,
   whether it's in the sidebar, a Settings tab, the Attendance legend, or
   any other page. That makes colour itself informative (green = done/
   success, red = danger/absent, amber = pending/editing, etc.) instead of
   decorative.

   A few icon groups are deliberately left out of this map because they
   already carry contextual meaning of their own that this would clash
   with: the Academic Calendar's per-day/holiday icons (fa-school,
   fa-book-open, fa-champagne-glasses, and the festival/muhurat icons like
   fa-om, fa-moon, fa-fire, fa-star-of-david, fa-place-of-worship,
   fa-bowl-rice) inherit the colour of whichever status badge or day-cell
   they sit in; fa-circle is left alone because it's already coloured per
   status via the .status-dot-* classes above.
   ========================================================================== */

/* Success / completion / save */
.fa-check, .fa-circle-check, .fa-square-check, .fa-floppy-disk, .fa-download, .fa-plus {
  color: var(--success);
}
/* Danger / destructive / security */
.fa-xmark, .fa-circle-xmark, .fa-trash, .fa-ban, .fa-road-barrier, .fa-lock, .fa-shield-halved, .fa-key {
  color: var(--error);
}
/* Pending / editing / in-progress */
.fa-hourglass-half, .fa-pen-to-square, .fa-pencil, .fa-pen-nib, .fa-caret-down, .fa-folder, .fa-folder-open, .fa-bullhorn, .fa-tag {
  color: var(--gold-dark);
}
/* Warning / physical assets */
.fa-triangle-exclamation, .fa-box, .fa-box-archive, .fa-store, .fa-trowel-bricks {
  color: #ea580c;
}
/* Documents / records / information */
.fa-file-lines, .fa-clipboard-list, .fa-scroll, .fa-receipt, .fa-chart-column, .fa-list-ol, .fa-house, .fa-upload, .fa-file-import, .fa-file-export, .fa-file-arrow-down, .fa-eye, .fa-envelope, .fa-envelope-open-text {
  color: #2563eb;
}
/* Calendar / schedule / public-facing */
.fa-calendar-days, .fa-calendar-check, .fa-globe, .fa-phone {
  color: #0891b2;
}
/* Search / testing */
.fa-magnifying-glass, .fa-flask, .fa-book {
  color: #0d9488;
}
/* People / roles / admin tools */
.fa-user, .fa-user-tie, .fa-shuffle, .fa-brain, .fa-gear, .fa-wrench {
  color: #7c3aed;
}
/* Students / media */
.fa-graduation-cap, .fa-image, .fa-camera, .fa-face-smile {
  color: #db2777;
}
/* Celebration / recognition */
.fa-champagne-glasses:not(.status-badge *), .fa-star, .fa-medal, .fa-trophy, .fa-sparkles, .fa-rocket, .fa-ranking-star {
  color: var(--gold);
}
/* Neutral utility (navigation arrows, generic chrome) */
.fa-print, .fa-bars, .fa-broom, .fa-arrow-left, .fa-arrow-right, .fa-arrow-up, .fa-arrow-down, .fa-arrow-turn-down, .fa-paperclip, .fa-icons, .fa-comment, .fa-rotate {
  color: #64748b;
}
/* Accounting (each sub-screen under the sidebar's "Accounting" group — see
   ACCOUNTING_CHILD_ORDER/navGroupHtml() in js/utils.js — gets its own
   colour, one per icon shape, same rule as every other bucket above: this
   is what lets a dozen finance screens sitting stacked in one collapsed
   menu read apart from each other at a glance instead of as a single grey
   block. fa-money-bill-transfer covers two screens (खर्च हिसाब/expense and
   बजेट निकासा/budget release) since both reuse that icon shape. */
.fa-file-invoice-dollar { color: #d97706; }   /* वार्षिक बजेट तर्जुमा — budget */
.fa-money-check-dollar { color: #4f46e5; }    /* कार्यसमिति तलब माग — salary demand */
.fa-file-signature { color: #c026d3; }        /* माग फारम — demand form */
.fa-sack-dollar { color: #10b981; }           /* आम्दानी हिसाब — income */
.fa-money-bill-transfer { color: #e11d48; }   /* खर्च हिसाब / बजेट निकासा — expense, budget release */
.fa-vault { color: #0f766e; }                 /* धरौटी खाता — deposit account */
.fa-route { color: #0284c7; }                 /* भ्रमण तथा काज — travel */
.fa-chart-line { color: #65a30d; }            /* आय व्यय विवरण — income/expense statement */
.fa-scale-balanced { color: #a16207; }        /* लेखा बन्दी हिसाब — year-end closing */

/* Buttons with a solid background keep a plain, high-contrast icon colour
   (matching their text) instead of the meaningful palette above — a
   button's own colour (navy/gold/green) already communicates its action,
   and mixing in unrelated icon colours there reads as noise rather than
   information. Declared after the map above so it wins ties on equal
   specificity. */
.btn-primary i, .btn-gold i, .btn-photo-upload i, .confirm-ok i,
.admin-menu-toggle i, .admin-drawer-close i, .user-circle i,
.account-trigger-btn i, .account-popover-switch i, #mobileLogoutBtn i, #sidebarLogoutBtn i,
.admin-nav-pill[aria-current="page"] i {
  color: inherit;
}


/* Round avatar-style icon used on the logout buttons (sidebar + mobile
   header) in renderAdminShell() — see js/utils.js. */
.user-circle {
  width: 30px;
  height: 30px;
  background-color: #e0e0e0;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  flex-shrink: 0;
  overflow: hidden;
}
/* Swapped in for the 👤 placeholder when the signed-in account has a
   photoUrl on their /users/{uid} profile — see currentAccountPhoto() /
   setupAccountPopover() in js/utils.js. Fills the same circle exactly. */
.user-circle img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}

/* Compact student-photo chip for ledger/roster table rows — see
   studentAvatarHtml() in js/utils.js. Sits inline right before the
   student's name so a row is recognizable at a glance without
   throwing off the table's row height or the name column's alignment. */
.ledger-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  min-width: 22px;
  border-radius: 50%;
  background-color: #e0e0e0;
  overflow: hidden;
  vertical-align: middle;
  margin-right: 6px;
  font-size: 11px;
}
.ledger-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
}
.ledger-avatar i { color: inherit; }

/* Small icon buttons for the Manage Teachers row actions — "Email reset
   link" (js-send-reset) and "Set new password" (js-set-password). Kept
   visually distinct from .btn-primary/.confirm-ok's rounded pill look
   since these sit inline among plain text links in the row's action
   cell (see renderTeacherRows() in js/admin-teachers.js). */
.row-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  border: 1.5px solid var(--border);
  background: var(--cream);
  color: var(--ink);
  cursor: pointer;
  font-size: 12px;
  margin-left: 0.35rem;
  vertical-align: middle;
}
.row-icon-btn:hover { background: var(--border); }
.row-icon-btn i { color: inherit; }
.row-icon-btn.js-set-password { color: var(--gold-dark); border-color: var(--gold); }

/* Manage Teachers row — "Assign Subjects" / "Assign Class Teacher".
   Colored + iconed instead of plain underlined text, so they read as
   distinct actions rather than more "edit" links next to the row's one
   real Edit button. --internal (blue) and --gold-dark reuse the app's
   existing palette rather than introducing new colors. */
.row-action-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.6rem;
  border-radius: 6px;
  font-size: 0.72rem;
  font-weight: 600;
  text-decoration: none;
  margin-left: 0.35rem;
  vertical-align: middle;
  white-space: nowrap;
}
.row-action-link i { font-size: 0.72rem; }
.row-action-subjects { color: var(--internal); background: rgba(26,61,124,0.09); }
.row-action-subjects:hover { background: rgba(26,61,124,0.18); }
.row-action-classteacher { color: var(--gold-dark); background: rgba(232,163,61,0.16); }
.row-action-classteacher:hover { background: rgba(232,163,61,0.26); }

/* Manage Teachers row — Mobile/WhatsApp/Viber/Messenger quick-contact
   icons (js/admin-teachers.js renderTeacherTable(), via
   teacherMessageLink()). Each icon's color/background come inline per
   platform (same brand colors as EMIS_INFO_FIELDS); .is-disabled marks a
   platform with no usable number, so it renders greyed-out and inert. */
.comm-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  margin-right: 0.3rem;
  vertical-align: middle;
  text-decoration: none;
  font-size: 0.78rem;
}
.comm-icon-btn:hover { filter: brightness(0.92); }
.comm-icon-btn.is-disabled { opacity: 0.32; color: var(--muted); background: var(--cream); cursor: default; }

/* Manage Teachers table only (.teacher-ledger, not the shared
   .ledger-name-col floor other tables like Manage Students rely on) —
   Name should hug the longest name actually on screen instead of always
   reserving 11rem, now that Actions carries far more (communication
   icons + Edit + Assign links) and needs the room instead. */
.teacher-ledger td.ledger-name-col {
  min-width: 0;
  width: 1%;
  white-space: nowrap;
}

/* Edit Teacher modal's small pill-style buttons.
   .quick-reset / .quick-setpw: "Reset Email" / "Set Password" — sit in the
   modal's footer, grouped with Delete (see .record-edit-actions-danger
   below). See js/admin-teachers.js's openTeacherEditModal()/
   teacherEditSendResetBtn/teacherEditSetPasswordBtn. */
.record-edit-quick-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.8rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  border: 1.5px solid var(--border);
  background: var(--cream);
  cursor: pointer;
  text-decoration: none;
}
.record-edit-quick-btn:hover { background: var(--border); }
.record-edit-quick-btn:disabled { opacity: 0.6; cursor: default; }
.record-edit-quick-btn.quick-reset { color: var(--ink); border-color: var(--ink-light); }
.record-edit-quick-btn.quick-setpw { color: var(--gold-dark); border-color: var(--gold); }

/* ---- Teacher EMIS record (Edit Teacher → Personal Information, and the
   Self Edit Profile modal's Profile tab) ------------------------------
   Print layout for the EMIS profile printout — deliberately its own boxed
   label:value grid (NOT the .ledger table styles the rest of the app's
   print pages use) since this mirrors the source government EMIS
   "Teacher Information" printout's own look: bordered section cards, each
   field a stacked label-over-value pair. showPrintPreview() (utils.js)
   injects the print body into the page's own DOM, so these rules apply
   to it directly. */
.emis-print-section { margin-bottom: 14px; }
.emis-print-section-title {
  text-align: center; font-weight: 700; font-size: 0.8rem; letter-spacing: 0.03em;
  background: var(--cream); border: 1px solid var(--border); border-bottom: none;
  padding: 4px 0; text-transform: uppercase;
}
.emis-print-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0;
  border: 1px solid var(--border);
}
.emis-print-field {
  padding: 5px 10px; border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
  font-size: 0.74rem;
}
.emis-print-grid .emis-print-field:nth-child(3n) { border-right: none; }
.emis-print-field-label { font-weight: 700; color: var(--ink); }
.emis-print-row-card { border: 1px solid var(--border); border-top: none; }
.emis-print-row-card:first-of-type { border-top: 1px solid var(--border); }
.emis-print-empty { padding: 10px; text-align: center; font-size: 0.78rem; color: var(--muted); border: 1px solid var(--border); }

/* On-screen editable repeating rows (Qualification/Experience/Training) */
.emis-row-card { position: relative; border: 1px solid var(--border); border-radius: 10px; padding: 0.9rem; margin-bottom: 0.6rem; background: white; }
.emis-row-remove { position: absolute; top: 0.6rem; right: 0.6rem; }
.emis-group-title { font-size: 0.78rem; font-weight: 700; color: var(--ink); margin: 1rem 0 0.5rem; }
.emis-group-title:first-child { margin-top: 0; }

/* ---- View Profile modal (account popover → View Profile; js/utils.js) ---- */
.vp-head { display: flex; align-items: center; gap: 0.9rem; margin-bottom: 0.4rem; }
.vp-avatar {
  width: 4rem; height: 4rem; border-radius: 999px; object-fit: cover; flex-shrink: 0;
  border: 2px solid var(--border); background: var(--cream);
  display: flex; align-items: center; justify-content: center; font-size: 1.5rem; color: var(--muted);
}
.vp-section-title {
  font-size: 0.78rem; font-weight: 700; color: var(--ink); text-transform: uppercase; letter-spacing: 0.03em;
  margin: 1.2rem 0 0.6rem; padding-bottom: 0.3rem; border-bottom: 1px solid var(--border);
}
.vp-subtitle { font-size: 0.74rem; font-weight: 700; color: var(--ink-light, var(--ink)); margin: 0.8rem 0 0.4rem; }
.vp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr)); gap: 0.6rem 0.9rem; }
.vp-label { font-size: 0.68rem; color: var(--muted); font-weight: 600; }
.vp-value { font-size: 0.85rem; color: var(--ink); word-break: break-word; }
.vp-card { border: 1px solid var(--border); border-radius: 0.6rem; padding: 0.7rem; margin-bottom: 0.5rem; background: #fff; }
.vp-doc {
  display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap;
  border: 1px solid var(--border); border-radius: 0.6rem; padding: 0.55rem 0.7rem; margin-bottom: 0.5rem; background: #fff;
}
.vp-doc-thumb {
  width: 3rem; height: 3rem; object-fit: cover; border-radius: 0.4rem; flex-shrink: 0;
  border: 1px solid var(--border); background: var(--cream);
}
.vp-doc-thumb-file { display: flex; align-items: center; justify-content: center; color: var(--muted); font-size: 1.2rem; }
.vp-doc-info { flex: 1; min-width: 8rem; }
.vp-doc-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.vp-doc-actions a { text-decoration: none; display: inline-flex; align-items: center; gap: 0.3rem; }

/* Desktop's account icon button — top-right of the page header (see
   renderAdminShell() in js/utils.js), just the circle icon with no extra
   chrome since the white header bar already provides the contrast. */
.account-trigger-btn {
  background: transparent;
  border: none;
  padding: 0;
  line-height: 0;
  cursor: pointer;
}

/* Account popover — opens under the 👤 logout icon (see
   setupAccountPopover() in js/utils.js). Shows who's signed in and holds
   the actual "Log out" action, so a click on the icon itself never signs
   anyone out by accident. */
.account-popover {
  position: absolute;
  z-index: 40;
  min-width: 200px;
  background: #fff;
  color: var(--ink);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  padding: 0.75rem;
}
/* Both the desktop header's account icon and the mobile header's sit at
   the top of the page (top-right corner), so both popovers open
   downward, right-aligned under the icon. account-popover-up is kept for
   any future spot where the trigger sits at the bottom of the screen. */
.account-popover-up { bottom: calc(100% + 8px); left: 0; }
/* पृष्ठको माथिको header (desktop/mobile) — account popover (Switch view · Log out) यहीभित्र खुल्छ। header लाई
   आफ्नै stacking layer दिइएको छ ताकि तलको सामग्री (ट्याब, कार्ड, sticky तत्व) ले popover नढाकोस्, र
   overflow:hidden भएका header (जस्तै Teachers को .tp-hero) ले पनि यसलाई नकाटोस्। */
.admin-shell-header { position: relative; z-index: 60; overflow: visible; }
.admin-shell-header .account-popover { z-index: 70; }
.account-popover-down { top: calc(100% + 8px); right: 0; }
.account-popover-name {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0.5rem;
  word-break: break-word;
}
.account-popover-logout {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
  background: var(--error, #c0392b);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 600;
}
.account-popover-logout:hover { opacity: 0.9; }

/* "Edit Profile" — sits in the account popover just above "Log out" (see
   renderAdminShell()'s sidebar/mobile popover markup and
   ensureSelfProfileModal() in js/utils.js), on every teacher AND admin
   page since they all share this one popover. Kept visually distinct from
   the red account-popover-logout button below it — this isn't
   destructive. */
.account-popover-editprofile {
  width: 100%;
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
  background: var(--cream);
  border: 1.5px solid var(--border);
  color: var(--ink);
  font-size: 0.8rem;
  font-weight: 600;
  margin-bottom: 0.4rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.account-popover-editprofile:hover { background: var(--border); }

/* Self Edit Profile modal (js/utils.js: ensureSelfProfileModal()) — reuses
   .record-edit-* (originally Manage Teachers/Manage Students' record
   editor) since the layout need is identical; adds its own password
   sub-section below. */
.self-profile-password-note {
  font-size: 0.75rem;
  color: var(--muted);
  margin: -0.5rem 0 0.75rem;
}

/* "Switch to Teacher View" / "Switch back to Admin View" — lives inside
   the account popover (see renderImpersonationControls() in js/utils.js),
   right between the "Signed in as…" line and Log out, so both account
   actions open from the same profile-circle click on both breakpoints.
   The popover itself is white on both breakpoints, so one style covers
   desktop and mobile. Given its own gradient + icon chip (rather than the
   plain gold-outline look) so it reads as a distinct, inviting action
   next to the plain white popover and the solid red Log out button. */
.account-popover-switch {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem 0.75rem;
  border-radius: 10px;
  border: none;
  background: linear-gradient(135deg, var(--gold) 0%, var(--gold-dark) 100%);
  color: #fff;
  font-size: 0.8rem;
  font-weight: 700;
  margin-bottom: 0.5rem;
  text-align: center;
  box-shadow: 0 3px 10px rgba(200, 129, 31, 0.35);
  transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
}
.account-popover-switch:hover { filter: brightness(1.06); box-shadow: 0 5px 14px rgba(200, 129, 31, 0.45); transform: translateY(-1px); }
.account-popover-switch:active { transform: translateY(0); box-shadow: 0 2px 6px rgba(200, 129, 31, 0.35); }
.account-popover-switch-icon { font-size: 0.95rem; line-height: 1; }
/* "Switch back to Admin View" — a cooler blue gradient so leaving Teacher
   View reads visually distinct from entering it. */
.account-popover-switch--admin {
  background: linear-gradient(135deg, var(--ink-light) 0%, var(--ink) 100%);
  box-shadow: 0 3px 10px rgba(27, 42, 74, 0.35);
}
.account-popover-switch--admin:hover { box-shadow: 0 5px 14px rgba(27, 42, 74, 0.45); }
.account-popover-switch--admin:active { box-shadow: 0 2px 6px rgba(27, 42, 74, 0.35); }

/* Persistent banner shown across the top of every page while an admin is
   previewing the Teacher view — a constant visual reminder they haven't
   actually left their admin session (see renderImpersonationControls()). */
.impersonation-banner {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--gold-dark);
  color: #fff;
  text-align: center;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.45rem 0.75rem;
}
.impersonation-banner-link {
  text-decoration: underline;
  font-weight: 700;
  color: #fff;
}

/* ---- Logout confirmation modal ("Confirm Logout") ----
   Opened by the account popover's "Log out" button instead of signing out
   immediately — see ensureLogoutConfirmModal()/openLogoutConfirmModal()
   in js/utils.js. Same overlay+box convention as .pdf-progress-overlay
   above. */
.confirm-modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(27, 42, 74, 0.55);
  z-index: 10001;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.confirm-modal-overlay.open { display: flex; }
/* लामो फारम (जस्तै दाता/प्रायोजक थप्ने) भए align-items:center ले बक्सको माथिल्लो भाग
   स्क्रिनबाहिर पुगेर scroll गर्नै नमिल्ने भएको थियो। overlay लाई आफैँ scroll हुने बनाइयो र
   बक्समा margin:auto दिइयो — छोटो भए बीचमा, लामो भए माथिबाट सुरु भई scroll हुन्छ। */
.confirm-modal-overlay {
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.confirm-modal-overlay > .confirm-modal-box { margin: auto; }
.confirm-modal-box {
  background: #fff;
  border-radius: 0.75rem;
  padding: 1.5rem;
  max-width: 22rem;
  width: 100%;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
}
.confirm-modal-title {
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--ink);
  margin-bottom: 0.5rem;
}
.confirm-modal-message {
  font-size: 0.88rem;
  color: var(--muted);
  margin-bottom: 1.25rem;
}
/* ---- Take Photo camera capture modal ----
   Same overlay+box convention as .confirm-modal-overlay above — see
   openCameraCapture_()/ensureCameraCaptureModal_() in js/utils.js. */
.camera-capture-box {
  max-width: 26rem;
}
.camera-capture-video {
  width: 100%;
  max-height: 60vh;
  border-radius: 0.5rem;
  background: #000;
  display: block;
  margin-bottom: 0.75rem;
  /* Mirror the preview like a normal front-camera/webcam app — capture
     itself is unaffected since we draw from the raw video track, not
     this CSS transform. */
  transform: scaleX(-1);
}
.camera-capture-error {
  font-size: 0.82rem;
  color: var(--danger, #b3261e);
  margin-bottom: 0.75rem;
}
.confirm-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
}
.btn-cancel {
  padding: 0.5rem 1rem;
  border-radius: 8px;
  border: 1.5px solid var(--border);
  background: #fff;
  color: var(--ink);
  font-size: 0.8rem;
  font-weight: 600;
}
.btn-cancel:hover { background: var(--cream, #fbf9f4); border-color: var(--gold); }

/* ---- "कार्यसमितिसँग सम्पर्क" popup — teacher bottom-nav's म्यासेज ट्याब ----
   Opened by openTeacherContactModal() in js/utils.js (see .tbn-messages-trigger
   delegated click handler there). Same overlay+box convention as
   .confirm-modal-overlay above, just wider/taller since it holds a search
   box + scrollable name list. Row layout (.tc-row/.tc-who/.tc-icons) and
   the name/role text mirror principal-desk.html's "कार्यसमितिसँग अन्तरक्रिया"
   tab (see pdInteractRowHtml_() in js/principal-desk.js) so the same list
   looks the same wherever it appears; .comm-icon-btn/.user-circle above
   are the same shared classes that tab already uses. */
.tc-modal-box {
  max-width: 30rem;
  max-height: 82vh;
  display: flex;
  flex-direction: column;
}
.tc-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}
.tc-modal-close {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: none;
  background: var(--cream);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  font-size: 0.85rem;
}
.tc-modal-close:hover { background: var(--border); }
.tc-modal-list { overflow-y: auto; flex: 1; margin: 0 -0.25rem; padding: 0 0.25rem; }
.tc-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
  padding: 0.6rem 0.1rem;
  border-bottom: 1px solid var(--border);
}
.tc-row:last-child { border-bottom: none; }
.tc-who { display: flex; align-items: center; gap: 0.6rem; min-width: 10rem; }
.tc-name { font-size: 0.85rem; font-weight: 600; color: var(--ink); }
.tc-role { font-size: 0.7rem; color: var(--muted); }
.tc-icons { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; }
.tc-status { text-align: center; padding: 1.5rem 0.5rem; font-size: 0.85rem; color: var(--muted); }
.tc-status i { margin-right: 0.35rem; }
.tc-status.tc-error { color: var(--danger, #b3261e); }

/* ---- "सूचना" popup — teacher bottom-nav's सूचना ट्याब ----
   Opened by openNotificationModal() in js/utils.js (see .tbn-notifications-trigger
   delegated click handler there). Reuses .tc-modal-box/.tc-modal-head/
   .tc-modal-close/.tc-modal-list/.tc-status above (same overlay+box
   convention as .confirm-modal-overlay); .ntf-row is its own row layout
   (a full-width tappable button, unlike .tc-row's two-column layout, since
   each row just opens one notice's letterpad preview). */
.ntf-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  width: 100%;
  padding: 0.7rem 0.35rem;
  border: none;
  border-bottom: 1px solid var(--border);
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.ntf-row:last-child { border-bottom: none; }
.ntf-row:hover, .ntf-row:focus-visible { background: var(--cream, #fbf9f4); }
.ntf-row-main { min-width: 0; }
.ntf-title { font-size: 0.85rem; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.ntf-meta { font-size: 0.72rem; color: var(--muted); margin-top: 0.1rem; }
.ntf-row-chevron { color: var(--muted); flex-shrink: 0; font-size: 0.75rem; }


/* ---- लेखा सङ्केत — व्याख्या popup (Inventory > लेखा सङ्केत सूची ट्याब) ----
   Reuses the .confirm-modal-overlay/.confirm-modal-box overlay convention
   above so it matches the app's existing modal look; the extra rules below
   are scoped to .code-explain-* only and do not touch any other modal. See
   wireCodesReference()/openCodeExplainModal() in js/inventory.js. */
.code-explain-overlay { z-index: 10002; }
.code-explain-box {
  position: relative;
  max-width: 32rem;
  max-height: 80vh;
  overflow-y: auto;
}
.code-explain-close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  border: none;
  background: var(--cream, #fbf9f4);
  color: var(--muted);
  font-size: 0.9rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.code-explain-close:hover { background: var(--border); color: var(--ink); }
.code-explain-code {
  display: inline-block;
  font-family: var(--font-mono, monospace);
  font-weight: 700;
  font-size: 0.78rem;
  color: #fff;
  background: var(--gold, #b08d3f);
  border-radius: 999px;
  padding: 0.15rem 0.75rem;
  margin-bottom: 0.5rem;
}
.code-explain-text {
  font-size: 0.88rem;
  line-height: 1.65;
  color: var(--ink);
  white-space: pre-line;
}
.codes-clickable-row { cursor: pointer; }
.codes-clickable-row:hover td { background: var(--cream, #fbf9f4); }

/* Destructive action inside a record-edit panel's footer (e.g. "Delete
   Teacher" in Manage Teachers' Edit modal) — sits opposite Cancel/Save via
   margin-right:auto so .record-edit-actions' own layout (flex, justify-end)
   doesn't need to change for pages that don't use it. */
.btn-delete {
  padding: 0.6rem 1.1rem;
  border-radius: 8px;
  border: 1.5px solid var(--error);
  background: #fff;
  color: var(--error);
  font-size: 0.8rem;
  font-weight: 600;
  margin-right: auto;
}
.btn-delete:hover { background: var(--error); color: #fff; }

/* ---- Dedicated record-edit panel ("Edit Student" / "Edit Teacher") ----
   Replaces the old plain per-cell row editing on Manage Students / Manage
   Teachers with one auto-responsive modal shared by both pages (see
   js/admin-students.js and js/admin-teachers.js — each just fills in its
   own fields). Same overlay/open convention as .confirm-modal-overlay
   above. Entirely separate from Bulk Import/Export, which never touches
   this component. */
.record-edit-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(27, 42, 74, 0.55);
  z-index: 10001;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.record-edit-overlay.open { display: flex; }
.record-edit-box {
  background: #fff;
  border-radius: 0.75rem;
  width: 100%;
  max-width: 40rem;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
  overflow: hidden;
}
.record-edit-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.record-edit-close {
  font-size: 1.1rem;
  line-height: 1;
  color: var(--muted);
  padding: 0.25rem 0.5rem;
  border-radius: 6px;
}
.record-edit-close:hover { background: var(--cream, #fbf9f4); color: var(--ink); }
.record-edit-body {
  padding: 1.25rem;
  overflow-y: auto;
}
/* Shared underline-style tabs for any record-edit-box modal — used by the
   Self Edit Profile modal's EMIS Profile/Account tabs (see
   ensureSelfProfileModal() in js/utils.js) AND Manage Teachers' Edit
   Teacher modal's Personal Information/Portal Setting tabs (see
   admin-teachers.html + js/admin-teachers.js's showTeacherEditTab()).
   Plain underline tabs, not full boxed pills, so they read as one view
   split in two rather than competing with the record-edit-* buttons
   below. */
.record-edit-tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1.5px solid var(--border);
  margin-bottom: 1.1rem;
  /* Four tabs (Personal Information / Communication / Documents / Account)
     don't fit a phone width — scroll sideways instead of wrapping. */
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
}
.record-edit-tabs::-webkit-scrollbar { display: none; }
.record-edit-tab-btn {
  padding: 0.55rem 0.2rem;
  margin-right: 1.1rem;
  border-bottom: 2.5px solid transparent;
  background: none;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.record-edit-tab-btn.active { color: var(--ink); border-bottom-color: var(--gold); }
.record-edit-tab-panel {}
.record-edit-subheading {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin: 1.25rem 0 0.75rem;
}
/* Auto-responsive field grid — as many columns as comfortably fit at
   >=11rem each, collapsing to a single column on narrow viewports,
   with no separate mobile media query needed. */
.record-edit-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.9rem;
}
.record-edit-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.8rem;
}
.record-edit-field > span {
  color: var(--muted);
  font-weight: 600;
}
.record-edit-field-wide { grid-column: 1 / -1; }
/* A checkbox row within the Day Editor (Holiday / School program) —
   see saveDayEditor() in js/admin-academic-calendar.js for why this
   spacing matters: the checkbox and the field right after it used to
   sit close enough together that an accidental tap on a small screen
   could untick it without the person noticing, right before Save. */
.record-edit-checkbox-row {
  flex-direction: row;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.25rem;
  margin: 0.15rem 0;
  cursor: pointer;
}
.record-edit-checkbox-row span { color: var(--ink); font-weight: 700; font-size: 0.85rem; }
.record-edit-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 0.6rem;
  padding: 1rem 1.25rem;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
}
/* Groups the footer into two clusters: sensitive/account actions (Delete,
   Reset Email, Set Password) on the left, and the normal Cancel/Save pair
   on the right — see admin-teachers.html's Edit Teacher modal. Pushed left
   via margin-right:auto on the group itself (rather than relying on
   .btn-delete's own margin) so Delete/Reset Email/Set Password stay
   visually grouped together instead of Delete alone splitting away from
   the other two. */
.record-edit-actions-danger {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-right: auto;
}
.record-edit-actions-danger .btn-delete { margin-right: 0; }
.record-edit-actions-main {
  display: flex;
  gap: 0.6rem;
}
/* Student's Leave Record — "Follow Up" popup (js/admin-students.js's
   openLeaveFollowUpPopup_()): one row per contact platform (Call/SMS/
   WhatsApp/Viber/IMO/Messenger), stacked instead of the small icon-only
   buttons the table row used to show, since there's a whole popup's width
   to use instead of a cramped Action column. */
.lv-fu-grid {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.lv-fu-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 0.5rem;
  font-size: 0.85rem;
  color: var(--ink);
  background: #fff;
  text-align: left;
  width: 100%;
  cursor: pointer;
}
a.lv-fu-row,
a.lv-fu-row:visited { color: var(--ink); text-decoration: none; }
button.lv-fu-row { font: inherit; }
span.lv-fu-row { cursor: default; }
.lv-fu-row:not(span):hover { background: var(--cream, #fbf9f4); }
/* Follow Up popup (openLeaveFollowUpPopup_()/openLockerFollowUpPopup_() in
   js/admin-students.js) — kept compact by default (matches the old inline
   max-width:24rem) but given real breathing room on desktop/tablet-width
   screens, where a floating 24rem card looked cramped next to the rest of
   the page. Mobile keeps the same 24rem cap it always had (the bottom-sheet
   @media rule below still forces full width under 640px regardless). */
.lv-fu-box { max-width: 24rem; }
@media (min-width: 641px) {
  .lv-fu-box { max-width: 34rem; }
}
/* On narrow/mobile viewports the panel becomes a full-height bottom sheet
   instead of a floating centered card, so the field grid gets the whole
   screen to breathe and the on-screen keyboard doesn't fight it for
   space. */
@media (max-width: 640px) {
  .record-edit-overlay { padding: 0; align-items: flex-end; }
  .record-edit-box {
    max-width: 100%;
    max-height: 92vh;
    border-radius: 1rem 1rem 0 0;
  }
  .record-edit-actions { flex-direction: column-reverse; }
  .record-edit-actions .btn-cancel,
  .record-edit-actions .btn-primary { width: 100%; text-align: center; }
  /* Cancel/Save (.record-edit-actions-main) render first since
     column-reverse flips the DOM order — the primary actions stay on top,
     the sensitive/account cluster sits below it. */
  .record-edit-actions-danger { width: 100%; margin-right: 0; justify-content: center; }
  .record-edit-actions-main { width: 100%; }
}

/* ---- Single-image upload box ("Photo" on Manage Students, "Signature
   URL" on Manage Teachers — anything with class="js-image-url", see
   enhanceImageUrlFields() in js/utils.js) ----
   Everything the widget needs — thumbnail, host picker, Choose/Upload
   buttons, filename, status line — sits inside one outlined box instead
   of a loose row of controls, so it visually reads as a single
   self-contained "upload one image here" unit rather than a scattered
   set of buttons next to the URL field. */
.image-upload-box {
  border: 1.5px solid var(--border);
  border-radius: 10px;
  padding: 0.65rem 0.75rem;
  background: var(--cream, #fbf9f4);
}
.image-upload-box-main {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
}
/* The thumbnail is the visual anchor of the box — deliberately sized and
   bordered like a single photo slot (not a gallery/multi-file dropzone)
   to signal this field holds exactly one image. */
.image-upload-thumb {
  width: 3.25rem;
  height: 3.25rem;
  min-width: 3.25rem;
  object-fit: cover;
  border-radius: 8px;
  border: 1.5px solid var(--border);
  background: #fff;
  flex-shrink: 0;
}
.image-upload-controls {
  display: grid;
  /* Two columns, sized to whichever item in that column is widest
     (grid's default track sizing) — this is what makes the host-picker
     pill above line up with the Choose/Scan box below it, and the Photo
     button line up with Upload, instead of each row sizing itself
     independently. */
  grid-template-columns: auto auto;
  justify-content: start;
  row-gap: 0.4rem;
  column-gap: 0.5rem;
  flex: 1;
  min-width: 12rem;
}
/* The host picker's visible "box" — icon + <select> together — rather
   than the bare <select> alone, so the cloud icon reads as part of the
   same control. Grid items stretch to fill their column by default, so
   this pill automatically widens to match the Choose/Scan box beneath
   it instead of hugging its own short content. */
.image-upload-provider-wrap {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0 0.4rem;
  border-radius: 6px;
  /* Tinted (rather than plain white, like every other input) so the
     "which platform" picker visually reads as its own control, distinct
     from the action buttons beside/below it and from a regular text
     field. */
  background: #eef2fb;
  border: 1.5px solid #c7d2e8;
}
.image-upload-provider-wrap i {
  font-size: 0.7rem;
  color: var(--ink-light);
  flex-shrink: 0;
}
.image-upload-provider {
  flex: 1;
  min-width: 0;
  width: auto;
  padding: 0.28rem 0 0.28rem 0.1rem;
  font-size: 0.68rem;
  background: transparent;
  border: none;
  color: var(--ink-light);
}
.image-upload-provider:focus { outline: none; }
/* Choose/Scan grouped into one joined "segmented control" (the two
   no-consequence steps of picking a file), sitting in its own grid cell
   above — not joined to — the Upload button, which keeps its own full
   outline so the one action that actually sends the file to the host
   stays easy to pick out at a glance. */
.image-upload-choose-group {
  display: flex;
  border-radius: 6px;
  overflow: hidden;
  border: 1.5px solid var(--gold);
}
.image-upload-choose-group .btn-photo-choose {
  flex: 1;
  justify-content: center;
  border: none;
  border-radius: 0;
}
.image-upload-choose-group .btn-photo-choose:not(:last-child) {
  border-right: 1px solid rgba(0, 0, 0, 0.12);
}
/* Photo (row 1) and Upload (row 2) share the second column, so they
   also stretch to match whichever of the two is wider, and get their
   icon+label centered in the extra space. */
.image-upload-controls > .btn-photo-choose,
.image-upload-controls > .btn-photo-upload {
  justify-content: center;
}
/* Compact by design: every button here is small/icon-led rather than the
   app's normal comfortable button size — see .btn-primary/.btn-gold
   elsewhere for that. */
.btn-photo-choose,
.btn-photo-upload {
  display: inline-flex;
  align-items: center;
  gap: 0.28rem;
  padding: 0.28rem 0.5rem;
  border-radius: 6px;
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.15;
  white-space: nowrap;
}
.btn-photo-choose i,
.btn-photo-upload i {
  font-size: 0.7rem;
}
/* Choose / Scan / Photo — neutral "pick a file" steps, so they get the
   app's existing gold accent outline instead of reusing the plain
   .btn-cancel gray, which reads as a dismiss/cancel action rather than a
   first, harmless step. */
.btn-photo-choose {
  border: 1.5px solid var(--gold);
  background: #fff;
  color: var(--gold-dark);
}
.btn-photo-choose:hover { background: #fdf3e2; }
.btn-photo-choose:disabled { opacity: 0.5; }
/* Upload — the one action that actually sends the file, so it gets a
   distinct green "go" color instead of reusing the dark .btn-primary,
   which is already used for ordinary form submits elsewhere on the same
   page and would blend right in. */
.btn-photo-upload {
  border: 1.5px solid var(--success);
  background: var(--success);
  color: #fff;
}
.btn-photo-upload:hover { background: #35664d; }
.btn-photo-upload:disabled { opacity: 0.5; background: var(--success); }
.image-upload-box .js-photo-filename {
  grid-column: 1 / -1;
}
/* Real upload progress (via XHR upload.onprogress in uploadImageToHost)
   shown in place of a plain "Uploading…" line — a thin track the full
   width of the box, with a green fill (matches .btn-photo-upload's "go"
   color) that grows as bytes actually go out. */
.upload-progress {
  flex-basis: 100%;
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
  margin-top: 0.5rem;
}
.upload-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--success);
  border-radius: 999px;
  transition: width 0.15s ease;
}
.image-upload-box .js-photo-status:not(:empty) {
  display: block;
  margin-top: 0.4rem;
}
/* Shown instead of the thumbnail when the field has no image yet — same
   footprint as .image-upload-thumb so the box doesn't jump size once a
   photo/signature is actually set. */
.image-upload-placeholder {
  width: 3.25rem;
  height: 3.25rem;
  min-width: 3.25rem;
  border-radius: 8px;
  border: 1.5px dashed var(--border);
  background: #fff;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 0.55rem;
  line-height: 1.1;
  text-align: center;
  gap: 0.15rem;
}
.image-upload-placeholder i { font-size: 0.9rem; }
/* Signature preview specifically needs a checkered backdrop — a plain
   white thumb can't show whether the PNG's background is actually
   transparent or just white, which is the one thing that matters for a
   signature that'll be stamped onto other documents. */
.js-image-url-signature .image-upload-thumb,
.js-image-url-signature .image-upload-placeholder {
  background-image: linear-gradient(45deg, #ddd 25%, transparent 25%), linear-gradient(-45deg, #ddd 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ddd 75%), linear-gradient(-45deg, transparent 75%, #ddd 75%);
  background-size: 10px 10px;
  background-position: 0 0, 0 5px, 5px -5px, -5px 0px;
}
.image-upload-help {
  flex-basis: 100%;
  margin-top: 0.5rem;
  font-size: 0.7rem;
  line-height: 1.4;
  color: var(--muted);
}
.image-upload-help a { color: var(--internal); text-decoration: underline; }

/* ---- Grade Summary card — a small, compact table (Class / Graded / NG /
   NG %) that sits inline in the page content (see admin.html, just below
   the Marks Entry Status card), not a large full-width ledger-style
   table. ---- */
.gradesum-scroll {
  max-width: 100%;
  overflow-x: auto;
}
.gradesum-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.72rem;
  background: #0F172A; /* charcoal slate — enterprise dark theme */
}
/* Full grid borders on every cell — matches the Marks Entry Status
   matrix table (.ledger) just above this card, instead of the old
   bottom-border-only rule rows used to have. */
.gradesum-table th, .gradesum-table td {
  padding: 0.35rem 0.5rem;
  text-align: center;
  border: 1px solid #1E293B;
  white-space: nowrap;
  color: #F8FAFC;
}
.gradesum-table th:first-child, .gradesum-table td:first-child {
  text-align: left;
  font-weight: 600;
  color: #F8FAFC;
  position: sticky;
  left: 0;
  background: #1E293B;
}
.gradesum-table th {
  font-size: 0.62rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #94A3B8;
  font-weight: 700;
  background: #1E293B;
}
.gradesum-table th:first-child { background: #1E293B; }

/* Graded/Graded % rows banded emerald, Non Graded/NG % rows banded amber —
   each pair reads as one group at a glance instead of four look-alike
   rows. The :first-child rules win over the sticky label column's own
   background above by matching on the same (higher-specificity)
   selector, so the label cell is tinted too. */
.gradesum-table tr.gsum-row-graded td { background: rgba(16, 185, 129, 0.16); color: #34D399; font-weight: 700; }
.gradesum-table tr.gsum-row-graded td:first-child { background: rgba(16, 185, 129, 0.22); color: #34D399; }
.gradesum-table tr.gsum-row-ng td { background: rgba(245, 158, 11, 0.16); color: #FBBF24; font-weight: 700; }
.gradesum-table tr.gsum-row-ng td:first-child { background: rgba(245, 158, 11, 0.22); color: #FBBF24; }

.gradesum-table tbody tr:hover td { background: #1E293B; }
.gradesum-table tbody tr:hover td:first-child { background: #29374d; }

/* ---- ई-हाजिरी सारांश (principal-desk.html) — gradesum-table कै आधारभूत
   ढाँचा (sticky first column, collapse) पाउँछ, तर एकसमान dark-black ब्याकग्राउन्डको
   सट्टा हरेक कक्षा-कोलमलाई छुट्टाछुट्टै रंग दिइन्छ (छिटो स्क्यान गर्न सजिलो हुन), र
   ग्रिड-लाइनहरू सुनौलो (gold) रंगले चम्किलो बनाइएको। रङहरू १२ वटासम्म (Nursery,
   KG, कक्षा १-१०) पालैपालो दोहोरिन्छन् — .pd-attsum-table मात्र असर गर्छ, अरू
   gradesum-table प्रयोग हुने ठाउँ (जस्तै Grade Summary widget) जस्ताको त्यस्तै रहन्छ। */
.pd-attsum-table th, .pd-attsum-table td {
  border: 1.5px solid var(--gold-dark, #c8811f);
}
.pd-attsum-table th:first-child, .pd-attsum-table td:first-child {
  border-right: 2px solid var(--gold, #e8a33d);
}
.pd-attsum-table th:nth-child(2),  .pd-attsum-table td:nth-child(2)  { background: #1e3a5f; }
.pd-attsum-table th:nth-child(3),  .pd-attsum-table td:nth-child(3)  { background: #1e4d3f; }
.pd-attsum-table th:nth-child(4),  .pd-attsum-table td:nth-child(4)  { background: #4d3319; }
.pd-attsum-table th:nth-child(5),  .pd-attsum-table td:nth-child(5)  { background: #4d1e3d; }
.pd-attsum-table th:nth-child(6),  .pd-attsum-table td:nth-child(6)  { background: #1e4d4d; }
.pd-attsum-table th:nth-child(7),  .pd-attsum-table td:nth-child(7)  { background: #3d1e4d; }
.pd-attsum-table th:nth-child(8),  .pd-attsum-table td:nth-child(8)  { background: #4d4d1e; }
.pd-attsum-table th:nth-child(9),  .pd-attsum-table td:nth-child(9)  { background: #4d1e1e; }
.pd-attsum-table th:nth-child(10), .pd-attsum-table td:nth-child(10) { background: #1e2f4d; }
.pd-attsum-table th:nth-child(11), .pd-attsum-table td:nth-child(11) { background: #2f4d1e; }
.pd-attsum-table th:nth-child(12), .pd-attsum-table td:nth-child(12) { background: #4d2f1e; }
.pd-attsum-table th:nth-child(13), .pd-attsum-table td:nth-child(13) { background: #1e4d2f; }
/* माथिका रंग १२ कोलमपछि दोहोरिने (१३औं कक्षा भए) */
.pd-attsum-table th:nth-child(14), .pd-attsum-table td:nth-child(14) { background: #1e3a5f; }
.pd-attsum-table th:nth-child(15), .pd-attsum-table td:nth-child(15) { background: #1e4d3f; }
.pd-attsum-table tbody tr:hover td:nth-child(n+2) { filter: brightness(1.25); }

/* ---- Completion status matrix ---- */
.status-cell {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 8px;
  font-size: 0.9rem;
  font-weight: 700;
}
.status-complete { background: rgba(63,122,92,0.15); color: var(--success); }
.status-partial { background: rgba(232,163,61,0.18); color: var(--gold-dark); }
.status-empty { background: rgba(193,68,60,0.12); color: var(--error); }
.status-na { background: transparent; color: var(--border); }

.stat-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 1.1rem 1.3rem;
}
.stat-card .stat-number {
  font-family: "Kalimati", "Poppins", "Nirmala UI", "Noto Sans Devanagari", sans-serif;
  font-size: 1.7rem;
  font-weight: 700;
  color: var(--ink);
}
.stat-card .stat-label {
  font-size: 0.75rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* ---- Print — Mark Ledger ---- */
.print-only { display: none; }

/* These render both in the on-screen print-preview modal AND in the
   actual printed page, so they're normal (non-@media) rules. */
.print-header-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  border-bottom: 2px solid #000;
  padding-bottom: 0.15rem;
  margin-bottom: 0.2rem;
}
.print-school-name {
  font-family: "Kalimati", "Poppins", "Nirmala UI", "Noto Sans Devanagari", sans-serif;
  font-weight: 700;
  font-size: 1.05rem;
  color: #000;
  line-height: 1.15;
}
.print-subtitle { font-weight: 700; font-size: 0.72rem; color: #333; line-height: 1.15; }
.print-exam-period {
  font-family: "Kalimati", "Poppins", "Nirmala UI", "Noto Sans Devanagari", sans-serif;
  font-weight: 700;
  font-size: 0.88rem;
  color: #000;
  margin-top: 0.15rem;
  line-height: 1.15;
}
/* Class (left) / Subject, underlined (center) / Printed date (right) —
   one row, three even columns via flex so the center item is truly
   centered on the page no matter how wide the left/right text is. */
.print-meta-row {
  display: flex;
  align-items: baseline;
  margin-bottom: 0.2rem;
}
.print-ledger-type {
  font-family: "Kalimati", "Poppins", "Nirmala UI", "Noto Sans Devanagari", sans-serif;
  font-weight: 700;
  font-size: 0.88rem;
  color: #000;
  margin-top: 0.15rem;
  line-height: 1.15;
}
/* कार्यसमितिको स्थायी सेवा अवधिको बिदा अभिलेख फारम (समष्टिगत तालिका + व्यक्तिगत
   फारम, दुवैको प्रिन्ट) — शीर्षकलाई फिक्का सादा background सहितको ribbon
   शैलीमा, ledgerTypeRibbon:true पास गरिएमा मात्र (buildPrintHeaderBlock,
   js/utils.js)। अरु सबै प्रिन्ट-पानाको शीर्षक यथावत् (.print-ledger-type मै)। */
.print-ledger-type-ribbon {
  display: inline-block;
  background: #f4f1ea;
  border: 1px solid #d8d2c2;
  border-radius: 999px;
  padding: 0.18rem 1.1rem;
  margin-top: 0.25rem;
}
.print-class-line,
.print-subject-line,
.print-date {
  flex: 1;
  margin: 0;
}
.print-class-line {
  font-weight: 700;
  font-size: 0.88rem;
  color: #000;
  text-align: left;
}
.print-subject-line {
  font-weight: 700;
  font-size: 0.88rem;
  color: #000;
  text-align: center;
}
.print-subject-line span {
  display: inline-block;
  border-bottom: 1px solid #000;
  padding: 0 0.15rem 0.1rem;
}
.print-date {
  font-size: 0.75rem;
  color: #333;
  text-align: right;
}
.print-signature-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.4rem 1.5rem;
  margin-top: 0.6rem;
  font-size: 0.78rem;
  color: #000;
}
/* Each signatory: signature mark, then their name (auto-filled from
   School Settings when saved there), then their post in parentheses — a
   standard three-line signature block instead of a single inline
   "Label: ____" row. */
.print-signature-block {
  text-align: center;
  min-width: 8rem;
}
.print-signature-block .sig-name {
  margin: 0;
  font-weight: 700;
  min-height: 1em;
}
.print-signature-block .sig-post {
  margin: 0.05rem 0 0;
  color: var(--muted);
  font-size: 0.72rem;
}

/* ---- Print — Leave Record Form (individual, "विदा अभिलेख फारम") — plain
   two-column field rows and inline dotted-fill blanks, matching the
   school's own paper form exactly (a plain letter, no grid/box borders).
   See pdLvRecBuildPrint_() (principal-desk.js).

   ONE shared two-column grid (.pd-lvrec-2col) for every paired-column
   block on this form — field rows, both signature rows, and the bottom
   रुजु/प्रमाणित pair — so the right-hand column always starts at the
   exact same x-position (grid-template-columns is fixed, unlike
   flex/space-between whose split point drifts with each side's own
   content width). ---- */
.pd-lvrec-2col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 2rem;
  row-gap: 0.1rem;
  font-size: 0.85rem;
  color: #000;
}
.pd-lvrec-2col + .pd-lvrec-2col { margin-top: 0.15rem; }
.pd-lvrec-line {
  margin: 0;
  font-size: 0.85rem;
  color: #000;
  line-height: 1.7;
}
/* Inline fill-in blank inside a running sentence (e.g. "...अवधि ..३४.. वर्ष").
   A fixed width (not min-width/padding-driven) so every blank on the page
   reads as the same length regardless of how short or long its value is —
   the value is centered on top of that fixed dotted stretch, so it lands
   in the middle rather than flush against the surrounding words. */
/* Dotted fill — drawn as a thin repeating background instead of a CSS
   "dotted" border. A border-style dotted line's dot size is tied to the
   border-width, and most print engines round/anti-alias a 1px border up
   into a chunky, uneven row of full-stop-like blobs; a flat, sub-1px
   background strip with a short, tight repeat prints as a genuinely
   thin, even line at any resolution instead. Width (7.5em/14em) is kept
   exactly as before — only the mark's own height/spacing is tuned finer. */
.pd-lvrec-fill {
  display: inline-block;
  width: 7.5em;
  background-image: linear-gradient(to right, #000 65%, transparent 0%);
  background-position: bottom;
  background-size: 3px 0.75px;
  background-repeat: repeat-x;
  text-align: center;
  font-weight: 700;
  margin: 0 0.15em;
  white-space: nowrap;
  padding-bottom: 1px;
}
.pd-lvrec-sig-fill {
  display: inline-block;
  width: 7.5em;
  background-image: linear-gradient(to right, #000 65%, transparent 0%);
  background-position: bottom;
  background-size: 3px 0.75px;
  background-repeat: repeat-x;
  margin-left: 0.4rem;
  text-align: center;
  padding-bottom: 1px;
}
/* नाम/दस्तखत — यी दुई सधैं अरू (पद/तह/मिति) भन्दा लामो लेख्नुपर्ने भएकाले
   (पूरा नाम/साँचो दस्तखतका लागि ठाउँ चाहिने), अरूकै सुरु-बिन्दुबाट सुरु भई
   अझ पर सम्म तानिने लामो fill। */
.pd-lvrec-sig-fill--long { width: 14em; }
/* .pd-lvrec-siglabel — केवल "रुजु गर्ने"/"प्रमाणित गर्ने" स्तम्भभित्रको पद/तह/
   दस्तखत/मिति (छोटा लेबल) लाई एउटै स्थिर चौडाइको बाकसमा राख्ने — ताकि लेबलको
   अक्षर-लम्बाइ जति भए पनि, अगाडिको dotted-fill सधैं ठ्याक्कै एउटै x-बिन्दुबाट
   सुरु होस् (हाल लेबल-पछि-सिधै-margin भएकाले सुरु-बिन्दु लेबलको लम्बाइ
   अनुसार अघि-पछि हुन्थ्यो)। नाम,थर: को लेबल यसमा नपर्ने (स्वाभाविक रूपमै लामो
   भएकाले फरक व्यवहार) — त्यसैले छुट्टै class। */
.pd-lvrec-siglabel {
  display: inline-block;
  width: 5em;
  white-space: nowrap;
}
.pd-lvrec-sigline { margin: 0.3rem 0; }
.pd-lvrec-bottom-col p { margin: 0.3rem 0; }
/* This form's own header tweaks — scoped to .pd-lvrec-print so the shared
   buildPrintHeaderBlock() (utils.js) used by every other printed ledger in
   the portal is untouched: no border line under the header here, the
   school-name line a touch bigger, the address subtitle a touch bigger too
   (so it doesn't look undersized next to the enlarged school name), a
   clear gap below the whole header block before the form's own fields
   begin, and no "Printed: <date>" meta row (this form is signed/dated by
   hand, not machine-timestamped). */
.pd-lvrec-print .print-header-row { border-bottom: none; padding-bottom: 0; margin-bottom: 0.9rem; }
.pd-lvrec-print .print-school-name { font-size: 1.2rem; }
.pd-lvrec-print .print-subtitle { font-size: 0.85rem; }
.pd-lvrec-print .print-meta-row { display: none; }

/* ---- Shared signature mark — used everywhere a person signs off on a
   printed document (Mark/Grade Ledger, Aptitude/Marks Entry, and the
   Gradesheet's Class Teacher / Prepared by / Exam Coordinator /
   Headmaster blocks). The dotted line is always drawn as the base "sign
   here" mark; when a digital signature image is on file it's layered
   over it rather than replacing it, so the printed page still shows
   where to sign by hand even with a digital signature attached. No
   image on file → dots only.

   The box is taller than the dotted line alone needs, and the dotted
   line sits partway down it (not at the very bottom) — this used to be
   a gradesheet-only override, but every signature field in the portal
   gets the same treatment now so an attached signature photo can
   render at a real, legible size and is free to cross over the dotted
   line above and below it, the way an actual pen signature does,
   instead of being squeezed flat on top of the line. */
.sig-mark {
  position: relative;
  width: 7rem;
  height: 2.1rem;
  margin: 0 auto 0.15rem;
}
.sig-mark-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.55rem;
  border-bottom: 1px dotted #000;
}
.sig-mark-img {
  position: absolute;
  left: 50%;
  bottom: 0.1rem;
  transform: translateX(-50%);
  max-height: 1.9rem;
  max-width: 6.8rem;
  object-fit: contain;
}

/* ---- Print — LO / Breakdown Mark Ledger: grouped subject headers ----
   NOTE: table-layout:fixed/width:100% used to be forced here to squeeze
   every column onto one screen without scrolling — but on a narrow
   mobile screen that just crushes/overlaps the text instead, since the
   table can never grow past 100% to fit its content. Grade Ledger (no
   ledger-lo) doesn't have this problem: in normal table-layout:auto, a
   table's declared width is only a *preference* — the browser still lets
   it grow past that to fit its content, and .table-scroll's
   overflow-x:auto then makes that overflow horizontally scrollable
   instead of squashed. Dropping table-layout:fixed here gives the Mark
   Ledger the same scrollable behavior. */
.ledger-lo { width: 100%; }
.ledger-lo th, .ledger-lo td {
  text-align: center;
  vertical-align: middle;
}
.ledger-lo .ledger-sn-col { width: 1.5rem; }
/* No forced width/wrap here anymore — a fixed 6rem column forced most
   student names onto 2-3 lines, which is exactly the "unnecessary
   height" the Grade Ledger doesn't have (its name column just sizes
   itself to the content). Letting this column size naturally, on one
   line, matches that same look; .ledger-lo's table-layout:auto (see
   note above) lets the column grow without upsetting the other
   columns, and .table-scroll's horizontal scroll covers the rare
   very-long name. */
.ledger-lo .ledger-name-col {
  white-space: nowrap;
  font-weight: 600;
}
.ledger-lo tbody td { color: var(--ink); font-weight: 600; }
.ledger-lo thead tr:first-child th {
  white-space: normal;
  word-break: break-word;
  line-height: 1.2;
  padding: 0.3rem 0.2rem;
}
.ledger-lo thead tr:last-child th {
  font-size: 0.68rem;
  padding: 0 0.15rem;
  /* Fixed height that comfortably fits the longest rotated label
     ("Obtained Learning Achievement" / "No. Of Learning Achievement")
     at this font-size. A rotate() transform never reflows layout height
     (unlike writing-mode), so leaving this height to "whatever the
     content needs" — the old approach — let long labels visually spill
     out of a too-short cell and overlap the subject-name row above.
     .rot-wrap below fills this fixed height and centers the rotated
     label inside it, so every column's label sits fully contained
     regardless of how long its text is. */
  height: 128px;
  vertical-align: bottom;
  text-align: center;
  line-height: 1.3;
  overflow: visible;
}
/* Fills the th's fixed height and centers the (still-unrotated, from a
   layout point of view) label both ways — a plain <div>, not the th
   itself, so flex centering never fights the table layout model the way
   display:flex directly on a <th> can. Rotating .rot-label in place after
   it's already centered keeps its visual footprint centered too, so a
   short label ("Total") and a long one ("Obtained Learning Achievement")
   both sit safely inside the same fixed-height cell without touching the
   row above or below. */
.ledger-lo thead tr:last-child th .rot-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
}
/* The actual bottom-to-top rotated label. Used to be writing-mode:
   vertical-rl + transform: rotate(180deg) directly on the <th> — visually
   fine on-screen, but html2canvas (the screenshot engine both the Page
   PDF and print-preview PDF export are built on) has long-standing bugs
   rendering vertical writing modes, which is what made these headers
   come out sideways/garbled/blank in an exported PDF while looking
   correct on the live page. A plain rotate transform on normal
   horizontal text is something html2canvas *does* render correctly, and
   looks identical: horizontal text rotated -90° reads bottom-to-top,
   same as the old vertical-rl+180° combo did. See loSubHeaderCells(),
   breakdownSubHeaderCells(), and buildWrittenOralLedgerTable() in
   admin-print-ledger.js, which wrap each subheader's text in this span. */
.ledger-lo thead tr:last-child th .rot-label {
  display: inline-block;
  white-space: nowrap;
  transform: rotate(-90deg);
  transform-origin: center;
}
/* S.N and Student Name stay upright even though they share the rotated
   header row structurally (rowspan across both header rows) — they never
   get a .rot-label span, so no override is needed here anymore. */
.ledger-lo thead .ledger-sn-col,
.ledger-lo thead .ledger-name-col {
  height: auto;
  vertical-align: middle;
  font-size: 0.68rem;
}

/* ---- Internal Form (Detailed) — rotated rubric-criterion headers ----
   Bottom-to-top rotated label for each individual evaluation criterion
   (Attendance, Creativity, Documentation, ...), so it reads in the same
   direction as the school's paper form while keeping columns narrow
   enough for every criterion to fit on one printed page. Applies to any
   header cell carrying .rot-th — both the leaf criterion row AND the
   rowspan-2 standalone columns (Practical & Project Total, Term Exam,
   Grand Total) that sit in the same row as the upright group headers —
   see renderDetailedTheadHtml() in js/internal-form-detailed.js.

   Uses writing-mode: vertical-rl (+ rotate(180deg) to read bottom-to-top
   instead of top-to-bottom), NOT transform: rotate() on horizontal text
   like .ledger-lo above. Two real, empirically-confirmed reasons this
   table needs the different technique despite .ledger-lo's long comment
   preferring rotate():
     1. .ledger-lo's rotate() approach relies on giving the (unrotated)
        label a fixed CSS width so wrapping keeps the rotated column
        narrow. But an element's `width` sizes it regardless of whatever
        transform is later applied to it — a fixed-width label sitting
        in NORMAL FLOW forces every one of this table's many rotated
        columns to reserve that same width in the table's auto-layout,
        which (confirmed by actually rendering it) starves the
        neighboring Roll/Student Name/Student ID columns down to almost
        nothing once enough rotated columns add up. Pulling the label
        out of flow with position:absolute avoids that — but:
     2. position:absolute inside a <th> turned out to not reliably use
        that <th> as its containing block during real Chromium print/PDF
        rendering (confirmed by actually printing it): every rotated
        label detached from its own cell and piled up in one spot near
        the middle of the page, completely different from the on-screen
        preview. This is exactly the "prints different from preview"
        failure — .ledger-lo's shorter, single-line labels never
        exercised this path, which is presumably why it wasn't caught
        there.
   writing-mode sidesteps both: it's real CSS layout (not a purely
   visual transform), so a wrapped vertical label's natural width really
   is just its wrapped-line thickness — no fixed width needed, nothing
   to pull out of flow, nothing that can detach from its cell. */
.ledger-rubric th.rot-th {
  height: 138px;
  vertical-align: bottom;
  text-align: center;
  padding: 0.1rem 0.05rem;
  overflow: hidden;
}
.ledger-rubric th.rot-th .rot-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
}
.ledger-rubric th.rot-th .rot-label {
  display: inline-block;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: normal;
  overflow-wrap: anywhere;
  /* max-height, not max-width: in vertical-rl the INLINE axis (the one
     a wrap boundary applies to) runs top-to-bottom, which maps to the
     physical height property, not width — this is what bounds how far
     down a single line runs before wrapping to a new one, turning a
     long label into more (horizontally stacked) lines rather than one
     line that runs off the bottom of the column. */
  max-height: 8rem;
  text-align: center;
  font-size: 0.66rem;
  line-height: 1.15;
}
/* Group headers (सहभागिता, प्रयोगात्मक र परियोजना कार्य, ...) span
   several leaf columns via colspan — letting a long group name wrap
   (rather than the base .ledger thead th's nowrap) means it simply
   flows onto 2-3 lines within whatever total width its own leaf columns
   already add up to, instead of forcing every one of them wider just to
   fit the group name on a single line. */
.ledger-rubric th.rubric-group-th {
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.2;
}

/* Roll / Student Name / Student ID carry no rotated content and (unlike
   every rotated column) no explicit width of their own — without a
   floor, table auto-layout can squeeze them down to almost nothing once
   the rotated columns' own widths add up, especially under a print
   page's fixed width (there's no .table-scroll horizontal-scroll escape
   hatch there like there is on screen), wrapping the student's name one
   letter per line. min-width, not width, so they still grow to use any
   spare room rather than staying pinned this narrow.
   Kept tight — these three are read-only roster labels, not rubric data
   competing for space, so every rem they don't need goes to the rotated
   criterion columns instead. */
.ledger-rubric .ledger-sn-col { min-width: 2.1rem; }
.ledger-rubric .ledger-name-col { min-width: 5.5rem; }
.ledger-rubric td.font-mono-data,
.ledger-rubric th.ledger-id-col { min-width: 4.2rem; }

/* Roll/Student Name/Student ID headers (see detailedRowLabels() in
   internal-form-detailed.js) are Nepali on every subject but English,
   and run longer than their English counterparts — letting them wrap
   onto their own rowspan=3 header, instead of .ledger thead th's
   default nowrap forcing a single wide line, is what keeps the tight
   min-widths above from getting overridden by the header text itself. */
.ledger-rubric thead th.ledger-sn-col,
.ledger-rubric thead th.ledger-name-col,
.ledger-rubric thead th.ledger-id-col {
  white-space: normal;
  overflow-wrap: anywhere;
  line-height: 1.15;
  padding-left: 0.35rem;
  padding-right: 0.35rem;
}

/* Row 3 — the plain, upright max-mark for every leaf/standalone column
   (see renderDetailedTheadHtml()'s row3 in internal-form-detailed.js).
   Sits directly under the rotated labels, exactly like the school's
   paper form, instead of being crammed as a second line inside the
   rotated label itself. */
.ledger-rubric .ledger-maxrow th {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.25rem 0.1rem;
  text-align: center;
  color: var(--ink);
}

/* Accent colors for the rubric's running-total columns — a group's own
   subtotal (any leaf column whose label says "जम्मा"/"Total", detected
   by content in isSubtotalLabel() since not every group ends in one),
   and the 3 fixed-role standalone columns (practical/project grand
   total, exam total, grand total — always in that order, see
   RUBRIC_TEMPLATES' header comment). Applied to both the rotated label
   and its row-3 mark so the whole column reads as one accented unit,
   matching the school's own color-coded paper form. */
/* The maxrow-cell color rules need !important: the print stylesheet
   (@media print .ledger thead th) forces color:#000 !important on every
   header cell including these, so a plain (non-!important) color here
   would be overridden and every total column would print black. The
   .rot-label rules don't need it — that span never has its own color
   set by the print rule (which targets the th, not its child), so an
   explicit child color always beats an inherited one regardless of
   !important on the parent. */
.ledger-rubric .rot-accent-subtotal .rot-label {
  color: #b45309;
}
.ledger-rubric th.ledger-maxrow-cell.rot-accent-subtotal {
  color: #b45309 !important;
}
.ledger-rubric .rot-accent-practical .rot-label {
  color: #15803d;
}
.ledger-rubric th.ledger-maxrow-cell.rot-accent-practical {
  color: #15803d !important;
}
.ledger-rubric .rot-accent-exam .rot-label {
  color: #7c3aed;
}
.ledger-rubric th.ledger-maxrow-cell.rot-accent-exam {
  color: #7c3aed !important;
}
.ledger-rubric .rot-accent-grand .rot-label {
  color: #b91c1c;
}
.ledger-rubric th.ledger-maxrow-cell.rot-accent-grand {
  color: #b91c1c !important;
  font-size: 0.8rem;
}

/* Wide ledgers (many subjects × sub-columns) print landscape and shrink
   to fit one A4 page. This USED to be done by assigning a named @page
   (`page: wideLedgerPage`) to the .wide-ledger wrapper — but putting a
   named page on an element forces Chrome to switch page "contexts" from
   the default page into the named one and back again, and Chrome pads
   both of those context switches with a genuinely blank page (blank
   page before the content, blank page after). That's what was showing
   up here. Since the print-preview modal only ever shows ONE document
   at a time (its whole innerHTML is replaced per document — see
   showPrintPreview() in utils.js), there's never actually a need for
   two page contexts to coexist in the same print job. showPrintPreview()
   now swaps the single default @page's size/margin (landscape 6mm,
   portrait 8mm for most documents, or 8mm/10mm for the Gradesheet — see
   the @media print block under .gs-page-frame below, fixed the same
   way) via a small injected <style> tag instead, so the whole print job
   stays on one page context throughout and no blank padding pages get
   inserted. See setPrintPageSetup() in utils.js.                       */

/* ---- Print — Gradesheet (individual student certificate) ----
   One .gradesheet-page per student — a bordered A4 portrait sheet
   modelled on the school's official gradesheet layout (see the sample
   images used to build this feature). Renders both in the on-screen
   preview and the actual print, same as the ledger rules above.

   Every font-size/padding/margin below is in em, not rem, ON PURPOSE:
   .gradesheet-page's own font-size is the single dial fitGradesheetsToOnePage()
   (utils.js) turns to make one gradesheet fill exactly one A4 page —
   shrinking it for content-heavy classes (9-10's Theory/Internal rows)
   and growing it for lighter ones (Nursery-5's shorter LO table) so the
   full page is used either way, with no second overflow page and no
   blank trailing page. Because everything here scales off that one
   font-size via em (not a fixed rem tied to the document root), the
   whole certificate — text AND spacing — grows or shrinks together as
   one unit. The em numbers look oddly precise (e.g. 1.4634em) because
   each was back-solved from the original rem-based design size so the
   default, unscaled appearance is unchanged from before this change.

   Each .gradesheet-page sits inside a .gs-page-frame wrapper (added by
   wrapGradesheetPagesForPrint() in utils.js) — the frame is what carries
   the fixed one-page height and page-break-after below. */
.gs-page-frame { margin: 0 auto 1rem; }
.gradesheet-page {
  position: relative;
  border: 2px solid #000;
  padding: 0.7927em 1.2195em;
  margin: 0 auto;
  width: 190mm; /* matches the 8mm/10mm gradesheet @page margin set dynamically by setPrintPageSetup("gradesheet") in utils.js (210mm A4 width − 10mm×2) — fitGradesheetsToOnePage() only ever changes font-size, never width, so this stays put */
  box-sizing: border-box;
  color: #000;
  font-size: 0.82rem; /* the scalable base — overridden inline (in px) by fitGradesheetsToOnePage() */
  font-family: "Kalimati", "Inter", "Nirmala UI", "Noto Sans Devanagari", system-ui, sans-serif;
  background: #fff;
  text-align: justify;
}
/* Reserve fixed physical space on both sides of the centered header text
   so it can never run under the 50mm logo/photo squares (see below) — a
   letterhead's name/address column is narrower than the full page width
   precisely because it sits between two fixed corner marks, not because
   its own text is short. 33mm ≈ 5mm inset + 25mm square + 3mm breathing
   gap, so the text column starts just clear of each square's outer edge. */
.gs-header { text-align: center; margin-bottom: 0.4268em; padding: 0 33mm; }
.gs-tagline {
  font-style: italic;
  font-size: 0.7317em;
  color: #444;
  margin: 0 0 0.1463em;
  line-height: 1.2;
}
/* Logo (top-left) / student photo (top-right) — see buildGsHeaderHtml()
   in js/gradesheet-engine.js. These are position:absolute overlays, NOT
   part of the .gs-header flex/flow — `.gradesheet-page` (position:
   relative, see above) is their positioning anchor, so they layer on top
   of the certificate's own top-left/top-right corner without adding any
   height or width to the document flow. That's deliberate: it means
   .gs-header — and everything below it (ribbon, title, table,
   signatures) — sits at exactly the same position whether a logo/photo
   is present or not, so injecting them can never shift or resize the
   certificate's native layout.

   Both squares are now a FIXED physical 50mm × 50mm — not a proportion
   of the page's available space — with a strict 15mm margin from the
   true paper edge on every print. That 15mm is measured from the actual
   sheet of paper, not from `.gradesheet-page`'s own border: the
   printable area already starts 8mm down / 10mm in from the paper edge
   (the gradesheet's own @page margin — see setPrintPageSetup() in
   utils.js, and the width comment on `.gradesheet-page` above), so the
   offset here is topped up by the remaining distance — 15mm − 8mm = 7mm
   from the top, 15mm − 10mm = 5mm from each side — minus the 2px page
   border so the image's outer edge (not its border) lands exactly on
   the 15mm line. The square itself is 25mm × 25mm. Because the size is physical (mm), it deliberately
   does NOT scale with fitGradesheetsToOnePage()'s font-size adjustment —
   a letterhead mark stays the same real-world size on every gradesheet,
   whether that student's table is dense or short. alignGsHeaderImages()
   in utils.js no longer computes size/position for these — this fixed
   CSS box is now the single source of truth for both corners. */
.gs-header-logo, .gs-header-photo {
  position: absolute;
  /* border-box so the photo's 1.5px border (below) sits INSIDE the fixed
     50mm × 50mm footprint instead of adding to it — logo and photo stay
     pixel-identical in size. */
  box-sizing: border-box;
  top: calc(7mm - 2px);
  width: 25mm;
  height: 25mm;
  z-index: 2;
}
.gs-header-logo { left: calc(5mm - 2px); object-fit: contain; }
.gs-header-photo {
  right: calc(5mm - 2px);
  object-fit: cover;
  border: 1.5px solid #000;
}
.gs-school-name {
  font-family: "Kalimati", "Poppins", "Nirmala UI", "Noto Sans Devanagari", sans-serif;
  font-weight: 800;
  font-size: 1.4634em;
  color: #8b1a1a;
  letter-spacing: 0.02em;
  line-height: 1.2;
}
.gs-school-address {
  font-weight: 700;
  font-size: 0.9756em;
  color: #8b1a1a;
  margin-top: 0.0625em;
  line-height: 1.2;
}
/* "Grade: <label>" ribbon — a centered banner sitting just above the
   "Grade Sheet" title, folded-banner style. .gs-grade-ribbon-wrap centers
   it; the ribbon itself stays position:relative so its ::before/::after
   fold triangles below still anchor to its own box. */
.gs-grade-ribbon-wrap { text-align: center; margin-bottom: 0.3659em; }
.gs-grade-ribbon {
  position: relative;
  display: inline-block;
  background: #8b1a1a;
  color: #fff;
  font-weight: 700;
  font-size: 0.9146em;
  letter-spacing: 0.03em;
  padding: 0.2667em 1.0667em;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.gs-grade-ribbon::before, .gs-grade-ribbon::after {
  content: "";
  position: absolute;
  top: 100%;
  border-style: solid;
  border-width: 5px 5px 0 5px;
  border-color: #5c1010 transparent transparent transparent;
}
.gs-grade-ribbon::before { left: 0; }
.gs-grade-ribbon::after { right: 0; }
.gs-title {
  text-align: center;
  font-weight: 700;
  font-size: 1.1585em;
  margin: 0.3158em 0 0.4211em;
}
/* The certifying paragraph sits inside its own outline (border box)
   rather than floating free in the page — a tab-space indent opens the
   first line, like a formal certificate. */
.gs-meta-outline {
  border: 1px solid #000;
  padding: 0.4878em 0.7317em 0.4268em;
  margin: 0.122em 0 0.4878em;
}
.gs-meta-text {
  font-size: 1em;
  line-height: 1.35;
  text-align: justify;
  margin: 0;
  text-indent: 2.4em;
}
.gs-meta-text strong { font-weight: 700; }
/* Dotted "fill-in-the-blank" underline for actual data values (name,
   symbol no., roll no., school name, EMIS code, exam type, etc.) inside
   the meta paragraph — reads like a formal certificate. */
.gs-data {
  border-bottom: 1px dotted #000;
  padding: 0 0.1829em;
}
.gs-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 1em;
  margin-bottom: 0.1829em;
}
.gs-table th, .gs-table td {
  border: 1px solid #000;
  padding: 0.3659em 0.5488em;
  text-align: center;
}
.gs-table th { font-weight: 700; background: #f2f2f2; }
.gs-table td.gs-subject-col, .gs-table th.gs-subject-col { text-align: center; }
.gs-table tfoot td { font-weight: 700; }
/* Only the "Grade Point Average = X" sentence cell (the one spanning
   multiple columns) reads as a left-aligned line of text — the row's
   other two cells (the Subjects-column label and the total Credit
   Hour/Grade Point number) stay centered like every other cell in the
   table, matching the rest of the columns above them. */
.gs-table tfoot td[colspan] { text-align: left; }
.gs-footnotes { font-size: 0.8537em; margin: 0.3571em 0 0.5em; text-align: justify; line-height: 1.25; }
.gs-details-title {
  text-align: center;
  font-weight: 700;
  border: 1px solid #000;
  border-bottom: none;
  padding: 0.2308em;
  font-size: 0.9512em;
}
.gs-details-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8537em;
  margin-bottom: 0.7143em;
}
.gs-details-table th, .gs-details-table td {
  border: 1px solid #000;
  padding: 0.3143em 0.5714em;
  text-align: center;
}
.gs-details-table th { font-weight: 700; background: #f2f2f2; }
.gs-signature-row {
  display: flex;
  justify-content: space-between;
  margin-top: 0.55rem;
  font-size: 0.7rem; /* fixed (rem), not em on purpose — see note below */
}
.gs-signature-block { text-align: center; min-width: 7.5rem; font-weight: 700; }
.gs-prepared-block { align-self: flex-end; }
/* Signature mark itself (dotted line + optional image) is the shared
   .sig-mark component in the print-signature-block rules above — same
   taller box, with the dotted line partway down it, as every other
   signature field in the portal now uses (see that section for why). */
.gs-signature-name { display: block; font-weight: 700; }

/* The gradesheet's Class Teacher / Prepared by / Exam Coordinator /
   Headmaster row uses the shared .sig-mark box as-is (see "Shared
   signature mark", styles.css, print-signature-block section) — the
   taller box with the dotted line sitting partway down it, so an
   attached signature photo can render at a real, legible size and is
   free to cross over the dotted line above and below it, is now the
   one rule for every signature field in the portal, not a gradesheet-
   only override. Only the width is trimmed slightly here, to keep the
   signature comfortably inside .gs-signature-block's narrower
   min-width without widening the row. */
.gs-signature-block .sig-mark {
  width: 6.5rem;
}
.gs-signature-block .sig-mark-img {
  max-width: 6.3rem;
}

@media print {
  /* No named @page here (was `@page gradesheetPage` + `page:
     gradesheetPage` on .gs-page-frame) — a named page forces Chrome to
     switch page "contexts" into it and back out again, and Chrome pads
     BOTH of those switches with a genuinely blank printed page (one
     before the gradesheet, one after) — exactly the same bug the
     wide-ledger comment above describes, and the reason a single
     one-page gradesheet used to print as 3 pages. The single unnamed
     default @page (swapped to this exact 8mm 10mm margin dynamically by
     setPrintPageSetup("gradesheet") in utils.js, since the print-preview
     modal only ever shows ONE document at a time) now covers gradesheet
     printing too, so it stays on one page context throughout — no
     blank padding pages, on any device. */
  .gs-page-frame {
    break-after: page;
    page-break-after: always;
    margin: 0 !important;
  }
  .gs-page-frame:last-child { break-after: auto; page-break-after: auto; }
  .gradesheet-page {
    border: 2px solid #000 !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    /* Belt-and-braces alongside fitGradesheetsToOnePage()'s sizing: even
       if a page still measured a hair too tall, this stops the browser
       from slicing the box mid-content and re-drawing its border around
       just the leftover bit (e.g. the signature row alone spilling onto
       a near-blank second sheet with its own border) — the box moves as
       one whole unit instead of fragmenting across the page break. */
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .gs-school-name, .gs-school-address { color: #8b1a1a !important; }
  .gs-header-photo {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .gs-grade-ribbon {
    background: #8b1a1a !important;
    color: #fff !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .gs-table th, .gs-details-table th { background: #f2f2f2 !important; }
}

/* ---- Save PDF — shared off-screen render holder ----
   Used by both admin-gradesheet.js (per-student canvas capture, then
   composited into the PDF with jsPDF) and any future html2canvas-based
   export. Pinned at the real viewport origin (not pushed thousands of
   pixels off-screen) and hidden purely with a negative z-index — never
   opacity/visibility, since html2canvas can render those as a blank
   capture. Content inside renders at its normal, untransformed size;
   any shrinking to fit multiple gradesheets per page happens afterward,
   on the already-rendered image, not via CSS transform. */
.pdf-export-holder {
  position: fixed;
  top: 0;
  left: 0;
  z-index: -9999;
  pointer-events: none;
}

/* ---- Save PDF — progress overlay ----
   Shown for the whole render (admin-gradesheet.js's Save PDF buttons and
   the shared "📄 Page PDF" button in utils.js/showPrintPreview) so a
   multi-second render never looks like an unresponsive click. */
.pdf-progress-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(27, 42, 74, 0.55);
  z-index: 10000;
  align-items: center;
  justify-content: center;
}
.pdf-progress-overlay.open { display: flex; }
.pdf-progress-box {
  background: #fff;
  border-radius: 0.75rem;
  padding: 1.5rem 2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25);
  min-width: 14rem;
}
.pdf-progress-spinner {
  width: 2rem;
  height: 2rem;
  border: 3px solid var(--border, #ddd);
  border-top-color: var(--gold, #E8A33D);
  border-radius: 50%;
  animation: pdfSpin 0.8s linear infinite;
}
.pdf-progress-label {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink, #1B2A4A);
  text-align: center;
}
@keyframes pdfSpin { to { transform: rotate(360deg); } }

/* ---- Print preview modal — shows print content on-screen first ---- */
.print-preview-modal {
  display: none;
  position: fixed;
  inset: 0;
  background: #fff;
  z-index: 9999;
  overflow-y: auto;
}
.print-preview-modal.open { display: block; }
.print-preview-toolbar {
  position: sticky;
  top: 0;
  background: #fff;
  border-bottom: 1px solid var(--border);
  padding: 0.75rem 1rem;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
  z-index: 1;
  overflow-x: auto;
}
/* The in-modal class (and, on class+subject screens like Mark Sheet,
   Internal Form, and Result Archive, subject) switcher sits on the left,
   Close/Print stay pinned right, all on one row — the toolbar scrolls
   horizontally on narrow screens instead of wrapping, so the switcher
   never pushes Close/Print out of alignment. */
.print-preview-toolbar .ppm-switcher {
  margin-right: auto;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.4rem;
  flex-shrink: 0;
}
.print-preview-toolbar #ppmCloseBtn,
.print-preview-toolbar #ppmPhotoBtn,
.print-preview-toolbar #ppmPrintBtn {
  flex-shrink: 0;
}
.print-preview-toolbar .ppm-switcher select {
  max-width: 8rem;
}
@media (max-width: 640px) {
  .print-preview-toolbar .ppm-switcher select {
    max-width: 6.5rem;
  }
  .print-preview-toolbar .ppm-switcher label {
    display: none;
  }
  /* Close / Download / Print Now all fit one row down to a small phone
     without wrapping (the toolbar itself scrolls horizontally instead —
     see .print-preview-toolbar above) by shortening "⬇️ Download
     Gradesheet"/"⬇️ Download All (N)" down to just "⬇️ Download" and
     trimming every button's side padding a little. */
  .print-preview-toolbar .ppm-download-label-full {
    display: none;
  }
  .print-preview-toolbar #ppmCloseBtn,
  .print-preview-toolbar #ppmDownloadBtn,
  .print-preview-toolbar #ppmPhotoBtn,
  .print-preview-toolbar #ppmPrintBtn {
    padding-left: 0.75rem;
    padding-right: 0.75rem;
  }
}
.print-preview-body {
  /* Fills the whole modal width instead of a narrow centered column —
     a fixed max-width here left large white gutters on either side of
     the sheet, which made the preview read as a small embedded frame
     floating in the middle of the screen instead of a true full-page
     print preview. The generous side padding keeps long lines from
     running edge-to-edge on very wide monitors. */
  padding: 1.25rem clamp(1rem, 4vw, 3rem) 3rem;
  max-width: 100%;
  width: 100%;
  margin: 0;
  color: #000;
  font-family: "Kalimati", "Inter", "Nirmala UI", "Noto Sans Devanagari", system-ui, sans-serif;
}
.print-preview-body .ledger { width: 100%; font-size: 0.8rem; }
.print-preview-body .ledger td {
  border: 1px solid #ccc;
}
.print-preview-body .ledger thead th {
  background: #e9e9e9;
  color: #000;
  border: 1px solid #999;
}
.print-preview-body .ledger tbody tr:nth-child(even) { background: #f7f7f7; }
.print-preview-body.wide-ledger { max-width: 100%; padding-left: 1rem; padding-right: 1rem; overflow-x: auto; }

/* Subject-group divider — marks the FIRST sub-column of every subject
   (group header, sub-header, and every data row) with a heavier left
   border, so each subject's block of sub-columns reads as one visual
   group instead of every column blurring into the next. Was applied as
   a class in the markup (loSubHeaderCells(), breakdownSubHeaderCells(),
   buildWrittenOralLedgerTable(), and their matching data-row builders in
   admin-print-ledger.js) but never actually had a rule. */
.ledger .subj-div {
  border-left: 2px solid #9ca3ab;
}
.print-preview-body .ledger thead .subj-div,
.ledger thead .subj-div {
  border-left: 2px solid var(--gold-dark);
}

/* Classes 6-10 (Breakdown A/B ledgers) have the most columns of any
   ledger — up to 7 subjects × 5 sub-columns each — so the standard
   ledger-lo sizing is too large and the header/data text overlaps.
   Shrink further specifically for these, both in the on-screen print
   preview and the actual printed page. */
.print-preview-body .ledger-breakdown { font-size: 0.62rem; }
.print-preview-body .ledger-breakdown th,
.print-preview-body .ledger-breakdown td { padding: 0.2rem; }
.print-preview-body .ledger-breakdown thead tr:last-child th { font-size: 0.6rem; height: 112px; }

/* Single-subject mark sheet print (marks-entry.html) — center every
   column so the printed page reads clean and even, not just the
   grouped ledgers. Scoped to the print table only; the live editable
   ledger on-screen keeps its normal left-aligned layout. */
.ledger-print th,
.ledger-print td {
  text-align: center;
}
.ledger-print tbody td { color: var(--ink); font-weight: 600; }

/* Header colour now matches the Grade Ledger exactly — both just use
   the base .ledger thead th styling (single dark-ink tone on screen,
   plain light gray when printed). The old two-tone treatment (dark
   first row / light-blue second row, here and in the print block
   below) was the one difference between how the two ledgers looked. */
.ledger-lo tbody tr:nth-child(even) td { background: #f7f9fc; }

/* ==========================================================================
   Portfolio Form print (portfolio-form.html / js/portfolio-form.js)

   The record sheet (.portfolio-record / .portfolio-record-table) is a copy of
   the school's paper "आन्तरिक मूल्याङ्कन अभिलेख (पोर्टफोलियो) फाराम" — landscape
   A4, that class's पाठ शीर्षक down the left edge, the subject's grouped
   criterion columns across the top, everything else blank for hand-filling.
   An optional pre-filled cover page (.portfolio-cover) can print in front of
   it. Each sheet is wrapped in its own .print-page-frame so one student's
   portfolio never shares a sheet with the next student's.

   Renders both in the on-screen preview and the actual print, same as the
   ledger/gradesheet rules above; the print-only additions (the page break
   itself, and forcing the table's header shading through) are in the main
   @media print block below.
   ========================================================================== */

/* Generic "one printed sheet" wrapper. Deliberately NOT named after the
   portfolio — .gs-page-frame already does this job for gradesheets and any
   future multi-sheet document should reuse this rather than invent a third
   copy. On screen it just spaces the sheets apart; the break-after that makes
   it real lives in @media print (see below), which is also why every frame
   must be a DIRECT child of .print-preview-body: the break's :last-child reset
   (no trailing blank sheet) only sees siblings. */
.print-page-frame { margin: 0 auto 1rem; }

/* 285mm × 182mm — one A4 LANDSCAPE sheet. runPortfolioPrint() passes a
   "wide-ledger" extraClass, so setPrintPageSetup("wide-ledger") in utils.js
   puts the print on A4 landscape with 6mm margins → a 285mm × 198mm printable
   area, and this sheet is cut to fill its width exactly with no horizontal
   clipping. The paper forms are landscape too, and the Classes 6-8 Nepali grid
   needs all 285mm of it: 15 scoring columns. (Measured off the scanned forms at
   150 DPI, their own grids are 286-291mm wide, i.e. the same full-bleed
   landscape sheet.)
   min-height, not height: 182mm keeps a short list from printing as a stub,
   and the sheet is free to grow towards the 198mm the page actually gives us.
   The tallest sheet the nine subjects can produce is Mathematics Class 9 —
   20 lessons plus four summary rows = 24 rows of 5mm = 120mm — with Science
   9-10 (19 + 4 = 23) and Nepali Classes 6-8 (17 + 4 = 21 rows = 105mm, but a
   taller header band) close behind. On top of that sits roughly 54mm of chrome
   (header block ~23mm, info strip ~7mm, closing note ~5mm, signature row ~15mm,
   this box's padding ~4mm) plus the header band: ~11mm on Mathematics, ~9mm on
   the single-row English header, but ~27mm on Classes 6-8 Nepali because its
   longest criterion label wraps to six lines in a ~15mm column. Both worst
   cases land near 186mm, so they still print on one sheet with ~12mm to spare.
   Raising the row height or the header font is what would spill a long list onto
   a second page — as would letting a lesson title wrap, which costs the same
   ~2.6mm as an extra row; that is what the wide unit column below is protecting.
   Column widths: 285mm less this box's padding leaves ~279mm of table, and
   table-layout: fixed hands the fixed columns below their widths first, so the
   criterion columns split what is left evenly: ~15mm each across 12 of them on
   Classes 6-8 Nepali, ~22mm across 8 on Nepali 9-10, ~20mm across 8 on
   Mathematics and Optional I - Mathematics, ~20mm on Science, ~19mm on Health,
   ~23mm across the 9 flat columns on English and ~19-21mm across the 11-12 on
   the other three flat papers (Hamro Chapakot, Economics, Education). Every one
   of those is inside the range the paper forms themselves use (12.7-22.2mm on
   Nepali, 16.1-21.0mm on Math, 15.9-36.9mm on English, 12.5-31.8mm on the six
   added later). Only the first header row sizes the columns under fixed layout,
   which is why a long criterion label in the second row cannot widen its own
   column.
   A fixed width rather than a max-width so the preview shows the real printed
   proportions and scrolls sideways on a narrow window (.print-preview-body
   .wide-ledger already carries overflow-x: auto on screen) instead of
   squeezing the grid into something that prints differently. */
.portfolio-page {
  width: 285mm;
  min-height: 182mm;
  margin: 0 auto;
  padding: 0.35rem 0.5rem 0.6rem;
  box-sizing: border-box;
  background: #fff;
  color: #000;
  border: 1px solid #000;
  display: flex;
  flex-direction: column;
  font-family: "Kalimati", "Inter", "Nirmala UI", "Noto Sans Devanagari", system-ui, sans-serif;
}
/* Pushes the signature row to the foot of the sheet on both pages, so the
   three signature lines always print in the same place whether a subject has
   6 lessons or 20. */
.portfolio-page .print-signature-row { margin-top: auto; padding-top: 0.6rem; }

/* ---- Cover page --------------------------------------------------------- */
/* A copy of the school's "Student Portfolio Cover" sheet — see
   portfolioCoverPageHtml() in js/portfolio-form.js. Same 285mm landscape sheet
   as the record page, filled top to bottom: title band, id line, section 1's
   bordered detail block, the weight/height table, the exam table, signatures.
   Everything is sized in mm or small rem steps because the whole thing has to
   land on ONE sheet — the paper original fills 297 × 210mm almost edge to edge,
   and there is no second page to spill onto.

   Height budget, at the 198mm of printable height A4 landscape gives with
   setPrintPageSetup("wide-ledger")'s 6mm margins (1rem = 16px = 4.23mm):
     4.6mm  page padding + border
    25.0mm  title band (.pc-head's min-height; its content is only ~16mm, the
            floor is there to clear the two 25mm corner boxes)
    16.9mm  three section headings
    77.1mm  section 1's box — 15 rows at 0.75rem × 1.35 + 2 × 0.08rem padding
    20.8mm  weight/height table, 1 header + 3 blank 5mm rows
    24.6mm  exam table, 3 header rows + 2 blank 5mm rows
    19.0mm  signature row
   = 188mm, so ~10mm of slack. That is the whole margin of safety, and section
   1's 15 rows are ~41% of it: adding a row costs ~5mm, and letting one WRAP
   costs the same (hence min-width: 0 on .pc-f and nowrap on .pc-lab below).
   If a future field has to be added, take the space back from .pc-row's
   padding rather than from its line-height — 1.35 is what stops Devanagari
   matras from clipping. Verify with outputs/covercheck.js, which recomputes
   this budget from these very declarations and fails under 5mm of slack.

   The five signature blocks are the width constraint: 5 × .sig-mark's 7rem +
   4 × the row's 1.5rem gap = 163mm inside a 280mm page, so they stay on one
   line. .pc-sign-row trims .print-signature-block's shared 8rem min-width to
   6rem, without which five blocks would wrap onto a second row. */

/* Title band. position: relative so the two corner boxes can be absolute
   overlays like the gradesheet's logo/photo corners (.gs-header-photo above) —
   that way they never add height to the flow, and the title stays optically
   centred on the sheet rather than centred in whatever space is left beside
   them. The side padding keeps the title clear of both boxes. */
.pc-head {
  position: relative;
  padding: 0 30mm 0.15rem;
  min-height: 25mm;
}
.pc-class-box {
  position: absolute;
  left: 0;
  top: 1mm;
  border: 1px solid #000;
  padding: 0.15rem 0.4rem;
  min-width: 26mm;
  font-size: 0.8rem;
  white-space: nowrap;
}
.pc-class-value { font-weight: 700; margin-left: 0.2rem; }
/* 25mm × 25mm with a 1.5px border — deliberately identical to
   .gs-header-photo on the gradesheet, so the same roster photo comes out the
   same physical size on both documents. box-sizing: border-box keeps the
   border inside that footprint instead of adding to it. */
.pc-photo-box {
  position: absolute;
  right: 0;
  top: 1mm;
  box-sizing: border-box;
  width: 25mm;
  height: 25mm;
  border: 1.5px solid #000;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #fff;
}
.pc-photo-img { width: 100%; height: 100%; object-fit: cover; }
.pc-photo-label { font-size: 0.68rem; color: #444; }
.pc-title {
  text-align: center;
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.25;
}
.pc-subtitle { text-align: center; font-size: 0.85rem; line-height: 1.25; }
/* The विषय / इमिज कोड / रोल नं line. Right padding clears the photo box, which
   overhangs this row on the paper too. */
.pc-idline {
  display: flex;
  gap: 1.2rem;
  align-items: baseline;
  padding: 0.3rem 28mm 0 0;
  font-size: 0.78rem;
}

/* "१. सदस्यको वैयक्तिक तथा पारिवारिक विवरण" and its two siblings. These sit
   OUTSIDE the bordered block they introduce, exactly as on the paper. */
.pc-section {
  margin: 0.25rem 0 0.1rem;
  font-size: 0.82rem;
  font-weight: 700;
  line-height: 1.2;
}
/* Section 1's bordered block. Everything inside is a stack of label-and-rule
   rows rather than a table: the paper runs two fields across one line and four
   across the next, which a table would force into a single column grid. */
.pc-box {
  border: 1px solid #000;
  padding: 0.2rem 0.45rem 0.3rem;
  font-size: 0.75rem;
}
.pc-row {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  padding: 0.08rem 0;
  line-height: 1.35;
}
/* The (अ)/(आ)/(ई) sub-rows sit under their parent's marker, as on the form. */
.pc-row-indent { padding-left: 9mm; }
.pc-row-split { gap: 1.5rem; }
.pc-half { display: flex; align-items: baseline; gap: 0.3rem; flex: 1 1 0; min-width: 0; }
.pc-mark { flex: 0 0 auto; white-space: nowrap; }
/* One field: its label, then the rule it is written on. EVERY field on a row
   grows by the same amount, so the rules on a row come out the same length and
   the short labels (पेसा, सम्पर्क नं, नाता) get as much writing room as the
   name sitting beside them. The name field used to be the only grower, which
   let it eat all the leftover width and starved the rest of the row down to
   .pc-rule's 12mm floor.
   flex-basis stays auto (not 0) so a long label still reserves its own width
   instead of squeezing its own rule away, and min-width: 0 so a row can never
   be pushed wide enough to wrap — a wrapped row costs ~5mm of a sheet that
   only has ~10mm of slack. */
.pc-f {
  display: flex;
  align-items: baseline;
  gap: 0.25rem;
  flex: 1 1 auto;
  min-width: 0;
}
.pc-lab { flex: 0 0 auto; white-space: nowrap; }
.pc-lab-plain { font-weight: 400; }
/* The dotted rule a hand-filled answer goes on. Pre-filled values print on the
   same rule in bold, so a filled field and a blank one line up. */
.pc-rule {
  flex: 1 1 auto;
  min-width: 12mm;
  border-bottom: 1px dotted #000;
  font-weight: 700;
  padding: 0 0.2rem;
  min-height: 1em;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* (क)'s school name — printed text, not a rule, because the school is not a
   field anyone fills in. */
.pc-fixed { font-weight: 700; white-space: nowrap; }
/* The two भएको भए / नभएको भए boxes. A bordered span rather than ☐ so it prints
   at a predictable size on any font the browser happens to fall back to. */
.pc-tickset { white-space: nowrap; }
.pc-tick {
  display: inline-block;
  width: 3mm;
  height: 3mm;
  border: 1px solid #000;
  vertical-align: middle;
  margin: 0 0.15rem;
}

/* Sections 2 and 3 are real tables — blank grids for hand-filling. */
.pc-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.72rem;
  table-layout: fixed;
}
.pc-table th,
.pc-table td {
  border: 1px solid #000;
  padding: 0.1rem 0.15rem;
  text-align: center;
  vertical-align: middle;
}
.pc-table thead th { font-weight: 700; line-height: 1.2; overflow-wrap: anywhere; }
.pc-table tbody td { height: 5mm; }
/* मिति / तौल / उचाइ take a fixed slice each and प्रतिक्रिया keeps the rest, the
   same lopsided split the paper uses. */
.pc-health-table th:nth-child(1) { width: 17%; }
.pc-health-table th:nth-child(2) { width: 15%; }
.pc-health-table th:nth-child(3) { width: 15%; }
/* 18 equal columns, so Grade/GP is the only label narrow enough to sit on one
   line — hence the smaller type on that bottom header row only. */
.pc-exam-table .pc-gp-th { font-size: 0.62rem; font-weight: 700; }
/* Five signatories instead of the record sheet's three, so each block gets
   less room; the shared min-width would force a wrap at 5 × 8rem. */
.pc-sign-row { font-size: 0.72rem; }
.pc-sign-row .print-signature-block { min-width: 6rem; }

/* ---- Record sheet ------------------------------------------------------- */
/* The paper form's one-line strip between the title and the table: कक्षा, नाम,
   इमिज आइडी, रोल नं. Four fields on one row, each a label followed by the
   pre-filled value on a rule, so it reads as a filled-in form line rather
   than a second table competing with the grid below it. */
.portfolio-info-row {
  display: flex;
  align-items: flex-end;
  gap: 0.6rem;
  font-size: 0.74rem;
  margin: 0.15rem 0 0.3rem;
}
.pf-info-field {
  display: flex;
  align-items: flex-end;
  gap: 0.25rem;
  min-width: 0;
}
.pf-info-label { font-weight: 700; white-space: nowrap; }
/* Underlined so an empty one (a student with no roll on file, say) is still
   obviously a blank to be written on. flex: 1 on the name field only — it's
   the one that can run long, and letting it take the slack keeps the other
   three from being pushed off the line. */
.pf-info-value {
  font-weight: 600;
  border-bottom: 1px solid #000;
  min-width: 18mm;
  padding: 0 0.2rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pf-info-class .pf-info-value { min-width: 12mm; text-align: center; }
.pf-info-name { flex: 1 1 auto; }
.pf-info-name .pf-info-value { flex: 1 1 auto; min-width: 40mm; }
.pf-info-id .pf-info-value { min-width: 30mm; text-align: center; }
.pf-info-roll .pf-info-value { min-width: 14mm; text-align: center; }
/* महिना — a fifth field, printed only by the papers whose strip carries one
   (rubric.monthField: Optional I - Economics). Narrow, because it holds a
   month name written by hand rather than a pre-filled value. */
.pf-info-month .pf-info-value { min-width: 20mm; }

/* table-layout: fixed so the criterion columns split whatever is left after
   the fixed ones evenly — ~15mm each on the Classes 6-8 Nepali form (12 of
   them), ~22mm on Nepali 9-10 (8), ~20mm on Mathematics and Optional I -
   Mathematics (8), ~20mm on Science (5 criteria on 6-8, 6 on 9-10), ~19mm on
   Health (6), and ~19-23mm on the four flat forms — English (9 columns),
   Hamro Chapakot (12), Economics (11) and Education (11) — instead of a long
   unbreakable Devanagari heading widening its own column and starving the
   rest. Across all nine papers the criterion columns measure 12.5-36.9mm, so
   an even share lands inside the measured range on every sheet. */
.portfolio-record-table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 0.68rem;
}
.portfolio-record-table th,
.portfolio-record-table td {
  border: 1px solid #000;
  padding: 0.12rem 0.15rem;
  text-align: center;
  vertical-align: middle;
}
.portfolio-record-table thead th {
  font-weight: 700;
  background: #e9e9e9;
  line-height: 1.1;
  font-size: 0.6rem;
  white-space: normal;
  overflow-wrap: anywhere;
}
/* सुनाइ र बोलाइ / पढाइ र लेखाइ — the spanning cells. Slightly larger than the
   criteria under them, which is the only cue the paper form gives that they're
   headings rather than columns of their own. */
.portfolio-record-table .pf-group-th { font-size: 0.68rem; }
/* Each criterion's full marks, printed under its label as "(२)" — the paper
   puts them inline like this rather than on a separate max-marks row (which
   is what the Internal Form (Detailed) ledgers do). The same slot carries a
   column's `note` where the paper prints a sum rather than a figure — the
   Health form's "(१४×२=२८)" and Hamro Chapakot's "(१८×२=३६)" — so those read
   as part of the heading exactly as they do on paper. */
.portfolio-record-table .pf-max {
  display: block;
  font-weight: 700;
  font-size: 0.62rem;
}
/* 57mm because that is what the paper gives its unit column — 57.1mm on the
   Nepali form, 58.9mm on the Math one, measured off 150 DPI scans. It was 46mm
   at first, which wrapped the longest titles ("महत्तम समापवर्तक र लघुत्तम
   समापवर्त्य", "व्यक्तित्व विकासमा परिवारको भूमिका") onto a second line and
   cost the sheet ~2.6mm of height per wrapped row. */
.portfolio-record-table .pf-lesson-th { width: 57mm; text-align: center; }
.portfolio-record-table .pf-standalone-th { width: 15mm; }
/* Only bites where जम्मा अंकभार is a standalone (first-row) column, as on the
   Nepali and Science forms: under table-layout: fixed only the first header row
   sizes columns, so on the Math and Health ones — where the paper puts the
   total inside a group — this width is ignored and the column takes an even
   share of the leftover width instead (~20mm, against 18.8mm on that paper).
   The class is on both kinds of total: the whole sheet's (col.total) and a
   band's own subtotal (col.groupTotal — Health's ८ and १४). */
.portfolio-record-table .pf-total-th { width: 16mm; }
/* The English form's own s.n. column (rubric.serialColumn) — 9.7mm on the
   paper. The other forms number the unit inside its own cell instead, and get
   no such column at all. */
.portfolio-record-table .pf-sn-th { width: 10mm; }
.portfolio-record-table .pf-sn { font-weight: 600; }
/* A rubric with no groups prints one plain header row (see
   portfolioRubricIsFlat) — the English, Hamro Chapakot, Economics and
   Education forms. Their columns are neither criteria under a band nor the
   narrow trailing columns .pf-standalone-th is sized for, so they drop that
   15mm and share the leftover width like criterion columns do: ~23mm each
   across English's nine and ~19-21mm across the other three's 11-12, against
   12.5-36.9mm on the papers. The unit column follows the English paper
   (65.5mm), which its longest title ("Global warming and climate change",
   ~30mm) sits well inside. */
.portfolio-record-table.pf-flat .pf-lesson-th { width: 65mm; }
.portfolio-record-table.pf-flat .pf-standalone-th { width: auto; }
/* कैफियत on the Classes 6-8 Nepali form, where 15 columns have to share 285mm
   and a horizontal "कैफियत" would cost 15mm the scoring columns need — and the
   same on the Health, Hamro Chapakot and Economics papers, which rotate it too.
   (Science, Education, Nepali 9-10 and Math print it flat and have the width to
   spare, so those rubrics leave rotate off.) Same writing-mode approach as
   .ledger-rubric th.rot-th above (real layout, not a transform, so the cell's
   width really is the label's line thickness) — without that rule's fixed 138px
   height, because this header band is only as tall as the wrapped criterion
   labels beside it. */
.portfolio-record-table th.pf-rot-th {
  width: 9mm;
  padding: 0.1rem 0.05rem;
  overflow: hidden;
}
.portfolio-record-table th.pf-rot-th .pf-rot-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
}
.portfolio-record-table th.pf-rot-th .pf-rot-label {
  display: inline-block;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: normal;
  overflow-wrap: anywhere;
  /* max-HEIGHT, not width: in vertical-rl the inline axis (the one a wrap
     boundary applies to) runs top to bottom. See the .rot-label rule above. */
  max-height: 20mm;
  text-align: center;
}

/* ---- The एकाइ column (rubric.unitColumn — the Economics paper only) ------- */
/* That paper is the one form of the nine that splits its left edge in two: a
   narrow rotated एकाइ column carrying the unit's ordinal, merged down over the
   पाठ rows belonging to it, then the पाठ title column. 8mm because the paper's
   measures 7.8mm; it overrides th.pf-rot-th's 9mm on equal specificity by
   sitting after it, and only the header cell can set the width at all (under
   table-layout: fixed the body cells never size a column). */
.portfolio-record-table th.pf-unit-th { width: 8mm; }
/* The body half of that column, and the merged मूल्याङ्कन cell beside the
   summary rows. Both hold a .pf-rot-wrap the same way the header does, but the
   header's rule is scoped to th.pf-rot-th, so they need their own copy. The
   cell inherits vertical-align: middle from the base rule, which is what
   centres the label down a rowspan of two to five rows. */
.portfolio-record-table td.pf-unit {
  width: 8mm;
  padding: 0.1rem 0.05rem;
  font-weight: 700;
  overflow: hidden;
}
.portfolio-record-table td.pf-unit .pf-rot-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
}
.portfolio-record-table td.pf-unit .pf-rot-label {
  display: inline-block;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  white-space: nowrap;
  text-align: center;
}
/* मूल्याङ्कन — where the एकाइ column runs on past the last पाठ and labels the
   four summary rows as a block. Shaded with them (.pf-summary paints the row's
   own cells, and this one is a child of the first row only) and unbolded
   relative to .pf-unit, because on the paper it reads as a band label rather
   than a number. */
.portfolio-record-table td.pf-eval {
  background: #f2f2f2;
  font-weight: 700;
  font-size: 0.62rem;
}
.portfolio-record-table td.pf-eval .pf-rot-label {
  white-space: normal;
  overflow-wrap: anywhere;
  max-height: 24mm;
}

/* The पाठ शीर्षक column is the only pre-filled one, so it's the only one that
   gets left-aligned and allowed to wrap onto a second line. */
.portfolio-record-table .pf-lesson {
  text-align: left;
  font-weight: 600;
  white-space: normal;
  line-height: 1.15;
}
/* Every scoring cell is written in by hand, so each row needs real vertical
   space. 5mm × up to 24 rows is what the sheet's height budget is built on (see
   .portfolio-page) — raising it will push long lists onto a second sheet. The
   tallest sheet across the nine papers is still Mathematics Class 9 (20 lessons
   + 4 summary = 24); Science 9-10 and Optional I - Economics Class 10 come next
   at 23 and 19. The paper forms themselves measure 4.1-5.3mm per row, so 5mm is
   inside their range. */
.portfolio-record-table tbody td { height: 5mm; }
/* प्रथम त्रैमासिक / अर्धवार्षिक / वार्षिक प्राप्तांक / जम्मा — or whatever the paper in
   hand words them as (rubric.summaryRows). Same blank cells as a lesson row,
   but the label is centred and shaded to read as a total line. */
.portfolio-record-table .pf-summary { background: #f2f2f2; }
.portfolio-record-table .pf-summary-label {
  text-align: center;
  font-weight: 700;
}
.portfolio-record-table .pf-empty {
  padding: 1.2rem 0.5rem;
  color: #666;
  font-style: italic;
}

/* Shared closing note on both sheets. */
.portfolio-note {
  font-size: 0.7rem;
  color: #333;
  line-height: 1.35;
  margin-top: 0.5rem;
  text-align: justify;
}
/* Only the record sheet carries a note now — the cover is a copy of a paper
   form that has no prose on it, so it shrinks to a footnote here, because every
   millimetre it takes comes off the table's row budget (see .portfolio-page). */
.portfolio-record .portfolio-note {
  font-size: 0.62rem;
  margin-top: 0.3rem;
}

/* Each .portfolio-page carries its own fixed 285mm sheet width, so
   .print-preview-body's generous clamp(1rem, 4vw, 3rem) side padding only eats
   into the window without buying anything — trimmed back on portfolio previews
   only (extraClass passed by runPortfolioPrint() in js/portfolio-form.js).
   That extraClass is "wide-ledger portfolio-print": this rule comes after
   .print-preview-body.wide-ledger, so it wins the padding, while wide-ledger's
   overflow-x: auto survives to scroll a landscape sheet sideways on a window
   narrower than 285mm. */
.print-preview-body.portfolio-print {
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

@media print {
  @page { margin: 8mm 8mm; }

  body { background: #fff !important; }
  .no-print { display: none !important; }
  .print-only { display: block !important; }
  /* Left sidebar (desktop) + hamburger/mobile header (see renderAdminShell()
     in utils.js, which injects both into these two slots on every admin
     page) are pure navigation chrome, never part of any printed document —
     same reasoning as .impersonation-banner just below. Fixed centrally
     here, once, rather than adding .no-print to each of the ~28 pages that
     include these slots (a couple of pages already tag their own <header>
     with .no-print directly; this covers the rest, plus the sidebar/mobile
     header itself everywhere). */
  #sidebarSlot, #mobileHeaderSlot { display: none !important; }
  /* Teacher/admin bottom nav (now shown at every screen width — see its own
     comment block far below) is pure navigation chrome too, same as the
     sidebar/mobile header above — never part of any printed page. */
  .teacher-bottom-nav, .admin-bottom-nav { display: none !important; }

  /* The REAL fix for "print prints the whole page" (tabs, notice text,
     page headings, etc. bleeding into the printout alongside the actual
     form): showPrintPreview()/closePrintPreview() (js/utils.js) now
     toggle this class on <body> for exactly as long as the modal is
     open, and every page's real content sits under ONE top-level
     wrapper that is always a direct child of <body> (e.g. inventory.html's
     `<div class="md:flex">`, or a page's own top-level container on
     pages that don't use that exact class) — so hiding every direct
     child of body except the modal itself, whenever the modal is open,
     hides that entire page underneath in one rule, on every page that
     uses this shared print-preview modal, without needing to know that
     page's specific wrapper class name. The #sidebarSlot/#mobileHeaderSlot
     rule above still matters for the handful of print paths that DON'T
     go through this modal (e.g. a page printing its own on-page content
     directly). */
  body.print-preview-active > *:not(.print-preview-modal):not(#printPreviewModal) {
    display: none !important;
  }
  /* The "Viewing as Teacher" admin-impersonation ribbon (see
     renderImpersonationControls() in utils.js) is a persistent on-screen
     reminder, not part of any printed document — it was never tagged
     .no-print, so it was bleeding into every print/PDF output (including
     both Print Internal Form sheets) whenever an admin previewed the
     Teacher view. */
  .impersonation-banner { display: none !important; }

  main { max-width: 100% !important; padding: 0 !important; margin: 0 !important; }

  /* When actually printing, only the open preview modal's body should
     appear — everything else on the page (including the modal's own
     toolbar) is hidden via .no-print. */
  .print-preview-modal { position: static !important; overflow: visible !important; }
  .print-preview-body { max-width: 100% !important; padding: 0 !important; }
  .print-preview-body.a4-preview { background: #fff !important; }
  /* चिठी: setPrintPageSetup("letter") ले @page margin 0 राख्छ — पानाको 8mm margin अब .letter-a4-paper को
     padding हो (स्क्रिनमा जस्तै), ताकि हरियो स्लोगान पट्टी र फुटर पानाको किनारसम्मै पुगून्। */
  .letter-a4-stage { width: 210mm !important; height: auto !important; margin: 0 !important; }
  .letter-a4-paper { width: 210mm !important; min-height: 296.4mm !important; padding: 8mm !important; box-shadow: none !important; transform: none !important; }
  /* Multi-sheet notice (नतिजा सूचना): every A4 sheet after the first starts a new printed page. */
  .letter-a4-stage + .letter-a4-stage { break-before: page; page-break-before: always; margin-top: 0 !important; }

  /* चिठी: fitLettersToOnePage() (js/utils.js) ले पानाभन्दा अग्लो चिठीमा --letter-fit राख्छ र
     पूरै चिठी (लेटरहेड + पाठ + हस्ताक्षर) समान अनुपातमा सानो हुन्छ — हस्ताक्षर दोस्रो
     पानामा झर्दैन। min-height पनि zoom ले गुणा हुने भएकाले भाग गरिएको छ। */
  .jinsi-print-form.letter-page.letter-fit-on { zoom: var(--letter-fit, 1); min-height: calc(279mm / var(--letter-fit, 1)); }
  .jinsi-print-form.letter-page .letter-sign, .jinsi-print-form.letter-page .lt-sign-row { break-inside: avoid; page-break-inside: avoid; }

  /* Form canvas (see .form-a4-stage above): on paper the sheet IS the page, so drop
     the on-screen sheet chrome and keep the fixed printable width, so the layout is
     identical to the preview. When the form is a little taller than one page,
     fitFormsToOnePage() (js/utils.js) sets --form-fit and the WHOLE form is scaled
     with one uniform zoom — header, table and signatures together — so the signature
     row can never drop onto a second page or get cut off. */
  .form-a4-stage, .form-a4-land { width: auto !important; height: auto !important; margin: 0 !important; }
  .form-a4-paper { width: auto !important; min-height: 0 !important; padding: 0 !important; box-shadow: none !important; transform: none !important; }
  .print-preview-body.form-a4-preview { overflow: visible !important; background: #fff !important; }
  .form-a4-fit { width: var(--form-w) !important; }
  .form-a4-fit.form-fit-on, .form-a4-fit .form-fit-on { zoom: var(--form-fit, 1); }
  .form-a4-fit .form-fit-on { width: var(--form-w); }
  /* A signature block is one unit: never split it, and never leave it alone on a new page. */
  .form-a4-fit .jp-signatures, .form-a4-fit .jp-signatures-2, .form-a4-fit .jp-remarks,
  .form-a4-fit .print-signature-row, .form-a4-fit .dh-sign-row, .form-a4-fit .pd-lvrec-sig,
  .form-a4-fit .tp-legend { break-inside: avoid; page-break-inside: avoid; }
  .form-a4-fit .jp-table + * { break-before: avoid; page-break-before: avoid; }
  .form-a4-stage + .form-a4-stage { break-before: page; page-break-before: always; }
  /* अन्तिम पाना पछि अतिरिक्त खाली पाना नबनोस् */
  .form-a4-stage:last-child, .form-a4-stage:last-child .form-a4-paper, .form-a4-stage:last-child .form-a4-fit { break-after: avoid; page-break-after: avoid; margin-bottom: 0 !important; padding-bottom: 0 !important; }
  /* .print-preview-body.wide-ledger carries overflow-x:auto (see the
     base rule, styles.css) so a wide Mark/Grade Ledger can be scrolled
     sideways on-screen — but that same rule was never reset for actual
     printing, so hitting Print (or Ctrl+P) clipped the table to
     whatever fit in the on-screen scroll viewport, baked the scrollbar
     itself into the output, and cut off everything past the visible
     edge. Printing (unlike a browser tab) has no scroll position, so
     the full, untruncated table must render at its natural width here —
     the wideLedgerPage landscape @page + the .wide-ledger font-size
     shrinking already in this file is what keeps that natural width
     within one A4 landscape sheet. */
  .print-preview-body.wide-ledger {
    overflow: visible !important;
    padding: 0 !important;
  }

  /* One printed sheet per .print-page-frame — see the base rule further up.
     Same shape (and the same reason for no named @page) as .gs-page-frame
     above: the :last-child reset is what stops the final sheet from ejecting
     a blank page after it, and it only works because portfolio-form.js emits
     the frames as direct children of .print-preview-body. */
  .print-page-frame {
    break-after: page;
    page-break-after: always;
    margin: 0 !important;
  }
  .print-page-frame:last-child { break-after: auto; page-break-after: auto; }
  .print-page-frame.pf-fit-on { zoom: var(--pf-fit, 1); }

  /* Keep a cover page or a record sheet whole rather than letting the browser
     slice it and redraw its border around the leftover strip. */
  .portfolio-page {
    border: 1px solid #000 !important;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  /* Label/header shading is structural here — these tables are hand-filled,
     and the tint is what separates the pre-printed labels from the blank
     cells someone has to write in. Browsers drop background colours when
     printing unless told not to. */
  .portfolio-record-table thead th,
  .portfolio-record-table .pf-summary {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .table-scroll { overflow: visible !important; }
  .table-scroll.table-scroll-y { max-height: none !important; }
  .ledger {
    width: 100%;
    font-size: 0.72rem;
  }
  .ledger thead th {
    position: static !important;
    background: #e9e9e9 !important;
    color: #000 !important;
    border: 1px solid #999 !important;
    padding: 0.2rem 0.3rem !important;
    white-space: normal !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .ledger tbody tr { break-inside: avoid; }
  .ledger tbody tr:nth-child(even) { background: #f7f7f7 !important; }
  .ledger td {
    border: 1px solid #ccc !important;
    padding: 0.16rem 0.25rem !important;
  }
  .ledger .subj-div {
    border-left: 2px solid #888 !important;
  }

  /* Marks/inputs render as plain values, not editable-looking boxes */
  .ledger input, .save-bar input {
    border: none !important;
    background: transparent !important;
    -webkit-appearance: none;
    appearance: none;
    padding: 0.08rem !important;
    font-weight: 600;
    color: #000 !important;
  }

  /* Signature footer must never split onto — or land entirely on — a
     second page by itself: keep it as one block and let the browser's
     page-fit decide, rather than the table's own break spilling one
     extra row's worth of height past the footer. Paired with the
     tighter header/table/footer spacing above, this is what keeps a
     normal-size class on a single printed page. */
  .print-signature-row, .gs-signature-row {
    break-inside: avoid;
    page-break-inside: avoid;
  }

  /* Every wide grouped ledger (LO / Breakdown A-B / Written-Oral / Grade
     Ledger / Internal Form Detailed's rubric) MUST land at exactly 100% of
     the printable page width — never more (clipped past the page edge,
     silently, since print has no horizontal scroll) and never less
     (whitespace down the right side instead of a full-bleed printout).
     table-layout:auto (the default, kept for the on-screen preview so
     .table-scroll can scroll sideways without squashing text — see the
     note by .ledger-lo above) only ever treats a declared width as a
     *preference*; the browser still lets the table grow past it to fit
     content — worse, any column with no declared width at all (just a
     min-width) is treated as fully flexible and absorbs 100% of whatever
     page width the other columns don't use, which is exactly what used to
     blow the Roll/Student Name/Student ID columns in the rubric table out
     into huge blank gaps. table-layout:fixed makes width 100% a hard rule
     instead, with EVERY column's share coming only from the <colgroup>
     the JS now emits — never from any cell's own width — so a column
     with no <col> entry can no longer silently claim the leftovers.
     See ledgerColgroupHtml() in admin-print-ledger.js for LO/Breakdown/
     Written-Oral/Grade Ledger, and renderDetailedColgroupHtml() in
     internal-form-detailed.js for the rubric table; changing a column's
     print share now only happens at those call sites. */
  .wide-ledger .ledger-lo,
  .wide-ledger .ledger-breakdown,
  .wide-ledger .ledger-rubric {
    table-layout: fixed !important;
    width: 100% !important;
  }

  /* Wide grouped ledgers (LO / Breakdown A / Breakdown B): compact
     everything so the full subject×sub-column grid fits one landscape
     A4 page. Header colour is intentionally left alone here now — it
     just inherits the plain light-gray .ledger thead th print style
     that the Grade Ledger also uses, instead of a separate dark/light
     two-tone treatment. */
  .wide-ledger .ledger-lo {
    font-size: 0.62rem;
  }
  .wide-ledger .ledger-lo td,
  .wide-ledger .ledger-lo thead tr:first-child th {
    padding: 0.18rem 0.1rem !important;
    border: 1px solid #bbb !important;
  }
  /* Fixed height (see the matching on-screen rule for why "let it size
     itself" doesn't work with a rotate() transform) — comfortably fits
     the longest rotated label at this print font-size without spilling
     into the subject-name row above. */
  .wide-ledger .ledger-lo thead tr:last-child th {
    padding: 0.35rem 0.25rem !important;
    border: 1px solid #bbb !important;
    font-size: 0.68rem !important;
    height: 118px !important;
  }
  .ledger-lo tbody td {
    color: var(--ink) !important;
  }
  .ledger-lo tbody tr:nth-child(even) td {
    background: #f7f9fc !important;
  }

  /* Classes 6-10 (Breakdown A/B): the widest ledgers on the page (up to
     7 subjects × 5 sub-columns = 35+ data columns). The general
     .wide-ledger .ledger-lo sizing above still overlaps at that width,
     so shrink text and padding further just for these. */
  .wide-ledger .ledger-breakdown {
    font-size: 0.52rem;
  }
  .wide-ledger .ledger-breakdown td,
  .wide-ledger .ledger-breakdown thead tr:first-child th {
    padding: 0.12rem 0.06rem !important;
  }
  .wide-ledger .ledger-breakdown thead tr:last-child th {
    font-size: 0.58rem !important;
    padding: 0.25rem 0.15rem !important;
    height: 98px !important;
  }
  /* Student ID cell (Grade Ledger only) carries Tailwind's .text-xs
     (0.75rem) for on-screen legibility — nearly double the Grade Ledger's
     compressed 0.52rem print size, and wide enough on its own to spill
     into the next column since a long numeric ID has no natural break
     point for word-wrap. Force it down to match the surrounding print
     size (the colgroup above already gives this column extra width on
     top of that), and add break-all purely as a safety net so an
     ID longer than expected wraps onto a second line instead of
     overlapping — it should never actually need to at this size. */
  .wide-ledger .ledger-breakdown td.font-mono-data {
    font-size: 0.5rem !important;
    line-height: 1.15 !important;
    letter-spacing: -0.01em;
    white-space: normal !important;
    word-break: break-all;
  }

  /* Internal Form (Detailed): one subject's full rubric only (not a
     multi-subject grid like Breakdown A/B above), but Nepali criterion
     names run long — compact print sizing so every rotated column still
     fits one landscape page, same idea as .ledger-lo/.ledger-breakdown
     above. */
  .wide-ledger .ledger-rubric {
    font-size: 0.62rem;
  }
  .wide-ledger .ledger-rubric td,
  .wide-ledger .ledger-rubric thead tr:first-child th {
    padding: 0.15rem 0.1rem !important;
  }
  /* Height only — NOT width/min-width here. Each column's width is set
     inline per-label by rotColumnWidthRem() in internal-form-detailed.js
     (narrow for a short criterion name, wider for a long one); a blanket
     width override here would force every column back to the same size
     and reintroduce the overflow this was built to avoid. */
  .wide-ledger .ledger-rubric th.rot-th {
    height: 112px !important;
  }
  /* Targets the label span directly, not just the th — the span carries
     its own explicit font-size and max-height (see the base
     .ledger-rubric th.rot-th .rot-label rule), neither of which the
     th's own font-size/height alone would override. The shorter
     max-height keeps the rotated label's wrap point under the shorter
     112px print row above (max-height, not max-width, for the same
     vertical-rl axis-mapping reason as the base rule — see its
     comment). */
  .wide-ledger .ledger-rubric th.rot-th .rot-label {
    max-height: 6.6rem !important;
    font-size: 0.58rem !important;
  }
  .wide-ledger .ledger-rubric .ledger-maxrow th {
    font-size: 0.66rem !important;
    padding: 0.18rem 0.08rem !important;
  }
  .wide-ledger .ledger-rubric th.ledger-maxrow-cell.rot-accent-grand {
    font-size: 0.74rem !important;
  }
  .wide-ledger .ledger-rubric td.font-mono-data {
    font-size: 0.52rem !important;
    word-break: break-all;
  }

  /* Nepali only (NEPALI_6_8 / NEPALI_9_10 — see the isNepaliRubric class
     hook in internal-form-detailed.js): its rubric has more leaf columns
     and longer criterion labels than any other subject's template, so
     even after the shared .wide-ledger .ledger-rubric compaction above
     (which every subject gets) it was still tall/wide enough to spill
     onto a second printed page. These rules sit ALONGSIDE that shared
     block rather than editing it, and only ever match a table carrying
     this extra class — so no other subject's Detailed print is touched. */
  .wide-ledger .ledger-rubric.ledger-rubric-nepali {
    font-size: 0.56rem;
  }
  .wide-ledger .ledger-rubric.ledger-rubric-nepali td,
  .wide-ledger .ledger-rubric.ledger-rubric-nepali thead tr:first-child th {
    padding: 0.1rem 0.06rem !important;
  }
  .wide-ledger .ledger-rubric.ledger-rubric-nepali th.rot-th {
    height: 92px !important;
  }
  .wide-ledger .ledger-rubric.ledger-rubric-nepali th.rot-th .rot-label {
    max-height: 5.4rem !important;
    font-size: 0.52rem !important;
  }
  .wide-ledger .ledger-rubric.ledger-rubric-nepali .ledger-maxrow th {
    font-size: 0.6rem !important;
    padding: 0.12rem 0.06rem !important;
  }
  .wide-ledger .ledger-rubric.ledger-rubric-nepali th.ledger-maxrow-cell.rot-accent-grand {
    font-size: 0.68rem !important;
  }
  .wide-ledger .ledger-rubric.ledger-rubric-nepali td.font-mono-data {
    font-size: 0.48rem !important;
  }

  /* Long student names still need somewhere to go now that every column's
     print width is fixed by the <colgroup> rather than by content —
     without this they'd overflow their cell sideways instead of wrapping
     to a second line, since fixed-layout cells no longer grow to fit
     unbroken text (that's the on-screen ledger-lo behaviour, deliberately
     kept only there — see the note above). */
  .wide-ledger .ledger-name-col {
    white-space: normal !important;
    word-break: break-word;
    overflow-wrap: break-word;
  }
  /* Roll/Student ID headers get the same print wrap treatment as
     Student Name above — needed here specifically because their Nepali
     labels (रोल नं. / सदस्यको इमिज आइडी) are longer than the
     plain "Roll"/"Student ID" this used to say. */
  .wide-ledger .ledger-rubric thead th.ledger-sn-col,
  .wide-ledger .ledger-rubric thead th.ledger-id-col {
    white-space: normal !important;
    overflow-wrap: anywhere;
  }
}

/* ---- Toasts ---- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 5.5rem;
  transform: translate(-50%, 12px);
  padding: 0.65rem 1.1rem;
  border-radius: 10px;
  font-size: 0.9rem;
  font-weight: 600;
  color: #fff;
  opacity: 0;
  transition: opacity 0.25s ease, transform 0.25s ease;
  z-index: 50;
  box-shadow: 0 6px 18px rgba(0,0,0,0.18);
}
.toast-success { background: var(--success); }
.toast-error { background: var(--error); }
.toast-show { opacity: 1; transform: translate(-50%, 0); }

/* ---- Confirm dialog — replaces the browser's native confirm() with a
   themed modal (see confirmDialog() in utils.js). Sits above the print
   preview modal (z-index 9999) and the PDF progress overlay (10000) so a
   confirmation can never be hidden behind either. ---- */
.confirm-overlay {
  position: fixed;
  inset: 0;
  background: rgba(27, 42, 74, 0.55);
  z-index: 10500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.25rem;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.confirm-overlay.confirm-show { opacity: 1; }
.confirm-box {
  background: var(--card);
  border-radius: 16px;
  box-shadow: 0 20px 50px rgba(27, 42, 74, 0.35);
  max-width: 26rem;
  width: 100%;
  padding: 1.5rem;
  transform: translateY(10px) scale(0.98);
  transition: transform 0.15s ease;
  border-top: 4px solid var(--gold);
}
.confirm-overlay.confirm-show .confirm-box { transform: translateY(0) scale(1); }
.confirm-box.confirm-danger { border-top-color: var(--error); }
.confirm-title {
  font-family: "Kalimati", "Poppins", "Nirmala UI", "Noto Sans Devanagari", sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 0.6rem;
}
.confirm-msg {
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--text);
  margin: 0 0 1.35rem;
  white-space: pre-line;
}
/* Text/password input for promptDialog() (see js/utils.js) — the same
   confirm-overlay/confirm-box shell as confirmDialog(), just with a
   field to type into (e.g. Manage Teachers' "Set new password"). */
.confirm-input {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 0.6rem 0.75rem;
  font-size: 0.92rem;
  border: 1.5px solid var(--border);
  border-radius: 8px;
  margin: -0.6rem 0 1.35rem;
  font-family: inherit;
}
.confirm-input:focus { outline: none; border-color: var(--gold); }
.confirm-input-error {
  color: var(--error);
  font-size: 0.8rem;
  margin: -1.1rem 0 1rem;
  display: none;
}
.confirm-input-error.confirm-input-error-show { display: block; }
.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
}
.confirm-actions button {
  padding: 0.55rem 1.1rem;
  font-size: 0.88rem;
  border: none;
  cursor: pointer;
}
.confirm-cancel {
  background: var(--cream);
  color: var(--ink);
  font-weight: 600;
  border-radius: 10px;
  border: 1.5px solid var(--border) !important;
}
.confirm-cancel:hover { background: var(--border); }
.confirm-ok {
  background: var(--ink);
  color: #fff;
  font-weight: 700;
  border-radius: 10px;
}
.confirm-ok:hover { background: var(--ink-light); }
.confirm-ok.confirm-ok-danger { background: var(--error); }
.confirm-ok.confirm-ok-danger:hover { background: #a4382f; }
body.confirm-open { overflow: hidden; }

/* ======================================================================
   सजावटी (professional + decorative) popup — सबै confirmDialog / alertDialog /
   promptDialog र toast यहीँबाट सजिन्छन् (js/utils.js)। kind: success · error ·
   warning · info · danger · question · input
   ====================================================================== */
.confirm-overlay {
  background: radial-gradient(ellipse at 50% 30%, rgba(47, 66, 112, 0.55), rgba(27, 42, 74, 0.78));
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}
.confirm-box {
  --dlg-accent: var(--gold);
  --dlg-accent-soft: #fdf3e2;
  position: relative;
  overflow: hidden;
  text-align: center;
  max-width: 24.5rem;
  padding: 1.1rem 1.5rem 1.4rem;
  border: 1px solid var(--border);
  border-top: 1px solid var(--border);
  border-radius: 20px;
  background:
    radial-gradient(circle at 1px 1px, rgba(27, 42, 74, 0.045) 1px, transparent 0) 0 0 / 14px 14px,
    linear-gradient(180deg, var(--dlg-accent-soft) 0, #fff 7rem);
  box-shadow: 0 24px 60px rgba(27, 42, 74, 0.38), 0 0 0 4px rgba(255, 255, 255, 0.35);
  transform: translateY(14px) scale(0.94);
  transition: transform 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.25);
}
.confirm-box::before { /* माथिको रङ्गीन पट्टी */
  content: "";
  position: absolute; left: 0; right: 0; top: 0; height: 6px;
  background: linear-gradient(90deg, var(--ink), var(--dlg-accent), var(--gold), var(--dlg-accent), var(--ink));
}
.confirm-overlay.confirm-show .confirm-box { transform: translateY(0) scale(1); }
.confirm-box.confirm-danger, .confirm-box.dlg-danger { --dlg-accent: var(--error); --dlg-accent-soft: #fdeceb; border-top-color: var(--border); }
.confirm-box.dlg-error { --dlg-accent: var(--error); --dlg-accent-soft: #fdeceb; }
.confirm-box.dlg-success { --dlg-accent: var(--success); --dlg-accent-soft: #e9f5ee; }
.confirm-box.dlg-warning { --dlg-accent: #d98a14; --dlg-accent-soft: #fff4dc; }
.confirm-box.dlg-info, .confirm-box.dlg-input { --dlg-accent: var(--ink-light); --dlg-accent-soft: #eaeef8; }
.confirm-box.dlg-question { --dlg-accent: var(--gold-dark); --dlg-accent-soft: #fdf3e2; }

.dlg-ornament { display: flex; align-items: center; justify-content: center; gap: 0.5rem; margin: 0.55rem 0 0.7rem; color: var(--gold); font-size: 0.5rem; }
.dlg-ornament span { height: 1px; width: 3.2rem; background: linear-gradient(90deg, transparent, var(--gold)); }
.dlg-ornament span:last-child { background: linear-gradient(270deg, transparent, var(--gold)); }
.dlg-badge {
  width: 3.6rem; height: 3.6rem; margin: 0 auto 0.75rem;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; font-size: 1.55rem; color: #fff;
  background: linear-gradient(145deg, var(--dlg-accent), var(--ink));
  box-shadow: 0 0 0 5px var(--dlg-accent-soft), 0 0 0 6px var(--dlg-accent), 0 8px 18px rgba(27, 42, 74, 0.28);
  animation: dlgPop 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.4) both;
}
.dlg-badge-success { background: linear-gradient(145deg, #52a37b, var(--success)); }
.dlg-badge-error, .dlg-badge-danger { background: linear-gradient(145deg, #e0645b, var(--error)); }
.dlg-badge-warning { background: linear-gradient(145deg, #f2b043, #d98a14); }
.dlg-badge-info, .dlg-badge-input { background: linear-gradient(145deg, #4a6199, var(--ink)); }
.dlg-badge-question { background: linear-gradient(145deg, #f0b44f, var(--gold-dark)); }
@keyframes dlgPop { 0% { transform: scale(0.3) rotate(-18deg); opacity: 0; } 100% { transform: scale(1) rotate(0); opacity: 1; } }

.confirm-title { text-align: center; font-size: 1.12rem; margin: 0 0 0.45rem; }
.confirm-msg { text-align: center; margin: 0 0 1.3rem; max-height: 40vh; overflow-y: auto; overflow-wrap: anywhere; }
.confirm-input { margin: -0.5rem 0 1.2rem; text-align: left; background: #fff; }
.confirm-input:focus { box-shadow: 0 0 0 3px rgba(232, 163, 61, 0.25); }
.confirm-input-error { text-align: left; }
.confirm-actions { justify-content: center; gap: 0.7rem; }
.confirm-actions button { flex: 1 1 0; max-width: 11rem; padding: 0.62rem 1rem; transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease; }
.confirm-actions button:only-child { max-width: 14rem; }
.confirm-actions button:hover { transform: translateY(-1px); box-shadow: 0 6px 14px rgba(27, 42, 74, 0.2); }
.confirm-actions button:active { transform: translateY(0); }
.confirm-ok { background: linear-gradient(135deg, var(--ink-light), var(--ink)); }
.confirm-ok:hover { background: linear-gradient(135deg, #3b528a, var(--ink-light)); }
.confirm-ok.confirm-ok-danger { background: linear-gradient(135deg, #d85a51, var(--error)); }
.confirm-ok.confirm-ok-danger:hover { background: linear-gradient(135deg, #e0645b, #a4382f); }
.dlg-success .confirm-ok { background: linear-gradient(135deg, #52a37b, var(--success)); }
.dlg-error .confirm-ok { background: linear-gradient(135deg, #d85a51, var(--error)); }
.dlg-warning .confirm-ok { background: linear-gradient(135deg, #f2b043, #d98a14); color: #3a2a05; }
.confirm-ok:focus-visible, .confirm-cancel:focus-visible { outline: 3px solid rgba(232, 163, 61, 0.55); outline-offset: 2px; }

/* Toast — आइकनसहित, गोलाकार, रङ्गीन किनाराको */
.toast {
  display: flex; align-items: center; gap: 0.55rem;
  max-width: min(92vw, 28rem);
  padding: 0.7rem 1.1rem 0.7rem 0.8rem;
  border-radius: 14px;
  border-left: 5px solid rgba(255, 255, 255, 0.55);
  box-shadow: 0 10px 28px rgba(27, 42, 74, 0.28);
  z-index: 10600;
}
.toast .toast-icon { font-size: 1.15rem; flex: none; }
.toast-success { background: linear-gradient(135deg, #52a37b, var(--success)); }
.toast-error { background: linear-gradient(135deg, #d85a51, var(--error)); }
.toast-warning { background: linear-gradient(135deg, #f2b043, #d98a14); color: #3a2a05; }
.toast-info { background: linear-gradient(135deg, #4a6199, var(--ink)); }
@media (prefers-reduced-motion: reduce) { .dlg-badge { animation: none !important; } }

@media (prefers-reduced-motion: reduce) {
  .confirm-overlay, .confirm-box { transition: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ---- Login page background flourish ---- */
.login-bg {
  background:
    radial-gradient(circle at 15% 10%, rgba(232,163,61,0.12), transparent 40%),
    radial-gradient(circle at 85% 90%, rgba(27,42,74,0.10), transparent 45%),
    var(--cream);
}

/* ==========================================================================
   जिन्सी व्यवस्थापन (Inventory — Goods Entry मलेप ४०१ / Goods Issue मलेप ४०४)
   See inventory.html / js/inventory.js. Namespaced under .jinsi- so nothing
   here can collide with any existing page's styles.
   ========================================================================== */

.jinsi-tabs {
  display: flex;
  gap: 0.4rem;
  border-bottom: 2px solid var(--border);
  margin-bottom: 1.25rem;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.jinsi-tabs::-webkit-scrollbar { height: 5px; }
.jinsi-tabs::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
.jinsi-tab {
  padding: 0.65rem 1.1rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--muted);
  border-bottom: 3px solid transparent;
  margin-bottom: -2px;
  border-radius: 8px 8px 0 0;
  white-space: nowrap;
  flex-shrink: 0;
}
.jinsi-tab:hover { color: var(--ink); background: rgba(27,42,74,0.04); }
/* सक्रिय ट्याब — गाढा नीलो (--ink) भरिएको पृष्ठभूमि + सेतो अक्षर + सुनौलो तल्लो रेखा, ताकि झट्ट देखियोस्।
   (अघि रेखा मात्र फरक थियो।) */
.jinsi-tab.active,
.jinsi-tab.active:hover { color: #fff; background: var(--ink); border-bottom-color: var(--gold); box-shadow: 0 -2px 8px rgba(27,42,74,0.18); }
.jinsi-panel { display: none; }
.jinsi-panel.active { display: block; }

/* accounting-demand-forms.html — माथिल्लो तहको समूह-पट्टी (माग फारम / निकासा पत्र / भरपाई / तलब सेटअप)।
   सक्रिय समूह सुनौलो भरिएको ताकि उप-ट्याब (गाढा नीलो) भन्दा फरक झट्ट देखियोस्। */
.dm-groups { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.9rem; }
.dm-group {
  padding: 0.55rem 1.15rem; font-size: 0.92rem; font-weight: 800; color: var(--ink);
  background: #fff; border: 2px solid var(--border); border-radius: 999px; white-space: nowrap;
}
.dm-group:hover { border-color: var(--gold); background: rgba(232,163,61,0.12); }
.dm-group.active, .dm-group.active:hover { background: var(--gold); border-color: var(--gold); color: var(--ink); box-shadow: 0 2px 8px rgba(27,42,74,0.18); }
.dm-subbar[hidden] { display: none !important; }
/* मोबाइलमा समूह-पट्टी (माग फारमहरू / निकासा पत्रहरू / भरपाई / दायित्व हिसाब / तलब सेटअप) अर्को लाइनमा
   नमडिइकन एउटै पङ्क्तिमा आडो (horizontal) scroll हुने — उप-ट्याब पट्टी (.jinsi-tabs) जस्तै। */
@media (max-width: 768px) {
  .dm-groups {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    max-width: 100%;
    min-width: 0;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
    padding-bottom: 0.4rem;
  }
  .dm-groups::-webkit-scrollbar { height: 5px; }
  .dm-groups::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
  .dm-group { flex: 0 0 auto; padding: 0.5rem 0.95rem; font-size: 0.85rem; scroll-snap-align: start; }
}

/* Colourful tab icons — each tab gets its own accent instead of the
   same flat ink/gray, so the row reads as distinct sections at a
   glance instead of one long strip of identical text. Colour holds on
   hover/active too so it never goes flat on interaction. */
.jinsi-tab:nth-child(1) i { color: #2563eb; }
.jinsi-tab:nth-child(2) i { color: #d97706; }
.jinsi-tab:nth-child(3) i { color: #16a34a; }
.jinsi-tab:nth-child(4) i { color: #7c3aed; }
.jinsi-tab:nth-child(5) i { color: #0891b2; }
.jinsi-tab:nth-child(6) i { color: #dc2626; }
.jinsi-tab:nth-child(7) i { color: #be185d; }
.jinsi-tab:nth-child(8) i { color: #4d7c0f; }
.jinsi-tab:nth-child(9) i { color: #9333ea; }
.jinsi-tab:nth-child(10) i { color: #0d9488; }
.jinsi-tab:nth-child(11) i { color: #b45309; }
.jinsi-tab:nth-child(12) i { color: #0f766e; }
/* सक्रिय ट्याबमा गाढा पृष्ठभूमि भएकाले आइकन सेतो (रङ्गीन आइकन गाढा नीलोमा नदेखिने भएकाले) */
.jinsi-tab.active i { color: #fff; }

/* भित्री (nested) ट्याब-पट्टी — जस्तै "पाठ्यपुस्तक तथा शैक्षिक सामग्री भरपाई" भित्रका
   उप-ट्याबहरू। .jinsi-tab/.jinsi-panel कै लुक तर छुट्टै class नामले, ताकि
   accounting-bills.js को माथिल्लो-तहको wireTabs()/activateBillsTab() ले यिनलाई
   documenowide query (.jinsi-panel सबैलाई active हटाउने) मार्फत नछोओस्। */
.jinsi-tabs-sub {
  display: flex;
  gap: 0.35rem;
  border-bottom: 2px solid var(--border);
  margin-bottom: 1rem;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.jinsi-tabs-sub::-webkit-scrollbar { height: 5px; }
.jinsi-tabs-sub::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; }
.jinsi-tab-sub {
  padding: 0.5rem 0.9rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--muted);
  border-bottom: 3px solid transparent;
  margin-bottom: -2px;
  border-radius: 8px 8px 0 0;
  white-space: nowrap;
  flex-shrink: 0;
}
.jinsi-tab-sub:hover { color: var(--ink); background: rgba(27,42,74,0.04); }
.jinsi-tab-sub.active,
.jinsi-tab-sub.active:hover { color: #fff; background: var(--ink); border-bottom-color: var(--gold); box-shadow: 0 -2px 8px rgba(27,42,74,0.18); }
.jinsi-panel-sub { display: none; }
.jinsi-panel-sub.active { display: block; }

/* Empty-tab placeholder — accounting-demand-forms.html का ट्याबहरूमा,
   कुनै ट्याबको भित्री फिल्ड/ढाँचा अझै नतोकिँदासम्म देखाइने कार्ड।
   ट्याबको वास्तविक फारम तयार भएपछि यो कार्ड हटाएर सोही ठाउँमा राख्ने। */
.jinsi-placeholder-card {
  border: 1px dashed var(--border);
  border-radius: 12px;
  background: #fff;
  padding: 3rem 1.5rem;
  text-align: center;
  max-width: 32rem;
  margin: 1rem auto;
}
.jinsi-placeholder-icon {
  font-size: 2.25rem;
  color: var(--gold);
  margin-bottom: 0.75rem;
  display: block;
}

/* Status badges — Goods Entry approval state. */
.jinsi-badge {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
}
.jinsi-badge-pending { background: #fdf1de; color: var(--gold-dark); }
.jinsi-badge-approved { background: #e6f2ec; color: var(--success); }
.jinsi-badge-rejected { background: #fdeaea; color: var(--error); }

/* Repeatable line-item rows inside the Goods Entry / Goods Issue modals —
   deliberately not a <table> here (the record-edit-box is a narrow fixed-
   width panel, especially on mobile where it becomes a full-width bottom
   sheet) so each row just wraps its fields at any width instead of forcing
   a horizontal scroll for a 2-3 row form. */
.jinsi-line-row {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr auto;
  gap: 0.5rem;
  align-items: end;
  padding: 0.6rem 0;
  border-bottom: 1px dashed var(--border);
}
.jinsi-line-row:last-of-type { border-bottom: none; }
.jinsi-line-row label { font-size: 0.7rem; color: var(--muted); font-weight: 600; display: block; margin-bottom: 0.2rem; }
.jinsi-line-remove {
  color: var(--error);
  font-size: 1rem;
  padding: 0.5rem 0.4rem;
  border-radius: 8px;
}
.jinsi-line-remove:hover { background: #fdeaea; }
@media (max-width: 640px) {
  .jinsi-line-row { grid-template-columns: 1fr 1fr; }
  .jinsi-line-row .jinsi-line-amount,
  .jinsi-line-row .jinsi-line-remove { grid-column: span 1; }
}
.jinsi-line-stock-hint { font-size: 0.7rem; color: var(--muted); margin-top: 0.15rem; }
.jinsi-line-stock-hint.insufficient { color: var(--error); font-weight: 700; }

.jinsi-total-row {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  padding-top: 0.75rem;
  font-weight: 700;
  color: var(--ink);
}

/* ---- Printed A4 government form (मलेप ४०१ / ४०४) — rendered inside the
   shared .print-preview-body (see showPrintPreview() in utils.js), so it
   inherits that modal's toolbar/close/print-now behavior for free; only
   the form's own layout lives here. ---- */
.jinsi-print-form { font-family: "Kalimati", "Nirmala UI", "Noto Sans Devanagari", "Inter", sans-serif; color: #000; padding: 4mm; }
.jinsi-print-form .jp-header { text-align: center; margin-bottom: 3mm; }
.jinsi-print-form .jp-school-name { font-size: 1.15rem; font-weight: 800; }
.jinsi-print-form .jp-school-sub { font-size: 0.8rem; margin-top: 1px; }
.jinsi-print-form .jp-form-title {
  margin-top: 2mm;
  font-weight: 800;
  font-size: 0.95rem;
  text-decoration: underline;
}
.jinsi-print-form .jp-form-no { font-size: 0.75rem; color: #333; }
.jinsi-print-form .jp-meta-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.15rem 1rem;
  font-size: 0.82rem;
  margin: 3mm 0;
  border: 1px solid #000;
  padding: 2mm 3mm;
}
/* दुई-स्तम्भ छाप्ने ढाँचा — जस्तै फाराम २८ (वासलात) मा दायित्व/सम्पत्ति छेउछेउ */
.jinsi-print-form .jp-two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 4mm;
  align-items: start;
}
.jinsi-print-form table.jp-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
  margin-top: 2mm;
}
.jinsi-print-form table.jp-table th,
.jinsi-print-form table.jp-table td {
  border: 1px solid #000;
  padding: 1.2mm 1.8mm;
  text-align: left;
}
.jinsi-print-form table.jp-table th { background: #eee !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; text-align: center; }
.jinsi-print-form table.jp-table td.jp-num { text-align: right; font-family: "Roboto Mono", monospace; }
.jinsi-print-form .jp-total-row td { font-weight: 800; }
/* Repeat the <thead> on every printed page the table spans, and never let
   a single row get sliced across a page boundary — thead re-printing is
   the browser's default for an un-styled <thead>, but it's made explicit
   here (same as .ledger tbody tr elsewhere) so it doesn't silently depend
   on that default; the table itself is deliberately left free to break
   (no page-break-inside: avoid on table.jp-table) since it's exactly the
   long, all-items lists (जिन्सी सामान सूची / मौज्दात) that are meant to
   spill onto a repeated-header second, third... page rather than being
   squeezed or clipped onto one. */
.jinsi-print-form table.jp-table thead { display: table-header-group; }
.jinsi-print-form table.jp-table tbody tr { break-inside: avoid; page-break-inside: avoid; }
/* Modifier for the long, unbounded मौज्दात listings (Annual Statement /
   फाराम ३६ — every stock item; Item Ledger / फाराम ३२-३३ — every
   transaction on one item) where row COUNT, not column width, is what
   threatens to run the form past one page. Smallest still-legible print
   font + the tightest cell padding in the sheet, so the maximum number of
   rows land on each printed page before the browser has to start a new
   (still fully headed, per the rules above) one. */
.jinsi-print-form table.jp-table.jp-table-compact { font-size: 0.62rem; }
.jinsi-print-form table.jp-table.jp-table-compact th,
.jinsi-print-form table.jp-table.jp-table-compact td {
  padding: 0.5mm 1.3mm;
  line-height: 1.05;
}
/* दायित्व हिसाब प्रिन्ट मात्र — तालिकाको डाटा फन्ट ठूलो देखिने गरी बढाइएको, स्तम्भको
   प्याडिङ्ग भने अझ tight (कम) गरेर पूरै उपलब्ध चौडाइ (width) कसिलो/tight ढंगले भरिने
   बनाइएको। बाहिरी फारमको padding पनि यही प्रिन्टका लागि मात्र घटाइएको (Title/हस्ताक्षर
   लगायत सबैका लागि 4mm जस्तै साझा .jinsi-print-form बाट फरक पार्न — हेर्नुहोस् line 3600)।
   Title (jp-form-title) र थप स्पष्टीकरण (jp-form-no — आ.व./महिना जनाउने लाइन) ठूलो देखिएर
   प्रिन्ट पेजको धेरै ठाउँ ओगट्ने भएकोले Title small+bold र jp-form-no अझ tiny बनाइएको —
   बाँकी (jp-school-name/jp-school-sub) भने साझा .jinsi-print-form कै साइजमा। */
.dh-print.jinsi-print-form { padding: 2mm; }
.dh-print .jp-header { margin-bottom: 1.5mm; }
.dh-print .jp-form-title { font-size: 0.7rem; font-weight: 800; margin-top: 0.5mm; }
.dh-print .jp-form-no { font-size: 0.55rem; }
/* अक्षरको आकार देखिने स्तम्भ सङ्ख्या अनुसार (printDayitvaHisab ले dh-fs-lg/md/sm राख्छ) — स्तम्भ कम भए ठूलो */
.dh-print { --dh-body: 0.95rem; --dh-head: 0.8rem; }
.dh-print.dh-fs-lg { --dh-body: 1.08rem; --dh-head: 0.92rem; }
.dh-print.dh-fs-md { --dh-body: 0.98rem; --dh-head: 0.84rem; }
.dh-print.dh-fs-sm { --dh-body: 0.88rem; --dh-head: 0.76rem; }
.dh-print table.jp-table.jp-table-compact { font-size: var(--dh-body); }
.dh-print table.jp-table.jp-table-compact th,
.dh-print table.jp-table.jp-table-compact td {
  padding: 0.3mm 0.6mm;
  line-height: 1.08;
}
/* हरेक कार्यसमिति/कर्मचारीको पङ्क्ति सुरुदेखि अन्तिमसम्म सजिलै छुट्याउन मिलोस् भनेर zebra
   crossing जस्तै एक/एक पङ्क्ति फरक-फरक हल्का रङमा (जम्मा/tfoot पङ्क्ति भने सधैं छुट्टै) — DOM मा
   जस्तो देखिन्छ त्यही क्रम प्रिन्टमा पनि कायम राख्न nth-child प्रयोग गरिएको। */
/* माथिल्लो header tiny+bold र एउटै लाइनमा; नाम स्तम्भ पनि एउटै लाइनमा (स्क्रिनमा जस्तै) */
/* header: पहिले 0.6rem (धेरै मसिनो) थियो। अब ठूलो; लामो header JS ले दुई लाइनमा (<br>) तोडेको हुन्छ र हरेक लाइन
   एउटै पटकमा (nowrap) रहन्छ — त्यसैले स्तम्भको चौडाइ header ले होइन, डाटाले निर्धारण गर्छ। समूह (colspan) header
   भने आवश्यक परे आफैं मिलेर मोडिन्छ। */
.dh-print table.jp-table.jp-table-compact thead th {
  font-size: var(--dh-head);
  font-weight: 800;
  line-height: 1.15;
  white-space: nowrap;
}
.dh-print table.jp-table.jp-table-compact thead th.dh-grp-th { white-space: normal; }
/* रकमका कक्ष: चौडा monospace (Roboto Mono) को सट्टा फारमकै फन्ट (tabular अंक) — एउटै लाइनमा, कम चौडाइमा */
.dh-print table.jp-table td.jp-num { font-family: inherit; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dh-print table.jp-table.jp-table-compact thead th .dh-sub { font-size: inherit; font-weight: inherit; }
.dh-print table.jp-table.jp-table-compact tbody td:nth-child(2) { white-space: nowrap; }
.dh-print table.jp-table tbody tr:nth-child(odd) td {
  background: #fff;
}
.dh-print table.jp-table tbody tr:nth-child(even) td {
  background: #eef3f7 !important;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
/* तयार गर्ने र प्र.अ. हस्ताक्षरको ठीक बिचमा "कट्टीको सूची" — border भएको box भित्र, शीर्षक अनुसार
   कति जनाको कति रकम (र जम्मा कट्टी) एक-एक लाइनमा (हेर्नुहोस् dhPrintListHtml())। कसैको पनि
   कट्टी रकम नै नभए (hasAdj false) यो box नै नआउने — printDayitvaHisab() मा। */
.dh-print .dh-sign-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 3mm;
  margin-top: 14mm;
}
/* तयार गर्ने / प्रमाणित गर्ने हस्ताक्षर-खण्ड आफ्नै चौडाइमा मात्र; बाँकी सबै खाली चौडाइ बिचको बाकसले लिन्छ */
.dh-print .dh-sign-row > div:not(.dh-explain-box) {
  flex: 0 0 auto;
  white-space: nowrap;
}
/* कट्टीको सूची बाकस — दुबैतिर तन्किएर दायाँ/बायाँ हस्ताक्षर-क्षेत्रसम्म पुग्ने (पहिलेको max-width हटाइयो) */
.dh-print .dh-explain-box {
  flex: 1 1 0;
  min-width: 0;
  max-width: none;
  box-sizing: border-box;
  border: 1px solid #000;
  padding: 1.5mm 2mm;
  font-size: 0.7rem;
  line-height: 1.3;
  text-align: left;
}
.dh-print .dh-explain-title {
  font-weight: 800;
  text-decoration: underline;
  margin-bottom: 0.8mm;
}
.dh-print .dh-explain-line,
.dh-print .dh-explain-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 3mm;
}
.dh-print .dh-explain-line { border-bottom: 1px dotted #777; padding: 0.2mm 0; }
/* शीर्षक-खण्ड: शीर्षक (बोल्ड) अनि व्यक्ति-पिच्छे पूरा नाम + रकम दुई स्तम्भमा */
.dh-print .dh-explain-head { font-weight: 800; border-bottom: 1px solid #000; margin-top: 1mm; }
.dh-print .dh-explain-people { column-count: 2; column-gap: 5mm; }
.dh-print .dh-explain-person { display: flex; justify-content: space-between; gap: 2mm; border-bottom: 1px dotted #999; padding: 0.15mm 0; break-inside: avoid; }
.dh-print .dh-explain-pname { min-width: 0; }
.dh-print .dh-explain-amt { flex: 0 0 auto; white-space: nowrap; font-variant-numeric: tabular-nums; }
.dh-print .dh-explain-total {
  font-weight: 800;
  border-top: 1px solid #000;
  margin-top: 0.8mm;
  padding-top: 0.6mm;
}
.jinsi-print-form .jp-signatures {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2mm;
  margin-top: 10mm;
  text-align: center;
  font-size: 0.78rem;
}
.jinsi-print-form .jp-sig-line { border-top: 1px solid #000; margin: 8mm 4mm 1mm; }
/* दुई-स्तम्भ हस्ताक्षर-खण्ड — "तयार गर्नेको"/"प्रमाणित गर्नेको" वा
   "पेश गर्नेको"/"स्वीकृत गर्नेको" जस्ता फाराम (१९, २०, २९, ३०, ३१, ३२-३७) मा
   जहाँ हस्ताक्षर अघि लाइन नभई नाम/ठेगाना/मिति/दर्जा जस्ता लेबल-पंक्तिहरू नै
   सिधै देखिन्छन्, dstta va rekha bina. */
.jinsi-print-form .jp-signatures-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2mm 6mm;
  margin-top: 8mm;
  font-size: 0.8rem;
}
.jinsi-print-form .jp-signatures-2 p { margin: 1.2mm 0; }
.jinsi-print-form .jp-remarks { margin-top: 3mm; font-size: 0.78rem; }

/* ---- Letterpad (सिरान · फुटर · वाटरमार्क) को स्टाइल अब js/letterpad-core.js (LHLetterpad.css) मा छ — एउटै स्रोत,
   पुरानो absolute-position डिजाइन हटाइएको छ। यहाँ केवल चिठीको पाठ (.letterpad-body …) को स्टाइल छ। ---- */
.jinsi-print-form .letterpad-body { font-size: 1.05rem; line-height: 1.8; margin-top: 1mm; text-align: justify; }
.jinsi-print-form .letterpad-sheet + .letterpad-body { margin-top: 7mm; }
/* Main message paragraphs start with a Word-style tab (first-line indent of
   12.7 mm = Word's default 0.5" tab stop). */
.jinsi-print-form .letterpad-body .lt-para { text-align: justify; text-indent: 12.7mm; }
/* चिठी Body (WYSIWYG) — सूची र अलाइनमेन्ट */
.jinsi-print-form .letterpad-body ul { list-style: disc; padding-left: 1.6em; margin: 0.3em 0 0.6em; text-align: left; }
.jinsi-print-form .letterpad-body ol { list-style: decimal; padding-left: 1.8em; margin: 0.3em 0 0.6em; text-align: left; }
.jinsi-print-form .letterpad-body li { margin: 0.1em 0; }
.lt-al-left { text-align: left !important; }
.lt-al-center { text-align: center !important; text-indent: 0 !important; }
.lt-al-right { text-align: right !important; text-indent: 0 !important; }
.lt-al-justify { text-align: justify !important; }
/* ---- WYSIWYG सम्पादक (पत्र सम्पादन popup) ---- */
.lt-rich-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 6px; border: 1px solid var(--border, #d9d4c7); border-bottom: 0; border-radius: .5rem .5rem 0 0; background: var(--cream, #fbf9f4); }
.lt-rich-bar button { min-width: 1.9rem; height: 1.9rem; padding: 0 .45rem; border: 1px solid var(--border, #d9d4c7); border-radius: .35rem; background: #fff; font-size: .78rem; cursor: pointer; }
.lt-rich-bar button:hover { background: #efe9da; }
.lt-rich-bar button:disabled { opacity: .5; cursor: not-allowed; }
.lt-rich-sep { width: 1px; height: 1.4rem; background: var(--border, #d9d4c7); margin: 0 3px; }
.lt-rich-tbl { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: .75rem; }
.lt-rich-tbl input[type="number"] { width: 3.4rem; height: 1.9rem; padding: 0 .3rem; border: 1px solid var(--border, #d9d4c7); border-radius: .35rem; }
.lt-rich-bar button.active { background: #e6dcc4; border-color: var(--primary, #8a5a1f); }
.lt-rich-bar.hidden { display: none !important; }
/* तालिका icon थिचेपछि मात्र देखिने नियन्त्रण पट्टी (पङ्क्ति/स्तम्भ/शीर्षक, + − पङ्क्ति/स्तम्भ, delete) */
.lt-rich-tblpanel { flex: 1 0 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 2px; padding-top: 6px; border-top: 1px dashed var(--border, #d9d4c7); }
.lt-rich-tblpanel.hidden { display: none !important; }
.rt-moderow { display: flex; flex-wrap: wrap; gap: .9rem; align-items: center; }
.rt-moderow-radios { display: inline-flex; flex-wrap: wrap; gap: .9rem; align-items: center; }
.rt-moderow-radios.hidden { display: none !important; }
.rt-moderow button.active { background: #e6dcc4; border-color: var(--primary, #8a5a1f); }
/* डाटा खोजेर घुसाउने panel */
.rt-datapanel { padding: .7rem; border: 1px solid var(--border, #d9d4c7); border-radius: .5rem; background: var(--cream, #fbf9f4); }
.rt-datapanel.hidden { display: none !important; }
.rt-data-tabs { display: flex; flex-wrap: wrap; gap: .3rem; align-items: center; margin-bottom: .5rem; }
.rt-data-tabs button { padding: .3rem .7rem; font-size: .78rem; font-weight: 700; border: 1px solid var(--border, #d9d4c7); border-radius: 999px; background: #fff; }
.rt-data-tabs button.active { background: var(--ink, #1b2a4a); color: #fff; border-color: var(--ink, #1b2a4a); }
.rt-data-tabs .rt-data-close { margin-left: auto; border-radius: .35rem; }
.rt-data-searchrow { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: .5rem; }
.rt-data-searchrow input { flex: 1 1 14rem; min-width: 0; }
.rt-data-searchrow select { flex: 0 0 9rem; }
.rt-data-searchrow select.hidden { display: none !important; }
.rt-data-list { max-height: 15rem; overflow: auto; border: 1px solid var(--border, #d9d4c7); border-radius: .4rem; background: #fff; }
.rt-data-row { display: flex; align-items: baseline; gap: .5rem; padding: .35rem .6rem; border-bottom: 1px solid #efe9da; cursor: pointer; font-size: .82rem; }
.rt-data-row:hover { background: #faf6ea; }
.rt-data-row input { flex: 0 0 auto; }
.rt-data-t { font-weight: 700; }
.rt-data-s { color: var(--muted, #6b6b6b); font-size: .74rem; }
.rt-data-empty { padding: .8rem; font-size: .8rem; color: var(--muted, #6b6b6b); }
.rt-data-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: .4rem; }
.rt-data-foot > span { margin-right: auto; color: var(--muted, #6b6b6b); }
.rt-data-h { margin: .6rem 0 .25rem; font-weight: 700; color: var(--muted, #6b6b6b); }
.rt-data-fields { display: flex; flex-wrap: wrap; gap: .3rem .5rem; }
.rt-chip { display: inline-flex; align-items: center; gap: .3rem; padding: .15rem .55rem; font-size: .76rem; border: 1px solid var(--border, #d9d4c7); border-radius: 999px; background: #fff; cursor: pointer; }
.rt-data-fmt { display: flex; flex-wrap: wrap; gap: .5rem .9rem; align-items: center; }
.rt-data-fmt label { display: inline-flex; align-items: center; gap: .3rem; }
/* चिठी — Full page editor */
.record-edit-overlay.rt-fullpage { padding: 0; align-items: stretch; justify-content: stretch; }
.rt-fullpage .record-edit-box { max-width: none; max-height: none; height: 100%; border-radius: 0; box-shadow: none; }
.rt-fullpage .record-edit-body { padding: 1.1rem clamp(1rem, 5vw, 4rem); }
.rt-fullpage .record-edit-grid { max-width: 64rem; margin: 0 auto; }
.rt-fullpage .lt-rich-editor { min-height: 24rem; max-height: none; }
.rt-fullpage .record-edit-actions { padding-left: clamp(1rem, 5vw, 4rem); padding-right: clamp(1rem, 5vw, 4rem); }
.lt-rich-editor { min-height: 14rem; max-height: 28rem; overflow: auto; padding: .7rem .9rem; border: 1px solid var(--border, #d9d4c7); border-radius: 0 0 .5rem .5rem; background: #fff; line-height: 1.8; text-align: justify; outline: none; }
.lt-rich-editor:focus { border-color: var(--primary, #8a5a1f); box-shadow: 0 0 0 2px rgba(138, 90, 31, .15); }
.lt-rich-editor:empty::before { content: attr(data-placeholder); color: #9a9484; pointer-events: none; }
.lt-rich-editor[contenteditable="false"] { background: #f6f4ee; }
.lt-rich-editor > p, .lt-rich-editor > div { text-indent: 12.7mm; margin: 0 0 .35em; }
.lt-rich-editor ul { list-style: disc; padding-left: 1.6em; margin: .3em 0 .6em; text-align: left; }
.lt-rich-editor ol { list-style: decimal; padding-left: 1.8em; margin: .3em 0 .6em; text-align: left; }
.lt-rich-editor table { width: 100%; border-collapse: collapse; margin: .5em 0; text-indent: 0; text-align: left; line-height: 1.4; }
.lt-rich-editor th, .lt-rich-editor td { border: 1px solid #444; padding: 3px 7px; min-width: 2rem; vertical-align: top; }
.lt-rich-editor th { font-weight: 700; background: #f0f0f0; }
.lt-rich-editor td > p, .lt-rich-editor th > p { margin: 0; text-indent: 0; }
/* चिठीभित्रको तालिका (Body मा "| क | ख |" ढाँचाबाट) */
.jinsi-print-form .letterpad-body .lt-table { width: 100%; border-collapse: collapse; margin: 0.5em 0 0.9em; font-size: 0.95em; line-height: 1.4; text-align: left; text-indent: 0; }
.jinsi-print-form .letterpad-body .lt-table th,
.jinsi-print-form .letterpad-body .lt-table td { border: 1px solid #000; padding: 3px 7px; vertical-align: top; }
.jinsi-print-form .letterpad-body .lt-table th { font-weight: 700; background: #f0f0f0; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.jinsi-print-form .letterpad-body .lt-table tr { page-break-inside: avoid; break-inside: avoid; }
/* सम्बोधन (महोदय, / Dear Sir/Madam,) — flush left, a little air before the message. */
.jinsi-print-form .letterpad-body .lt-salutation { text-align: left; margin: 0 0 0.9em; }
/* सूचना (Notice) heading */
.jinsi-print-form .letterpad-body .lt-notice-title { text-align: center; font-weight: 700; font-size: 1.3em; margin: 0.6em 0 0.5em; }
/* ---- Letters as a real A4 page: the signature block always sits at the
   foot of the page (a flexible spacer pushes it down), however short or long
   the body is. 279mm = A4's 297mm minus the 8mm top/bottom @page margins,
   with a little slack so it never spills a blank second page. ---- */
.jinsi-print-form.letter-page { display: flex; flex-direction: column; min-height: 279mm; }
.jinsi-print-form.letter-page .letterpad-body { flex: 1 1 auto; display: flex; flex-direction: column; }
.jinsi-print-form.letter-page .lt-spacer { flex: 1 1 auto; min-height: 12mm; }
/* चिठीको अक्षर-आकार स्वतः: fitLetterBodyText() (js/utils.js) ले पाठको लम्बाइअनुसार
   --lt-k (आधार 1.05rem को गुणक) र --lt-lh (लाइन-उचाइ) यही .letter-page मा राख्छ —
   छोटो चिठी ठूलो अक्षरमा, लामो चिठी एक A4 पानामा अटाउने गरी सानो। मान नराखिए
   (जस्तै तालिकायुक्त निकासा/बैंक पत्र) पुरानै 1.05rem / 1.8 रहन्छ। */
.jinsi-print-form.letter-page .letterpad-body { font-size: calc(1.05rem * var(--lt-k, 1)); line-height: var(--lt-lh, 1.8); text-rendering: geometricPrecision; }
.jinsi-print-form.letter-page .letter-sign { margin-top: 0; font-size: 0.95em; width: calc(52mm * var(--lt-k, 1)); }
/* तलब निकासा पत्र (तालिका सहित): fitLetterBodyText() ले --lt-k घटाएर एउटै A4 पानामा
   अटाउँछ — तालिकाको अक्षर र कक्षको खाली ठाउँ पनि उही गुणकसँगै सानो हुन्छ। */
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.jp-table { font-size: calc(0.78rem * var(--lt-k, 1)); }
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.jp-table th,
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.jp-table td { padding: calc(1.2mm * var(--lt-k, 1)) calc(1.8mm * var(--lt-k, 1)); line-height: 1.25; }
.jinsi-print-form.letter-page .lt-fit-table .lt-spacer { min-height: 4mm; }
.print-preview-body.a4-preview { background: #e5e7eb; }

/* ---- A4 canvas for every printed FORM (ई-हाजिरी, माग/खर्च/आम्दानी/जिन्सी फारम, बिदा
   अभिलेख ...) — showPrintPreview() wraps the form in
   .form-a4-stage > .form-a4-paper > .form-a4-fit (js/utils.js, wrapFormA4Html()).
   The sheet is a REAL A4 page in the preview too: 210x297mm portrait (297x210mm
   landscape when the caller passes "wide-ledger"), with the same margin the @page
   rule uses (8mm / 6mm), so .form-a4-fit is exactly the printable width
   (194mm / 285mm) on screen AND on paper. The form therefore wraps the same way
   in preview and print — no more "fits in preview, signature falls onto page 2".
   A narrow phone screen just scales the whole sheet down (fitA4PreviewToScreen()). ---- */
.form-a4-stage { margin: 0 auto 14px; width: 210mm; max-width: none; --form-w: 194mm; }
.form-a4-stage.form-a4-land { width: 297mm; --form-w: 285mm; }
.form-a4-paper {
  width: 210mm; min-height: 297mm; box-sizing: border-box; padding: 8mm;
  background: #fff; box-shadow: 0 2px 14px rgba(0, 0, 0, 0.28);
}
.form-a4-land .form-a4-paper { width: 297mm; min-height: 210mm; padding: 6mm; }
.form-a4-fit { width: var(--form-w); box-sizing: border-box; }
/* ---- एउटै पेजमा अटाउन: लाइन स्पेसिङ / खाली ठाउँ घटाउने तह ----
   fitFormsToOnePage() (js/utils.js) ले फारम पानाभन्दा अग्लो भए पहिले form-tight-1, अझै
   अग्लो भए form-tight-2 थप्छ — अक्षरको साइज नबदली पङ्क्तिबीचको दूरी, हस्ताक्षर माथिको
   खाली ठाउँ, शीर्षकको margin घटाएर; त्यसपछि मात्र (चाहिए) zoom गरिन्छ। स्क्रिन र छाप्दा उस्तै। */
/* Useful Forms (सम्पत्ति विवरण …): a multi-page form, one sheet per person; each person starts on a new page. */
.form-a4-fit .uf-page + .uf-page { margin-top: 10mm; padding-top: 6mm; border-top: 1px dashed #bbb; }
@media print {
  .form-a4-fit .uf-page + .uf-page { break-before: page; page-break-before: always; margin-top: 0; padding-top: 0; border-top: 0; }
}
.form-tight-1 .jp-header { margin-bottom: 1.5mm; }
.form-tight-1 .jp-form-title { margin-top: 1mm; }
.form-tight-1 table.jp-table { margin-top: 1mm; }
.form-tight-1 table.jp-table th, .form-tight-1 table.jp-table td { padding-top: 0.6mm !important; padding-bottom: 0.6mm !important; line-height: 1.2 !important; }
.form-tight-1 .jp-signatures, .form-tight-1 .jp-signatures-2 { margin-top: 5mm !important; }
.form-tight-1 .jp-sig-line { margin-top: 5mm; }
.form-tight-1 .jp-signatures-2 p { margin: 0.6mm 0; }
.form-tight-1 .jp-remarks, .form-tight-1 .tp-legend, .form-tight-1 .tb-legend { margin-top: 1mm !important; line-height: 1.2 !important; }
.form-tight-1 table.tb-grid:not(.tb-mgrid) tr, .form-tight-1 table.tb-grid:not(.tb-mgrid) td { height: 3.6mm !important; }
.form-tight-2 .jp-header { margin-bottom: 1mm; }
.form-tight-2 .jp-form-title { margin-top: 0.5mm; }
.form-tight-2 table.jp-table { margin-top: 0.5mm; }
.form-tight-2 table.jp-table th, .form-tight-2 table.jp-table td { padding-top: 0.2mm !important; padding-bottom: 0.2mm !important; line-height: 1.1 !important; }
.form-tight-2 .jp-signatures, .form-tight-2 .jp-signatures-2 { margin-top: 3mm !important; }
.form-tight-2 .jp-sig-line { margin-top: 3mm; }
.form-tight-2 .jp-signatures-2 p { margin: 0.3mm 0; }
.form-tight-2 .jp-remarks, .form-tight-2 .tp-legend, .form-tight-2 .tb-legend { margin-top: 0.5mm !important; line-height: 1.1 !important; }
.form-tight-2 table.tb-grid:not(.tb-mgrid) tr, .form-tight-2 table.tb-grid:not(.tb-mgrid) td { height: 3mm !important; }
/* The preview modal's own wide-ledger side padding/overflow must not squeeze the sheet. */
.print-preview-body.form-a4-preview { overflow-x: auto; }
.letter-a4-stage { margin: 0 auto; width: 210mm; max-width: none; }
.letter-a4-paper {
  width: 210mm; min-height: 297mm; box-sizing: border-box; padding: 8mm;
  background: #fff; box-shadow: 0 2px 14px rgba(0, 0, 0, 0.28);
}
/* Several A4 sheets on screen (multi-page notice) — a small gap between them. */
.letter-a4-stage + .letter-a4-stage { margin-top: 14px; }

/* == नतिजा सूचना (Result Notice): table of passed students + पुनश्च/QR ==
   Row heights are FIXED (nowrap + ellipsis, explicit height) so how many rows
   fit on one A4 sheet is exact — see RESULT_NOTICE_PAGE in js/utils.js. */
.jinsi-print-form .letterpad-body .lt-nb { white-space: nowrap; }
.jinsi-print-form .letterpad-body .lt-url { overflow-wrap: anywhere; word-break: break-all; }
/* Result notice: tighter line-height than a plain letter (the sheet also has to hold the table). */
.jinsi-print-form.letter-page .letterpad-body.lt-result-body { line-height: var(--lt-lh, 1.65); }
/* The gap above the signature only needs to be a hair on a result sheet — the table is what uses the page. */
.jinsi-print-form.letter-page .lt-result-body .lt-spacer { min-height: 3mm; }
.jinsi-print-form .letterpad-body .lt-result-title { font-size: 1.12em; line-height: 1.5; margin: 0.5em 0 0.7em; }
/* "कक्षा १० को" — red, bold, underlined (message + continuation line). */
.jinsi-print-form .letterpad-body .lt-class-hl {
  color: #d10000; font-weight: 700; text-decoration: underline; white-space: nowrap;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.jinsi-print-form .lt-cont-head { font-size: 1em; font-weight: 700; text-align: left; margin: 1mm 0 2mm; }
.jinsi-print-form .letterpad-body .lt-more { text-align: right; font-weight: 700; margin: 1.5mm 0 0; }
.lt-result-table {
  width: 100%; border-collapse: collapse; table-layout: fixed;
  font-size: var(--rfs, 0.85rem); margin: 2mm 0 0; color: #000;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.lt-result-table th, .lt-result-table td {
  border: 1px solid #000; padding: 0 1.5mm; height: var(--rh, 7mm); line-height: 1.2;
  text-align: center; vertical-align: middle;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lt-result-table thead th { height: var(--thh, 9mm); font-weight: 700; background: #f2f2f2; white-space: normal; line-height: 1.15; font-size: var(--thfs, 0.8rem); }
.lt-result-table td.lt-rt-name { text-align: left; }
/* इमिज आइडी (16 अङ्क) पूरै देखिने — Latin अङ्कको साँघुरो फन्ट, कहिल्यै नकाटिने। */
.lt-result-table td.lt-rt-id { font-family: Arial, "Liberation Sans", Helvetica, sans-serif; letter-spacing: 0; padding: 0 0.5mm; overflow: visible; text-overflow: clip; }
/* Two column groups side by side on one sheet (class too long for a single list) */
.lt-result-2col { display: flex; gap: 2mm; align-items: flex-start; margin-top: 2mm; }
.lt-result-2col .lt-result-table { width: calc(50% - 1mm); flex: 0 0 auto; margin: 0; }
.lt-result-table2 th, .lt-result-table2 td { padding: 0 0.6mm; }
.lt-result-table2 td.lt-rt-id { padding: 0; }
/* second column group: a light shade so the two groups read as separate lists */
.lt-result-2col .lt-result-table2:nth-child(2) tbody td { background: #ececec; }
/* Top-4 position in कैफियत */
.lt-result-table .lt-top { color: #d10000; font-weight: 700; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
/* medal before a Top-4 position — emoji fonts, colour kept as drawn */
.lt-result-table .lt-top .lt-medal { font-family: "Segoe UI Emoji", "Apple Color Emoji", "Noto Color Emoji", "Twemoji Mozilla", sans-serif; font-weight: 400; margin-right: 0.6mm; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
/* GPA beside the position: Latin digits/letters in Arial (the Kalimati font would draw 3.85 with Devanagari digits) */
.lt-result-table .lt-top .lt-gpa { font-family: Arial, "Liberation Sans", Helvetica, sans-serif; font-size: 0.92em; letter-spacing: 0; }
.lt-result-table td.lt-rk, .lt-result-table:has(.lt-top) td:nth-child(6) { padding-left: 0.4mm; padding-right: 0.4mm; overflow: visible; text-overflow: clip; }
/* क्र.सं., इमिज आइडी, रोल नं./सिम्बोल नं., जीपीए/कैफियत, कक्षा स्थान — always centred (only the name stays left).
   The generic ".letterpad-body table td { text-align:left }" rule is more specific than the table's own, hence this. */
.jinsi-print-form .letterpad-body .lt-result-table td:not(.lt-rt-name) { text-align: center; }
.jinsi-print-form .letterpad-body .lt-result-table td .lt-top { display: inline-block; text-align: center; }
.lt-result-table thead { display: table-header-group; }
.lt-result-table tr { break-inside: avoid; page-break-inside: avoid; }
.jinsi-print-form .letterpad-body .lt-postscript { text-align: left; text-indent: 0; margin: 3mm 0 1mm; font-size: 0.95em; }
/* Result QR — centred; --qr is set per notice (grows into any spare room on the sheet). */
.jinsi-print-form .letterpad-body .lt-qr { display: flex; justify-content: center; margin: 1mm 0 3mm; }
.jinsi-print-form .letterpad-body .lt-qr img { width: var(--qr, 28mm); height: var(--qr, 28mm); object-fit: contain; }
/* QR does not fit under the पुनश्च line -> it sits IN the signature row: centred on the page
   (equal 1fr columns either side of it), the signature block stays at the right. */
.jinsi-print-form .letterpad-body .lt-sign-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: end; break-inside: avoid; page-break-inside: avoid; }
.jinsi-print-form .letterpad-body .lt-sign-row .lt-sign-qr { grid-column: 2; grid-row: 1; display: flex; }
.jinsi-print-form .letterpad-body .lt-sign-row .lt-sign-qr img { width: var(--qr, 26mm); height: var(--qr, 26mm); object-fit: contain; }
.jinsi-print-form .letterpad-body .lt-sign-row .letter-sign { grid-column: 3; grid-row: 1; justify-self: end; margin: 0; }
/* Off-screen measuring of the result notice (buildResultNoticePagesFitted() in js/utils.js):
   the text column is 6mm narrower so a line that only just fits on screen counts as wrapped —
   print can break it either way. */
.lt-measure-host .letterpad-body.lt-result-body { padding-right: 6mm; }
.jinsi-print-form .letterpad-body .lt-closing { margin-top: 4mm; }
.lt-badge { display: inline-block; padding: 1px 8px; border-radius: 999px; font-size: 0.72rem; font-weight: 700; white-space: nowrap; }
.lt-badge-draft { background: #fef3c7; color: #92400e; }
.lt-badge-pub { background: #dcfce7; color: #166534; }

/* == चिठी: हातैले प्रविष्ट गरिएको नम्बर (चलानी/दर्ता) र प्रणाली-निर्मित लिंकको सूचक == */
.lt-manual-flag { color: #b45309; margin-left: 0.3rem; cursor: help; }
.lt-view-link { color: var(--ink, #1b2a4a); text-decoration: none; border-bottom: 1px dashed var(--gold, #b8860b); }
.lt-view-link:hover { color: var(--gold-dark, #8a6200); border-bottom-style: solid; }
.lt-view-link i { font-size: 0.78em; margin-right: 0.2rem; color: var(--muted); }
.corr-src-icon { font-size: 0.78em; color: var(--muted); }
.corr-manual-link { color: #92400e; text-decoration: none; border-bottom: 1px dashed #b45309; }
.corr-manual-link:hover { color: #b45309; border-bottom-style: solid; }

/* == चिठी: सुरक्षित ठेगाना खोज/स्वतः-भर्ती ड्रपडाउन (see initLetters() in
   js/admin-correspondence.js) — the search box sits inside a position:relative
   wrapper (#lt_contactBox) so this panel floats directly below it. == */
.lt-contact-dropdown {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 20;
  background: #fff; border: 1px solid var(--border); border-radius: 0.6rem;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); max-height: 16rem; overflow-y: auto;
  padding: 0.35rem;
}
.lt-contact-dropdown.hidden { display: none; }
.lt-contact-empty { padding: 0.6rem 0.5rem; font-size: 0.78rem; color: var(--muted); text-align: center; }
.lt-contact-item { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; padding: 0.45rem 0.5rem; border-radius: 0.4rem; }
.lt-contact-item:hover { background: var(--cream, #fbf9f4); }
.lt-contact-item-main { flex: 1; min-width: 0; cursor: pointer; }
.lt-contact-item-title { font-size: 0.82rem; font-weight: 700; color: var(--ink); margin: 0; }
.lt-contact-item-sub { font-size: 0.74rem; color: var(--muted); margin: 1px 0 0; }
.lt-contact-item-subject { font-size: 0.72rem; color: var(--gold-dark, #8a6200); margin: 1px 0 0; font-style: italic; }
.lt-contact-item-actions { display: flex; gap: 0.3rem; flex-shrink: 0; }
.lt-contact-item-actions button { font-size: 0.78rem; color: var(--muted); padding: 0.2rem 0.4rem; border-radius: 0.3rem; }
.lt-contact-item-actions button:hover { background: #fff; color: var(--ink); }
.lt-contact-del:hover { color: #b91c1c !important; }
.lt-contact-edit-form { display: flex; flex-direction: column; gap: 0.35rem; width: 100%; }
.lt-contact-edit-form input { font-size: 0.78rem; padding: 0.4rem 0.55rem; }

/* == चिठी: चलानी नं. हातैले प्रविष्ट गरिएको भए देखिने औपचारिक सूचना == */
#lt_chalaniManualNote { background: #fffbeb; border: 1px solid #fde68a; color: #92400e; padding: 0.45rem 0.6rem; border-radius: 0.4rem; line-height: 1.5; }
#lt_chalaniManualNote i { margin-right: 0.3rem; }
#lt_autoSaveNote { color: var(--muted); font-style: italic; }
.jinsi-print-form .letterpad-body p { margin: 0 0 1.5mm; }
.jinsi-print-form .letterpad-recipient { margin-bottom: 3mm; }
.jinsi-print-form .letterpad-recipient p { margin: 0; }
/* Letter signature block (निकासा पत्र / बैंकलाई पत्र) — right-aligned, the
   digital signature image sits ON the line, centred over it; unticking
   "डिजिटल हस्ताक्षर" (see dmLetterSignatureHtml()) leaves the same blank
   space + line for a hand signature. */
.jinsi-print-form .letter-sign { width: 52mm; margin: 12mm 0 0 auto; text-align: center; break-inside: avoid; page-break-inside: avoid; font-size: 0.85rem; }
.jinsi-print-form .letter-sign .ls-mark { position: relative; height: 16mm; }
.jinsi-print-form .letter-sign .ls-mark img { position: absolute; left: 50%; bottom: 0.6mm; transform: translateX(-50%); max-height: 15mm; max-width: 100%; object-fit: contain; }
.jinsi-print-form .letter-sign .ls-line { border-top: 1px solid #000; }
.jinsi-print-form .letter-sign p { margin: 0.8mm 0 0; }
/* Letter body text is ALWAYS justified (set once on .letterpad-body above and
   inherited by every paragraph). The few things that must not be justified
   keep their own alignment: the table's column titles (th) and any caption are
   centred, table cells stay left (numbers right), the signature block is
   centred/right, and the subject line below is centred. */
.jinsi-print-form .letterpad-body table th,
.jinsi-print-form .letterpad-body table caption { text-align: center; }
.jinsi-print-form .letterpad-body table td { text-align: left; }
/* विषय — normal weight (not bold), underlined and centred, with exactly one
   blank line above and below (1 line = 1.8em, the body's line-height). The
   preview page is a flex column where margins don't collapse, so the
   recipient block's own 3mm bottom margin is dropped when the subject follows
   it — otherwise the space above would be a line PLUS 3mm. */
.jinsi-print-form .letterpad-body .letterpad-subject { font-weight: 400; text-decoration: underline; text-align: center; margin: 1.8em 0; }
/* चिठी / सूचना: विषय पछि थप एक खाली लाइन, ताकि विषय र मुख्य भाग बीच स्पष्ट ठाउँ रहोस्। */
.jinsi-print-form .letterpad-body .letterpad-subject.lt-subject { margin-bottom: 2.4em; }
.jinsi-print-form .letterpad-body .lt-notice-title + .letterpad-subject.lt-subject { margin-top: 0.6em; }
.jinsi-print-form .letterpad-recipient:has(+ .letterpad-subject) { margin-bottom: 0; }

/* ---- "खाली फाराम" (Blank Form) प्रिन्ट — हातैले भर्नका लागि खाली लाइन/    */
/* खाली पंक्ति। jp-blank-row ले सामान्य पंक्तिभन्दा अलि बढी अग्लो ठाउँ दिन्छ  */
/* ताकि कलमले भर्न मिल्ने ठाउँ रहोस्।                                        */
.jinsi-print-form .jp-blank-line {
  display: inline-block; border-bottom: 1px solid #000;
  min-width: 6rem; height: 1em; vertical-align: middle;
}
.jinsi-print-form table.jp-table tr.jp-blank-row td { height: 7mm; }
.jinsi-print-form table.jp-table.jp-table-compact tr.jp-blank-row td { height: 5mm; }

/* ---------------------------------------------------------------------- */
/* Icon color helpers — added when swapping emoji icons (🔴🟢🟡⚪🥇🥈🥉) for  */
/* Font Awesome <i> icons across the portal, so the colored-dot/medal      */
/* meaning those emoji carried isn't lost. Pair with fa-solid fa-circle    */
/* (or fa-regular for the empty/gray dot) and fa-solid fa-medal.           */
/* ---------------------------------------------------------------------- */
.status-dot-red { color: #dc2626; }
.status-dot-green { color: #16a34a; }
.status-dot-yellow { color: #ca8a04; }
.status-dot-gray { color: #9ca3af; }
.medal-gold { color: #d4af37; }
.medal-silver { color: #a8a9ad; }
.medal-bronze { color: #cd7f32; }

/* Inventory (जिन्सी) action-button icons — plain-ink fa-print/fa-plus
   read as flat/monochrome next to the coloured tab icons above; a
   little colour here keeps the page consistent instead of the tabs
   being the only spot of colour. */
#annualStatementBtn i, #printLandRegisterBtn i, #ledgerViewPrintBtn i { color: #0891b2; }
.jinsi-badge-pending i { color: var(--gold-dark); }
.jinsi-badge-approved i { color: var(--success); }
.jinsi-badge-rejected i { color: var(--error); }

/* ==========================================================================
   माग फारम (accounting-demand-forms.html) — A4 landscape sheet templates.
   Every measurement below is taken from the reference PDFs (pt = PDF points),
   so the on-screen sheet and the printed page match the original form.
   The sheet is a fixed 841.44pt × 595.2pt canvas; on screen it is scaled to
   fit via --dm-scale (js/accounting-demand-forms.js), in print scale is 1.
   ========================================================================== */
.dm-toolbar { display: flex; align-items: center; justify-content: space-between; gap: .75rem; margin-bottom: .75rem; flex-wrap: wrap; }
.dm-fit { width: 100%; overflow: hidden; }
.dm-scaler { width: calc(841.44pt * var(--dm-scale, 1)); height: calc(595.2pt * var(--dm-scale, 1)); border: 1px solid var(--border); background: #fff; box-shadow: 0 1px 6px rgba(0,0,0,.08); overflow: hidden; }
.dm-sheet {
  position: relative; width: 841.44pt; height: 595.2pt; background: #fff; color: #000; overflow: hidden;
  transform: scale(var(--dm-scale, 1)); transform-origin: 0 0;
  font-family: "Aparajita", "Kalimati", "Nirmala UI", "Noto Sans Devanagari", "Mangal", sans-serif;
  font-size: 9.1pt; font-weight: 700; line-height: 1.15;
}
.dm-abs { position: absolute; white-space: nowrap; }
.dm-c { text-align: center; }
.dm-name, .dm-title { font-size: 15.1pt; font-weight: 800; }
.dm-addr, .dm-fy { font-size: 10.6pt; font-weight: 700; }
.dm-info { font-size: 10.6pt; font-weight: 400; }
.dm-sig { font-size: 10.6pt; font-weight: 700; }
.dm-sigl { font-size: 8.4pt; font-weight: 700; }
.dm-sigl.dm-sigbig { font-size: 10.6pt; }
.dm-us { display: inline-block; height: 0; border-bottom: .75pt solid #000; vertical-align: -1.5pt; }
.dm-tbl, .dm-sum { position: absolute; border-collapse: collapse; table-layout: fixed; }
.dm-tbl th, .dm-tbl td, .dm-sum th, .dm-sum td { border: .75pt solid #000; padding: 0 1pt; text-align: center; vertical-align: middle; overflow: hidden; font-weight: 700; }
.dm-tbl th { font-size: 9.1pt; line-height: 1.12; white-space: nowrap; }
.dm-tbl th.dm-sm { font-size: 8.4pt; }
.dm-tbl th.dm-v { padding: 0; }
.dm-rot { display: inline-block; writing-mode: vertical-rl; transform: rotate(180deg); white-space: nowrap; line-height: 1.12; text-align: center; }
.dm-lat { font-family: "Cambria", "Kalimati", serif; font-size: 8.4pt; }
/* कार्यसमिति माग फारमको साँघुरो ठाडो शीर्षक (प्रोत्साहन भत्ता) — ३ पङ्क्ति, ८.२pt (भरपाईमा .dm-rcpt .dm-rsm पहिलेदेखि छ) */
.dm-teacher .dm-rot.dm-rsm { font-size: 8.2pt; line-height: 1.08; }
.dm-tbl tr.dm-row { height: 14.58pt; }
.dm-tbl tr.dm-total { height: 14.4pt; }
.dm-tbl td { font-size: 9.1pt; }
.dm-tbl td.dm-amt { text-align: right; padding-right: 5pt; }
.dm-sum th { font-size: 7.7pt; }
.dm-sum th.dm-lvl { font-size: 6pt; padding: 0; }
.dm-sum td { font-size: 10.6pt; }
@media print {
  .dm-scaler { width: 841.44pt !important; height: 595.2pt !important; border: 0; box-shadow: none; }
  .dm-sheet { transform: none !important; height: 594pt; }
  .dm-fit { overflow: visible; }
  .dm-tbl th, .dm-tbl td, .dm-sum th, .dm-sum td { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* माग फारम — Plain/Data toggle, डाटा-बार, सम्पादन योग्य कक्ष */
.dm-controls { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.dm-controls .dm-ptype, .dm-controls .dm-pval, .dm-controls .dm-rfy, .dm-controls .dm-rmonth, .dm-controls .dm-rdate { width: auto; padding-top: .4rem; padding-bottom: .4rem; }
.dm-seg { display: inline-flex; border: 1px solid var(--border); border-radius: .5rem; overflow: hidden; background: #fff; }
.dm-seg button { padding: .45rem .8rem; font-size: .85rem; font-weight: 600; color: var(--muted); background: #fff; }
.dm-seg button + button { border-left: 1px solid var(--border); }
.dm-seg button.active { background: var(--ink); color: #fff; }
.dm-databar { margin-bottom: .75rem; padding: .6rem .75rem; background: #fff; border: 1px solid var(--border); border-radius: .5rem; }
.dm-bar-row { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.dm-bar-row .input-field { width: auto; min-width: 12rem; max-width: 100%; }
.dm-tbl td.dm-l { text-align: left; padding-left: 2pt; }
.dm-tbl td { white-space: nowrap; }
.dm-editing .dm-tbl td[contenteditable="true"]:focus { outline: 1.5px dashed #c8102e; outline-offset: -1px; background: #fffbe6; }
.dm-editing .dm-tbl td[contenteditable="true"]:hover { background: #fffbe6; }
@media print {
  .dm-scaler { break-after: page; page-break-after: always; }
  .dm-scaler:last-child { break-after: auto; page-break-after: auto; }
  .dm-editing .dm-tbl td[contenteditable="true"] { outline: none !important; background: transparent !important; }
}

.dm-signrow { display: flex; flex-wrap: wrap; gap: .5rem 1rem; align-items: center; margin-bottom: .75rem; font-size: .8rem; color: var(--muted); }
.dm-signrow label { display: inline-flex; align-items: center; gap: .4rem; }
.dm-signrow .input-field { width: auto; min-width: 11rem; padding-top: .3rem; padding-bottom: .3rem; }
/* हस्ताक्षर क्षेत्र: उचाइ ४०pt निर्धारित (नाम-पङ्क्ति र मिति-पङ्क्तिबीच), "हस्ताक्षर" को रेखा यसको ठीक बीचमा।
   हस्ताक्षर छवि रेखाको ठीक बीचमा (तेर्सो + ठाडो) राखिन्छ; छवि ३२pt भन्दा अग्लो हुँदैन, त्यसैले नाम/मिति ओभरराइट हुँदैन। */
.dm-sigarea { height: 40pt; width: 0; }
.dm-sigarea .dm-sigrow { position: absolute; left: 0; bottom: 50%; white-space: nowrap; }
.dm-sigarea .dm-us { position: relative; }
.dm-lbl { display: inline-block; min-width: 4.6em; }
.dm-sigimg { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); max-width: 100%; max-height: 32pt; width: auto; height: auto; object-fit: contain; pointer-events: none; }

/* ===== भरपाई (मासिक तलबी भरपाई) — A4 लन्डस्केप, कार्यसमिति भरपाईको ढाँचामा पूरा पाना ===== */
.dm-rcpt .dm-name, .dm-rcpt .dm-title { font-size: 16.3pt; }
.dm-rcpt .dm-addr { font-size: 11.4pt; }
.dm-rcpt .dm-info { font-size: 11.5pt; }
.dm-rcpt .dm-sig, .dm-rcpt .dm-sigl { font-size: 11.4pt; }
.dm-rcpt .dm-stmt { font-size: 9.9pt; font-weight: 700; }
.dm-rcpt .dm-stmt-gap { display: inline-block; width: 22pt; }
.dm-rcpt .dm-stmt-gap2 { display: inline-block; width: 30pt; }
.dm-rcpt .dm-tbl th, .dm-rcpt .dm-tbl td { font-size: 9.9pt; }
.dm-rcpt .dm-tbl tr.dm-row { height: 15.84pt; }
.dm-rcpt .dm-tbl tr.dm-total { height: 19.44pt; }
.dm-rcpt .dm-tbl tr.dm-total td { background: #d9d9d9; }
.dm-rcpt .dm-us { position: relative; }
.dm-rcpt .dm-datetxt { position: absolute; left: 0; right: 0; bottom: 1.5pt; text-align: center; font-weight: 700; }
.dm-rcpt .dm-rot.dm-rsm { font-size: 8pt; line-height: 1.05; }

/* ---- Task progress dialog (openTaskProgress() in js/utils.js) ---- */
.task-progress-box { align-items: stretch; gap: 0.5rem; width: min(26rem, calc(100vw - 2rem)); padding: 1.25rem 1.5rem; }
.task-progress-title { font-size: 0.95rem; font-weight: 700; color: var(--ink, #1B2A4A); }
.task-progress-label { font-size: 0.78rem; color: var(--muted, #6b7280); min-height: 1.1rem; }
.task-progress-bar { flex: 0 0 10px; height: 10px; margin-top: 0.1rem; background: var(--border, #e5e7eb); }
.task-progress-fill { background: linear-gradient(90deg, #2f9e5b, #43b874); transition: width 0.25s ease; }
.task-progress-pct { font-size: 0.75rem; font-weight: 700; color: var(--ink, #1B2A4A); text-align: right; }


/* ---- Teacher Personal Information / Communication (js/utils.js) ---------- */
/* Small icon before a field label / group heading. */
.emis-field-icon { color: var(--gold-dark); margin-right: 0.4rem; width: 1em; text-align: center; }
.emis-group-icon { color: var(--ink-light); }
/* Portal-detected value (EMIS Code, School Name): read-only, tinted, tagged "Auto". */
.emis-auto-input { background: #f4f1e9; color: var(--ink); cursor: default; }
/* अस्थायी कार्यसमिति: Sheet Roll / CIT / PF / Insurance / Grade लागू हुँदैन — disable */
.emis-temp-locked, .emis-temp-locked:disabled { background: #eceae4; color: var(--muted); cursor: not-allowed; opacity: 0.75; }
/* The Choose/Scan/Upload widget next to a locked photo field (e.g. CIT/PF/
   Sheet Roll for a permanent teacher) — greyed and inert, matching the
   locked text field beside it, since disabling its inner buttons alone
   still lets clicks reach them visually. */
.emis-temp-locked-box { opacity: 0.6; pointer-events: none; }
.emis-auto-badge {
  display: inline-flex; align-items: center; gap: 0.25rem; margin-left: 0.35rem;
  padding: 0.05rem 0.4rem; border-radius: 999px; font-size: 0.65rem; font-weight: 700;
  color: var(--success); background: #e6f2eb; vertical-align: middle;
}
.emis-field-note { font-size: 0.68rem; color: var(--muted); margin-top: 0.25rem; }
/* कागजात नम्बर + फोटो एउटै समूह — outline border भित्र (Edit Teacher / Edit Profile / View Profile) */
.emis-doc-box {
  border: 1.5px solid var(--gold-dark); border-radius: 10px;
  padding: 0.6rem 0.7rem 0.7rem; background: #fffdf8; min-width: 0;
}

/* Communication tab — one row per channel: brand badge, input, one-click buttons. */
.comm-list { display: flex; flex-direction: column; gap: 0.7rem; }
.comm-row {
  display: flex; align-items: center; gap: 0.75rem; padding: 0.7rem 0.8rem;
  border: 1px solid var(--border); border-radius: 12px; background: white;
}
.comm-badge {
  flex: 0 0 auto; width: 2.4rem; height: 2.4rem; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center; font-size: 1.2rem;
  color: var(--comm-color, var(--ink));
  background: color-mix(in srgb, var(--comm-color, var(--ink)) 12%, white);
}
.comm-body { flex: 1 1 auto; min-width: 0; }
.comm-label { display: block; font-size: 0.78rem; font-weight: 700; color: var(--ink); margin-bottom: 0.25rem; }
.comm-hint { font-size: 0.68rem; color: var(--muted); margin-top: 0.2rem; }
.comm-actions { flex: 0 0 auto; display: flex; gap: 0.35rem; }
.comm-act {
  width: 2.2rem; height: 2.2rem; border-radius: 10px; border: 1px solid var(--border);
  background: var(--cream); color: var(--ink); display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.85rem; cursor: pointer;
}
.comm-act:hover:not(:disabled) { background: var(--ink); color: white; border-color: var(--ink); }
.comm-act:disabled { opacity: 0.35; cursor: not-allowed; }
@media (max-width: 520px) {
  .comm-row { flex-wrap: wrap; }
  .comm-body { flex-basis: calc(100% - 3.5rem); }
  .comm-actions { margin-left: 3.15rem; }
}
.vp-comm-link { color: var(--ink); text-decoration: underline; text-decoration-color: var(--gold); text-underline-offset: 2px; }

/* "Fill from portal" button on an Experience row (js/utils.js) */
.emis-row-fill {
  display: inline-flex; align-items: center; gap: 0.35rem; margin-bottom: 0.6rem;
  padding: 0.25rem 0.6rem; border-radius: 999px; border: 1px solid var(--border);
  background: var(--cream); color: var(--ink); font-size: 0.72rem; font-weight: 700; cursor: pointer;
}
.emis-row-fill i { color: var(--gold-dark); }
.emis-row-fill:hover { background: var(--ink); color: white; border-color: var(--ink); }
.emis-row-fill:hover i { color: white; }


/* == चिठी पत्र (admin-correspondence.html): सूचीहरू सानो आकारमा, आफ्नै scroll box भित्र — सकेसम्म कम height ==
   • चिठी / चलानी किताब / दर्ता किताब / सूचनाका सूची तालिका (.corr-list-scroll)
   • "डाटा खोजेर घुसाउनुहोस्" को व्यक्ति सूची (.rt-data-list) र घुसाउने विवरणका chips (.rt-data-fields)
   • सुरक्षित ठेगाना / पहिलाका सूचनाको खोज drop-down (.lt-contact-dropdown)
   screen मात्र — प्रिन्टका नियम (माथिको @media print) जस्ताको तस्तै। */
/* Student's Leave Record / Student Locker tables (#leaveTable/#lockerTable):
   table-layout:fixed + colgroup percentages + .ledger's width:100% means the
   table always fills its container exactly — on a narrow phone that just
   crushes/overlaps every column's text instead of scrolling, since the table
   can never grow past 100% to fit its content (same issue documented above
   for the print Mark Ledger). Their .table-scroll wrapper already scrolls
   horizontally; it just never gets the chance to, because nothing forces the
   table wider than the screen. A min-width fixes that at the source — same
   approach as .ledger-fixed's nk-table/bk-table/nk-list-table below. */
.ledger.leave-table { min-width: 46rem; }
.ledger.locker-table { min-width: 60rem; }

@media screen {
  .table-scroll.table-scroll-y.corr-list-scroll { max-height: min(45vh, 20rem); border-radius: 10px; }
  .corr-list-scroll .ledger thead th { padding: 0.3rem 0.4rem; font-size: 0.64rem; }
  .corr-list-scroll .ledger td { padding: 0.2rem 0.4rem; font-size: 0.74rem; line-height: 1.25; }
  .corr-list-scroll .ledger td .btn-cancel,
  .corr-list-scroll .ledger td .btn-primary,
  .corr-list-scroll .ledger td .btn-gold,
  .corr-list-scroll .ledger td button { padding: 0.12rem 0.4rem; font-size: 0.68rem; line-height: 1.2; }

  .rt-data-list { max-height: 6.5rem; border-radius: 0.3rem; overscroll-behavior: contain; }
  .rt-data-row { padding: 0.15rem 0.45rem; gap: 0.35rem; font-size: 0.72rem; line-height: 1.25; }
  .rt-data-row input { width: 0.8rem; height: 0.8rem; }
  .rt-data-s { font-size: 0.64rem; }
  .rt-data-empty { padding: 0.4rem 0.5rem; font-size: 0.72rem; }
  .rt-data-h { margin: 0.35rem 0 0.15rem; font-size: 0.7rem; }
  .rt-data-fields { max-height: 3.4rem; overflow-y: auto; gap: 0.2rem 0.35rem; padding: 0.15rem; border: 1px solid var(--border, #d9d4c7); border-radius: 0.3rem; background: #fff; overscroll-behavior: contain; }
  .rt-chip { padding: 0.05rem 0.4rem; font-size: 0.66rem; gap: 0.2rem; }
  .rt-datapanel { padding: 0.45rem; }
  .rt-data-searchrow { margin-bottom: 0.3rem; }

  .lt-contact-dropdown { max-height: 8.5rem; padding: 0.2rem; }
  .lt-contact-item { padding: 0.2rem 0.35rem; gap: 0.35rem; }
  .lt-contact-item-title { font-size: 0.72rem; }
  .lt-contact-item-sub { font-size: 0.64rem; margin-top: 0; }
  .lt-contact-item-subject { font-size: 0.62rem; margin-top: 0; }
  .lt-contact-item-actions button { font-size: 0.68rem; padding: 0.1rem 0.3rem; }
  .lt-contact-empty { padding: 0.35rem; font-size: 0.7rem; }
}


/* दायित्व हिसाब (accounting-demand-forms.html → panelDayitvaHisab) */
.dh-scroll { overflow-x: auto; background: #fff; border: 1px solid var(--border); border-radius: .5rem; }
.dh-tbl { border-collapse: collapse; width: 100%; min-width: 60rem; font-size: .82rem; }
.dh-tbl th, .dh-tbl td { border: 1px solid #333; padding: .3rem .4rem; text-align: center; vertical-align: middle; }
.dh-tbl th { background: #eee; font-weight: 700; line-height: 1.25; }
.dh-tbl tbody tr:nth-child(even) > td { background: #f4f6f8; }
.dh-tbl tbody tr:nth-child(odd) > td { background: #fff; }
.dh-tbl .dh-sub { font-weight: 400; font-size: .7rem; }
.dh-tbl td.dh-l { text-align: left; min-width: 9rem; }
.dh-tbl td.dh-n { text-align: right; font-variant-numeric: tabular-nums; }
.dh-tbl tfoot td { background: #d9d9d9; font-weight: 800; }
.dh-tbl td[contenteditable="true"]:hover, .dh-tbl td[contenteditable="true"]:focus { background: #fffbe6; outline: 1.5px dashed #c8102e; outline-offset: -1px; }
.dh-tbl td.dh-x { border: 0; padding: 0 .3rem; width: 1.6rem; }
.dh-del { color: var(--error); font-size: .8rem; opacity: .6; }
.dh-del:hover { opacity: 1; }
.dh-tbl .dh-adj-cell { font-weight: 700; }

/* दायित्व कट्टी सूची बाकस — तालिकामुनि, तयार गर्ने र प्रमाणित गर्नेको हस्ताक्षरको ठीक बिचमा
   (accounting-demand-forms.js: dhRenderBox())। स्क्रिनमा मात्र; प्रिन्टमा .dh-explain-box (माथि) आउँछ। */
.dh-sign-screen { display: grid; grid-template-columns: minmax(8rem, 1fr) minmax(0, 2.8fr) minmax(8rem, 1fr); gap: 1rem; align-items: start; margin-top: 1.25rem; }
.dh-sign-side { font-size: .85rem; line-height: 2; padding-top: .4rem; }
.dh-sign-right { text-align: right; }
.dh-box { background: #fff; border: 1.5px solid var(--ink); border-radius: .6rem; padding: .8rem .9rem; min-width: 0; }
.dh-box-title { font-weight: 800; color: var(--ink); margin-bottom: .3rem; }
.dh-box-hint { font-size: .72rem; color: var(--muted); line-height: 1.45; margin-bottom: .55rem; }
.dh-box-who { margin-bottom: .55rem; }
.dh-box-tbl, .dh-added-tbl { width: 100%; border-collapse: collapse; }
.dh-box-tbl th, .dh-box-tbl td, .dh-added-tbl th, .dh-added-tbl td { border: 1px solid var(--border); padding: .25rem .35rem; font-size: .8rem; text-align: left; vertical-align: middle; }
.dh-box-tbl th, .dh-added-tbl th { background: #f4f1e8; font-weight: 700; }
.dh-box-tbl td.sn-col, .dh-added-tbl td.sn-col, .dh-box-tbl th.sn-col, .dh-added-tbl th.sn-col { width: 2.6rem; text-align: center; }
.dh-box-tbl .input-field { padding: .3rem .45rem; font-size: .85rem; min-width: 0; width: 100%; }
.dh-box-tbl td:last-child { width: 2rem; text-align: center; border-color: transparent; }
.dh-it-del, .dh-added-del { color: var(--error); opacity: .6; font-size: .8rem; padding: 0 .3rem; }
.dh-it-del:hover, .dh-added-del:hover { opacity: 1; }
.dh-added-edit { color: var(--ink); opacity: .75; font-size: .9rem; padding: 0 .3rem; }
.dh-added-edit:hover { opacity: 1; }
.dh-box-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: .6rem; }
.dh-box-total { margin-left: auto; font-size: .9rem; }
.dh-box-sync, .dh-box-msg { font-size: .75rem; margin-top: .35rem; min-height: 1rem; }
.dh-added-title { font-weight: 700; font-size: .85rem; color: var(--ink); margin: .8rem 0 .35rem; padding-top: .6rem; border-top: 1px dashed var(--border); }
.dh-added-empty { font-size: .8rem; color: var(--muted); }
.dh-added-tbl td.dh-n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dh-added-tbl tfoot td { background: #f4f1e8; font-weight: 800; }
.dh-added-act { white-space: nowrap; width: 4.5rem; text-align: center; }
.dh-added-sub { font-weight: 700; font-size: .8rem; color: var(--ink); margin: .6rem 0 .3rem; }
.dh-added-tbl + .dh-added-sub { margin-top: .9rem; }
.dh-agg-tbl td.dh-n, .dh-agg-tbl th:nth-child(3), .dh-agg-tbl th:nth-child(4) { text-align: right; }
.dh-hd-line { display: flex; align-items: center; gap: .5rem; padding: .1rem 0; border-bottom: 1px dotted var(--border); }
.dh-hd-line:last-child { border-bottom: 0; }
.dh-hd-name { flex: 1 1 auto; min-width: 0; }
.dh-hd-line b { flex: 0 0 auto; font-variant-numeric: tabular-nums; }
.dh-hd-del, .dh-agg-del { color: var(--error); opacity: .6; font-size: .75rem; padding: 0 .3rem; }
.dh-hd-del:hover, .dh-agg-del:hover { opacity: 1; }
@media (max-width: 900px) {
  .dh-sign-screen { grid-template-columns: 1fr; }
  .dh-box { order: -1; }
  .dh-sign-right { text-align: left; }
}

/* दायित्व हिसाब सूची (ट्याब) */
.dh-list-table { min-width: 48rem; }
.dh-tbl th { min-width: 4.2rem; }
.dh-tbl .dh-col-hide, .dh-print .dh-col-hide { display: none; }
/* दायित्व सेटअप — तालिकाको माथिल्लो header (thead) tiny+bold र हरेक नाम एउटै लाइनमा (अनावश्यक ठाउँ नओगट्न);
   कार्यसमिति/कर्मचारीको नाम स्तम्भ पनि एउटै लाइनमा — width सामग्री (सबैभन्दा लामो नाम) अनुसार आफैं मिल्छ। */
.dh-tbl thead th { font-size: .66rem; font-weight: 800; line-height: 1.2; padding: .2rem .3rem; min-width: 0; white-space: nowrap; }
.dh-tbl thead th .dh-sub { font-size: inherit; font-weight: inherit; }
.dh-tbl td.dh-l { white-space: nowrap; width: 1%; min-width: 0; }


/* क्र.सं. (सिरियल नं.) स्तम्भ — सबै तालिकामा टाइट (js/utils.js: tightenSerialColumns)।
   width:1% + nowrap = auto-layout तालिकामा सामग्रीजति मात्र; बाँकी स्तम्भ डाटाको लम्बाइअनुसार बाँकी ठाउँ लिन्छन्। */
table .sn-tight,
.ledger th.sn-col, .ledger td.sn-col {
  width: 1% !important;
  min-width: 0 !important;
  white-space: nowrap;
  text-align: center;
}
.ledger .sn-tight, .ledger th.sn-col, .ledger td.sn-col {
  padding-left: 0.35rem !important;
  padding-right: 0.35rem !important;
}

/* ==========================================================================
   निकासा पत्र / बैंकलाई पत्र — स्क्रिन तालिकाको स्तम्भ-चौडाइ (क्र.सं. साँघुरो)
   पहिले तालिका table-layout:auto थियो र भित्रका input (width:100%) ले पहिलो
   स्तम्भ (क्र.सं.) लाई नै सबैभन्दा फराकिलो बनाइदिन्थ्यो। अब स्तम्भ-चौडाइ
   <colgroup> ले तोक्छ; क्र.सं. सधैं साँघुरो, "विवरण" ले बाँकी ठाउँ लिन्छ, र
   सानो स्क्रिनमा तालिका आफ्नै .table-scroll भित्र क्षैतिज स्क्रोल हुन्छ।
   ========================================================================== */
.ledger.ledger-fixed { table-layout: fixed; width: 100%; min-width: 46rem; }
.ledger.ledger-fixed td input.input-field,
.ledger.ledger-fixed td select.input-field { min-width: 0; width: 100%; }
.ledger.ledger-fixed th.sn-col,
.ledger.ledger-fixed td.sn-col { width: 3.25rem; min-width: 0; padding-left: .25rem; padding-right: .25rem; }
.ledger.ledger-fixed th { white-space: normal; line-height: 1.25; }
.ledger-fixed col.nk-c-sn    { width: 3.25rem; }
.ledger-fixed col.nk-c-label { width: auto; }
.ledger-fixed col.nk-c-amt   { width: 8.5rem; }
.ledger-fixed col.nk-c-tax   { width: 9.5rem; }
.ledger-fixed col.nk-c-rem   { width: 10rem; }
.ledger-fixed col.nk-c-act   { width: 3.25rem; }
.ledger-fixed col.bk-c-name  { width: auto; }
.ledger-fixed col.bk-c-acct  { width: 12rem; }
.ledger-fixed col.nkl-c-period { width: auto; }
.ledger-fixed col.nkl-c-date { width: 8rem; }
.ledger-fixed col.nkl-c-status { width: 13rem; }
.ledger-fixed col.nkl-c-act  { width: 11rem; }
/* स्तम्भ-चौडाइको जोड + "विवरण"/"नाम" ले कम्तीमा ~१४rem पाउने गरी न्यूनतम चौडाइ — सानो स्क्रिनमा तालिका आफ्नै फ्रेममा स्क्रोल हुन्छ */
.ledger.ledger-fixed.nk-table { min-width: 60rem; }
.ledger.ledger-fixed.bk-table { min-width: 52rem; }
.ledger.ledger-fixed.nk-list-table { min-width: 54rem; }

/* निकासा पत्र — स्थिति बैनर (ड्राफ्ट / चलानीमा पठाइसकेको) */
.nk-banner { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .9rem; padding: .65rem .9rem; border-radius: 12px; margin-bottom: .9rem; font-size: .85rem; border: 1px solid; }
.nk-banner-draft { background: #fffbeb; border-color: #fde68a; color: #92400e; }
.nk-banner-sent  { background: #f0fdf4; border-color: #86efac; color: #166534; }
.nk-banner a { text-decoration: underline; font-weight: 600; }
.nk-locked .nk-lockable { background: #f5f3ec; }
@media print { .nk-banner { display: none !important; } }

/* ==========================================================================
   Teacher Bottom Navigation — a fixed, always-on-top bar shown for a
   teacher session (renderTeacherBottomNav() in js/utils.js, called from
   renderAdminShell() whenever it's given a teacher navLinks array — see
   that function's own comment). Injected once per page load, so it stays
   on screen no matter which teacher page is open, without every teacher
   page having to add it itself. Colors reuse the site's own --ink/--gold
   palette (same gradient as .brand-header) instead of an unrelated brand
   color, so it reads as part of this app rather than a bolted-on widget.
   Shown at EVERY screen width, including desktop (alongside the sidebar) —
   not just mobile/tablet, so the same quick-access tabs (सूचना, म्यासेज…)
   stay one tap away no matter how the person is viewing the site. Labels
   are small and allowed to wrap onto a second line (see .tbn-item span
   below) instead of truncating with an ellipsis, so every label — even a
   two-word one like "आन्तरिक फारम" — reads in full inside its narrow tab.
   z-index sits above everything else on the page (10000, one above
   .floating-bottom-nav's old 9999 and the admin drawer/overlay, and above
   the desktop sidebar too) so it can never end up hidden behind another
   fixed element. */
.teacher-bottom-nav, .admin-bottom-nav {
  display: flex;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 60px;
  background: var(--nav-bg, #ffffff);
  box-shadow: 0 -3px 16px rgba(27, 42, 74, 0.14);
  z-index: 10000;
  justify-content: space-around;
  align-items: center;
  padding: 0 4px;
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.teacher-bottom-nav .tbn-item, .admin-bottom-nav .tbn-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  /* flex (not a fixed %) so the bar automatically re-splits the width
     whichever number of tabs it holds — was a fixed 19% back when there
     were only 5 tabs total; kept relative here so adding/removing a tab
     (e.g. सूचना/म्यासेज on either side of home) never causes overflow. */
  flex: 1 1 0;
  min-width: 0;
  color: var(--muted);
  text-decoration: none;
  font-size: 9px;
  font-weight: 700;
  text-align: center;
  line-height: 1.1;
  transition: transform 0.15s ease, color 0.15s ease;
}
.teacher-bottom-nav .tbn-item i, .admin-bottom-nav .tbn-item i { font-size: 16px; }
.teacher-bottom-nav .tbn-item span, .admin-bottom-nav .tbn-item span {
  max-width: 100%;
  /* Small + allowed to wrap (not the ellipsis-truncating nowrap this used
     to be) so a two-word label breaks onto a second line at its own
     space instead of being cut off — every label stays fully readable. */
  white-space: normal;
  overflow-wrap: break-word;
  word-break: keep-all;
}
.teacher-bottom-nav .tbn-item:active, .admin-bottom-nav .tbn-item:active { transform: scale(0.92); }
.teacher-bottom-nav .tbn-item.tbn-active, .admin-bottom-nav .tbn-item.tbn-active { color: var(--gold-dark); }
/* Center Home button — floats above the bar, same navy→gold treatment as
   .brand-header, so it reads as "this app's" accent button rather than a
   generic red FAB. Slightly wider flex-grow than the other tabs (was 21%
   of 5 fixed-width tabs ≈ 1.1x a plain 19% tab — kept that same ratio now
   that widths are relative). */
.teacher-bottom-nav .tbn-home, .admin-bottom-nav .tbn-home {
  position: relative;
  top: -15px;
  flex: 1.1 1 0;
}
.teacher-bottom-nav .tbn-home .tbn-home-icon, .admin-bottom-nav .tbn-home .tbn-home-icon {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--ink) 0%, var(--ink-light) 100%);
  border: 2px solid #ffffff;
  box-shadow: 0 4px 14px rgba(27, 42, 74, 0.4);
  transition: transform 0.15s ease;
}
.teacher-bottom-nav .tbn-home.tbn-active .tbn-home-icon, .admin-bottom-nav .tbn-home.tbn-active .tbn-home-icon {
  background: linear-gradient(135deg, var(--gold-dark) 0%, var(--gold) 100%);
  box-shadow: 0 4px 14px rgba(200, 129, 31, 0.45);
}
/* Home icon is always white (normal and active state) — only the icon, the circle keeps its navy/gold fill. */
.teacher-bottom-nav .tbn-home i, .admin-bottom-nav .tbn-home i,
.teacher-bottom-nav .tbn-home.tbn-active i, .admin-bottom-nav .tbn-home.tbn-active i,
.teacher-bottom-nav .tbn-home .tbn-home-icon i, .admin-bottom-nav .tbn-home .tbn-home-icon i { color: #ffffff !important; font-size: 20px; }
.teacher-bottom-nav .tbn-home span, .admin-bottom-nav .tbn-home span { color: var(--ink); font-size: 9px; margin-top: 1px; }
.teacher-bottom-nav .tbn-home.tbn-active span, .admin-bottom-nav .tbn-home.tbn-active span { color: var(--gold-dark); }
/* Keeps the fixed bar from covering the page's own bottom content — only
   applied when the bar is actually on the page (body gets this class from
   renderTeacherBottomNav()/renderAdminBottomNav()) — unconditional now that
   the bar itself is shown at every width, not just mobile/tablet. */
body.has-teacher-bottom-nav, body.has-admin-bottom-nav { padding-bottom: 68px; }
/* Print Preview (पूरा-पाना, z-index 9999) खुल्दा तल्लो navigation (z-index 10000) ले छेक्थ्यो — preview खुलेकै बेला लुकाउने। */
body.print-preview-active .teacher-bottom-nav,
body.print-preview-active .admin-bottom-nav { display: none !important; }
body.print-preview-active.has-teacher-bottom-nav,
body.print-preview-active.has-admin-bottom-nav { padding-bottom: 0; }

/* ==========================================================================
   Full-page image lightbox (see the matching block at the end of
   js/utils.js — "Full-page image lightbox"). Every uploaded-photo /
   certificate thumbnail opens here on click instead of navigating away:
   Documents (View Profile), condition/item photos, upload-widget
   previews, Uploaded Media gallery, etc.
   ========================================================================== */
.img-lightbox-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(10, 14, 26, 0.92);
  z-index: 20000;
  align-items: center;
  justify-content: center;
  touch-action: none;
}
.img-lightbox-overlay.open { display: flex; }
body.img-lightbox-lock { overflow: hidden; }

.img-lightbox-stage {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  padding: 3.5rem 1rem;
  box-sizing: border-box;
}
.img-lightbox-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 0.5rem;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
  user-select: none;
  -webkit-user-drag: none;
}
.img-lightbox-caption {
  color: #fff;
  font-size: 0.85rem;
  margin-top: 0.75rem;
  text-align: center;
  max-width: 90%;
}
.img-lightbox-caption.hidden { display: none; }
.img-lightbox-counter {
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.75rem;
  margin-top: 0.25rem;
}
.img-lightbox-close, .img-lightbox-nav {
  position: absolute;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border: none;
  border-radius: 50%;
  width: 2.75rem;
  height: 2.75rem;
  font-size: 1.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s ease;
  z-index: 1;
}
.img-lightbox-close:hover, .img-lightbox-nav:hover { background: rgba(255, 255, 255, 0.25); }
.img-lightbox-close { top: 1rem; right: 1rem; }
.img-lightbox-prev { left: 1rem; top: 50%; transform: translateY(-50%); }
.img-lightbox-next { right: 1rem; top: 50%; transform: translateY(-50%); }
.img-lightbox-nav.hidden { display: none; }
@media (max-width: 640px) {
  .img-lightbox-close, .img-lightbox-nav { width: 2.4rem; height: 2.4rem; font-size: 1rem; }
  .img-lightbox-stage { padding: 3rem 0.5rem; }
}

/* थाहा होस् भनेर — यी thumbnail हरूमा क्लिक गर्दा ठूलो प्रिभ्यू खुल्छ। */
.vp-doc-thumb, .image-upload-thumb, .um-thumb, .js-lightbox-img { cursor: zoom-in; }

/* ---- विदा निवेदनको औपचारिक पत्र (A4) — teacher-leave.html, Principal Desk र
   admin-teachers.html ले साझा गर्ने (js/utils.js — buildLeaveLetterHtml()) ---- */
.leave-letter { background:#fff; padding: 2.2cm 2cm; width: 210mm; box-sizing: border-box; margin: 0 auto; font-size: 0.95rem; line-height: 1.9; color:#1a1a1a; }
.ll-stage { margin: 0 auto; }
.leave-letter .ll-date-corner { text-align:right; font-size: 0.9rem; margin-bottom: 0.8rem; }
.leave-letter .ll-to { margin-bottom: 1.2rem; }
.leave-letter .ll-subject { text-align:center; font-weight:600; text-decoration: underline; margin: 1rem 0; }
.leave-letter .ll-body { text-align: justify; }
.leave-letter .ll-sign { margin-top: 2.8rem; display:flex; justify-content: flex-end; }
.leave-letter .ll-sign-box { text-align:center; min-width: 200px; }
.leave-letter .ll-sign-img { height: 56px; max-width: 180px; object-fit: contain; display:block; margin: 0 auto 0.2rem; }
.leave-letter .ll-sign-line { border-top: 1px solid #333; margin-top: 0.3rem; padding-top: 0.3rem; font-size: 0.85rem; }
.leave-letter .ll-sign-missing { font-size: 0.75rem; color: var(--muted); font-style: italic; height: 56px; display:flex; align-items:flex-end; justify-content:center; }
@media print {
  .leave-letter { padding: 0; max-width: none; width: auto; }
}

/* कागजात छाप्ने पाना (जन्मदर्ता / कार्यसमितिका कागजात): एक A4 = एक कागजात, फोटो अटाउने गरी */
.doc-print-page { height: 272mm; display: flex; align-items: center; justify-content: center; box-sizing: border-box; }
.doc-print-img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* Highest Attendance card (utils.js renderHighestAttendanceInto) — विजेताको फोटो + crown badge */
.haw-photos { display: inline-flex; flex: none; padding-top: 6px; }
.haw-av { position: relative; display: inline-flex; flex: none; }
.haw-av + .haw-av { margin-left: -10px; }
.haw-photo {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; min-width: 40px; border-radius: 50%;
  background-color: #e0e0e0; overflow: hidden; border: 2px solid var(--gold, #d4a017);
  box-shadow: 0 0 0 1px #fff;
}
.haw-photo img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
.haw-photo i { color: #888; font-size: 16px; }
.haw-crown {
  position: absolute; top: -9px; left: 50%; transform: translateX(-50%) rotate(-12deg);
  font-size: 13px; line-height: 1; filter: drop-shadow(0 1px 1px rgba(0,0,0,.35));
}
.haw-crown i, .fa-crown { color: var(--gold, #d4a017); }

/* ---- आम्दानी / खर्च भौचर (सरकारी भौचर ढाँचा) — js/accounting-voucher-common.js ---- */
.jinsi-print-form.vch-form { padding: 2mm 3mm; }
/* भौचर सूची: छनोट स्तम्भ */
.vch-sel-cell { width: 2.2rem; text-align: center; }
.vch-sel-cell input, #voucherSelectAll, #voucher9SelectAll { width: 1.05rem; height: 1.05rem; cursor: pointer; }
tr.vch-row-selected td { background: rgba(212, 160, 23, 0.14); }
.vch-batch-bar button:disabled { opacity: .5; cursor: not-allowed; }
.vch-form .vch-head { display: grid; grid-template-columns: 26mm 1fr 40mm; align-items: center; gap: 3mm; }
.vch-form .vch-logo-box { text-align: left; }
.vch-form .vch-logo { width: 22mm; height: 22mm; object-fit: contain; }
.vch-form .vch-center { text-align: center; line-height: 1.25; }
.vch-form .vch-center p { margin: 0; }
.vch-form .vch-school { font-size: 1.35rem; font-weight: 800; }
.vch-form .vch-addr { font-size: 1rem; }
.vch-form .vch-code { font-size: 0.85rem; }
.vch-form .vch-right { text-align: right; }
.vch-form .vch-qr { width: 25mm; height: 25mm; display: inline-block; vertical-align: top; }
.vch-form .vch-formno { font-size: 0.85rem; margin: 1mm 0 0; }
.vch-form .vch-title { text-align: center; font-weight: 800; font-size: 1.05rem; margin: 4mm 0 2mm; }
.vch-form .vch-meta { display: flex; justify-content: space-between; gap: 6mm; font-size: 0.85rem; margin: 0.6mm 0; }
.vch-form table.jp-table { margin-top: 1.5mm; }
.vch-form table.jp-table th { background: #d9d9d9 !important; }
.vch-form .vch-words { border: 1px solid #000; border-top: 0; padding: 1mm 1.8mm; margin: 0; font-size: 0.85rem; }
.vch-form .vch-summary { border: 1px solid #000; border-top: 0; padding: 1mm 1.8mm; font-size: 0.85rem; }
.vch-form .vch-summary p { margin: 0; }
.vch-form .vch-summary-h { font-weight: 800; text-decoration: underline; }
.vch-form .vch-proof { display: flex; justify-content: space-between; gap: 6mm; font-size: 0.85rem; margin: 1mm 0; }
.vch-form .vch-proof .vch-proof-line { text-decoration: underline; }
.vch-form .vch-pay-h { font-weight: 800; font-size: 0.9rem; margin: 1.5mm 0 0; }
.vch-form .vch-signs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4mm; margin: 14mm 0 0 12mm; font-size: 0.85rem; }
.vch-form .vch-signs p { margin: 0.8mm 0; }
.vch-form table.jp-table td.vch-c { text-align: center; }

/* ---- PAN/VAT स्वतः-भर्ने (js/pan-lookup.js) ---- */
.pan-lookup-status { margin-top: 0.3rem; font-size: 0.78rem; line-height: 1.35; color: var(--muted, #6b7280); }
.pan-lookup-status[hidden] { display: none; }
.pan-lookup-ok { color: #15803d; }
.pan-lookup-warn { color: #b45309; }
.pan-lookup-error { color: #b91c1c; }
.pan-lookup-btn {
  margin-left: 0.25rem; padding: 0.1rem 0.5rem; font-size: 0.75rem; cursor: pointer;
  border: 1px solid var(--border, #d6d9e0); border-radius: 6px; background: #fff; color: var(--ink, #1b2a4a);
}
input.pan-lookup-loading {
  padding-right: 2rem;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><circle cx='8' cy='8' r='6' fill='none' stroke='%23d6d9e0' stroke-width='2'/><path d='M8 2a6 6 0 0 1 6 6' fill='none' stroke='%231b2a4a' stroke-width='2' stroke-linecap='round'><animateTransform attributeName='transform' type='rotate' from='0 8 8' to='360 8 8' dur='0.8s' repeatCount='indefinite'/></path></svg>");
  background-repeat: no-repeat; background-position: right 0.6rem center;
}
@media print { .pan-lookup-status { display: none !important; } }

/* छोटो, स्व-निहित "SASS पोर्टल प्रयोग गर्नुहोस्" सूचना पट्टी — sass-portal.html
   कै भावनासँग मिल्दो तर एक-हरफे, किनभने यो त्यहाँको पूर्ण पृष्ठको सट्टा हरेक
   आम्दानी-सम्बन्धी ट्याबमाथि सधैं देखिने सानो नुज मात्र हो। */
.acc-sass-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  background: #fbf6e9; border: 1px solid var(--gold); border-left: 4px solid var(--gold-dark);
  border-radius: 12px; padding: 0.75rem 1.1rem; margin-bottom: 1rem;
}
.acc-sass-banner p { font-size: 0.82rem; color: var(--text); line-height: 1.4; }
.acc-sass-banner b { color: var(--ink); }
.acc-sass-banner a {
  display: inline-flex; align-items: center; gap: 0.4rem; white-space: nowrap;
  background: var(--gold-dark); color: #fff; font-weight: 700; font-size: 0.82rem;
  padding: 0.55rem 1rem; border-radius: 10px;
}
.acc-sass-banner a:hover { background: #a86a15; }


/* ==== लाइटबक्स — पूरा-स्क्रिन मोड (प्रमाण-पत्र), स्वाइप सूचक, बिन्दु ==== */
.img-lightbox-overlay.img-lightbox-full { background: #000; }
.img-lightbox-full .img-lightbox-stage { padding: calc(env(safe-area-inset-top, 0px) + 2.6rem) 0 calc(env(safe-area-inset-bottom, 0px) + 4.2rem); }
.img-lightbox-full .img-lightbox-img { width: 100%; height: 100%; max-width: 100vw; max-height: 100%; border-radius: 0; box-shadow: none; }
.img-lightbox-full .img-lightbox-caption { position: absolute; left: 0; right: 0; bottom: calc(env(safe-area-inset-bottom, 0px) + 2.3rem); margin: 0 auto; }
.img-lightbox-full .img-lightbox-counter { position: absolute; top: calc(env(safe-area-inset-top, 0px) + 1.1rem); left: 1rem; margin: 0; font-size: 0.85rem; font-weight: 600; }
.img-lightbox-close { top: calc(env(safe-area-inset-top, 0px) + 0.75rem); }
.img-lightbox-dots {
  position: absolute; left: 0; right: 0; bottom: calc(env(safe-area-inset-bottom, 0px) + 0.9rem);
  display: flex; justify-content: center; gap: 0.45rem; z-index: 2; pointer-events: none;
}
.img-lightbox-dots.hidden, .img-lightbox-hint.hidden { display: none; }
.img-lightbox-dot { pointer-events: auto; width: 0.55rem; height: 0.55rem; padding: 0; border: 0; border-radius: 999px; background: rgba(255,255,255,0.4); transition: all 0.2s ease; cursor: pointer; }
.img-lightbox-dot.on { width: 1.5rem; background: #fff; }
.img-lightbox-hint {
  position: absolute; left: 50%; bottom: calc(env(safe-area-inset-bottom, 0px) + 2.4rem); transform: translateX(-50%);
  z-index: 3; color: #fff; background: rgba(0,0,0,0.6); border-radius: 999px; padding: 0.4rem 0.9rem; font-size: 0.8rem; white-space: nowrap;
  pointer-events: none; animation: imgLbHint 3.2s ease forwards;
}
@keyframes imgLbHint { 0%,80% { opacity: 1; } 100% { opacity: 0; } }
.img-lightbox-img { transition: transform 0.2s ease, opacity 0.2s ease; will-change: transform; }
.img-lightbox-img.img-lb-in-r { animation: imgLbInR 0.25s ease; }
.img-lightbox-img.img-lb-in-l { animation: imgLbInL 0.25s ease; }
@keyframes imgLbInR { from { transform: translateX(14%); opacity: 0.3; } to { transform: none; opacity: 1; } }
@keyframes imgLbInL { from { transform: translateX(-14%); opacity: 0.3; } to { transform: none; opacity: 1; } }
@media (max-width: 640px) { .img-lightbox-full .img-lightbox-nav { display: none; } }


/* ==== प्रिन्ट पानामा "मुद्रित मिति" देखाउने/नदेखाउने tick (showPrintPreview toolbar) ====
   .print-date (साझा हेडर) / .js-printed-date (अन्य प्रिन्ट पाना) — लुकाउँदा ठाउँ जस्ताको तस्तै रहन्छ,
   ताकि बीचको/दायाँको लेआउट नसरोस्। प्रिन्ट र preview दुवैमा लागू। */
.print-preview-modal.hide-printed-date .print-date,
.print-preview-modal.hide-printed-date .js-printed-date { visibility: hidden; }
.ppm-date-toggle {
  display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.35rem 0.7rem;
  background: #fff; border: 1px solid var(--border, #e6e0d4); border-radius: 0.6rem;
  font-size: 0.85rem; font-weight: 600; color: var(--ink, #1b2a4a); cursor: pointer; user-select: none;
}
.ppm-date-toggle input { width: 1.05rem; height: 1.05rem; accent-color: #1b2a4a; cursor: pointer; }


/* ==========================================================================
   Menu icon tiles — Sidebar र mobile drawer का हरेक मेनु आइकनको आफ्नै रङ (टाइल सहित)
   रङ js/utils.js → NAV_ICON_COLORS / navIconColor() बाट inline `--mi` ले आउँछ। माथिको "Meaningful icon colours"
   (आकार अनुसार) को सट्टा यहाँ मेनुमा मात्र page अनुसार रङ लाग्छ — अन्य पृष्ठका आइकनमा असर पर्दैन।
   सक्रिय पृष्ठ (सुनौलो पट्टी) मा आइकन गाढा नै रहन्छ (माथिको [aria-current] नियम)।
   ========================================================================== */
.admin-sidebar-nav .sidebar-link .admin-menu-icon,
.admin-drawer-nav .sidebar-link .admin-menu-icon {
  width: 1.9rem; height: 1.9rem; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  border-radius: 0.55rem; background: color-mix(in srgb, var(--mi, #cbd5e1) 17%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mi, #cbd5e1) 30%, transparent);
  transition: background 0.12s ease, transform 0.12s ease;
}
.admin-sidebar-nav .sidebar-link .admin-menu-icon i,
.admin-drawer-nav .sidebar-link .admin-menu-icon i { color: var(--mi, #cbd5e1); font-size: 0.95rem; }
.admin-sidebar-nav .sidebar-link:hover .admin-menu-icon,
.admin-drawer-nav .sidebar-link:hover .admin-menu-icon { background: color-mix(in srgb, var(--mi, #cbd5e1) 30%, transparent); transform: scale(1.06); }
.admin-sidebar-nav .sidebar-link[aria-current="page"] .admin-menu-icon,
.admin-drawer-nav .sidebar-link[aria-current="page"] .admin-menu-icon { background: rgba(27, 42, 74, 0.14); box-shadow: inset 0 0 0 1px rgba(27, 42, 74, 0.25); }
.admin-sidebar-nav .sidebar-group-toggle-active .admin-menu-icon,
.admin-drawer-nav .sidebar-group-toggle-active .admin-menu-icon { box-shadow: 0 0 0 1.5px var(--mi, #cbd5e1); }
@media (prefers-reduced-motion: reduce) {
  .admin-sidebar-nav .sidebar-link .admin-menu-icon, .admin-drawer-nav .sidebar-link .admin-menu-icon { transition: none; }
  .admin-sidebar-nav .sidebar-link:hover .admin-menu-icon, .admin-drawer-nav .sidebar-link:hover .admin-menu-icon { transform: none; }
}


/* ==========================================================================
   चहकिला मेनु आइकन (Vivid menu icons)
   - Sidebar / mobile drawer: हरेक आइकन टाइल अब ठोस gradient (आइकनको आफ्नै रङको hue, उज्यालो र गाढा),
     सेतो आइकन सहित। रङ अझै js/utils.js को --mi बाट आउँछ; oklch(from …) ले फिक्का रङलाई पनि
     उही hue मै चहकिलो बनाउँछ (पुराना ब्राउजरमा तलको color-mix fallback लाग्छ)।
   - सक्रिय पृष्ठ (सुनौलो पट्टी) को आइकन पहिलेकै गाढा शैलीमा रहन्छ।
   - तलको Bottom nav (Admin/Teacher): हरेक आइकनको फरक चहकिलो रङ।
   ========================================================================== */
.admin-sidebar-nav .sidebar-link:not([aria-current="page"]) .admin-menu-icon,
.admin-drawer-nav .sidebar-link:not([aria-current="page"]) .admin-menu-icon {
  /* fallback (oklch relative colour नचल्ने ब्राउजर) */
  background: linear-gradient(135deg, var(--mi, #cbd5e1), color-mix(in srgb, var(--mi, #cbd5e1) 60%, #1e1b4b));
  /* vivid */
  background: linear-gradient(135deg, oklch(from var(--mi, #cbd5e1) 0.74 0.19 h), oklch(from var(--mi, #cbd5e1) 0.54 0.22 h));
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.38);
}
.admin-sidebar-nav .sidebar-link:not([aria-current="page"]) .admin-menu-icon i,
.admin-drawer-nav .sidebar-link:not([aria-current="page"]) .admin-menu-icon i {
  color: #fff;
  font-size: 0.95rem;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
.admin-sidebar-nav .sidebar-link:not([aria-current="page"]):hover .admin-menu-icon,
.admin-drawer-nav .sidebar-link:not([aria-current="page"]):hover .admin-menu-icon {
  filter: brightness(1.12) saturate(1.15);
  transform: scale(1.08);
}
/* खुलेको/सक्रिय समूहको आइकनमा सेतो घेरा */
.admin-sidebar-nav .sidebar-link.sidebar-group-toggle-active:not([aria-current="page"]) .admin-menu-icon,
.admin-drawer-nav .sidebar-link.sidebar-group-toggle-active:not([aria-current="page"]) .admin-menu-icon {
  box-shadow: 0 0 0 2px #fff, 0 2px 8px rgba(0, 0, 0, 0.4);
}

/* ---- Bottom nav icons (Admin + Teacher) — हरेकको फरक चहकिलो रङ ---- */
.teacher-bottom-nav .tbn-item:not(.tbn-home) i,
.admin-bottom-nav .tbn-item:not(.tbn-home) i {
  font-size: 18px;
  filter: drop-shadow(0 1px 1px rgba(27, 42, 74, 0.18));
  transition: transform 0.15s ease;
}
.teacher-bottom-nav .tbn-item:nth-child(1) i, .admin-bottom-nav .tbn-item:nth-child(1) i { color: #2563eb; }
.teacher-bottom-nav .tbn-item:nth-child(2) i, .admin-bottom-nav .tbn-item:nth-child(2) i { color: #ea580c; }
.teacher-bottom-nav .tbn-item:nth-child(3) i, .admin-bottom-nav .tbn-item:nth-child(3) i { color: #9333ea; }
.teacher-bottom-nav .tbn-item:nth-child(4) i, .admin-bottom-nav .tbn-item:nth-child(4) i { color: #16a34a; }
.teacher-bottom-nav .tbn-item:nth-child(5) i, .admin-bottom-nav .tbn-item:nth-child(5) i { color: #db2777; }
.teacher-bottom-nav .tbn-item:nth-child(6) i, .admin-bottom-nav .tbn-item:nth-child(6) i { color: #0891b2; }
.teacher-bottom-nav .tbn-item:nth-child(7) i, .admin-bottom-nav .tbn-item:nth-child(7) i { color: #dc2626; }
.teacher-bottom-nav .tbn-item:nth-child(8) i, .admin-bottom-nav .tbn-item:nth-child(8) i { color: #ca8a04; }
.teacher-bottom-nav .tbn-item:not(.tbn-home) span,
.admin-bottom-nav .tbn-item:not(.tbn-home) span { color: var(--ink-light); }
.teacher-bottom-nav .tbn-item.tbn-active:not(.tbn-home) i,
.admin-bottom-nav .tbn-item.tbn-active:not(.tbn-home) i { transform: scale(1.18); }
.teacher-bottom-nav .tbn-item.tbn-active:not(.tbn-home) span,
.admin-bottom-nav .tbn-item.tbn-active:not(.tbn-home) span { color: var(--gold-dark); }


/* ==========================================================================
   (१) तल्लो navigation ले Sidebar / Drawer का अन्तिम मेनु नछेक्ने।
   Bottom nav (60px, z-index 10000) fixed छ — Sidebar र Drawer पनि त्यसको माथिसम्म मात्र फैलिन्छन्,
   भित्रको सूची आफ्नै scroll हुन्छ, त्यसैले अन्तिम मेनु (Logout सहित) सधैँ पुगिन्छ।
   ========================================================================== */
body.has-admin-bottom-nav .admin-sidebar,
body.has-teacher-bottom-nav .admin-sidebar {
  position: sticky; top: 0;
  height: calc(100vh - 60px - env(safe-area-inset-bottom, 0px));
  height: calc(100dvh - 60px - env(safe-area-inset-bottom, 0px));
  min-height: 0 !important;
  overflow: hidden;
}
body.has-admin-bottom-nav .admin-sidebar .admin-sidebar-nav,
body.has-teacher-bottom-nav .admin-sidebar .admin-sidebar-nav { min-height: 0; overflow-y: auto; padding-bottom: 1.2rem; }
body.has-admin-bottom-nav .admin-drawer,
body.has-teacher-bottom-nav .admin-drawer { bottom: calc(60px + env(safe-area-inset-bottom, 0px)); }
body.has-admin-bottom-nav .admin-drawer .admin-drawer-nav,
body.has-teacher-bottom-nav .admin-drawer .admin-drawer-nav { min-height: 0; padding-bottom: 1.2rem; }

/* ==========================================================================
   (२) Sidebar / drawer का मेनु आइकन — ठोस रङ्गको टाइल (shape) होइन।
   टाइलको पृष्ठभूमि, gradient, छाया र घेरा सबै हटाइयो; आइकन आफ्नै रङमा (--mi) मात्र देखिन्छ।
   सक्रिय पृष्ठ (सुनौलो पट्टी) मा आइकन गाढा नै रहन्छ।
   ========================================================================== */
.admin-sidebar-nav .sidebar-link .admin-menu-icon,
.admin-drawer-nav .sidebar-link .admin-menu-icon,
.admin-sidebar-nav .sidebar-link:not([aria-current="page"]) .admin-menu-icon,
.admin-drawer-nav .sidebar-link:not([aria-current="page"]) .admin-menu-icon,
.admin-sidebar-nav .sidebar-link[aria-current="page"] .admin-menu-icon,
.admin-drawer-nav .sidebar-link[aria-current="page"] .admin-menu-icon,
.admin-sidebar-nav .sidebar-group-toggle-active .admin-menu-icon,
.admin-drawer-nav .sidebar-group-toggle-active .admin-menu-icon,
.admin-sidebar-nav .sidebar-link.sidebar-group-toggle-active:not([aria-current="page"]) .admin-menu-icon,
.admin-drawer-nav .sidebar-link.sidebar-group-toggle-active:not([aria-current="page"]) .admin-menu-icon {
  background: none !important; box-shadow: none !important; filter: none !important; border-radius: 0;
  width: 1.4rem; height: auto;
}
.admin-sidebar-nav .sidebar-link:not([aria-current="page"]) .admin-menu-icon i,
.admin-drawer-nav .sidebar-link:not([aria-current="page"]) .admin-menu-icon i {
  color: var(--mi, #cbd5e1); text-shadow: none; font-size: 1rem;
}
.admin-sidebar-nav .sidebar-link:not([aria-current="page"]):hover .admin-menu-icon,
.admin-drawer-nav .sidebar-link:not([aria-current="page"]):hover .admin-menu-icon { transform: none; filter: none; }
.admin-sidebar-nav .sidebar-link:not([aria-current="page"]):hover .admin-menu-icon i,
.admin-drawer-nav .sidebar-link:not([aria-current="page"]):hover .admin-menu-icon i { color: #fff; }


/* बैंकलाई पत्रको तालिका: हरेक कक्ष एक लाइनमै (दोस्रो लाइनमा नभाँचिने); चौडाइ सामग्री अनुसार, अटाउन नसके
   printBankPatra() ले table को font-size घटाउँछ। रकम स्तम्भको चौडा monospace को सट्टा फारमकै फन्ट। */
.jinsi-print-form table.jp-table.bk-oneline th,
.jinsi-print-form table.jp-table.bk-oneline td { white-space: nowrap; }
.jinsi-print-form table.jp-table.bk-oneline td.jp-num { font-family: inherit; font-variant-numeric: tabular-nums; }

/* बैंकलाई पत्र: तालिकाका पङ्क्ति कस्सिएको (tight) — चिठीको 1.8 line-height नभई कम उचाइ, कम padding; सबै पङ्क्ति
   एउटै A4 पानामा अटाउन। अक्षर = आधार × चौडाइ-fit (--bk-w) × उचाइ-fit (--lt-k, fitLetterBodyText)। */
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.jp-table.bk-oneline { font-size: calc(0.78rem * var(--bk-w, 1) * var(--lt-k, 1)); margin: 1mm 0 0; }
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.jp-table.bk-oneline th,
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.jp-table.bk-oneline td { padding: calc(0.35mm * var(--lt-k, 1)) calc(1.5mm * var(--lt-k, 1)); line-height: 1.15; height: auto; }
.jinsi-print-form table.jp-table.bk-oneline tr { height: auto; }

/* चिठी भित्रको सामान्य तालिका (.lt-table, पत्राचार): कस्सिएको पङ्क्ति + अक्षरसँगै घट्ने खाली ठाउँ — एउटै पानामा अटाउन। */
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.lt-table { margin: 0.3em 0 0.5em; line-height: 1.2; }
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.lt-table th,
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.lt-table td { padding: calc(0.6mm * var(--lt-k, 1)) calc(1.8mm * var(--lt-k, 1)); line-height: 1.2; }
.jinsi-print-form.letter-page .letterpad-body.lt-fit-table table.lt-table td { vertical-align: middle; }

/* ---- बि.सं. मिति छान्ने (वर्ष / महिना / गते) — js/family-engine.js: FE.bsPickerHtml() ---- */
.fe-bs-date { display: grid; grid-template-columns: 1.1fr 1.6fr 1fr; gap: 0.4rem; }
.fe-bs-date .input-field { min-width: 0; padding-left: 0.5rem; padding-right: 1.2rem; }
