/* ==========================================================================
   Rental App design system
   Single source of truth for all custom styling. Loaded from base.html and
   cached by the service worker (everything under /static/ is cached).
   Sections:
     1. Design tokens
     2. Theme (light / dark)
     3. Bootstrap component overrides
     4. App shell (sidebar + topbar + content)
     5. Navigation
     6. Cards, stats, sections
     7. Tables (incl. the responsive stacking table)
     8. Forms
     9. Feedback (flash, empty state, offline)
    10. Utilities
    11. Print & reduced motion
   ========================================================================== */

/* -------------------------------------------------------------------------
   1. Design tokens
   ------------------------------------------------------------------------- */
:root {
  /* Brand ramp — deep teal reads as "operations software" rather than
     default-Bootstrap blue, and stays legible on both themes. */
  --brand-50:  #eefaf8;
  --brand-100: #d3f2ee;
  --brand-200: #a8e5de;
  --brand-300: #6fd0c7;
  --brand-400: #38b3a8;
  --brand-500: #14958c;
  --brand-600: #0f766e;
  --brand-700: #115e59;
  --brand-800: #124c48;
  --brand-900: #113f3c;

  /* Accent used for "needs your attention" states that are not errors. */
  --accent-400: #fbbf24;
  --accent-500: #f59e0b;
  --accent-600: #d97706;

  --brand: var(--brand-600);
  --brand-hover: var(--brand-700);
  --brand-active: var(--brand-800);
  --brand-subtle: var(--brand-50);
  --brand-rgb: 15, 118, 110;

  /* Shape */
  --radius-sm: .375rem;
  --radius-md: .625rem;
  --radius-lg: .875rem;
  --radius-xl: 1.125rem;

  /* Elevation — soft and low-contrast; the app is dense, heavy shadows
     turn a data table page into visual noise. */
  --shadow-xs: 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-sm: 0 1px 3px rgba(16, 24, 40, .08), 0 1px 2px rgba(16, 24, 40, .04);
  --shadow-md: 0 4px 12px rgba(16, 24, 40, .08), 0 2px 4px rgba(16, 24, 40, .04);
  --shadow-lg: 0 12px 32px rgba(16, 24, 40, .12);

  /* Layout */
  --sidebar-width: 16rem;
  --topbar-height: 3.5rem;
  --touch-target: 44px;

  /* Type */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
               "Noto Sans", "Liberation Sans", Arial, sans-serif,
               "Apple Color Emoji", "Segoe UI Emoji";
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;
}

/* -------------------------------------------------------------------------
   2. Theme
   Bootstrap 5.3 does the heavy lifting through data-bs-theme; we only
   re-point the brand-derived variables and a few surfaces.
   ------------------------------------------------------------------------- */
:root,
[data-bs-theme="light"] {
  --bs-primary: var(--brand-600);
  --bs-primary-rgb: var(--brand-rgb);
  --bs-link-color: var(--brand-700);
  --bs-link-color-rgb: 17, 94, 89;
  --bs-link-hover-color: var(--brand-800);
  --bs-body-font-family: var(--font-sans);
  --bs-body-bg: #f5f7f8;
  --bs-body-color: #1b2426;
  --bs-secondary-color: #5c6b70;
  --bs-border-color: #e2e8ea;

  --surface: #ffffff;
  --surface-muted: #f9fafb;
  --surface-sunken: #eef1f3;
  --sidebar-bg: #ffffff;
  --topbar-bg: #ffffff;
  --shell-border: #e2e8ea;
}

[data-bs-theme="dark"] {
  --brand: var(--brand-400);
  --brand-hover: var(--brand-300);
  --brand-active: var(--brand-200);
  --brand-subtle: rgba(56, 179, 168, .14);
  --brand-rgb: 56, 179, 168;

  --bs-primary: var(--brand-400);
  --bs-primary-rgb: var(--brand-rgb);
  --bs-link-color: var(--brand-300);
  --bs-link-color-rgb: 111, 208, 199;
  --bs-link-hover-color: var(--brand-200);
  --bs-body-bg: #0f1416;
  --bs-body-color: #e3e8ea;
  --bs-secondary-color: #9aa8ad;
  --bs-border-color: #263135;
  --bs-emphasis-color: #f4f7f8;

  --surface: #171f22;
  --surface-muted: #1c262a;
  --surface-sunken: #121a1c;
  --sidebar-bg: #131b1e;
  --topbar-bg: #131b1e;
  --shell-border: #263135;

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, .45);
  --shadow-md: 0 4px 12px rgba(0, 0, 0, .5);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, .55);
}

/* Follow the OS when the user has not made an explicit choice. */
@media (prefers-color-scheme: dark) {
  :root:not([data-bs-theme="light"]) {
    color-scheme: dark;
  }
}

html { color-scheme: light dark; }
[data-bs-theme="light"] { color-scheme: light; }
[data-bs-theme="dark"] { color-scheme: dark; }

body {
  font-family: var(--font-sans);
  background-color: var(--bs-body-bg);
  -webkit-font-smoothing: antialiased;
}

/* Surface helpers replace the hard-coded bg-white / bg-light that used to be
   scattered through the templates and broke under a dark theme. */
.surface { background-color: var(--surface) !important; }
.surface-muted { background-color: var(--surface-muted) !important; }
.surface-sunken { background-color: var(--surface-sunken) !important; }

/* -------------------------------------------------------------------------
   3. Bootstrap component overrides
   ------------------------------------------------------------------------- */
:focus-visible {
  outline: 3px solid rgba(var(--brand-rgb), .5);
  outline-offset: 2px;
}

.btn { --bs-btn-border-radius: var(--radius-sm); font-weight: 500; }

.btn-primary {
  --bs-btn-bg: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand-hover);
  --bs-btn-hover-border-color: var(--brand-hover);
  --bs-btn-active-bg: var(--brand-active);
  --bs-btn-active-border-color: var(--brand-active);
  --bs-btn-disabled-bg: var(--brand);
  --bs-btn-disabled-border-color: var(--brand);
  --bs-btn-color: #fff;
  --bs-btn-hover-color: #fff;
  --bs-btn-active-color: #fff;
  --bs-btn-disabled-color: #fff;
}

[data-bs-theme="dark"] .btn-primary {
  --bs-btn-color: #08211f;
  --bs-btn-hover-color: #08211f;
  --bs-btn-active-color: #08211f;
  --bs-btn-disabled-color: #08211f;
}

.btn-outline-primary {
  --bs-btn-color: var(--brand);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand);
  --bs-btn-hover-border-color: var(--brand);
  --bs-btn-active-bg: var(--brand-hover);
  --bs-btn-active-border-color: var(--brand-hover);
  --bs-btn-disabled-color: var(--brand);
  --bs-btn-disabled-border-color: var(--brand);
}

[data-bs-theme="dark"] .btn-outline-primary {
  --bs-btn-hover-color: #08211f;
  --bs-btn-active-color: #08211f;
}

.card {
  --bs-card-bg: var(--surface);
  --bs-card-border-color: var(--bs-border-color);
  --bs-card-border-radius: var(--radius-lg);
  --bs-card-inner-border-radius: calc(var(--radius-lg) - 1px);
}

.card.shadow-sm { box-shadow: var(--shadow-sm) !important; }
.card.shadow { box-shadow: var(--shadow-md) !important; }

.card-header {
  --bs-card-cap-bg: transparent;
  border-bottom-color: var(--bs-border-color);
  padding-block: .875rem;
}

.modal-content {
  --bs-modal-bg: var(--surface);
  --bs-modal-border-radius: var(--radius-lg);
  --bs-modal-border-color: var(--bs-border-color);
}

.dropdown-menu {
  --bs-dropdown-bg: var(--surface);
  --bs-dropdown-border-color: var(--bs-border-color);
  --bs-dropdown-border-radius: var(--radius-md);
  --bs-dropdown-link-active-bg: var(--brand);
  box-shadow: var(--shadow-md);
}

.offcanvas { --bs-offcanvas-bg: var(--sidebar-bg); }

.badge { --bs-badge-border-radius: 999px; font-weight: 600; letter-spacing: .01em; }

.progress { --bs-progress-bg: var(--surface-sunken); border-radius: 999px; }
.progress-bar { border-radius: 999px; }

.form-control, .form-select {
  --bs-border-radius: var(--radius-sm);
  background-color: var(--surface);
}
.form-control:focus, .form-select:focus {
  border-color: var(--brand-400);
  box-shadow: 0 0 0 .2rem rgba(var(--brand-rgb), .2);
}

.table { --bs-table-bg: transparent; }

/* -------------------------------------------------------------------------
   4. App shell
   Desktop gets a persistent sidebar; below lg the same nav is rendered into
   an offcanvas. The sidebar is a single markup block reused by both.
   ------------------------------------------------------------------------- */
.app-shell { min-height: 100vh; }

.app-topbar {
  position: sticky;
  top: 0;
  z-index: 1035;
  height: var(--topbar-height);
  display: flex;
  align-items: center;
  gap: .75rem;
  padding-inline: 1rem;
  background-color: var(--topbar-bg);
  border-bottom: 1px solid var(--shell-border);
}

.app-brand {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--bs-emphasis-color);
  text-decoration: none;
  white-space: nowrap;
}
.app-brand:hover { color: var(--brand); }
.app-brand-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: var(--radius-sm);
  background: linear-gradient(140deg, var(--brand-500), var(--brand-700));
  color: #fff;
  flex: 0 0 auto;
}
[data-bs-theme="dark"] .app-brand-mark { color: #08211f; }

/* Top-bar buttons (menu, theme, user): borderless, tinted only on hover/open. */
.app-topbar-btn {
  --bs-btn-color: var(--bs-body-color);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-color: var(--brand);
  --bs-btn-hover-bg: var(--surface-muted);
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-color: var(--brand);
  --bs-btn-active-bg: var(--surface-muted);
  --bs-btn-active-border-color: transparent;
}

.app-body { display: block; }

.app-sidebar { display: none; }

@media (min-width: 992px) {
  .app-body {
    display: grid;
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
    align-items: start;
  }
  /* Signed-out pages (login, register) render no sidebar: give main the whole width. */
  .app-body--no-sidebar { grid-template-columns: minmax(0, 1fr); }
  .app-sidebar {
    display: block;
    position: sticky;
    top: var(--topbar-height);
    height: calc(100vh - var(--topbar-height));
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 1.25rem .875rem 2rem;
    background-color: var(--sidebar-bg);
    border-right: 1px solid var(--shell-border);
  }
  /* The hamburger only exists for the offcanvas fallback. */
  .app-nav-toggle { display: none !important; }
}

.app-main { min-width: 0; padding: 1.5rem 1rem 4rem; }
@media (min-width: 992px) { .app-main { padding: 1.75rem 1.75rem 4rem; } }

.app-main > .container-fluid,
.app-main > .app-main-inner { max-width: 1600px; margin-inline: auto; }

.skip-link {
  position: fixed;
  top: .5rem;
  left: .5rem;
  z-index: 2000;
  transform: translateY(-160%);
}
.skip-link:focus { transform: translateY(0); }

/* -------------------------------------------------------------------------
   5. Navigation
   ------------------------------------------------------------------------- */
.nav-menu { display: grid; gap: 1.25rem; }

.nav-menu-section-title {
  margin: 0 0 .375rem .75rem;
  color: var(--bs-secondary-color);
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
}

.nav-menu-links { display: grid; gap: .125rem; }

.nav-menu-link {
  display: flex;
  align-items: center;
  gap: .625rem;
  min-height: var(--touch-target);
  padding: .5rem .75rem;
  border-radius: var(--radius-sm);
  color: var(--bs-body-color);
  font-size: .9375rem;
  text-decoration: none;
  transition: background-color .12s ease, color .12s ease;
}
.nav-menu-link:hover,
.nav-menu-link:focus-visible {
  color: var(--brand);
  background-color: var(--surface-muted);
}
.nav-menu-link.nav-current {
  color: var(--brand);
  background-color: var(--brand-subtle);
  box-shadow: inset 3px 0 0 var(--brand);
  font-weight: 600;
}
.nav-menu-link .icon { flex: 0 0 auto; opacity: .85; }
.nav-menu-link.nav-current .icon { opacity: 1; }

.nav-menu-count {
  margin-left: auto;
  font-size: .75rem;
  font-weight: 700;
  padding: .0625rem .4375rem;
  border-radius: 999px;
  background-color: var(--bs-danger);
  color: #fff;
}

/* -------------------------------------------------------------------------
   6. Cards, stats, page sections
   ------------------------------------------------------------------------- */
.page-header {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 1.5rem;
}
.page-header h1 { font-size: 1.5rem; font-weight: 700; letter-spacing: -.02em; margin-bottom: .25rem; }
.page-header .page-header-sub { color: var(--bs-secondary-color); margin-bottom: 0; }
.page-header-actions { display: flex; flex-wrap: wrap; gap: .5rem; }
.page-header-inline > div:first-child { min-width: 0; }
.page-header-inline h1:only-child { margin-bottom: 0; }

/* Page-level tabs (property page): brand underline, two equal halves on phones. */
.page-tabs {
  --bs-nav-underline-gap: 0;
  --bs-nav-underline-link-active-color: var(--brand);
  --bs-nav-link-color: var(--bs-secondary-color);
  --bs-nav-link-hover-color: var(--bs-emphasis-color);
  flex-wrap: nowrap;
  margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--bs-border-color);
}
.page-tabs .nav-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: var(--touch-target);
  margin-bottom: -1px;
  padding-inline: 1rem;
  font-weight: 600;
}
@media (max-width: 767.98px) {
  .page-tabs .nav-item { flex: 1 1 0; }
  .page-tabs .nav-link { width: 100%; }
}

/* A strip of tappable counts (property page: rooms / vacant / unpaid). */
.stat-strip { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.stat-strip-item {
  display: grid;
  justify-items: center;
  gap: .125rem;
  min-height: var(--touch-target);
  padding: .75rem .5rem;
  border: 0;
  background: transparent;
  color: inherit;
}
.stat-strip-item + .stat-strip-item { border-left: 1px solid var(--bs-border-color); }
.stat-strip-item:hover { background-color: var(--surface-muted); }
.stat-strip-item:focus-visible { outline-offset: -3px; }
.stat-strip-value { font-size: 1.375rem; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
.stat-strip-label { font-size: .8125rem; color: var(--bs-secondary-color); }

/* "Needs attention" list: each line links to the room or section concerned. */
.attention-list { padding-block: .25rem; }
.attention-list a {
  display: flex;
  align-items: center;
  gap: .5rem;
  min-height: var(--touch-target);
  font-weight: 500;
  text-decoration: none;
}
.attention-list a:hover span { text-decoration: underline; }
.attention-list li + li { border-top: 1px solid var(--bs-warning-border-subtle); }

.breadcrumb { --bs-breadcrumb-divider-color: var(--bs-secondary-color); font-size: .875rem; margin-bottom: .75rem; }
.breadcrumb-item + .breadcrumb-item::before { content: "/"; }

/* KPI / stat tiles */
.stat-card {
  height: 100%;
  padding: 1.125rem 1.25rem;
  background-color: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
}
.stat-card-label {
  display: block;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--bs-secondary-color);
  margin-bottom: .375rem;
}
.stat-card-value {
  font-size: 1.75rem;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  margin-bottom: 0;
}
.stat-card-meta { font-size: .8125rem; color: var(--bs-secondary-color); margin-bottom: 0; }

/* The one thing on the dashboard that should interrupt you. */
.action-banner {
  border: 1px solid var(--bs-border-color);
  border-left: 4px solid var(--bs-secondary-color);
  border-radius: var(--radius-lg);
  background-color: var(--surface);
  box-shadow: var(--shadow-xs);
  padding: 1.125rem 1.25rem;
}
.action-banner.is-urgent { border-left-color: var(--bs-primary); }
.action-banner.is-clear { border-left-color: var(--bs-success); }
.action-banner-count {
  font-size: 2.25rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.action-chip {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  padding: .3125rem .625rem;
  border-radius: 999px;
  border: 1px solid var(--bs-border-color);
  background-color: var(--surface-muted);
  color: var(--bs-body-color);
  font-size: .8125rem;
  font-weight: 500;
  text-decoration: none;
  /* Matches the 44px minimum used everywhere else, so chips are tappable. */
  min-height: 44px;
}
.action-chip:hover, .action-chip:focus-visible {
  border-color: var(--brand);
  color: var(--brand);
}
.action-chip .action-chip-count { font-weight: 700; font-variant-numeric: tabular-nums; }
.action-chip.is-zero { opacity: .6; }

/* Definition rows used in snapshot cards */
.stat-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding-block: .375rem;
}
.stat-row + .stat-row { border-top: 1px solid var(--bs-border-color); }
.stat-row dt, .stat-row .stat-row-label { color: var(--bs-secondary-color); font-weight: 400; margin: 0; }
.stat-row dd, .stat-row .stat-row-value { font-weight: 600; font-variant-numeric: tabular-nums; margin: 0; text-align: right; }

/* Simple CSS bar chart used for the collections trend. */
.mini-chart { display: flex; align-items: stretch; gap: .5rem; height: 9rem; padding-top: .5rem; }
.mini-chart-col { flex: 1 1 0; display: flex; flex-direction: column; justify-content: flex-end; gap: .25rem; min-width: 0; }
.mini-chart-stack { position: relative; flex: 1 1 auto; min-height: 0; border-radius: var(--radius-sm); }
.mini-chart-bar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  transition: height .3s ease;
}
/* Billed is the outline; collected fills it in. */
.mini-chart-billed { background-color: var(--surface-sunken); border: 1px solid var(--bs-border-color); }
.mini-chart-collected { background-color: var(--brand); }
.mini-chart-label { font-size: .6875rem; color: var(--bs-secondary-color); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* -------------------------------------------------------------------------
   7. Tables
   ------------------------------------------------------------------------- */
.table-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  align-items: flex-end;
  padding: .875rem 1rem;
  background-color: var(--surface-muted);
  border-bottom: 1px solid var(--bs-border-color);
}
.table-toolbar .toolbar-search { flex: 1 1 18rem; min-width: 0; }
.table-toolbar .toolbar-filter { flex: 0 1 12rem; }
.table-toolbar-summary { flex-basis: 100%; font-size: .8125rem; color: var(--bs-secondary-color); margin: 0; }

.table > :not(caption) > * > * { padding: .75rem .75rem; }
.table thead th {
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--bs-secondary-color);
  background-color: var(--surface-muted);
  border-bottom-color: var(--bs-border-color);
  white-space: nowrap;
}
.table tbody td { vertical-align: middle; }
.table .num, .table .text-end { font-variant-numeric: tabular-nums; }

/* Sortable headers */
.th-sort { cursor: pointer; user-select: none; }
.th-sort::after {
  content: "";
  display: inline-block;
  width: 0; height: 0;
  margin-left: .375rem;
  vertical-align: middle;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  opacity: .25;
}
.th-sort[aria-sort="ascending"]::after { border-top: 0; border-bottom: 5px solid currentColor; opacity: .9; }
.th-sort[aria-sort="descending"]::after { opacity: .9; }

/* Expandable detail rows (billing charge breakdown, etc.) */
.row-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--radius-sm);
  background-color: transparent;
  color: var(--bs-secondary-color);
}
.row-toggle:hover { border-color: var(--brand); color: var(--brand); }
.row-toggle .icon { transition: transform .15s ease; }
.row-toggle[aria-expanded="true"] .icon { transform: rotate(90deg); }
.detail-row > td { background-color: var(--surface-muted); padding: 0 !important; }
.detail-row-inner { padding: 1rem 1.25rem; }

/*  The responsive stacking table.
    One table in the markup: it renders as a table at md+ and as a stack of
    cards below that, using each cell's data-label as its field name. This
    replaces the parallel "desktop table + mobile card list" markup that used
    to be duplicated on every list page. */
@media (max-width: 767.98px) {
  .table-stack-wrap { overflow: visible; }
  .table-stack { border-collapse: separate; }
  .table-stack thead { display: none; }
  .table-stack, .table-stack tbody, .table-stack tr, .table-stack td { display: block; width: 100%; }
  .table-stack tr {
    border: 1px solid var(--bs-border-color);
    border-radius: var(--radius-md);
    background-color: var(--surface);
    padding: .875rem 1rem;
    margin-bottom: .75rem;
    box-shadow: var(--shadow-xs);
  }
  .table-stack tr:last-child { margin-bottom: 0; }
  .table-stack td {
    border: 0;
    padding: .3125rem 0;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1rem;
    text-align: right;
  }
  .table-stack td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    font-size: .75rem;
    font-weight: 600;
    color: var(--bs-secondary-color);
    text-align: left;
  }
  .table-stack td:not([data-label])::before,
  .table-stack td[data-label=""]::before { display: none; }
  /* The identifying cell reads as the card title, full width. */
  .table-stack td.cell-primary {
    display: block;
    text-align: left;
    padding-top: 0;
    padding-bottom: .5rem;
    margin-bottom: .375rem;
    border-bottom: 1px solid var(--bs-border-color);
    font-size: 1rem;
  }
  .table-stack td.cell-primary::before { display: none; }
  .table-stack td.cell-actions {
    display: grid;
    gap: .5rem;
    text-align: left;
    margin-top: .75rem;
    padding-top: .75rem;
    border-top: 1px solid var(--bs-border-color);
  }
  .table-stack td.cell-actions::before { display: none; }
  .table-stack td.cell-actions .btn,
  .table-stack td.cell-actions form { width: 100%; }
  .table-stack td.cell-hide-sm { display: none; }
  .table-stack .detail-row,
  .table-stack tr.detail-row { padding: 0; border: 0; box-shadow: none; margin-bottom: .75rem; }
  .table-stack .detail-row > td { border-radius: var(--radius-md); }
  .table-stack td[colspan] { text-align: center; }

  /* Compact variant (.table-stack.table-stack-rows): a divided list of tappable rows
     instead of cards. Captions are dropped, so cells say what they are by position:
     .cell-primary takes the first line(s), .cell-grow and .cell-end share the last.
     The primary cell's .row-link covers the whole row; a chevron marks it. */
  .table-stack-rows tr {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .25rem .75rem;
    position: relative;
    margin: 0;
    padding: .75rem 2.75rem .75rem 1rem;
    border: 0;
    border-bottom: 1px solid var(--bs-border-color);
    border-radius: 0;
    box-shadow: none;
    background: transparent;
  }
  .table-stack-rows tr:last-child { border-bottom: 0; }
  .table-stack-rows tr:hover, .table-stack-rows tr:active { background-color: var(--surface-muted); }
  .table-stack-rows td { display: block; width: auto; padding: 0; text-align: left; box-shadow: none; }
  .table-stack-rows td::before { display: none; }
  .table-stack-rows td.cell-primary { flex: 0 0 100%; min-width: 0; padding: 0; margin: 0; border: 0; }
  .table-stack-rows td.cell-grow { flex: 1 1 auto; min-width: 0; }
  .table-stack-rows td.cell-end { order: 1; margin-left: auto; text-align: right; }
  .table-stack-rows .row-link { color: var(--bs-emphasis-color); text-decoration: none; }
  button.row-link { padding: 0; border: 0; background: none; font: inherit; font-weight: 600; text-align: left; }
  .table-stack-rows .row-link::after { content: ""; position: absolute; inset: 0; }
  /* A row without a .row-link is not tappable: no chevron, no space kept for one. */
  .table-stack-rows tr:not(:has(.row-link)) { padding-right: 1rem; }
  .table-stack-rows tr:not(:has(.row-link))::after { display: none; }
  /* Extra lines after the status/amount line: .cell-full (e.g. receipts) and actions. */
  .table-stack-rows td.cell-full,
  .table-stack-rows td.cell-actions { order: 2; flex: 0 0 100%; }
  .table-stack-rows td.cell-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin: .25rem 0 0;
    padding: 0;
    border: 0;
  }
  .table-stack-rows td.cell-actions > * { flex: 1 1 auto; }
  .table-stack-rows td.cell-actions .input-group .btn { width: auto; }
  .table-stack-rows td.cell-hide-sm { display: none; }
  /* Rows that expand in place (data-detail-row, toggled by a button.row-link): the
     chevron points down and flips while the detail row is open. */
  .table-stack-rows tr[data-detail-row]::after { transform: rotate(90deg); }
  .table-stack-rows tr[data-detail-row]:has(.row-link[aria-expanded="true"])::after { transform: rotate(-90deg); }
  .table-stack-rows tr.detail-row { display: block; padding: 0; background-color: var(--surface-muted); }
  .table-stack-rows tr.detail-row::after { display: none; }
  .table-stack-rows tr.detail-row > td { display: block; width: 100%; text-align: left; }
  .bill-actions-mobile {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .5rem;
    margin-bottom: 1rem;
  }
  .bill-actions-mobile form, .bill-actions-mobile .btn { width: 100%; margin: 0; }
  .table-stack-rows .row-link:focus-visible { outline: 0; }
  .table-stack-rows .row-link:focus-visible::after { outline: 3px solid rgba(var(--brand-rgb), .5); outline-offset: -3px; }
  .table-stack-rows tr::after {
    content: "";
    position: absolute;
    top: 50%;
    right: 1rem;
    width: 1rem;
    height: 1rem;
    margin-top: -.5rem;
    background: var(--bs-secondary-color);
    -webkit-mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M6 3l5 5-5 5'/%3e%3c/svg%3e") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M6 3l5 5-5 5'/%3e%3c/svg%3e") center / contain no-repeat;
  }
}

@media (min-width: 768px) {
  .table-stack td::before { display: none; }
}

/* Pagination */
.pagination { --bs-pagination-border-radius: var(--radius-sm); --bs-pagination-active-bg: var(--brand); --bs-pagination-active-border-color: var(--brand); --bs-pagination-color: var(--bs-body-color); }
.pager-bar {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  align-items: center;
  justify-content: space-between;
  padding: .75rem 1rem;
  border-top: 1px solid var(--bs-border-color);
}
.pager-summary { font-size: .8125rem; color: var(--bs-secondary-color); margin: 0; }

/* -------------------------------------------------------------------------
   8. Forms
   ------------------------------------------------------------------------- */
.form-label { font-weight: 500; font-size: .875rem; margin-bottom: .25rem; }
.form-section + .form-section { margin-top: 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--bs-border-color); }
.form-section-title {
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--bs-secondary-color);
  margin-bottom: .75rem;
}

/* Accordions (settings sections, collapsible cards): brand colours and focus ring. */
.app-accordion {
  --bs-accordion-bg: transparent;
  --bs-accordion-border-color: var(--bs-border-color);
  --bs-accordion-active-bg: var(--brand-subtle);
  --bs-accordion-active-color: var(--brand);
  --bs-accordion-btn-focus-box-shadow: inset 0 0 0 3px rgba(var(--brand-rgb), .5);
}
.app-accordion .accordion-button:focus:not(:focus-visible) { box-shadow: none; }
.app-accordion .accordion-button:not(.collapsed):focus:not(:focus-visible) {
  box-shadow: inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color);
}
/* Chevron in the text colour; Bootstrap's dark theme hard-codes a blue one. */
.app-accordion .accordion-button::after {
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='M2 5L8 11L14 5'/%3e%3c/svg%3e") center / contain no-repeat;
}
.app-accordion .accordion-button.collapsed::after { color: var(--bs-secondary-color); }
.accordion-heading { display: grid; gap: .125rem; font-weight: 600; }
.accordion-heading small { color: var(--bs-secondary-color); font-weight: 400; }
.settings-section-actions { display: flex; justify-content: flex-end; margin-top: 1.25rem; }

/* Collapsible card (collapse_header macro): the whole header toggles the body.
   Open cards keep a neutral header; badges and summaries sit before the chevron. */
.collapsible-card {
  --bs-accordion-btn-padding-x: 1rem;
  --bs-accordion-btn-padding-y: .875rem;
  --bs-accordion-active-bg: transparent;
  --bs-accordion-active-color: var(--bs-emphasis-color);
  overflow: hidden;
}
.collapsible-card-header {
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .5rem .75rem;
  min-width: 0;
  margin-right: .75rem;
}
[data-list-controls] .table-toolbar { border-bottom: 0; }

/* Submit guard: the button reports that it is working and cannot be
   double-clicked into duplicate records. */
.btn[data-submitting="true"] { pointer-events: none; opacity: .75; }
.btn[data-submitting="true"] .btn-label::after {
  content: "";
  display: inline-block;
  width: .875em;
  height: .875em;
  margin-left: .5em;
  vertical-align: -.125em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: btn-spin .6s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* File input helper */
.file-field-preview {
  display: none;
  gap: .625rem;
  align-items: center;
  margin-top: .5rem;
  padding: .5rem .625rem;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--radius-sm);
  background-color: var(--surface-muted);
  font-size: .8125rem;
}
.file-field-preview.is-visible { display: flex; }
.file-field-preview img {
  width: 40px; height: 40px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  flex: 0 0 auto;
}
.file-field-preview .file-field-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-field-preview .file-field-size { color: var(--bs-secondary-color); margin-left: auto; white-space: nowrap; }
.file-field-preview.is-oversize { border-color: var(--bs-danger); color: var(--bs-danger); }

/* -------------------------------------------------------------------------
   9. Feedback
   ------------------------------------------------------------------------- */
.flash-stack {
  position: fixed;
  top: calc(var(--topbar-height) + .75rem);
  right: .75rem;
  z-index: 1080;
  width: min(24rem, calc(100vw - 1.5rem));
  display: grid;
  gap: .5rem;
  pointer-events: none;
}
.flash-notification {
  width: 100%;
  padding-right: 3.25rem;
  pointer-events: auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  margin-bottom: 0;
}
.flash-notification .btn-close {
  top: 50%;
  right: .25rem;
  width: var(--touch-target);
  height: var(--touch-target);
  padding: 0;
  background-position: center;
  transform: translateY(-50%);
}

.empty-state {
  display: grid;
  justify-items: center;
  gap: .625rem;
  padding: 2.5rem 1.25rem;
  text-align: center;
}
.empty-state-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background-color: var(--surface-sunken);
  color: var(--bs-secondary-color);
}
.empty-state-title { font-size: 1rem; font-weight: 600; margin: 0; }
.empty-state-text { color: var(--bs-secondary-color); font-size: .875rem; margin: 0; max-width: 32rem; }

.offline-banner {
  display: none;
  align-items: center;
  gap: .5rem;
  justify-content: center;
  padding: .5rem 1rem;
  background-color: var(--accent-500);
  color: #3d2a04;
  font-size: .875rem;
  font-weight: 600;
}
body.is-offline .offline-banner { display: flex; }

/* Status dot so state is never carried by colour alone. */
.status-dot {
  display: inline-block;
  width: .5rem;
  height: .5rem;
  border-radius: 50%;
  margin-right: .375rem;
  vertical-align: baseline;
  background-color: currentColor;
}

/* -------------------------------------------------------------------------
   10. Utilities
   ------------------------------------------------------------------------- */
.icon {
  display: inline-block;
  width: 1em; height: 1em;
  vertical-align: -.125em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: 0 0 auto;
}
.icon-lg { width: 1.25em; height: 1.25em; }
.icon-xl { width: 1.5em; height: 1.5em; }

.num { font-variant-numeric: tabular-nums; }
/* Amounts and month labels read as one token; "RM" on one line and the figure on the next does not. */
td.num, th.num, td.cell-month { white-space: nowrap; }
.text-truncate-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.avatar {
  width: 2rem; height: 2rem;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
}
.avatar-fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--surface-sunken);
  color: var(--bs-secondary-color);
  font-weight: 600;
  font-size: .8125rem;
}

.card-action { color: inherit; text-decoration: none; display: block; }
.card-action:hover .card,
.card-action:focus-visible .card {
  border-color: var(--brand) !important;
  transform: translateY(-1px);
}
.card-action .card { transition: border-color .15s ease, transform .15s ease; }

@media (max-width: 767.98px) {
  .btn, .form-control, .form-select, .page-link { min-height: var(--touch-target); }
  .btn { display: inline-flex; align-items: center; justify-content: center; }
  .btn-close { min-width: var(--touch-target); min-height: var(--touch-target); background-position: center; }
  .mobile-stack-actions .btn, .mobile-stack-actions form { width: 100%; }
  .page-header-actions { width: 100%; }
  .page-header-actions .btn { flex: 1 1 auto; }
  .page-header-inline { flex-wrap: nowrap; align-items: center; }
  .page-header-inline .page-header-actions { width: auto; flex: 0 0 auto; flex-wrap: nowrap; }
}

/* Property gallery: uniform thumbnails and a full-screen viewer that zooms in place. */
.gallery-thumb-img { height: 180px; width: 100%; object-fit: cover; }
.gallery-fullscreen-img {
  max-height: 88vh;
  max-width: 94vw;
  transform-origin: center center;
  transition: transform .15s ease;
}

/* Collapse toggle labels: Bootstrap puts .collapsed on the trigger while its
   target is hidden, so the button can say what clicking it will do. */
.if-collapsed { display: none; }
.collapsed .if-collapsed { display: inline; }
.collapsed .if-expanded { display: none; }

/* Anchor targets must clear the sticky topbar. */
:target,
[id]:target,
.scroll-anchor,
[data-list-controls] { scroll-margin-top: calc(var(--topbar-height) + 1rem); }

/* -------------------------------------------------------------------------
   11. Print & motion
   ------------------------------------------------------------------------- */
@media print {
  .app-topbar, .app-sidebar, .flash-stack, .page-header-actions,
  .table-toolbar, .pager-bar, .offline-banner, .skip-link { display: none !important; }
  .app-body { display: block; }
  .app-main { padding: 0; }
  .card { border: 1px solid #ccc !important; box-shadow: none !important; break-inside: avoid; }
  /* A closed card still prints its content. */
  .collapsible-card > .collapse,
  .collapsible-card > .accordion-item > .collapse { display: block !important; height: auto !important; }
  .collapsible-card .accordion-button::after { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    scroll-behavior: auto !important;
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* Owner statement payout: method and reference fit beside the button. */
.payout-form .form-control {
  max-width: 7rem;
}

/* Property card without a photo: a small, quiet placeholder instead of a 210px grey box (T-70). */
.property-card-placeholder {
  height: 96px;
}

/* One-time login details: easy to read and copy (T-75). */
.credential-box code {
  font-size: 1rem;
}

/* WhatsApp invitations: the sign-up card and the QR code (white in both themes, so it scans). */
.auth-card {
  max-width: 26rem;
  width: 100%;
}

.invite-qr {
  display: inline-block;
  padding: 0.5rem;
  background: #fff;
  border-radius: 0.5rem;
  line-height: 0;
}
