/* ============================================================================
   Larnaca Storage — Accounting Panel
   public/styles.css — the complete design system. No external resources.

   CLASS INDEX (grep this list; app.js must use these names verbatim)
   ---------------------------------------------------------------------------
   ROOTS       #app  #modal-root  #toast-root
   LAYOUT      .shell .sidebar .sidebar-brand .nav .nav-item .nav-item.active
               .main .topbar .topbar-title .topbar-meta .content
               .grid .grid-2 .grid-3 .grid-4
   CARDS       .card .card-head .card-title .card-body
               .kpi .kpi-label .kpi-value .kpi-sub
   TABLES      .table-wrap table.table .table th .table td .table .num
               .table tr.clickable .sortable .sort-asc .sort-desc
               .table-empty .table-total
   BADGES      .badge .badge-overdue .badge-due-soon .badge-upcoming .badge-ok
               .badge-credit .badge-archived .badge-flag .badge-error .room-badge
   DATA ERRORS .row-error .cell-error .row-error-note .err-glyph
               .room-card.is-error   (red = the value itself is wrong)
   MONEY       .money .money-pos .money-neg .money-zero
   FORMS       .form .form-row .field .field label .input .select .textarea
               .checkbox .field-error .field-hint
   BUTTONS     .btn .btn-primary .btn-danger .btn-ghost .btn-sm .btn-icon
               .btn-group
   FILTERS     .toolbar .toolbar-end .search .chips .chip .chip.active
   MODAL       .modal-backdrop .modal .modal-head .modal-body .modal-foot
               .modal-lg .modal-sm
   FEEDBACK    .toast .toast-ok .toast-err .spinner .empty-state .skeleton
   CHART       .chart .chart-bar-billed .chart-bar-collected .chart-axis
               .chart-legend
   EXTRAS      .login-wrap .login-card .login-title .login-sub
               .page-head .page-title .page-sub .page-actions
               .detail-head .detail-name .detail-meta .detail-balance
               .room-grid .room-card .room-card-head .room-card-num
               .room-card-body .room-card-foot
               .room-card.is-free .room-card.is-occupied .room-card.is-overdue
               .tabs .tab .tab.active .pager .pager-info
               .notice .notice-info .notice-warn .notice-danger .notice-ok
               .dl .dl dt .dl dd .progress .progress-bar .kbd .tag
               .theme-toggle .file-drop .divider
   UTILITIES   .row .col .stack .spacer .right .center .nowrap .truncate
               .muted .dim .small .strong .mono .hidden .sr-only
               .mt-0 .mt-1 .mt-2 .mt-3 .mb-0 .mb-1 .mb-2 .mb-3 .w-full
   STATE HOOKS .table tr.flagged  .is-loading  [aria-invalid="true"]
   ---------------------------------------------------------------------------
   THEME  :root = light, :root[data-theme="dark"] = dark; with no data-theme
          attribute the palette follows prefers-color-scheme.
          app.js sets document.documentElement.dataset.theme = 'light'|'dark'.
   MONEY SEMANTICS  .money-pos = positive balance = client OWES = RED.
                    .money-neg = negative balance = credit = GREEN.
   MOBILE  < 900px: sidebar becomes a fixed bottom nav and every .table-wrap
           table reflows into stacked cards using td[data-label].
   ============================================================================ */

/* ---------------------------------------------------------------------------
   1. DESIGN TOKENS — LIGHT (default)
   --------------------------------------------------------------------------- */
:root {
  /* type */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
               Arial, "Noto Sans", "Liberation Sans", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", "Courier New", monospace;
  --fs-xs: 11.5px;
  --fs-sm: 12.5px;
  --fs-base: 14px;
  --fs-md: 15px;
  --fs-lg: 17px;
  --fs-xl: 21px;
  --fs-2xl: 27px;
  --fs-3xl: 34px;

  /* metrics */
  --sidebar-w: 240px;
  --topbar-h: 60px;
  --content-max: 2400px;
  --content-pad: 28px;
  --gap: 18px;
  --gap-sm: 10px;
  --gap-lg: 26px;
  --r-sm: 6px;
  --r: 10px;
  --r-lg: 14px;
  --r-pill: 999px;
  --tr: 140ms cubic-bezier(.2, .6, .3, 1);
  --tap: 44px;

  /* surfaces */
  --bg: #f4f6f9;
  --bg-alt: #eef1f6;
  --surface: #ffffff;
  --surface-2: #fafbfd;
  --surface-3: #eef1f6;
  --surface-hover: #f2f6fc;
  --surface-active: #e8effa;
  --border: #dde3ec;
  --border-strong: #c3ccd9;
  --shadow-1: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .05);
  --shadow-2: 0 4px 12px rgba(16, 24, 40, .09), 0 2px 4px rgba(16, 24, 40, .05);
  --shadow-3: 0 18px 48px rgba(16, 24, 40, .22);

  /* text */
  --text: #101828;
  --text-muted: #505c6d;
  --text-dim: #6b7684;
  --text-inverse: #ffffff;

  /* sidebar (intentionally dark in both themes — ledger-tool look) */
  --sidebar-bg: #182231;
  --sidebar-bg-2: #131c29;
  --sidebar-text: #c8d2e0;
  --sidebar-text-dim: #8493a8;
  --sidebar-hover: #223044;
  --sidebar-active-bg: #24344a;
  --sidebar-active: #ffffff;
  --sidebar-border: #26313f;
  --sidebar-accent: #7fb0ff;

  /* accent */
  --accent: #1f5aa6;
  --accent-hover: #1a4d8f;
  --accent-press: #163f76;
  --accent-fg: #ffffff;
  --accent-soft: #e7effb;
  --accent-soft-fg: #14417c;
  --accent-border: #c4d8f3;

  /* semantic */
  --danger: #b42318;
  --danger-hover: #99190f;
  --danger-fg: #ffffff;
  --danger-soft: #fdeaea;
  --danger-soft-fg: #a11a1a;
  --danger-border: #f3c9c9;

  --warn: #8a4b00;
  --warn-soft: #fff3e0;
  --warn-soft-fg: #8a4b00;
  --warn-border: #f5d8ac;

  --success: #12693a;
  --success-soft: #e7f6ec;
  --success-soft-fg: #12693a;
  --success-border: #c3e5d1;

  --info-soft: #e9f0fd;
  --info-soft-fg: #1c4ba8;
  --info-border: #cddffa;

  --credit-soft: #e2f3f6;
  --credit-soft-fg: #0d5c6b;
  --credit-border: #bee0e7;

  --neutral-soft: #ecf0f4;
  --neutral-soft-fg: #4a5565;
  --neutral-border: #d6dde5;

  /* money */
  --money-pos: #b3261e;   /* owes  */
  --money-neg: #12693a;   /* credit */
  --money-zero: #6b7684;

  /* room chip */
  --room-bg: #e7effb;
  --room-fg: #143a76;
  --room-bd: #c2d6f4;

  /* chart */
  --chart-billed: #4a7fc1;
  --chart-collected: #2f9e63;
  --chart-grid: #e2e7ee;
  --chart-axis: #98a3b1;

  /* misc */
  --focus: #2f7ad6;
  --backdrop: rgba(16, 24, 40, .48);
  --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7684' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20.5 20.5 16.7 16.7'/%3E%3C/svg%3E");
  --icon-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b7684' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

/* ---------------------------------------------------------------------------
   2. DESIGN TOKENS — DARK
   Applied automatically when the OS prefers dark and no explicit light theme
   is set, and always when data-theme="dark".
   --------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0d1117;
    --bg-alt: #10161e;
    --surface: #151b24;
    --surface-2: #19212b;
    --surface-3: #1e2732;
    --surface-hover: #1d2733;
    --surface-active: #22314a;
    --border: #2a3440;
    --border-strong: #3c4a5a;
    --shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
    --shadow-2: 0 4px 14px rgba(0, 0, 0, .55);
    --shadow-3: 0 20px 52px rgba(0, 0, 0, .7);

    --text: #e6ecf3;
    --text-muted: #aeb9c6;
    --text-dim: #8a95a3;
    --text-inverse: #0d1117;

    --sidebar-bg: #0b1017;
    --sidebar-bg-2: #080c12;
    --sidebar-text: #c2ccda;
    --sidebar-text-dim: #7b8798;
    --sidebar-hover: #18212d;
    --sidebar-active-bg: #1c2939;
    --sidebar-active: #ffffff;
    --sidebar-border: #1a222c;
    --sidebar-accent: #7fb0ff;

    --accent: #3b7fd8;
    --accent-hover: #4c8ce0;
    --accent-press: #2f6cbb;
    --accent-fg: #ffffff;
    --accent-soft: #16263d;
    --accent-soft-fg: #9cc2ff;
    --accent-border: #26436b;

    --danger: #c8443a;
    --danger-hover: #d8544a;
    --danger-fg: #ffffff;
    --danger-soft: #3a1a1c;
    --danger-soft-fg: #ff9d9d;
    --danger-border: #5c2a2d;

    --warn: #f0b429;
    --warn-soft: #382810;
    --warn-soft-fg: #f5c164;
    --warn-border: #5a4318;

    --success: #2b8f57;
    --success-soft: #12301f;
    --success-soft-fg: #6fdc9b;
    --success-border: #1f4a31;

    --info-soft: #16294a;
    --info-soft-fg: #93b9ff;
    --info-border: #244070;

    --credit-soft: #0f2f34;
    --credit-soft-fg: #6ad4e2;
    --credit-border: #1a4d55;

    --neutral-soft: #222a34;
    --neutral-soft-fg: #a6b1bf;
    --neutral-border: #333d49;

    --money-pos: #ff8078;
    --money-neg: #58d68f;
    --money-zero: #8a95a3;

    --room-bg: #17263f;
    --room-fg: #a3c5ff;
    --room-bd: #26436b;

    --chart-billed: #5b93d8;
    --chart-collected: #3fb87a;
    --chart-grid: #263141;
    --chart-axis: #7b8798;

    --focus: #6aa5ff;
    --backdrop: rgba(0, 0, 0, .65);
    --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a95a3' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20.5 20.5 16.7 16.7'/%3E%3C/svg%3E");
    --icon-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a95a3' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  }
}

:root[data-theme="dark"] {
  --bg: #0d1117;
  --bg-alt: #10161e;
  --surface: #151b24;
  --surface-2: #19212b;
  --surface-3: #1e2732;
  --surface-hover: #1d2733;
  --surface-active: #22314a;
  --border: #2a3440;
  --border-strong: #3c4a5a;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-2: 0 4px 14px rgba(0, 0, 0, .55);
  --shadow-3: 0 20px 52px rgba(0, 0, 0, .7);

  --text: #e6ecf3;
  --text-muted: #aeb9c6;
  --text-dim: #8a95a3;
  --text-inverse: #0d1117;

  --sidebar-bg: #0b1017;
  --sidebar-bg-2: #080c12;
  --sidebar-text: #c2ccda;
  --sidebar-text-dim: #7b8798;
  --sidebar-hover: #18212d;
  --sidebar-active-bg: #1c2939;
  --sidebar-active: #ffffff;
  --sidebar-border: #1a222c;
  --sidebar-accent: #7fb0ff;

  --accent: #3b7fd8;
  --accent-hover: #4c8ce0;
  --accent-press: #2f6cbb;
  --accent-fg: #ffffff;
  --accent-soft: #16263d;
  --accent-soft-fg: #9cc2ff;
  --accent-border: #26436b;

  --danger: #c8443a;
  --danger-hover: #d8544a;
  --danger-fg: #ffffff;
  --danger-soft: #3a1a1c;
  --danger-soft-fg: #ff9d9d;
  --danger-border: #5c2a2d;

  --warn: #f0b429;
  --warn-soft: #382810;
  --warn-soft-fg: #f5c164;
  --warn-border: #5a4318;

  --success: #2b8f57;
  --success-soft: #12301f;
  --success-soft-fg: #6fdc9b;
  --success-border: #1f4a31;

  --info-soft: #16294a;
  --info-soft-fg: #93b9ff;
  --info-border: #244070;

  --credit-soft: #0f2f34;
  --credit-soft-fg: #6ad4e2;
  --credit-border: #1a4d55;

  --neutral-soft: #222a34;
  --neutral-soft-fg: #a6b1bf;
  --neutral-border: #333d49;

  --money-pos: #ff8078;
  --money-neg: #58d68f;
  --money-zero: #8a95a3;

  --room-bg: #17263f;
  --room-fg: #a3c5ff;
  --room-bd: #26436b;

  --chart-billed: #5b93d8;
  --chart-collected: #3fb87a;
  --chart-grid: #263141;
  --chart-axis: #7b8798;

  --focus: #6aa5ff;
  --backdrop: rgba(0, 0, 0, .65);
  --icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a95a3' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20.5 20.5 16.7 16.7'/%3E%3C/svg%3E");
  --icon-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a95a3' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

:root { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark; }
}

/* ---------------------------------------------------------------------------
   3. RESET & BASE
   --------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  padding: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-wrap: break-word;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; }
img, svg, video, canvas { max-width: 100%; }
img, video { height: auto; }

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

button, input, select, textarea {
  font: inherit;
  color: inherit;
  margin: 0;
}

hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: var(--gap) 0;
}

code, kbd, samp, pre { font-family: var(--font-mono); font-size: .92em; }

::selection { background: var(--accent-soft); color: var(--accent-soft-fg); }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
:focus:not(:focus-visible) { outline: none; }

/* thin, unobtrusive scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border: 3px solid var(--bg);
  border-radius: var(--r-pill);
}
*::-webkit-scrollbar-thumb:hover { background: var(--text-dim); }

#modal-root:empty, #toast-root:empty { display: none; }

/* ---------------------------------------------------------------------------
   4. APP SHELL — sidebar + main column
   Large-monitor first: fixed 240px sidebar, main column fills everything else,
   content centred at max 2400px so a 2560px screen is genuinely used.
   --------------------------------------------------------------------------- */
#app {
  min-height: 100vh;
  display: block;
}

.shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  align-items: start;
  min-height: 100vh;
}

.sidebar {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 12px 14px;
  background: linear-gradient(180deg, var(--sidebar-bg) 0%, var(--sidebar-bg-2) 100%);
  border-right: 1px solid var(--sidebar-border);
  color: var(--sidebar-text);
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 40;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px 16px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--sidebar-border);
  color: #fff;
  font-size: var(--fs-md);
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.2;
  text-decoration: none;
}
.sidebar-brand:hover { text-decoration: none; }
.sidebar-brand::before {
  content: "";
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--accent);
  background-image: linear-gradient(150deg, #3f83d8, #1f5aa6 70%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
}
.sidebar-brand small,
.sidebar-brand span {
  display: block;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--sidebar-text-dim);
  letter-spacing: .02em;
}

.nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  list-style: none;
  min-width: 0;
}
.nav li { list-style: none; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 40px;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--sidebar-text);
  font-size: var(--fs-base);
  font-weight: 500;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background var(--tr), color var(--tr);
}
.nav-item:hover {
  background: var(--sidebar-hover);
  color: #fff;
  text-decoration: none;
}
.nav-item:focus-visible {
  outline: 2px solid var(--sidebar-accent);
  outline-offset: -2px;
}
.nav-item.active {
  background: var(--sidebar-active-bg);
  color: var(--sidebar-active);
  font-weight: 600;
  box-shadow: inset 3px 0 0 var(--sidebar-accent);
}
.nav-item .nav-count,
.nav-item .badge {
  margin-left: auto;
  flex: 0 0 auto;
}
.nav-count {
  min-width: 22px;
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .12);
  color: #fff;
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.nav-count.is-alert { background: var(--danger); }

.nav-section {
  padding: 16px 12px 6px;
  color: var(--sidebar-text-dim);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
}

.sidebar-foot {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--sidebar-border);
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--sidebar-text-dim);
  font-size: var(--fs-sm);
}

/* main column ------------------------------------------------------------- */
.main {
  min-width: 0;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background: var(--bg);
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: var(--topbar-h);
  padding: 8px var(--content-pad);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 0 rgba(16, 24, 40, .02);
}

.topbar-title {
  font-size: var(--fs-lg);
  font-weight: 650;
  letter-spacing: -.01em;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar-meta {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 0 0 auto;
  color: var(--text-dim);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.topbar-meta strong { color: var(--text-muted); font-weight: 600; }

.content {
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--gap-lg) var(--content-pad) 72px;
  flex: 1 1 auto;
  min-width: 0;
}

/* grids ------------------------------------------------------------------- */
.grid,
.grid-2,
.grid-3,
.grid-4 {
  display: grid;
  gap: var(--gap);
  align-items: start;
  min-width: 0;
}
.grid { grid-template-columns: minmax(0, 1fr); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.grid > *, .grid-2 > *, .grid-3 > *, .grid-4 > * { min-width: 0; }

/* span helpers for mixed dashboards */
.span-2 { grid-column: span 2; }
.span-3 { grid-column: span 3; }
.span-4 { grid-column: span 4; }
.span-full { grid-column: 1 / -1; }

/* page headings ------------------------------------------------------------ */
.page-head {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 12px var(--gap);
  margin-bottom: var(--gap);
}
.page-title {
  font-size: var(--fs-2xl);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.15;
  color: var(--text);
}
.page-sub {
  color: var(--text-dim);
  font-size: var(--fs-sm);
}
.page-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  flex-wrap: wrap;
}

/* ---------------------------------------------------------------------------
   5. CARDS & KPI TILES
   --------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  min-width: 0;
}
.card + .card { margin-top: var(--gap); }
.grid .card + .card,
.grid-2 .card + .card,
.grid-3 .card + .card,
.grid-4 .card + .card { margin-top: 0; }

.card-head {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  min-height: 48px;
}
.card-title {
  font-size: var(--fs-md);
  font-weight: 650;
  letter-spacing: -.01em;
  color: var(--text);
  margin-right: auto;
  min-width: 0;
}
.card-title small {
  display: block;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--text-dim);
  letter-spacing: 0;
}
.card-head .btn,
.card-head .chips,
.card-head .toolbar { flex: 0 0 auto; }

.card-body { padding: 16px; }
/* a table as the last block of a card-body sits flush with the card edges */
.card-body > .table-wrap {
  margin: 0 -16px -16px;
  width: auto;
  border-radius: 0;
}
.card-body > .table-wrap:first-child { margin-top: -16px; }
.card-body > .table-wrap:not(:last-child) { margin-bottom: 0; }
.card-body > :first-child { margin-top: 0; }
.card-body > :last-child { margin-bottom: 0; }
.card-foot {
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  flex-wrap: wrap;
}
/* a card whose only child is a table needs no inner padding */
.card > .table-wrap { border: 0; border-radius: 0; box-shadow: none; }

/* KPI ---------------------------------------------------------------------- */
.kpi {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  min-width: 0;
  position: relative;
  overflow: hidden;
}
.kpi::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--accent);
  opacity: .85;
}
.kpi.is-danger::before { background: var(--money-pos); }
.kpi.is-warn::before { background: var(--warn); }
.kpi.is-ok::before { background: var(--money-neg); }
.kpi.is-neutral::before { background: var(--border-strong); }

.kpi-label {
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kpi-value {
  font-size: var(--fs-2xl);
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1.1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kpi-value.money-pos { color: var(--money-pos); }
.kpi-value.money-neg { color: var(--money-neg); }
.kpi-sub {
  font-size: var(--fs-sm);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kpi-sub .up { color: var(--money-neg); }
.kpi-sub .down { color: var(--money-pos); }

/* ---------------------------------------------------------------------------
   6. TABLES
   Desktop: full width, sticky header parked under the sticky topbar.
   .table-wrap only becomes a horizontal scroller in the narrow desktop band —
   a scroll container would otherwise break position:sticky headers.
   --------------------------------------------------------------------------- */
.table-wrap {
  position: relative;
  width: 100%;
  min-width: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
}
.card .table-wrap,
.card-body > .table-wrap { box-shadow: none; }

table.table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--fs-base);
  table-layout: auto;
}

.table caption {
  caption-side: top;
  text-align: left;
  padding: 12px 16px;
  font-weight: 650;
  color: var(--text);
}

.table thead th {
  position: sticky;
  top: var(--topbar-h);
  z-index: 5;
  background: var(--surface-3);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-strong);
  vertical-align: middle;
}
.table thead th:first-child { border-top-left-radius: var(--r); }
.table thead th:last-child { border-top-right-radius: var(--r); }
/* flush inside a card: no rounded header corners */
.card .table thead th { border-radius: 0; }

.table tbody td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  color: var(--text);
  line-height: 1.4;
}
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:nth-child(even) td { background: var(--surface-2); }
.table tbody tr:hover td { background: var(--surface-hover); }

/* numeric / money columns */
.table .num,
.table th.num,
.table td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  white-space: nowrap;
}

/* the room column: keep it tight and scannable at the left edge */
.table td:first-child,
.table th:first-child { padding-left: 16px; }
.table td:last-child,
.table th:last-child { padding-right: 16px; }
.table td.col-room,
.table th.col-room { width: 1%; white-space: nowrap; }
.table td.col-actions,
.table th.col-actions {
  width: 1%;
  white-space: nowrap;
  text-align: right;
}
.table td.col-actions .btn + .btn { margin-left: 6px; }

/* clickable rows */
.table tr.clickable { cursor: pointer; }
.table tr.clickable:hover td { background: var(--surface-active); }
.table tr.clickable:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
}
.table tr.clickable:active td { background: var(--surface-active); }

/* sortable headers */
.sortable,
th.sortable {
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  padding-right: 26px;
  position: relative;
  transition: color var(--tr), background var(--tr);
}
.sortable:hover { color: var(--text); background: var(--surface-active); }
.sortable::after {
  content: "";
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  opacity: .22;
}
.sortable.sort-asc::after,
.sort-asc::after {
  border-top: 0;
  border-bottom: 5px solid currentColor;
  opacity: 1;
}
.sortable.sort-desc::after,
.sort-desc::after {
  border-bottom: 0;
  border-top: 5px solid currentColor;
  opacity: 1;
}
.sort-asc, .sort-desc { color: var(--accent); }
th.sort-asc, th.sort-desc { background: var(--accent-soft); }

/* empty + totals */
.table-empty,
.table td.table-empty,
tr.table-empty td {
  padding: 34px 16px !important;
  text-align: center !important;
  color: var(--text-dim);
  font-size: var(--fs-md);
  background: var(--surface) !important;
}

.table-total,
tr.table-total td,
tfoot.table-total td {
  background: var(--surface-3) !important;
  font-weight: 700;
  color: var(--text);
  border-top: 2px solid var(--border-strong);
  border-bottom: 0;
  font-variant-numeric: tabular-nums;
}
/* totals stay visible while a long ledger scrolls */
.table tfoot td {
  position: sticky;
  bottom: 0;
  z-index: 4;
  background: var(--surface-3);
  border-top: 2px solid var(--border-strong);
  border-bottom: 0;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* flagged / anomaly rows (Review view) */
.table tr.flagged td {
  background: var(--warn-soft) !important;
  box-shadow: inset 3px 0 0 var(--warn);
}
.table tr.flagged:hover td { filter: brightness(.98); }
.table tr.is-archived td { color: var(--text-dim); }

/* dense variant for the ledger */
.table.dense tbody td,
.table.dense thead th { padding-top: 6px; padding-bottom: 6px; }

.table td .room-badge { vertical-align: middle; }
.table td small { color: var(--text-dim); font-size: var(--fs-xs); display: block; }

/* ---------------------------------------------------------------------------
   7. BADGES & THE ROOM CHIP
   Colour semantics: red = overdue, amber = due soon, blue = upcoming,
   green = ok, teal = credit, grey = archived.
   --------------------------------------------------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  border: 1px solid var(--neutral-border);
  background: var(--neutral-soft);
  color: var(--neutral-soft-fg);
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: .02em;
  line-height: 1.7;
  white-space: nowrap;
  vertical-align: middle;
}
.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
  opacity: .9;
}
.badge.no-dot::before { display: none; }

.badge-overdue {
  background: var(--danger-soft);
  color: var(--danger-soft-fg);
  border-color: var(--danger-border);
}
.badge-due-soon {
  background: var(--warn-soft);
  color: var(--warn-soft-fg);
  border-color: var(--warn-border);
}
.badge-upcoming {
  background: var(--info-soft);
  color: var(--info-soft-fg);
  border-color: var(--info-border);
}
.badge-ok {
  background: var(--success-soft);
  color: var(--success-soft-fg);
  border-color: var(--success-border);
}
.badge-credit {
  background: var(--credit-soft);
  color: var(--credit-soft-fg);
  border-color: var(--credit-border);
}
.badge-archived {
  background: var(--neutral-soft);
  color: var(--neutral-soft-fg);
  border-color: var(--neutral-border);
}
.badge-flag {
  background: var(--warn-soft);
  color: var(--warn-soft-fg);
  border-color: var(--warn-border);
}
.badge + .badge { margin-left: 6px; }

/* ---------------------------------------------------------------------------
   7b. DATA ERRORS — red treatment for rows / cells whose data is wrong
   RED here means "this value is wrong", not "this client owes money".
   The tint is mixed into the surface so body text keeps AA contrast in both
   themes; the red left border and the ⚠ glyph carry the meaning without
   relying on colour alone.
   --------------------------------------------------------------------------- */
/* the double class keeps the red text when the chip sits inside a context
   that restyles links (e.g. .detail-meta a) */
.badge-error,
.badge.badge-error,
a.badge.badge-error,
.detail-meta a.badge-error {
  background: var(--danger-soft);
  color: var(--danger-soft-fg);
  border-color: var(--danger-border);
}
a.badge-error { text-decoration: none; }
a.badge-error:hover {
  text-decoration: none;
  border-color: var(--danger);
  filter: brightness(1.04);
}

/* the small red warning glyph used by every error treatment */
.err-glyph {
  color: var(--money-pos);
  font-weight: 700;
  font-size: 12.5px;
  line-height: 1;
  flex: 0 0 auto;
}

/* a whole row whose underlying record is flagged / invalid */
.table tbody tr.row-error td,
.table tbody tr.row-error:nth-child(even) td,
.table tbody tr.row-error:hover td,
.table tbody tr.row-error.clickable:hover td {
  background: var(--danger-soft) !important;
  background: color-mix(in srgb, var(--danger-soft) 55%, var(--surface)) !important;
}
.table tbody tr.row-error:hover td { filter: brightness(.985); }

/* a single cell whose value is wrong (also the anchor cell of a .row-error) */
.table tbody td.cell-error {
  box-shadow: inset 3px 0 0 var(--danger);
  background: var(--danger-soft) !important;
  background: color-mix(in srgb, var(--danger-soft) 55%, var(--surface)) !important;
}
.table tbody tr.row-error td:first-child { box-shadow: inset 3px 0 0 var(--danger); }

/* inline flavour: a chip-sized error marker inside any cell or block */
.cell-error:not(td) {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 1px 7px;
  border: 1px solid var(--danger-border);
  border-left: 3px solid var(--danger);
  border-radius: var(--r-sm);
  background: var(--danger-soft);
  color: var(--danger-soft-fg);
  font-weight: 650;
}

/* the flag text, repeated under the row on phones (hidden on desktop, where
   it is shown as the row's title tooltip instead) */
.row-error-note { display: none; }

/* non-table blocks (room cards, headers) */
.room-card.is-error {
  border-color: var(--danger-border);
  border-left-color: var(--danger);
  background: var(--danger-soft);
  background: color-mix(in srgb, var(--danger-soft) 45%, var(--surface));
}
.room-card.is-error .room-card-num { color: var(--danger-soft-fg); }

/* room-number chip — the owner's primary identifier, must be scannable ------ */
.room-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3.6ch;
  padding: 3px 9px;
  border-radius: 7px;
  background: var(--room-bg);
  color: var(--room-fg);
  border: 1px solid var(--room-bd);
  font-family: var(--font-mono);
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: .01em;
  line-height: 1.35;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  vertical-align: middle;
  text-decoration: none;
}
a.room-badge:hover {
  text-decoration: none;
  border-color: var(--accent);
  filter: brightness(1.02);
}
.room-badge + .room-badge { margin-left: 5px; }
.room-badge.is-none,
.room-badge.empty {
  background: transparent;
  color: var(--text-dim);
  border-style: dashed;
  border-color: var(--border-strong);
  font-weight: 500;
}
.room-badge.lg {
  font-size: 20px;
  padding: 6px 14px;
  border-radius: 9px;
  min-width: 4ch;
}
.room-badge.sm { font-size: 12px; padding: 1px 7px; }

/* small neutral tag (methods, periods, misc.) */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 1px 8px;
  border-radius: var(--r-sm);
  background: var(--surface-3);
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-weight: 600;
  white-space: nowrap;
}
.tag-charge { background: var(--info-soft); color: var(--info-soft-fg); border-color: var(--info-border); }
.tag-payment { background: var(--success-soft); color: var(--success-soft-fg); border-color: var(--success-border); }

.kbd {
  display: inline-block;
  min-width: 20px;
  padding: 1px 6px;
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: var(--r-sm);
  background: var(--surface-3);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-align: center;
}

/* ---------------------------------------------------------------------------
   8. MONEY
   .money-pos = owes (red)   .money-neg = credit (green)   .money-zero = grey
   --------------------------------------------------------------------------- */
.money {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  text-align: right;
  white-space: nowrap;
  letter-spacing: -.01em;
}
td.money, th.money { text-align: right; }
.money-pos { color: var(--money-pos); font-weight: 650; }
.money-neg { color: var(--money-neg); font-weight: 650; }
.money-zero { color: var(--money-zero); font-weight: 500; }
.money.lg { font-size: var(--fs-xl); font-weight: 700; letter-spacing: -.02em; }
.money.xl { font-size: var(--fs-3xl); font-weight: 700; letter-spacing: -.03em; }

/* ---------------------------------------------------------------------------
   9. FORMS
   --------------------------------------------------------------------------- */
.form {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  min-width: 0;
}

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px var(--gap);
  align-items: start;
  min-width: 0;
}
.form-row.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-row.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.form-row.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}
.field label,
.field > label {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-muted);
  letter-spacing: .01em;
}
.field label .req { color: var(--money-pos); margin-left: 2px; }
.field-hint {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  line-height: 1.4;
}
.field-error {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--money-pos);
  min-height: 0;
}
.field-error:empty { display: none; }

.input,
.select,
.textarea {
  display: block;
  width: 100%;
  min-height: 38px;
  padding: 8px 11px;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  font-size: var(--fs-base);
  font-family: inherit;
  line-height: 1.35;
  transition: border-color var(--tr), box-shadow var(--tr), background var(--tr);
  appearance: none;
  -webkit-appearance: none;
}
.input::placeholder,
.textarea::placeholder { color: var(--text-dim); opacity: 1; }

.input:hover:not(:disabled),
.select:hover:not(:disabled),
.textarea:hover:not(:disabled) { border-color: var(--text-dim); }

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 28%, transparent);
}
.input:focus-visible,
.select:focus-visible,
.textarea:focus-visible { outline: none; }

.input:disabled,
.select:disabled,
.textarea:disabled,
.input[readonly] {
  background: var(--surface-3);
  color: var(--text-dim);
  cursor: not-allowed;
}

.input[type="number"],
.input.num,
.input[inputmode="decimal"] {
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.input[type="date"],
.input[type="month"] { font-variant-numeric: tabular-nums; min-height: 38px; }
.input[type="date"]::-webkit-calendar-picker-indicator,
.input[type="month"]::-webkit-calendar-picker-indicator { opacity: .6; cursor: pointer; }
:root[data-theme="dark"] .input[type="date"]::-webkit-calendar-picker-indicator,
:root[data-theme="dark"] .input[type="month"]::-webkit-calendar-picker-indicator { filter: invert(1); }

.textarea {
  min-height: 84px;
  resize: vertical;
  line-height: 1.5;
}

.select {
  padding-right: 32px;
  background-image: var(--icon-caret);
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 16px 16px;
  cursor: pointer;
}
.select option { background: var(--surface); color: var(--text); }

/* invalid states */
.input[aria-invalid="true"],
.select[aria-invalid="true"],
.textarea[aria-invalid="true"],
.input.is-invalid,
.field.has-error .input,
.field.has-error .select,
.field.has-error .textarea {
  border-color: var(--money-pos);
  background: color-mix(in srgb, var(--danger-soft) 55%, var(--surface));
}

/* checkbox / radio --------------------------------------------------------- */
input[type="checkbox"],
input[type="radio"],
input.checkbox {
  width: 17px;
  height: 17px;
  accent-color: var(--accent);
  cursor: pointer;
  flex: 0 0 auto;
  margin: 0;
}
.checkbox:not(input) {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 34px;
  padding: 2px 0;
  font-size: var(--fs-base);
  color: var(--text);
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
.checkbox:not(input):hover { color: var(--accent); }
.checkbox input { margin: 0; }
.checkbox span { min-width: 0; }

fieldset {
  border: 1px solid var(--border);
  border-radius: var(--r);
  padding: 14px 16px;
  margin: 0;
}
legend {
  padding: 0 6px;
  font-size: var(--fs-sm);
  font-weight: 650;
  color: var(--text-muted);
}

/* file input / drop zone */
.file-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 26px 18px;
  border: 2px dashed var(--border-strong);
  border-radius: var(--r);
  background: var(--surface-2);
  color: var(--text-dim);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--tr), background var(--tr), color var(--tr);
}
.file-drop:hover,
.file-drop.is-over {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-soft-fg);
}
input[type="file"] { max-width: 100%; font-size: var(--fs-sm); }
input[type="file"]::file-selector-button {
  margin-right: 10px;
  padding: 7px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface-3);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--surface-hover); }

/* ---------------------------------------------------------------------------
   10. BUTTONS
   --------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 38px;
  padding: 7px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-base);
  font-weight: 600;
  font-family: inherit;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: background var(--tr), border-color var(--tr), color var(--tr),
              box-shadow var(--tr), transform var(--tr);
}
.btn:hover {
  background: var(--surface-hover);
  border-color: var(--text-dim);
  text-decoration: none;
}
.btn:active { transform: translateY(1px); }
.btn:disabled,
.btn[aria-disabled="true"],
.btn.is-disabled {
  opacity: .5;
  cursor: not-allowed;
  transform: none;
  pointer-events: none;
}

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
  box-shadow: var(--shadow-1);
}
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-fg); }
.btn-primary:active { background: var(--accent-press); border-color: var(--accent-press); }

.btn-danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--danger-fg);
}
.btn-danger:hover { background: var(--danger-hover); border-color: var(--danger-hover); color: var(--danger-fg); }

.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-muted);
}
.btn-ghost:hover {
  background: var(--surface-3);
  border-color: transparent;
  color: var(--text);
}
.btn-ghost.is-danger { color: var(--money-pos); }
.btn-ghost.is-danger:hover { background: var(--danger-soft); color: var(--danger-soft-fg); }

.btn-sm {
  min-height: 30px;
  padding: 3px 10px;
  font-size: var(--fs-sm);
  gap: 5px;
}

.btn-icon {
  min-height: 34px;
  width: 34px;
  padding: 0;
  flex: 0 0 auto;
  border-radius: var(--r-sm);
  font-size: var(--fs-md);
  line-height: 1;
}
.btn-icon.btn-sm { min-height: 28px; width: 28px; font-size: var(--fs-sm); }

.btn-group {
  display: inline-flex;
  align-items: stretch;
}
.btn-group .btn { border-radius: 0; margin-left: -1px; }
.btn-group .btn:first-child { border-radius: var(--r-sm) 0 0 var(--r-sm); margin-left: 0; }
.btn-group .btn:last-child { border-radius: 0 var(--r-sm) var(--r-sm) 0; }
.btn-group .btn:hover { z-index: 1; }

.btn.is-loading { color: transparent !important; position: relative; pointer-events: none; }
.btn.is-loading::after {
  content: "";
  position: absolute;
  width: 15px;
  height: 15px;
  border: 2px solid currentColor;
  border-radius: 50%;
  border-top-color: transparent;
  color: var(--accent-fg);
  animation: spin .7s linear infinite;
}

/* ---------------------------------------------------------------------------
   11. TOOLBAR / SEARCH / CHIPS
   --------------------------------------------------------------------------- */
.toolbar {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  flex-wrap: wrap;
  margin-bottom: var(--gap);
  min-width: 0;
}
.card-head .toolbar,
.card-body > .toolbar:first-child { margin-bottom: 0; }
.toolbar > * { flex: 0 0 auto; }
.toolbar-end { margin-left: auto; display: flex; align-items: center; gap: var(--gap-sm); flex-wrap: wrap; }
.toolbar .field { flex: 0 0 auto; }
.toolbar .field label { font-size: var(--fs-xs); }
.toolbar .input,
.toolbar .select { min-width: 130px; width: auto; }
.toolbar .divider {
  width: 1px;
  height: 24px;
  background: var(--border);
  margin: 0 4px;
}

/* search box — works whether .search is the input itself or a wrapper */
.search,
input.search,
.search > input,
.search > .input {
  min-height: 38px;
  padding: 8px 12px 8px 34px;
  background-color: var(--surface);
  background-image: var(--icon-search);
  background-repeat: no-repeat;
  background-position: left 10px center;
  background-size: 16px 16px;
  color: var(--text);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  font-size: var(--fs-base);
  font-family: inherit;
  appearance: none;
  -webkit-appearance: none;
  transition: border-color var(--tr), box-shadow var(--tr);
}
input.search,
.search > input,
.search > .input { width: 100%; }
.search {
  flex: 1 1 300px;
  min-width: 200px;
  max-width: 460px;
}
.search:not(input) {
  padding: 0;
  background-image: none;
  border: 0;
  display: block;
}
input.search:focus,
.search > input:focus,
.search > .input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 28%, transparent);
}
input.search::-webkit-search-cancel-button { cursor: pointer; }
.search::placeholder { color: var(--text-dim); }

/* quick-filter chips */
.chips {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  min-width: 0;
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 4px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: 600;
  font-family: inherit;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  transition: background var(--tr), color var(--tr), border-color var(--tr);
}
.chip:hover {
  background: var(--surface-hover);
  color: var(--text);
  border-color: var(--text-dim);
  text-decoration: none;
}
.chip.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-fg);
}
.chip.active:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-fg); }
.chip .chip-count,
.chip small {
  font-variant-numeric: tabular-nums;
  opacity: .75;
  font-weight: 700;
}
.chip.is-danger:not(.active) { color: var(--money-pos); border-color: var(--danger-border); }
.chip.is-warn:not(.active) { color: var(--warn-soft-fg); border-color: var(--warn-border); }

/* tabs (client detail sections, reports) */
.tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--gap);
  overflow-x: auto;
}
.tab {
  padding: 9px 14px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-base);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.tab:hover { color: var(--text); background: var(--surface-3); }
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* pagination */
.pager {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  flex-wrap: wrap;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.pager-info {
  color: var(--text-dim);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  margin-right: auto;
}

/* ---------------------------------------------------------------------------
   12. MODAL
   --------------------------------------------------------------------------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 6vh 20px 20px;
  background: var(--backdrop);
  overflow-y: auto;
  overscroll-behavior: contain;
  animation: fade-in 120ms ease-out;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}

.modal {
  width: 100%;
  max-width: 620px;
  margin: auto 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3);
  display: flex;
  flex-direction: column;
  max-height: 88vh;
  animation: modal-in 160ms cubic-bezier(.2, .8, .3, 1);
  overflow: hidden;
}
.modal-sm { max-width: 440px; }
.modal-lg { max-width: 1000px; }
.modal-xl { max-width: 1400px; }

.modal-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 15px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  flex: 0 0 auto;
}
.modal-head h2,
.modal-head h3,
.modal-title {
  font-size: var(--fs-lg);
  font-weight: 650;
  letter-spacing: -.01em;
  margin: 0;
  margin-right: auto;
  min-width: 0;
}
.modal-head .btn-icon { margin-left: auto; }

.modal-body {
  padding: 20px;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.modal-body > :first-child { margin-top: 0; }

.modal-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--gap-sm);
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
  flex: 0 0 auto;
  flex-wrap: wrap;
}
.modal-foot .left,
.modal-foot .btn-danger:first-child { margin-right: auto; }

body.modal-open { overflow: hidden; }

/* ---------------------------------------------------------------------------
   13. FEEDBACK — toasts, spinner, empty state, notices, skeleton
   --------------------------------------------------------------------------- */
#toast-root {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  pointer-events: none;
  max-width: min(420px, calc(100vw - 40px));
}

.toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-height: 42px;
  padding: 11px 15px;
  border-radius: var(--r);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-2);
  font-size: var(--fs-base);
  font-weight: 500;
  line-height: 1.4;
  animation: toast-in 180ms cubic-bezier(.2, .8, .3, 1);
  word-break: break-word;
}
.toast::before {
  content: "";
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  margin-top: 6px;
  border-radius: 50%;
  background: var(--text-dim);
}
.toast-ok {
  border-color: var(--success-border);
  background: var(--success-soft);
  color: var(--success-soft-fg);
}
.toast-ok::before { background: var(--success); }
.toast-err {
  border-color: var(--danger-border);
  background: var(--danger-soft);
  color: var(--danger-soft-fg);
}
.toast-err::before { background: var(--danger); }
.toast.is-leaving { animation: toast-out 160ms ease-in forwards; }
.toast .btn-icon { margin-left: auto; }

.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
  vertical-align: -3px;
}
.spinner.lg { width: 30px; height: 30px; border-width: 3px; }
.spinner.center { display: block; margin: 40px auto; }

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 56px 24px;
  text-align: center;
  color: var(--text-dim);
  font-size: var(--fs-md);
}
.empty-state strong {
  display: block;
  color: var(--text);
  font-size: var(--fs-lg);
  font-weight: 650;
}
.empty-state .btn { margin-top: 8px; }

.notice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-base);
  line-height: 1.5;
}
.notice-info { background: var(--info-soft); color: var(--info-soft-fg); border-color: var(--info-border); border-left-color: var(--accent); }
.notice-warn { background: var(--warn-soft); color: var(--warn-soft-fg); border-color: var(--warn-border); border-left-color: var(--warn); }
.notice-danger { background: var(--danger-soft); color: var(--danger-soft-fg); border-color: var(--danger-border); border-left-color: var(--danger); }
.notice-ok { background: var(--success-soft); color: var(--success-soft-fg); border-color: var(--success-border); border-left-color: var(--success); }

.skeleton {
  display: block;
  min-height: 14px;
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--surface-3) 25%, var(--surface-hover) 37%, var(--surface-3) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s ease-in-out infinite;
}

.progress {
  width: 100%;
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--surface-3);
  overflow: hidden;
}
.progress-bar {
  height: 100%;
  background: var(--accent);
  border-radius: var(--r-pill);
  transition: width 300ms ease;
}
.progress-bar.is-ok { background: var(--success); }
.progress-bar.is-warn { background: var(--warn); }
.progress-bar.is-danger { background: var(--danger); }

/* keyframes */
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-in {
  from { opacity: 0; transform: translateY(-10px) scale(.985); }
  to { opacity: 1; transform: none; }
}
@keyframes toast-in {
  from { opacity: 0; transform: translateY(10px) scale(.98); }
  to { opacity: 1; transform: none; }
}
@keyframes toast-out {
  from { opacity: 1; transform: none; }
  to { opacity: 0; transform: translateX(20px); }
}
@keyframes shimmer {
  from { background-position: 100% 0; }
  to { background-position: 0 0; }
}

/* ---------------------------------------------------------------------------
   14. CHART (inline SVG — no library)
   .chart-bar-billed / .chart-bar-collected work both as SVG <rect> fills and
   as HTML legend swatches.
   --------------------------------------------------------------------------- */
.chart {
  position: relative;
  width: 100%;
  min-width: 0;
  padding: 4px 0 0;
}
.chart svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
.chart text {
  fill: var(--text-dim);
  font-family: var(--font-sans);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.chart .chart-value {
  fill: var(--text-muted);
  font-size: 10.5px;
  font-weight: 600;
}

.chart-bar-billed {
  fill: var(--chart-billed);
  background-color: var(--chart-billed);
}
.chart-bar-collected {
  fill: var(--chart-collected);
  background-color: var(--chart-collected);
}
.chart-bar-billed, .chart-bar-collected { transition: opacity var(--tr); }
.chart svg .chart-bar-billed:hover,
.chart svg .chart-bar-collected:hover { opacity: .82; }

.chart-axis {
  stroke: var(--chart-grid);
  stroke-width: 1;
  shape-rendering: crispEdges;
}
.chart-axis line { stroke: var(--chart-grid); stroke-width: 1; }
.chart-axis text,
text.chart-axis { fill: var(--chart-axis); stroke: none; font-size: 10.5px; }
.chart-axis.baseline { stroke: var(--border-strong); }

.chart-legend {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 10px;
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.chart-legend > span,
.chart-legend > li,
.chart-legend > div {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  list-style: none;
}
.chart-legend span[class*="chart-bar-"],
.chart-legend i[class*="chart-bar-"],
.chart-legend em[class*="chart-bar-"],
.chart-legend .swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  flex: 0 0 auto;
}
.chart-legend .swatch.billed { background-color: var(--chart-billed); }
.chart-legend .swatch.collected { background-color: var(--chart-collected); }

/* ---------------------------------------------------------------------------
   15. LOGIN
   --------------------------------------------------------------------------- */
.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(1200px 600px at 50% -10%, var(--accent-soft), transparent 70%),
    var(--bg);
}
.login-card {
  width: 100%;
  max-width: 400px;
  padding: 28px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}
.login-title {
  font-size: var(--fs-xl);
  font-weight: 700;
  letter-spacing: -.02em;
  text-align: center;
}
.login-sub {
  margin-top: -12px;
  text-align: center;
  color: var(--text-dim);
  font-size: var(--fs-sm);
}
.login-card .btn { width: 100%; min-height: 42px; }

/* ---------------------------------------------------------------------------
   16. CLIENT DETAIL HEADER
   --------------------------------------------------------------------------- */
.detail-head {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 18px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  margin-bottom: var(--gap);
}
.detail-name {
  font-size: var(--fs-xl);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.2;
  min-width: 0;
}
.detail-meta {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  color: var(--text-dim);
  font-size: var(--fs-sm);
}
.detail-meta a { color: var(--text-muted); }
.detail-balance {
  margin-left: auto;
  text-align: right;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-variant-numeric: tabular-nums;
}
.detail-balance .kpi-label { text-align: right; }
.detail-balance .money { font-size: var(--fs-2xl); font-weight: 700; letter-spacing: -.03em; }
.detail-head .page-actions { margin-left: 0; }

/* ---------------------------------------------------------------------------
   17. ROOMS GRID
   --------------------------------------------------------------------------- */
.room-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px;
}
.room-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--r);
  box-shadow: var(--shadow-1);
  cursor: pointer;
  transition: box-shadow var(--tr), border-color var(--tr), transform var(--tr);
  min-width: 0;
}
.room-card:hover {
  box-shadow: var(--shadow-2);
  transform: translateY(-1px);
}
.room-card:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.room-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.room-card-num {
  font-family: var(--font-mono);
  font-size: var(--fs-xl);
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.room-card-head .badge { margin-left: auto; }
.room-card-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-height: 40px;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  min-width: 0;
}
.room-card-body strong {
  font-size: var(--fs-base);
  font-weight: 650;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.room-card-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.room-card-foot .btn { margin-left: auto; }
.room-card.is-free { border-left-color: var(--border-strong); background: var(--surface-2); }
.room-card.is-free .room-card-num { color: var(--text-dim); }
.room-card.is-occupied { border-left-color: var(--success); }
.room-card.is-overdue { border-left-color: var(--money-pos); }
.room-card.is-due-soon { border-left-color: var(--warn); }

/* ---------------------------------------------------------------------------
   18. SMALL COMPONENTS & UTILITIES
   --------------------------------------------------------------------------- */
.dl {
  display: grid;
  grid-template-columns: minmax(120px, max-content) minmax(0, 1fr);
  gap: 6px 16px;
  align-items: baseline;
  margin: 0;
  font-size: var(--fs-base);
}
.dl dt {
  color: var(--text-dim);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.dl dd {
  margin: 0;
  color: var(--text);
  min-width: 0;
  overflow-wrap: anywhere;
}
.dl-row { display: contents; }

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
  font-size: var(--fs-md);
  line-height: 1;
  transition: background var(--tr), color var(--tr);
}
.theme-toggle:hover { background: var(--surface-hover); color: var(--text); }

.divider {
  height: 1px;
  width: 100%;
  background: var(--border);
  border: 0;
  margin: var(--gap) 0;
}

/* layout utilities */
.row { display: flex; align-items: center; gap: var(--gap-sm); flex-wrap: wrap; min-width: 0; }
.row.tight { gap: 6px; }
.row.nowrap { flex-wrap: nowrap; }
.col { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.stack { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }
.spacer { flex: 1 1 auto; }
.right { margin-left: auto; text-align: right; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
  display: block;
}
.w-full { width: 100%; }

/* text utilities */
.muted { color: var(--text-muted); }
.dim { color: var(--text-dim); }
.small { font-size: var(--fs-sm); }
.strong { font-weight: 700; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.upper { text-transform: uppercase; letter-spacing: .06em; font-size: var(--fs-xs); font-weight: 700; }

/* spacing utilities */
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 6px; }
.mt-2 { margin-top: var(--gap-sm); }
.mt-3 { margin-top: var(--gap); }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: 6px; }
.mb-2 { margin-bottom: var(--gap-sm); }
.mb-3 { margin-bottom: var(--gap); }

.hidden, [hidden] { display: none !important; }

.sr-only {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.is-loading { cursor: progress; }

/* ---------------------------------------------------------------------------
   19. RESPONSIVE
   >= 1900px  roomier type, wider sidebar
   <= 1600px  .grid-4 -> 2 columns
   <= 1280px  .grid-3 -> 2 columns
   <= 1150px  tables may scroll horizontally
   <=  900px  bottom nav + tables become stacked cards (td[data-label])
   <=  560px  single-column everything, 44px tap targets
   --------------------------------------------------------------------------- */
@media (min-width: 1900px) {
  :root {
    --fs-base: 14.5px;
    --fs-md: 15.5px;
    --fs-lg: 18px;
    --sidebar-w: 250px;
    --content-pad: 34px;
    --gap: 20px;
  }
  .table thead th { font-size: 12px; }
}

@media (max-width: 1600px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .span-4 { grid-column: span 2; }
}

@media (max-width: 1280px) {
  :root { --content-pad: 20px; --gap: 16px; }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .span-3 { grid-column: span 2; }
}

@media (max-width: 1150px) and (min-width: 901px) {
  /* narrow desktop: let very wide tables scroll sideways.
     (this makes .table-wrap a scroll container, so headers stop sticking —
     acceptable only in this band; the app is large-monitor first.) */
  .table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .table { min-width: 780px; }
  .table thead th { position: static; }
}

@media (max-width: 1024px) {
  .grid-2 { grid-template-columns: minmax(0, 1fr); }
  .span-2 { grid-column: span 1; }
  .detail-balance { margin-left: 0; text-align: left; width: 100%; }
  .detail-balance .kpi-label { text-align: left; }
}

/* ---- MOBILE / TABLET: bottom nav + stacked-card tables ------------------- */
@media (max-width: 900px) {
  :root {
    --content-pad: 14px;
    --gap: 14px;
    --topbar-h: 54px;
  }

  .shell { grid-template-columns: minmax(0, 1fr); }

  /* sidebar -> fixed bottom nav */
  .sidebar {
    position: fixed;
    inset: auto 0 0 0;
    top: auto;
    height: auto;
    width: 100%;
    flex-direction: row;
    align-items: stretch;
    gap: 0;
    padding: 0 0 env(safe-area-inset-bottom, 0px);
    border-right: 0;
    border-top: 1px solid var(--sidebar-border);
    box-shadow: 0 -4px 16px rgba(0, 0, 0, .22);
    overflow: visible;
    z-index: 60;
  }
  .sidebar-brand,
  .nav-section,
  .sidebar-foot { display: none; }

  .nav {
    flex-direction: row;
    align-items: stretch;
    width: 100%;
    gap: 0;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav li { flex: 1 0 auto; display: flex; }

  .nav-item {
    flex: 1 0 auto;
    min-width: 72px;
    min-height: 56px;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 3px;
    padding: 6px 10px;
    border-radius: 0;
    font-size: var(--fs-xs);
    font-weight: 600;
    text-align: center;
    white-space: nowrap;
  }
  .nav-item.active {
    box-shadow: inset 0 3px 0 var(--sidebar-accent);
    background: var(--sidebar-active-bg);
  }
  .nav-item .nav-count,
  .nav-item .badge { margin-left: 0; }

  .main { min-height: 100vh; }
  .content { padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }

  .topbar { padding: 8px var(--content-pad); gap: 10px; }
  .topbar-title { font-size: var(--fs-md); }
  .topbar-meta { font-size: var(--fs-xs); gap: 8px; }

  .page-head { align-items: flex-start; flex-direction: column; gap: 10px; }
  .page-title { font-size: var(--fs-xl); }
  .page-actions { margin-left: 0; width: 100%; }
  .page-actions .btn { flex: 1 1 auto; }

  .grid, .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .span-2, .span-3, .span-4, .span-full { grid-column: span 1; }

  .kpi { padding: 13px 14px; }
  .kpi-value { font-size: var(--fs-xl); }

  .card-body { padding: 13px; }
  .card-body > .table-wrap { margin: 0; }

  /* --- tables reflow into stacked cards ---------------------------------- */
  .table-wrap {
    overflow: visible;
    border: 0;
    background: transparent;
    box-shadow: none;
    border-radius: 0;
  }
  .table,
  .table thead,
  .table tbody,
  .table tfoot,
  .table tr,
  .table th,
  .table td {
    display: block;
    width: auto;
  }
  .table { min-width: 0; }
  .table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .table tbody tr {
    position: relative;
    margin-bottom: 10px;
    padding: 4px 13px;
    background: var(--surface) !important;
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: var(--shadow-1);
  }
  .table tbody tr:last-child { margin-bottom: 0; }
  .table tbody tr:hover td,
  .table tbody tr:nth-child(even) td,
  .table tr.clickable:hover td { background: transparent; }

  .table tbody td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    width: auto;
    min-height: 44px;
    padding: 8px 0 !important;
    border: 0;
    border-bottom: 1px solid var(--border);
    text-align: right;
    background: transparent !important;
  }
  .table tbody td:last-child { border-bottom: 0; }
  .table tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    max-width: 45%;
    padding-right: 10px;
    color: var(--text-dim);
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    text-align: left;
    white-space: normal;
  }
  .table tbody td:not([data-label])::before { content: none; }
  .table tbody td.num,
  .table tbody td .money { text-align: right; }
  .table tbody td small { display: inline; }
  .table td.col-actions,
  .table td.col-room { width: auto; }
  .table td.col-actions { justify-content: flex-end; gap: 8px; }
  .table td.col-actions .btn { min-height: var(--tap); min-width: var(--tap); }

  /* first cell = room chip, give it presence at the top of each card */
  .table tbody td:first-child { padding-top: 10px !important; }
  .table tbody td .room-badge { font-size: 15px; padding: 4px 11px; }

  .table tr.flagged td { background: transparent !important; }
  .table tbody tr.flagged {
    border-color: var(--warn-border);
    box-shadow: inset 3px 0 0 var(--warn), var(--shadow-1);
  }

  /* data errors: the whole card turns red and the flag text is spelled out */
  .table tbody tr.row-error {
    border-color: var(--danger-border);
    box-shadow: inset 3px 0 0 var(--danger), var(--shadow-1);
    background: var(--danger-soft) !important;
    background: color-mix(in srgb, var(--danger-soft) 45%, var(--surface)) !important;
  }
  .table tbody tr.row-error td,
  .table tbody tr.row-error:nth-child(even) td,
  .table tbody tr.row-error:hover td,
  .table tbody td.cell-error {
    background: transparent !important;
    box-shadow: none;
  }
  .table tbody td.cell-error,
  .table tbody td.has-row-note { flex-wrap: wrap; }
  .row-error-note {
    display: block;
    flex: 1 0 100%;
    margin-top: 4px;
    text-align: left;
    color: var(--danger-soft-fg);
    font-size: var(--fs-xs);
    font-weight: 650;
    line-height: 1.35;
    overflow-wrap: anywhere;
  }

  .table-empty,
  .table td.table-empty,
  tr.table-empty td {
    display: block;
    text-align: center !important;
    padding: 28px 12px !important;
    border: 0;
  }
  tr.table-empty { background: var(--surface) !important; }
  .table td.table-empty::before,
  tr.table-empty td::before { content: none; }

  .table tfoot td { position: static; }
  .table tfoot tr,
  .table tr.table-total {
    background: var(--surface-3) !important;
    border-color: var(--border-strong);
  }
  .table tr.table-total td { background: transparent !important; }

  /* controls get thumb-sized */
  .btn { min-height: var(--tap); padding: 10px 16px; }
  .btn-sm { min-height: 36px; padding: 6px 12px; }
  .btn-icon { min-height: var(--tap); width: var(--tap); }
  .chip { min-height: var(--tap); padding: 8px 14px; font-size: var(--fs-base); }
  .input, .select, .textarea,
  input.search, .search > input { min-height: var(--tap); font-size: 16px; }
  .checkbox:not(input) { min-height: var(--tap); }
  input[type="checkbox"], input[type="radio"], input.checkbox { width: 20px; height: 20px; }
  .tab { min-height: var(--tap); }

  .toolbar { gap: 8px; }
  .search { flex: 1 1 100%; max-width: none; }
  .toolbar-end { margin-left: 0; width: 100%; }
  .chips { width: 100%; overflow-x: auto; flex-wrap: nowrap; padding-bottom: 4px; }

  /* modal becomes a bottom sheet */
  .modal-backdrop { padding: 0; align-items: flex-end; }
  .modal {
    max-width: none;
    max-height: 94vh;
    margin: 0;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    border-bottom: 0;
    animation: sheet-in 200ms cubic-bezier(.2, .8, .3, 1);
  }
  .modal-foot { padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px)); }
  .modal-foot .btn { flex: 1 1 auto; }

  #toast-root {
    right: 10px;
    left: 10px;
    bottom: calc(70px + env(safe-area-inset-bottom, 0px));
    align-items: stretch;
    max-width: none;
  }

  .detail-head { padding: 14px; gap: 10px; }
  .room-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .dl { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .dl dd { margin-bottom: 8px; }
}

@keyframes sheet-in {
  from { opacity: 0; transform: translateY(24px); }
  to { opacity: 1; transform: none; }
}

@media (max-width: 560px) {
  :root { --content-pad: 12px; }
  .content { padding-top: var(--gap); }
  .form-row,
  .form-row.cols-2,
  .form-row.cols-3,
  .form-row.cols-4 { grid-template-columns: minmax(0, 1fr); }
  .kpi-value { font-size: var(--fs-lg); }
  .detail-name { font-size: var(--fs-lg); }
  .detail-balance .money { font-size: var(--fs-xl); }
  .room-grid { grid-template-columns: repeat(auto-fill, minmax(135px, 1fr)); }
  .nav-item { min-width: 64px; font-size: 10.5px; padding: 6px 6px; }
  .table tbody td::before { max-width: 50%; }
  .topbar-meta span.hide-xs { display: none; }
}

@media (max-width: 380px) {
  :root { --content-pad: 10px; --fs-base: 13.5px; }
  .nav-item { min-width: 58px; }
  .room-grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
  .table tbody td { gap: 8px; }
}

/* ---------------------------------------------------------------------------
   20. USER PREFERENCES — reduced motion, high contrast
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .btn:active { transform: none; }
  .room-card:hover { transform: none; }
}

@media (prefers-contrast: more) {
  :root {
    --border: var(--border-strong);
    --text-dim: var(--text-muted);
  }
  .btn, .input, .select, .textarea, .chip { border-width: 2px; }
  .table tbody td { border-bottom-color: var(--border-strong); }
}

@media (forced-colors: active) {
  .btn, .card, .kpi, .table-wrap, .modal, .chip, .badge, .room-badge {
    border: 1px solid CanvasText;
  }
  .nav-item.active { forced-color-adjust: none; }
  .money-pos, .money-neg { color: CanvasText; }
}

/* ---------------------------------------------------------------------------
   21. PRINT — the ledger must print cleanly on A4
   --------------------------------------------------------------------------- */
@media print {
  @page { size: A4 landscape; margin: 12mm; }

  :root {
    --bg: #fff;
    --surface: #fff;
    --surface-2: #fff;
    --surface-3: #f0f0f0;
    --surface-hover: #fff;
    --border: #b8b8b8;
    --border-strong: #888;
    --text: #000;
    --text-muted: #222;
    --text-dim: #444;
    --shadow-1: none;
    --shadow-2: none;
    --shadow-3: none;
    color-scheme: light;
  }

  html, body {
    background: #fff !important;
    color: #000 !important;
    font-size: 10.5pt;
  }

  .sidebar,
  .nav,
  #toast-root,
  #modal-root,
  .toolbar,
  .chips,
  .tabs,
  .pager,
  .page-actions,
  .card-head .btn,
  .col-actions,
  th.col-actions,
  td.col-actions,
  .btn,
  .theme-toggle,
  .file-drop,
  .empty-state .btn {
    display: none !important;
  }

  .shell { display: block; }
  .main { min-height: 0; }
  .topbar {
    position: static;
    border-bottom: 2px solid #000;
    padding: 0 0 6pt;
    margin-bottom: 10pt;
    background: #fff;
    min-height: 0;
  }
  .topbar-title { font-size: 15pt; font-weight: 700; }
  .topbar-meta { margin-left: auto; color: #333; }
  .content { max-width: none; margin: 0; padding: 0; }

  .card, .kpi, .table-wrap, .detail-head, .room-card {
    border: 1px solid #999 !important;
    box-shadow: none !important;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .grid, .grid-2, .grid-3, .grid-4 { gap: 8pt; }
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  .table { width: 100%; font-size: 9.5pt; }
  .table thead { display: table-header-group; }
  .table tfoot { display: table-footer-group; }
  .table thead th {
    position: static;
    background: #ececec !important;
    color: #000 !important;
    border-bottom: 1px solid #666;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .table tbody td {
    background: #fff !important;
    border-bottom: 1px solid #ccc;
    padding: 4pt 6pt;
  }
  .table tbody tr { break-inside: avoid; page-break-inside: avoid; }
  .table tbody td::before { content: none !important; }

  .money-pos, .money-neg, .money-zero { color: #000 !important; }
  .money-pos { font-weight: 700; }
  .money-pos::after { content: " (owed)"; font-size: 8pt; font-weight: 400; }

  .badge, .room-badge, .tag {
    border: 1px solid #666 !important;
    background: #fff !important;
    color: #000 !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .badge::before { display: none; }
  .room-badge { font-weight: 700; }

  .chart svg { max-height: 60mm; }
  .chart-bar-billed { fill: #8c8c8c; }
  .chart-bar-collected { fill: #3f3f3f; }

  a { color: #000 !important; text-decoration: none; }
  .card + .card, .page-head { break-after: avoid; }
}


/* =====================================================================
   16. DENSITY & OVERFLOW REWORK
   ---------------------------------------------------------------------
   Measured on the live app with the real 61-client dataset:
     - Clients rows were 149px tall at 1440px, so only 4 of 61 fitted on
       screen. Cause: `.toolbar` inside the Actions cell is a wrapping
       flexbox; three 30px buttons (145px of content) in an 89px column
       stacked vertically. Ctrl+minus "fixed" it only by widening the
       column in CSS pixels until the buttons un-wrapped.
     - `.table-wrap` had `overflow-x: visible` and `.card` had
       `overflow: hidden`, so the table could not scroll and was instead
       CLIPPED — 130 elements were cut off and unreachable at 1440px.
       `overflow: hidden` also made `.card` a scroll container, which is
       why the sticky `thead` never stuck.
   Targets: 36px rows, ~19 visible at 1440x900, page never scrolls
   sideways, table scrolls inside its own container.
   ===================================================================== */

:root {
  --row-h: 36px;
  --row-h-head: 32px;
  --cell-px: 12px;
  --cell-fs: 13px;
}
:root[data-density="compact"] {
  --row-h: 28px;
  --row-h-head: 28px;
  --cell-px: 10px;
  --cell-fs: 12px;
}

/* --- never let the page scroll sideways; `clip` (not `hidden`) so that
       position:sticky keeps working on descendants ------------------- */
html { overflow-x: clip; scrollbar-gutter: stable; }
body { overflow-x: clip; }

/* --- every link in the chain must be allowed to shrink -------------- */
.main, .content, .card, .card-body, .table-wrap, .kpi { min-inline-size: 0; }

/* --- the card clips, it must not become a scroll container ---------- */
.card { overflow: clip; }

@media (min-width: 901px) {
  /* --- THE scroller: the table scrolls, the page does not ----------- */
  .table-wrap {
    overflow: auto;                          /* both axes: required so the
                                                sticky thead has a real
                                                scrollport to stick to */
    max-block-size: calc(100dvh - 220px);
    overscroll-behavior: contain;
    scrollbar-gutter: stable;
  }
  .card-body > .table-wrap { max-block-size: calc(100dvh - 250px); }

  /* the table sizes to its content; the wrapper scrolls if that is wider */
  table.table { width: 100%; font-size: var(--cell-fs); }

  /* --- rows: height on the cell, no vertical padding --------------- */
  .table tbody td {
    height: var(--row-h);
    padding: 0 var(--cell-px);
    line-height: 18px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .table td:first-child, .table th:first-child { padding-left: 16px; }
  .table td:last-child,  .table th:last-child  { padding-right: 16px; }

  /* the Notes column is the only one allowed to wrap */
  .table td.wrap {
    white-space: normal;
    overflow-wrap: anywhere;
    max-width: 320px;
    text-overflow: clip;
  }

  /* --- header: sticky to the wrapper, calmer weight ---------------- */
  .table thead th {
    top: 0;                                  /* was var(--topbar-h): the
                                                page used to be the scroller */
    height: var(--row-h-head);
    padding: 0 var(--cell-px);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    line-height: 16px;
    border-bottom: 0;
    box-shadow: inset 0 -1px 0 var(--border-strong);
  }

  /* --- the actual cause of the 149px rows -------------------------- */
  .table td .toolbar {
    flex-wrap: nowrap;
    gap: 4px;
    margin-bottom: 0;
    justify-content: flex-end;
  }
  .table td .btn,
  .table td .btn-sm {
    height: 24px;
    min-height: 24px;
    padding: 0 8px;
    font-size: 12px;
    line-height: 1;
    white-space: nowrap;
  }
  .table td .btn-icon { width: 24px; padding: 0; }

  /* badges must not inflate the row either */
  .table td .badge { height: 20px; padding: 0 8px; font-size: 11px; line-height: 20px; }
  .table td .room-badge { height: 20px; line-height: 20px; padding: 0 7px; }
}

/* --- wide screens: more information, never bigger type -------------- */
@media (min-width: 1600px) {
  :root { --content-pad: 24px; --gap: 20px; }
}

/* --- mobile: undo the desktop density so the stacked-card reflow that
       already exists below 900px keeps working ---------------------- */
@media (max-width: 900px) {
  .table-wrap { overflow: visible; max-block-size: none; }
  .table tbody td {
    height: auto;
    min-height: 32px;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }
  .table td .toolbar { flex-wrap: wrap; }
  .table td .btn, .table td .btn-sm { height: 36px; min-height: 36px; font-size: 14px; padding: 0 12px; }
  /* iOS zooms the viewport when a focused control is under 16px */
  .input, .select, .textarea, input, select, textarea { font-size: 16px; min-height: 40px; }
}

/* =====================================================================
   17. MOBILE NAVIGATION DRAWER (hamburger)
   ---------------------------------------------------------------------
   The bottom bar crammed 8 destinations into a horizontally scrolling
   strip, so most of them were off-screen and undiscoverable. Below 900px
   the sidebar is now a proper off-canvas drawer opened by a hamburger in
   the top bar. Above 900px the hamburger is hidden and the sidebar is a
   normal static column.
   ===================================================================== */

.nav-toggle { display: none; }

.nav-backdrop {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: rgba(2, 6, 12, .55);
  backdrop-filter: blur(2px);
  border: 0;
}
.nav-backdrop[hidden] { display: none; }

@media (max-width: 900px) {
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    margin-right: 4px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: var(--r);
    background: var(--surface-2);
    color: var(--text);
    cursor: pointer;
  }
  .nav-toggle:active { background: var(--surface-3); }
  .nav-toggle-bars { display: block; width: 18px; }
  .nav-toggle-bars span {
    display: block;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform .18s ease, opacity .18s ease;
  }
  .nav-toggle-bars span + span { margin-top: 4px; }

  .nav-open .nav-toggle-bars span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .nav-open .nav-toggle-bars span:nth-child(2) { opacity: 0; }
  .nav-open .nav-toggle-bars span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  /* --- the drawer itself: override the old bottom-bar layout --------- */
  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    top: 0;
    height: 100dvh;
    width: min(82vw, 300px);
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding: 12px 10px calc(12px + env(safe-area-inset-bottom, 0px));
    border-top: 0;
    border-right: 1px solid var(--sidebar-border);
    box-shadow: 6px 0 28px rgba(0, 0, 0, .38);
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateX(-102%);
    transition: transform .22s cubic-bezier(.4, 0, .2, 1);
    z-index: 60;
  }
  .nav-open .sidebar { transform: translateX(0); }

  .sidebar-brand {
    display: block;
    padding: 6px 10px 12px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--sidebar-border);
  }
  .nav-section { display: block; }
  .sidebar-foot { display: block; margin-top: auto; }

  .nav {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: 2px;
    overflow: visible;
  }
  .nav li { flex: 0 0 auto; display: block; }

  .nav-item {
    flex: 0 0 auto;
    min-width: 0;
    min-height: 46px;              /* comfortably above the 44px target */
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    gap: 10px;
    padding: 0 12px;
    border-radius: var(--r);
    font-size: var(--fs-base);
    font-weight: 500;
    text-align: left;
    white-space: nowrap;
  }
  .nav-item.active {
    box-shadow: inset 3px 0 0 var(--sidebar-accent);
    background: var(--sidebar-active-bg);
    font-weight: 600;
  }
  .nav-item .nav-count,
  .nav-item .badge { margin-left: auto; }

  /* the content no longer needs to clear a bottom bar */
  .content { padding-bottom: calc(var(--content-pad) + env(safe-area-inset-bottom, 0px)); }

  body.nav-locked { overflow: hidden; }
}

@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .sidebar { transition: none; }
  .nav-toggle-bars span { transition: none; }
}

/* =====================================================================
   18. MOBILE: show the essentials, not all 12 columns
   ---------------------------------------------------------------------
   Stacked as cards, the Clients table produced a 503px-tall block per
   client — one and a half clients per screen. On a phone the owner wants
   to know: which room, who, how much do they owe, when is it due. The
   rest stays one tap away in the client detail view.
   ===================================================================== */

@media (max-width: 900px) {
  .table td[data-label="Phone"],
  .table td[data-label="Units"],
  .table td[data-label="Monthly"],
  .table td[data-label="Charged"],
  .table td[data-label="Paid"],
  .table td[data-label="Last payment"] { display: none; }

  /* the room number is the owner's primary identifier: lead with it */
  .table td[data-label="Room"] {
    border-bottom: 1px solid var(--border);
    padding-bottom: 8px;
    margin-bottom: 4px;
  }
  .table td[data-label="Balance"] { font-weight: 600; }
}

/* =====================================================================
   19. HEADER — mobile polish
   ---------------------------------------------------------------------
   At 390px the top bar was ~250px tall: Refresh / Light theme / Sign out
   wrapped onto three lines down the right-hand side and squeezed the
   title until it read "C.". Those three actions now live at the foot of
   the navigation drawer, so the header is a single 54px row:
   hamburger | title | timestamp.
   ===================================================================== */

.sidebar-foot { flex-wrap: wrap; }
.sidebar-foot .btn { flex: 1 1 auto; justify-content: center; }

.topbar { flex-wrap: nowrap; }
.topbar-title { min-width: 0; flex: 0 1 auto; }
.topbar-meta  { min-width: 0; }

@media (max-width: 900px) {
  .topbar {
    gap: 10px;
    min-height: var(--topbar-h);
    padding: 0 var(--content-pad);
    align-items: center;
  }
  .topbar-title {
    flex: 0 1 auto;
    font-size: var(--fs-md);
    font-weight: 600;
  }
  /* the timestamp keeps its own line's worth of room but never pushes the
     title out; it drops to the short form below 380px */
  .topbar-meta {
    flex: 1 1 auto;
    margin-left: auto;
    text-align: right;
    font-size: var(--fs-xs);
    line-height: 1.25;
    color: var(--text-muted);
    white-space: normal;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
  .sidebar-foot {
    margin-top: auto;
    padding: 12px 2px 0;
    gap: 6px;
  }
  .sidebar-foot .btn {
    flex: 1 1 30%;
    min-height: 40px;
    font-size: var(--fs-sm);
  }
}

@media (max-width: 420px) {
  .topbar-meta { font-size: 10.5px; max-width: 46%; }
}
