/* =============================================================================
   JMNL Admin — design system
   Janhvi Mudra Nidhi Limited

   Built as a single token-driven stylesheet rather than on top of Bootstrap:
   this is a money-handling product that must not read as a bootstrap template,
   and one 20KB file loads faster on the weak connections the office actually
   has than a 200KB framework of which we would use a tenth.

   Palette follows the banking/traditional-finance convention — trust navy with
   a teal accent, crisp white surfaces — with status colour carrying a single
   consistent meaning across the whole product:
       green = paid/positive, amber = due soon, red = overdue.
   Every status is also labelled in text, never colour alone.

   These same tokens are what the Flutter theme mirrors, so mobile and web
   read as one product.
   ============================================================================= */

/* ---------- Tokens ---------- */
:root {
  /* Brand */
  --navy-900: #0b1f38;
  --navy-800: #102a4c;
  --navy-700: #16375f;
  --navy-600: #1d4a7a;
  --teal-700: #0d5c63;
  --teal-600: #0f7178;
  --teal-500: #15919b;
  --teal-50:  #e7f3f4;

  --primary: var(--navy-800);
  --primary-hover: var(--navy-700);
  --on-primary: #ffffff;
  --accent: var(--teal-700);
  --accent-hover: var(--teal-600);

  /* Surfaces */
  --bg: #f4f7fa;
  --surface: #ffffff;
  --surface-sunken: #fafbfd;
  --surface-hover: #f2f6fa;

  /* Ink */
  --ink: #0d1b2a;
  --ink-strong: #06111d;
  --ink-muted: #5b7186;
  --ink-subtle: #8098ad;
  --on-dark: #e8eef5;
  --on-dark-muted: #93a9bf;

  /* Lines */
  --line: #dde5ee;
  --line-strong: #c7d3e0;

  /* Status — each one paired with a tint for badges */
  --paid: #0f7a3d;
  --paid-tint: #e6f5ec;
  --due: #a86a00;
  --due-tint: #fdf2e0;
  --overdue: #c0271d;
  --overdue-tint: #fdeceb;
  --info: var(--teal-700);
  --info-tint: var(--teal-50);
  --neutral: #5b7186;
  --neutral-tint: #eef2f7;

  /* Type — 12/13/14/16/18/22/28/36, base 14 for a dense admin surface */
  --text-2xs: 0.6875rem;  /* 11px — badge, table meta */
  --text-xs:  0.75rem;    /* 12px — labels, captions */
  --text-sm:  0.8125rem;  /* 13px — table body, secondary */
  --text-base:0.875rem;   /* 14px — body */
  --text-md:  1rem;        /* 16px — inputs (16px avoids iOS auto-zoom) */
  --text-lg:  1.125rem;   /* 18px — card titles */
  --text-xl:  1.375rem;   /* 22px — page title */
  --text-2xl: 1.75rem;    /* 28px — KPI value */
  --text-3xl: 2.25rem;    /* 36px — hero figure */

  --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, "Noto Sans Devanagari", sans-serif;
  /* Money and ids use tabular figures so columns never jitter as values change. */
  --font-num: "SF Mono", ui-monospace, "Cascadia Mono", Menlo, Consolas, monospace;

  /* Spacing — 4px rhythm, dense end of the scale for a data-heavy admin */
  --s1: 0.25rem;  /*  4 */
  --s2: 0.5rem;   /*  8 */
  --s3: 0.75rem;  /* 12 */
  --s4: 1rem;     /* 16 */
  --s5: 1.25rem;  /* 20 */
  --s6: 1.5rem;   /* 24 */
  --s8: 2rem;     /* 32 */
  --s10: 2.5rem;  /* 40 */

  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(11, 31, 56, 0.06);
  --shadow: 0 1px 3px rgba(11, 31, 56, 0.08), 0 4px 12px rgba(11, 31, 56, 0.04);
  --shadow-lg: 0 8px 28px rgba(11, 31, 56, 0.12);

  --sidebar-w: 236px;
  --header-h: 60px;

  /* Motion — 150-250ms, the range that reads as responsive rather than sluggish */
  --ease: cubic-bezier(0.32, 0.72, 0, 1);
  --t-fast: 140ms;
  --t: 200ms;

  --z-dropdown: 40;
  --z-sticky: 60;
  --z-drawer: 90;
  --z-modal: 100;
  --z-toast: 120;
}

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

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

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

h1, h2, h3, h4, p, figure { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg { vertical-align: middle; max-width: 100%; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* A visible focus ring is non-negotiable on a keyboard-heavy admin tool. */
:focus-visible {
  outline: 2px solid var(--teal-500);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Respect the user's motion preference rather than overriding it. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Screen-reader-only text, used for table sort state and icon-only buttons. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: var(--s4); top: -3rem;
  z-index: var(--z-toast);
  padding: var(--s2) var(--s4);
  background: var(--primary); color: var(--on-primary);
  border-radius: var(--radius-sm); font-weight: 600;
  transition: top var(--t) var(--ease);
}
.skip-link:focus { top: var(--s4); text-decoration: none; }

/* ---------- App shell ---------- */
.shell { display: flex; min-height: 100dvh; }

.sidebar {
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--navy-900);
  color: var(--on-dark);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100dvh;
  z-index: var(--z-drawer);
}

.sidebar__brand {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  min-height: var(--header-h);
}
.sidebar__mark {
  width: 34px; height: 34px; flex: 0 0 34px;
  display: grid; place-items: center;
  background: var(--teal-600); color: #fff;
  border-radius: var(--radius-sm);
  font-weight: 700; font-size: var(--text-sm); letter-spacing: -0.02em;
}
.sidebar__name { font-weight: 650; font-size: var(--text-base); letter-spacing: -0.01em; }
.sidebar__tagline { font-size: var(--text-2xs); color: var(--on-dark-muted); }

.sidebar__nav { padding: var(--s3) var(--s3) var(--s6); overflow-y: auto; flex: 1; }
.sidebar__section {
  padding: var(--s4) var(--s2) var(--s2);
  font-size: var(--text-2xs); font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--on-dark-muted);
}

.nav-link {
  display: flex; align-items: center; gap: var(--s3);
  /* 40px tall — comfortable for a mouse, still tappable on a tablet. */
  padding: var(--s2) var(--s3); min-height: 40px;
  border-radius: var(--radius-sm);
  color: var(--on-dark); font-size: var(--text-sm); font-weight: 500;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.nav-link:hover { background: rgba(255, 255, 255, 0.07); text-decoration: none; }
.nav-link svg { width: 17px; height: 17px; flex: 0 0 17px; opacity: 0.85; }
/* Current location is marked by weight and a left rule, not colour alone. */
.nav-link[aria-current="page"] {
  background: rgba(21, 145, 155, 0.18);
  color: #fff; font-weight: 600;
  box-shadow: inset 2px 0 0 var(--teal-500);
}
.nav-link[aria-current="page"] svg { opacity: 1; color: var(--teal-500); }

.nav-link__badge {
  margin-left: auto;
  min-width: 20px; padding: 1px var(--s2);
  background: var(--due); color: #fff;
  border-radius: var(--radius-pill);
  font-size: var(--text-2xs); font-weight: 700; text-align: center;
  font-variant-numeric: tabular-nums;
}

.main { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: var(--s4);
  min-height: var(--header-h);
  padding: 0 var(--s6);
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: var(--z-sticky);
}
.topbar__title { font-size: var(--text-xl); font-weight: 650; letter-spacing: -0.02em; }
.topbar__sub { font-size: var(--text-xs); color: var(--ink-muted); }
.topbar__actions { margin-left: auto; display: flex; align-items: center; gap: var(--s3); }

.user-chip {
  display: flex; align-items: center; gap: var(--s2);
  padding: var(--s1) var(--s2) var(--s1) var(--s1);
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--surface);
}
.user-chip__avatar {
  width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--navy-800); color: #fff;
  font-size: var(--text-xs); font-weight: 650;
}
.user-chip__name { font-size: var(--text-xs); font-weight: 600; }
.user-chip__role { font-size: var(--text-2xs); color: var(--ink-muted); text-transform: capitalize; }

.content { padding: var(--s6); flex: 1; }
.content > * + * { margin-top: var(--s6); }

.page-foot {
  padding: var(--s5) var(--s6);
  border-top: 1px solid var(--line);
  font-size: var(--text-xs); color: var(--ink-muted);
  display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5);
}

/* Mobile: the sidebar becomes a drawer behind a scrim. */
.sidebar__toggle { display: none; }
.scrim {
  position: fixed; inset: 0; z-index: calc(var(--z-drawer) - 1);
  background: rgba(6, 17, 29, 0.55);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t) var(--ease);
}

@media (max-width: 1023px) {
  .sidebar {
    position: fixed; inset: 0 auto 0 0;
    transform: translateX(-100%);
    transition: transform var(--t) var(--ease);
    box-shadow: var(--shadow-lg);
  }
  body.nav-open .sidebar { transform: translateX(0); }
  body.nav-open .scrim { opacity: 1; pointer-events: auto; }
  .sidebar__toggle { display: inline-grid; }
  .content, .topbar { padding-left: var(--s4); padding-right: var(--s4); }
}

/* ---------- Cards ---------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.card__head {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--line);
}
.card__title { font-size: var(--text-lg); font-weight: 650; letter-spacing: -0.01em; }
.card__sub { font-size: var(--text-xs); color: var(--ink-muted); }
.card__actions { margin-left: auto; display: flex; align-items: center; gap: var(--s2); }
.card__body { padding: var(--s5); }
.card__body--flush { padding: 0; }

/* ---------- KPI row ----------
   Six metrics in one row on a wide screen, wrapping to 3 / 2 / 1.
   Label above, value below, one number per card — nothing else. */
.kpi-row {
  display: grid; gap: var(--s4);
  grid-template-columns: repeat(6, minmax(0, 1fr));
}
@media (max-width: 1439px) { .kpi-row { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 767px)  { .kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 420px)  { .kpi-row { grid-template-columns: 1fr; } }

.kpi {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--s4) var(--s4) var(--s5);
  box-shadow: var(--shadow-sm);
  position: relative; overflow: hidden;
}
/* A 3px top rule carries the metric's tone without tinting the whole card. */
.kpi::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--tone, var(--navy-600));
}
.kpi__label {
  font-size: var(--text-2xs); font-weight: 600;
  letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--ink-muted);
  display: flex; align-items: center; gap: var(--s1);
}
.kpi__value {
  margin-top: var(--s3);
  font-family: var(--font-num);
  /* Scales with the card so a crore figure shrinks instead of wrapping —
     a rupee amount split across two lines is unreadable. */
  font-size: clamp(1.25rem, 1.05rem + 0.9vw, var(--text-2xl));
  font-weight: 650;
  letter-spacing: -0.03em; line-height: 1.15;
  color: var(--ink-strong);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kpi__value--sm { font-size: var(--text-xl); }
.kpi__meta { margin-top: var(--s2); font-size: var(--text-xs); color: var(--ink-muted); }
.kpi--paid    { --tone: var(--paid); }
.kpi--due     { --tone: var(--due); }
.kpi--overdue { --tone: var(--overdue); }
.kpi--info    { --tone: var(--teal-600); }

/* ---------- Charts ---------- */
.chart-grid {
  display: grid; gap: var(--s4);
  grid-template-columns: 2fr 1fr;
}
@media (max-width: 1023px) { .chart-grid { grid-template-columns: 1fr; } }

/* Fixed height reserves the space before Chart.js paints, so the page does
   not shift as data arrives. */
.chart-box { position: relative; height: 288px; }
.chart-box canvas { position: absolute; inset: 0; }

.chart-empty {
  position: absolute; inset: 0;
  display: grid; place-content: center; gap: var(--s2);
  text-align: center; color: var(--ink-muted); font-size: var(--text-sm);
  background: var(--surface);
}
/* A `display` value on the element itself beats the browser's default
   `[hidden] { display: none }`, so the hidden state has to be restated. */
.chart-empty[hidden] { display: none; }

/* Legend rendered as markup, so it is readable by a screen reader and each
   series carries its exact value rather than only a colour. */
.legend { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s5); }
.legend__item { display: flex; align-items: baseline; gap: var(--s2); font-size: var(--text-xs); }
.legend__swatch { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 10px; }
.legend__value {
  font-family: var(--font-num); font-weight: 650; color: var(--ink-strong);
  font-variant-numeric: tabular-nums;
}

/* ---------- Tables ---------- */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.table th, .table td {
  padding: var(--s3) var(--s4);
  text-align: left;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--surface-sunken);
  font-size: var(--text-2xs); font-weight: 650;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-muted);
  border-bottom: 1px solid var(--line-strong);
}
.table tbody tr { transition: background var(--t-fast) var(--ease); }
.table tbody tr:hover { background: var(--surface-hover); }
.table tbody tr:last-child td { border-bottom: 0; }

/* Money and dates right-align on tabular figures so the decimal points line up. */
.table .num, .num {
  text-align: right;
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums;
  font-weight: 550;
}
.table .num--strong { font-weight: 650; color: var(--ink-strong); }
.table .wrap { white-space: normal; min-width: 180px; }

.table__primary { font-weight: 600; color: var(--ink-strong); }
.table__meta { font-size: var(--text-2xs); color: var(--ink-muted); }

/* Sortable headers announce their state via aria-sort. */
.table th[aria-sort] { cursor: pointer; user-select: none; }
.table th[aria-sort] .sort-icon { opacity: 0.35; margin-left: var(--s1); }
.table th[aria-sort="ascending"] .sort-icon,
.table th[aria-sort="descending"] .sort-icon { opacity: 1; color: var(--accent); }

.empty {
  padding: var(--s10) var(--s5);
  text-align: center; color: var(--ink-muted);
}
.empty__title { font-size: var(--text-base); font-weight: 600; color: var(--ink); }
.empty__hint { margin-top: var(--s1); font-size: var(--text-sm); }
.empty svg { width: 36px; height: 36px; color: var(--ink-subtle); margin-bottom: var(--s3); }

/* ---------- Badges ----------
   Status always carries a word, never colour on its own. */
.badge {
  display: inline-flex; align-items: center; gap: var(--s1);
  padding: 2px var(--s2);
  border-radius: var(--radius-pill);
  font-size: var(--text-2xs); font-weight: 650;
  letter-spacing: 0.03em; text-transform: uppercase;
  white-space: nowrap;
}
.badge::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; flex: 0 0 5px;
}
.badge--paid    { background: var(--paid-tint);    color: var(--paid); }
.badge--due     { background: var(--due-tint);     color: var(--due); }
.badge--overdue { background: var(--overdue-tint); color: var(--overdue); }
.badge--info    { background: var(--info-tint);    color: var(--info); }
.badge--neutral { background: var(--neutral-tint); color: var(--neutral); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  /* 38px default / 44px on touch — meets the touch-target minimum. */
  min-height: 38px; padding: var(--s2) var(--s4);
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: var(--text-sm); font-weight: 600;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
}
.btn svg { width: 15px; height: 15px; }
.btn:hover { text-decoration: none; }

.btn--primary { background: var(--primary); color: var(--on-primary); }
.btn--primary:hover { background: var(--primary-hover); }
.btn--accent { background: var(--accent); color: #fff; }
.btn--accent:hover { background: var(--accent-hover); }
.btn--outline { border-color: var(--line-strong); color: var(--ink); }
.btn--outline:hover { background: var(--surface-hover); border-color: var(--ink-subtle); }
.btn--ghost { background: transparent; color: var(--ink-muted); }
.btn--ghost:hover { background: var(--surface-hover); color: var(--ink); }
.btn--paid { background: var(--paid); color: #fff; }
.btn--paid:hover { filter: brightness(0.93); }
/* Destructive actions are visually separated and semantically coloured. */
.btn--danger { background: var(--overdue); color: #fff; }
.btn--danger:hover { filter: brightness(0.93); }
.btn--sm { min-height: 30px; padding: var(--s1) var(--s3); font-size: var(--text-xs); }
.btn--icon { padding: var(--s2); min-width: 38px; }

.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.45; cursor: not-allowed; pointer-events: none;
}
/* Async buttons show a spinner and stop accepting clicks. */
.btn[data-loading="true"] { position: relative; color: transparent !important; pointer-events: none; }
.btn[data-loading="true"]::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 15px; height: 15px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.4); border-top-color: #fff;
  animation: spin 600ms linear infinite;
}
.btn--outline[data-loading="true"]::after,
.btn--ghost[data-loading="true"]::after { border-color: var(--line-strong); border-top-color: var(--accent); }
@keyframes spin { to { transform: rotate(360deg); } }

@media (pointer: coarse) {
  .btn { min-height: 44px; }
  .btn--sm { min-height: 36px; }
}

/* ---------- Forms ---------- */
.field { display: block; }
.field + .field { margin-top: var(--s4); }
.field__label {
  display: block; margin-bottom: var(--s1);
  font-size: var(--text-xs); font-weight: 600; color: var(--ink);
}
.field__label .req { color: var(--overdue); margin-left: 2px; }

.input, .select, .textarea {
  width: 100%;
  /* 16px font on inputs stops iOS from zooming the page on focus. */
  min-height: 40px; padding: var(--s2) var(--s3);
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink);
  font-family: inherit; font-size: var(--text-md);
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.input:hover, .select:hover, .textarea:hover { border-color: var(--ink-subtle); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--teal-500);
  box-shadow: 0 0 0 3px rgba(21, 145, 155, 0.16);
}
.textarea { min-height: 80px; resize: vertical; }
.input[readonly] { background: var(--surface-sunken); color: var(--ink-muted); }
.input--num { font-family: var(--font-num); text-align: right; font-variant-numeric: tabular-nums; }

/* Helper text is persistent, not a placeholder that vanishes on focus. */
.field__help { margin-top: var(--s1); font-size: var(--text-xs); color: var(--ink-muted); }
/* The error sits directly below its own field. */
.field__error { margin-top: var(--s1); font-size: var(--text-xs); font-weight: 550; color: var(--overdue); }
.field--invalid .input, .field--invalid .select, .field--invalid .textarea { border-color: var(--overdue); }

.form-grid { display: grid; gap: var(--s4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-grid .field + .field { margin-top: 0; }
.form-grid__full { grid-column: 1 / -1; }
@media (max-width: 767px) { .form-grid { grid-template-columns: 1fr; } }

/* ---------- Filter bar ---------- */
.filters {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s3);
  padding: var(--s4) var(--s5);
  background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.filters .field { min-width: 150px; flex: 0 1 auto; }
.filters__spacer { margin-left: auto; }

/* ---------- Alerts ---------- */
.alert {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) var(--s4);
  border: 1px solid; border-radius: var(--radius-sm);
  font-size: var(--text-sm);
}
.alert svg { width: 17px; height: 17px; flex: 0 0 17px; margin-top: 1px; }
.alert--success { background: var(--paid-tint);    border-color: #b7e0c6; color: #0a5a2c; }
.alert--warning { background: var(--due-tint);     border-color: #efd39a; color: #7c4e00; }
.alert--error   { background: var(--overdue-tint); border-color: #f2bdb9; color: #94201a; }
.alert--info    { background: var(--info-tint);    border-color: #b6dcdf; color: #0a464b; }
.alert__title { font-weight: 650; }
.alert__list { margin-top: var(--s1); font-size: var(--text-xs); }
.alert__close { margin-left: auto; }

/* ---------- Pagination ---------- */
.pager {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s5);
  border-top: 1px solid var(--line);
  font-size: var(--text-xs); color: var(--ink-muted);
}
.pager__links { margin-left: auto; display: flex; gap: var(--s1); }
.pager__link {
  min-width: 32px; min-height: 32px; padding: 0 var(--s2);
  display: inline-grid; place-items: center;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums;
}
.pager__link:hover { background: var(--surface-hover); text-decoration: none; }
.pager__link[aria-current="page"] {
  background: var(--primary); border-color: var(--primary); color: var(--on-primary);
}
.pager__link[aria-disabled="true"] { opacity: 0.4; pointer-events: none; }

/* ---------- Detail lists ---------- */
.dl { display: grid; grid-template-columns: max-content 1fr; gap: var(--s2) var(--s5); }
.dl dt { font-size: var(--text-xs); color: var(--ink-muted); }
.dl dd { margin: 0; font-size: var(--text-sm); font-weight: 550; }
.dl dd.num { text-align: left; }
@media (max-width: 520px) { .dl { grid-template-columns: 1fr; gap: var(--s1) 0; } .dl dd { margin-bottom: var(--s2); } }

/* ---------- Progress ---------- */
.progress {
  height: 6px; border-radius: var(--radius-pill);
  background: var(--neutral-tint); overflow: hidden;
}
.progress__fill { height: 100%; border-radius: inherit; background: var(--paid); }

/* ---------- Login ---------- */
.auth {
  min-height: 100dvh;
  display: grid; place-items: center;
  padding: var(--s6) var(--s4);
  background:
    radial-gradient(1100px 520px at 50% -20%, rgba(21, 145, 155, 0.16), transparent 70%),
    var(--navy-900);
}
.auth__card {
  width: 100%; max-width: 396px;
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.auth__head { padding: var(--s8) var(--s6) var(--s5); text-align: center; }
.auth__mark {
  width: 52px; height: 52px; margin: 0 auto var(--s4);
  display: grid; place-items: center;
  background: var(--navy-800); color: #fff;
  border-radius: var(--radius);
  font-size: var(--text-lg); font-weight: 700; letter-spacing: -0.02em;
}
.auth__title { font-size: var(--text-lg); font-weight: 650; letter-spacing: -0.01em; }
.auth__sub { margin-top: var(--s1); font-size: var(--text-sm); color: var(--ink-muted); }
.auth__body { padding: 0 var(--s6) var(--s6); }
.auth__foot {
  padding: var(--s4) var(--s6);
  background: var(--surface-sunken);
  border-top: 1px solid var(--line);
  font-size: var(--text-2xs); color: var(--ink-muted); text-align: center;
  line-height: 1.6;
}

/* ---------- Utilities ---------- */
.stack     { display: flex; flex-direction: column; gap: var(--s4); }
.stack--sm { gap: var(--s2); }
.row       { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.row--tight{ gap: var(--s2); }
.push      { margin-left: auto; }
.muted     { color: var(--ink-muted); }
.tiny      { font-size: var(--text-xs); }
.strong    { font-weight: 650; color: var(--ink-strong); }
.money     { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-weight: 600; }
.text-paid    { color: var(--paid); }
.text-due     { color: var(--due); }
.text-overdue { color: var(--overdue); }
.nowrap    { white-space: nowrap; }
.split     { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }

.grid-2 { display: grid; gap: var(--s4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { display: grid; gap: var(--s4); grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1023px) { .grid-3 { grid-template-columns: 1fr; } }
@media (max-width: 767px)  { .grid-2 { grid-template-columns: 1fr; } }

/* ---------- Print (receipts, statements) ---------- */
@media print {
  .sidebar, .topbar, .filters, .pager, .page-foot, .btn { display: none !important; }
  body { background: #fff; }
  .card { border: none; box-shadow: none; }
  .content { padding: 0; }
}
