/* =====================================================
   Appliance & Home Layby System — shared styles
   Brand: red #ED1C24, grey #777777, white
   ===================================================== */

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');

:root {
  --brand-red:       #ED1C24;
  --brand-red-dark:  #c81820;
  --brand-grey:      #777777;
  --brand-grey-dark: #444444;
  --brand-bg:        #F5F6F8;
  --brand-card:      #FFFFFF;
  --brand-subtle:    #FAFBFC;  /* table headers, modal footers, etc. */
  --brand-border:    #E4E6EA;
  --brand-text:      #222222;
  --brand-muted:     #6B7280;
  --status-active:   #2F7D32;
  --status-amber:    #B26A00;
  --status-overdue:  #C0392B;
  --status-pending:  #1F5FB3;
  --status-done:     #2F7D32;
  --status-grey:     #6B7280;
  --pill-active-bg:    #E6F4EA;
  --pill-overdue-bg:   #FBEAE6;
  --pill-pending-bg:   #E3EDFB;
  --pill-completed-bg: #E6F4EA;
  --pill-cancelled-bg: #EEEEEE;
  --pill-owned-bg:     #FFF1E6;
  --pill-consignment-bg: #E6F0FB;
  --shadow-sm:       0 1px 2px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.04);
  --shadow-md:       0 4px 6px -1px rgba(0,0,0,0.06), 0 2px 4px -1px rgba(0,0,0,0.04);
  --radius:          8px;
  --radius-sm:       4px;
}

/* Dark theme — admin only sets data-theme on <html>. Customer-facing pages
 * stay light by never setting it. Pure variable override — no other CSS
 * changes needed because everything below already reads from these vars. */
[data-theme="dark"] {
  --brand-bg:        #0F1115;
  --brand-card:      #1A1D24;
  --brand-subtle:    #14171D;
  --brand-border:    #2A2F38;
  --brand-text:      #E4E7EB;
  --brand-muted:     #8A93A1;
  --brand-grey:      #B8BFC9;        /* lifted for legibility on dark */
  --brand-grey-dark: #D8DDE3;
  --status-active:   #4ADE80;        /* brighter greens/reds for dark backgrounds */
  --status-done:     #4ADE80;
  --status-overdue:  #F87171;
  --status-pending:  #60A5FA;
  --status-amber:    #FBBF24;
  --pill-active-bg:    rgba(74,222,128,0.16);
  --pill-overdue-bg:   rgba(248,113,113,0.18);
  --pill-pending-bg:   rgba(96,165,250,0.18);
  --pill-completed-bg: rgba(74,222,128,0.16);
  --pill-cancelled-bg: rgba(255,255,255,0.08);
  --pill-owned-bg:     rgba(251,191,36,0.16);
  --pill-consignment-bg: rgba(96,165,250,0.16);
  --shadow-sm:       0 1px 2px rgba(0,0,0,0.3), 0 1px 3px rgba(0,0,0,0.25);
  --shadow-md:       0 4px 14px rgba(0,0,0,0.45), 0 2px 4px rgba(0,0,0,0.3);
  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--brand-bg);
  color: var(--brand-text);
  font-size: 14px;
  line-height: 1.5;
}

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

h1, h2, h3, h4 { margin: 0 0 0.5em; font-weight: 600; }
h1 { font-size: 24px; }
h2 { font-size: 18px; }
h3 { font-size: 15px; color: var(--brand-grey-dark); }

/* ---------- Top bar ---------- */
.topbar {
  background: var(--brand-card);
  border-bottom: 1px solid var(--brand-border);
  padding: 12px 24px;
  display: flex;
  align-items: center;
  gap: 24px;
  position: sticky; top: 0; z-index: 100;
  box-shadow: var(--shadow-sm);
}
.topbar .brand { display: flex; align-items: center; gap: 12px; }
.topbar .brand img { height: 72px; width: auto; display: block; }
/* Dark-mode logo handled by JS (applyTenantBranding) — was a global CSS
 * `content: url(/shared/logo-white.png)` override which forced A&H's logo
 * on every tenant in dark mode. JS now picks brand.admin_logo (light) or
 * brand.admin_logo_dark (dark) per tenant. Don't add the CSS override back. */
.topbar .brand-text { display: flex; flex-direction: column; line-height: 1; }
.topbar .brand-text .biz { font-weight: 700; font-size: 14px; color: var(--brand-grey-dark); letter-spacing: 0.5px;}
.topbar .brand-text .tagline { font-size: 9px; color: var(--brand-grey); letter-spacing: 1.5px; text-transform: uppercase; margin-top: 2px;}
.topbar nav { display: flex; gap: 4px; flex: 1; margin-left: 24px; flex-wrap: wrap; }
.topbar nav a {
  padding: 8px 14px; border-radius: var(--radius-sm);
  color: var(--brand-grey-dark); font-weight: 500;
  text-decoration: none; font-size: 13px;
}
.topbar nav a:hover { background: var(--brand-bg); }
.topbar nav a.active { background: var(--brand-red); color: white; }
.topbar .user { display: flex; align-items: center; gap: 12px; font-size: 13px; color: var(--brand-grey); }
.topbar .user button { padding: 6px 12px; }

/* ---------- Layout ---------- */
.container { max-width: 1280px; margin: 0 auto; padding: 24px; }
.page-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px; flex-wrap: wrap; gap: 12px; }
.page-header h1 { margin: 0; }
.page-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------- Cards ---------- */
.card {
  background: var(--brand-card);
  border: 1px solid var(--brand-border);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow-sm);
}
.card + .card { margin-top: 16px; }
.card-header {
  display: flex; align-items: center; justify-content: space-between;
  padding-bottom: 12px; margin-bottom: 16px;
  border-bottom: 1px solid var(--brand-border);
}
.card-header h2 { margin: 0; }
.card-header .actions { display: flex; gap: 8px; }

/* ---------- Stat cards ---------- */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin-bottom: 24px;
}
.stat-card {
  background: var(--brand-card);
  border: 1px solid var(--brand-border);
  border-radius: var(--radius);
  padding: 16px;
  border-left: 3px solid var(--brand-red);
}
.stat-card .label { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--brand-muted); }
.stat-card .value { font-size: 26px; font-weight: 700; color: var(--brand-text); margin-top: 4px; }
.stat-card .sub { font-size: 12px; color: var(--brand-muted); margin-top: 2px; }
.stat-card.urgent { border-left-color: var(--status-overdue); }
.stat-card.success { border-left-color: var(--status-done); }
.stat-card.pending { border-left-color: var(--status-pending); }

/* ---------- New dashboard KPI strip ---------- */
/* ===== KPI cards (2030 refresh) =====
   Tinted gradient backgrounds per status, soft layered shadows, icon orb
   top-right, large tabular values, smoother hover. The 4px left-border
   pattern is gone — colour now lives in the background gradient + value
   colour, both more subtle and more refined than a hard stripe. */
.kpi-hero {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  margin-bottom: 16px;
}
.kpi-card {
  position: relative;
  background: var(--brand-card);
  border: 1px solid var(--brand-border);
  border-radius: 16px;
  padding: 22px 24px 20px;
  text-decoration: none;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 8px;
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1),
              box-shadow 0.2s cubic-bezier(0.22, 1, 0.36, 1),
              border-color 0.2s;
  overflow: hidden;
  /* Layered base shadow — subtle but present, gives the card lift */
  box-shadow:
    0 1px 2px rgba(14, 27, 23, 0.04),
    0 4px 14px -6px rgba(14, 27, 23, 0.06);
}
/* Soft tinted background gradient per status. Painted via ::before so it
   sits behind the content and can be tweaked without touching layout. */
.kpi-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--kpi-tint, var(--brand-grey)) 6%, transparent) 0%,
    color-mix(in srgb, var(--kpi-tint, var(--brand-grey)) 1%, transparent) 100%);
  z-index: 0;
  pointer-events: none;
}
/* All card content sits above the gradient layer */
.kpi-card > * { position: relative; z-index: 1; }

.kpi-card.pending { --kpi-tint: #E8A93F; }
.kpi-card.active  { --kpi-tint: #2F7D32; }
.kpi-card.overdue { --kpi-tint: #C0392B; }
.kpi-card.today   { --kpi-tint: var(--brand-red); }

/* Icon orb top-right — a soft circle in the status tint. Decorative; not
   wired to a real icon to keep this CSS-only. */
.kpi-card::after {
  content: '';
  position: absolute;
  top: 18px; right: 18px;
  width: 36px; height: 36px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 30%,
      color-mix(in srgb, var(--kpi-tint, var(--brand-grey)) 30%, white) 0%,
      color-mix(in srgb, var(--kpi-tint, var(--brand-grey)) 20%, white) 70%);
  border: 1px solid color-mix(in srgb, var(--kpi-tint, var(--brand-grey)) 25%, transparent);
  z-index: 0;
  opacity: 0.85;
}

.kpi-card[href]:hover {
  transform: translateY(-3px);
  box-shadow:
    0 1px 2px rgba(14, 27, 23, 0.04),
    0 12px 28px -10px color-mix(in srgb, var(--kpi-tint, var(--brand-grey)) 30%, rgba(14, 27, 23, 0.12));
  border-color: color-mix(in srgb, var(--kpi-tint, var(--brand-grey)) 40%, var(--brand-border));
}

.kpi-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.4px;
  color: var(--brand-muted);
  text-transform: uppercase;
}
.kpi-value {
  font-size: 32px;
  font-weight: 800;
  color: var(--brand-text);
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}
.kpi-card.overdue .kpi-value { color: var(--status-overdue); }
.kpi-card.today .kpi-value   { color: var(--status-done); }
.kpi-card.pending .kpi-value { color: var(--status-amber); }
.kpi-sub {
  font-size: 12.5px;
  color: var(--brand-grey-dark);
  line-height: 1.45;
}
.kpi-sub b { color: var(--brand-text); font-weight: 700; }

/* ===== Mini KPI strip (also refreshed) =====
   Same family — softer tint, larger value, refined typography. */
.kpi-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 24px;
}
.kpi-mini {
  background: var(--brand-card);
  border: 1px solid var(--brand-border);
  border-radius: 12px;
  padding: 14px 16px;
  box-shadow: 0 1px 2px rgba(14, 27, 23, 0.03);
  transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
}
.kpi-mini:hover {
  transform: translateY(-1px);
  border-color: color-mix(in srgb, var(--brand-red) 30%, var(--brand-border));
  box-shadow: 0 4px 12px -4px rgba(14, 27, 23, 0.08);
}
.kpi-mini-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.2px;
  color: var(--brand-muted);
  text-transform: uppercase;
  margin-bottom: 4px;
}
.kpi-mini-value {
  font-size: 18px;
  font-weight: 800;
  color: var(--brand-text);
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
}
.kpi-mini-sub { font-size: 11.5px; color: var(--brand-muted); font-weight: 500; }

/* Slim traffic-summary strip — one-liner on the dashboard that links into
 * the Reports tab for the full Plausible widget. Operator mode stays
 * uncluttered; analytical detail lives one click away. */
.traffic-summary-strip {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 18px;
  margin-bottom: 18px;
  border: 1px solid var(--brand-border);
  border-radius: 10px;
  background: var(--brand-subtle);
  color: var(--brand-grey-dark);
  font-size: 13px;
  text-decoration: none;
  transition: background 0.15s, border-color 0.15s;
}
.traffic-summary-strip:hover {
  background: var(--brand-card);
  border-color: var(--brand-grey);
  text-decoration: none;
}
.traffic-summary-strip .traffic-summary-icon { font-size: 18px; flex-shrink: 0; }
.traffic-summary-strip .traffic-summary-text { flex: 1; color: var(--brand-text); }
.traffic-summary-strip .traffic-summary-text b { font-weight: 700; color: var(--brand-text); }
.traffic-summary-strip .traffic-summary-cta {
  font-size: 12px; font-weight: 600; color: var(--brand-red);
  white-space: nowrap; flex-shrink: 0;
}

/* "All caught up" celebration card — replaces the empty void at the
 * bottom of the dashboard when no actionable items exist. */
.card.all-caught-up {
  background: rgba(47, 125, 50, 0.04);
  border: 1px solid rgba(47, 125, 50, 0.25);
}
[data-theme="dark"] .card.all-caught-up {
  background: rgba(74, 222, 128, 0.06);
  border-color: rgba(74, 222, 128, 0.25);
}
.card.all-caught-up h2 { font-size: 18px; }

/* ===== Site-traffic widget — Reports tab ===== */
/* Stat cells: distinct from .kpi-mini so they don't visually echo it. */
.ts-stat {
  background: var(--brand-card);
  border: 1px solid var(--brand-border);
  border-radius: 10px;
  padding: 14px 16px;
}
.ts-stat-label {
  font-size: 10px; font-weight: 700;
  color: var(--brand-muted); text-transform: uppercase; letter-spacing: 1.2px;
  margin-bottom: 4px;
}
.ts-stat-value {
  font-size: 24px; font-weight: 800;
  color: var(--brand-text); letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.ts-stat-sub { font-size: 11px; color: var(--brand-muted); margin-top: 4px; }

/* Period switcher — subtle pill group, not the loud primary red */
.ts-period-group {
  display: inline-flex; gap: 0;
  background: var(--brand-subtle);
  border: 1px solid var(--brand-border);
  border-radius: 8px;
  padding: 2px;
}
.ts-period-btn {
  padding: 4px 10px; border: 0; background: transparent;
  font-size: 12px; font-weight: 600;
  color: var(--brand-muted);
  border-radius: 6px;
  cursor: pointer; font-family: inherit;
  transition: background 0.1s, color 0.1s;
}
.ts-period-btn:hover { color: var(--brand-text); }
.ts-period-btn.is-active {
  background: var(--brand-card);
  color: var(--brand-text);
  box-shadow: 0 1px 2px rgba(0,0,0,0.06);
}

/* Site selector dropdown */
.ts-site {
  font-size: 12px; padding: 4px 8px;
  border: 1px solid var(--brand-border);
  border-radius: 6px;
  background: var(--brand-card);
  color: var(--brand-text);
  margin-right: 8px;
}

/* List-row inside the widget — top sources / pages / countries */
.ts-list-title {
  font-size: 10px; color: var(--brand-muted);
  font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase;
  margin-bottom: 8px;
}
.ts-list-row {
  display: flex; justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px solid var(--brand-border);
  font-size: 13px;
}
.ts-list-row:last-child { border-bottom: 0; }

@media (max-width: 640px) {
  .kpi-hero { grid-template-columns: 1fr 1fr; gap: 10px; }
  .kpi-card { padding: 14px 16px; }
  .kpi-value { font-size: 22px; }
  .kpi-strip { grid-template-columns: 1fr 1fr; }
}

/* ---------- Reports tab: charts grid ---------- */
.reports-grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 16px;
  margin-bottom: 16px;
}
@media (max-width: 880px) {
  .reports-grid { grid-template-columns: 1fr; }
}
.chart-wrap {
  position: relative;
  width: 100%;
  height: 240px;
}
@media (max-width: 640px) {
  .chart-wrap { height: 200px; }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 14px;
  border: 1px solid var(--brand-border);
  border-radius: var(--radius-sm);
  background: var(--brand-card);
  color: var(--brand-grey-dark);
  cursor: pointer; font-family: inherit;
  font-size: 13px; font-weight: 500;
  transition: all 0.1s;
}
.btn:hover { border-color: var(--brand-grey); color: var(--brand-text); }
.btn-primary { background: var(--brand-red); color: white; border-color: var(--brand-red); }
.btn-primary:hover { background: var(--brand-red-dark); border-color: var(--brand-red-dark); color: white; }
.btn-ghost { background: transparent; border-color: transparent; }
.btn-ghost:hover { background: var(--brand-bg); }
.btn-danger { background: var(--brand-card); border-color: var(--status-overdue); color: var(--status-overdue); }
.btn-danger:hover { background: var(--status-overdue); color: white; }
.btn-sm { padding: 4px 10px; font-size: 12px; }
.btn-lg { padding: 12px 20px; font-size: 15px; }
.btn-block { width: 100%; justify-content: center; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ---------- Forms ---------- */
.form-group { margin-bottom: 14px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.form-row-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
@media (max-width: 600px) {
  .form-row, .form-row-3 { grid-template-columns: 1fr; }
}
.form-group label {
  display: block;
  font-size: 11px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--brand-muted);
  margin-bottom: 4px;
  font-weight: 600;
}
.form-group .hint { font-size: 12px; color: var(--brand-muted); margin-top: 4px; }
input, select, textarea {
  width: 100%; padding: 9px 12px;
  border: 1px solid var(--brand-border);
  border-radius: var(--radius-sm);
  font-family: inherit; font-size: 14px;
  background: var(--brand-card);
  color: var(--brand-text);
  transition: border-color 0.1s;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand-red);
  box-shadow: 0 0 0 3px rgba(237, 28, 36, 0.08);
}
textarea { min-height: 80px; resize: vertical; }
.checkbox-line { display: flex; align-items: flex-start; gap: 10px; }
.checkbox-line input[type="checkbox"] { width: auto; margin-top: 3px; }
.checkbox-line label { text-transform: none; letter-spacing: normal; font-size: 13px; color: var(--brand-text); }

/* ---------- Tables ---------- */
.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.data-table th, .data-table td { padding: 10px 12px; text-align: left; border-bottom: 1px solid var(--brand-border); }
.data-table th {
  font-size: 11px; text-transform: uppercase; letter-spacing: 1px;
  color: var(--brand-muted); font-weight: 600; background: var(--brand-subtle);
}
.data-table tbody tr:hover { background: var(--brand-bg); cursor: pointer; }
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table .center { text-align: center; }

/* ---------- Status pills ---------- */
.pill {
  display: inline-block; padding: 2px 8px;
  border-radius: 999px; font-size: 11px;
  font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;
}
.pill-active   { background: var(--pill-active-bg);    color: var(--status-active); }
.pill-overdue  { background: var(--pill-overdue-bg);   color: var(--status-overdue); }
.pill-pending  { background: var(--pill-pending-bg);   color: var(--status-pending); }
.pill-completed{ background: var(--pill-completed-bg); color: var(--status-done); }
.pill-cancelled{ background: var(--pill-cancelled-bg); color: var(--status-grey); }
.pill-defaulted{ background: var(--pill-overdue-bg);   color: var(--status-overdue); }
.pill-owned    { background: var(--pill-owned-bg);     color: var(--status-amber); }
.pill-consignment { background: var(--pill-consignment-bg); color: var(--status-pending); }

/* ---------- Progress bar — tiered colour by completion ----------
   Tiering matches the operational signal:
     0–49%  tier-low  red     → "lots still owed, focus area"
     50–69% tier-mid  amber   → "halfway, monitor"
     70–99% tier-high green   → "almost there, ready-to-collect soon"
     100%   done     solid green → "fully paid"
   Apply via JS based on balance.progress_pct (see renderLaybyDetail in
   admin/index.html and renderLaybyCard in portal/index.html). */
.progress {
  height: 8px; background: var(--brand-border);
  border-radius: 99px; overflow: hidden;
}
.progress-bar { height: 100%; background: var(--brand-red); transition: width 0.3s, background 0.3s; }
.progress-bar.tier-low  { background: linear-gradient(90deg, var(--brand-red) 0%, var(--brand-red-dark) 100%); }
.progress-bar.tier-mid  { background: linear-gradient(90deg, #F59E0B 0%, #D97706 100%); }
.progress-bar.tier-high { background: linear-gradient(90deg, #10B981 0%, #059669 100%); }
.progress-bar.done      { background: linear-gradient(90deg, #10B981 0%, #047857 100%); }
.progress-bar.overdue-bar { background: linear-gradient(90deg, #EF4444 0%, #B91C1C 100%); }

/* ---------- Payment receipt link — positive-event styling ----------
   Receipts are GOOD events (money in). Default link colour is red
   (brand) but for receipt rows specifically we want green so the
   payment history reads at a glance as "all good things happening." */
.payment-receipt-link {
  color: #059669 !important;
  font-weight: 700;
  text-decoration: none;
  display: inline-flex; align-items: center; gap: 4px;
}
.payment-receipt-link:hover { text-decoration: underline; color: #047857 !important; }
.payment-row { transition: background 0.12s; }
.payment-row:hover { background: color-mix(in srgb, #10B981 6%, transparent); }

/* Contextual progress hint sub-text, sits below the bar */
.progress-hint {
  font-size: 11.5px; color: var(--brand-grey-dark);
  margin-top: 8px; display: flex; align-items: center; gap: 6px;
}
.progress-hint.high { color: #047857; font-weight: 600; }
.progress-hint.done { color: #059669; font-weight: 700; }
.progress-hint.mid  { color: #92400E; font-weight: 600; }

/* ---------- Empty state ---------- */
.empty {
  padding: 48px 24px; text-align: center;
  color: var(--brand-muted); font-size: 14px;
}
.empty .big { font-size: 20px; color: var(--brand-grey-dark); margin-bottom: 6px; }

/* ---------- Modal ---------- */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.4);
  display: none; z-index: 1000;
  align-items: flex-start; justify-content: center;
  padding: 40px 16px; overflow-y: auto;
}
.modal-backdrop.open { display: flex; }
.modal {
  background: var(--brand-card); border-radius: var(--radius);
  width: 100%; max-width: 600px;
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.modal.wide { max-width: 900px; }
.modal-header { padding: 16px 20px; border-bottom: 1px solid var(--brand-border); display: flex; justify-content: space-between; align-items: center; }
.modal-header h2 { margin: 0; }
.modal-body { padding: 20px; max-height: 70vh; overflow-y: auto; }
.modal-footer { padding: 14px 20px; border-top: 1px solid var(--brand-border); display: flex; justify-content: flex-end; gap: 8px; background: var(--brand-subtle); }
.modal-close { background: transparent; border: 0; font-size: 22px; cursor: pointer; color: var(--brand-muted); padding: 4px 8px; }

/* ---------- Toasts ---------- */
.toast-host { position: fixed; bottom: 24px; right: 24px; z-index: 2000; display: flex; flex-direction: column; gap: 8px; }
.toast {
  background: var(--brand-text); color: white;
  padding: 12px 16px; border-radius: var(--radius);
  font-size: 13px; box-shadow: var(--shadow-md);
  min-width: 240px; max-width: 360px;
  animation: slidein 0.2s ease-out;
}
.toast.success { background: var(--status-done); }
.toast.error { background: var(--status-overdue); }
@keyframes slidein { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

/* ---------- Auth pages ---------- */
.auth-wrap {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #FAFBFC 0%, var(--brand-bg) 100%);
  padding: 20px;
}
.auth-card {
  background: var(--brand-card); padding: 40px; border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  width: 100%; max-width: 400px;
  text-align: center;
}
.auth-card img { height: 64px; margin-bottom: 20px; }
.auth-card h1 { font-size: 18px; margin-bottom: 24px; color: var(--brand-grey-dark); }
.auth-card .form-group { text-align: left; }
.auth-card .error { color: var(--status-overdue); font-size: 13px; margin-top: 12px; min-height: 18px; }

/* ---------- Sidebar layout (used in admin layby detail and intake) ---------- */
.split { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; }
@media (max-width: 900px) { .split { grid-template-columns: 1fr; } }

/* ---------- Misc ---------- */
.muted { color: var(--brand-muted); }
.mono { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum'; }
.right { text-align: right; }
.tag-strip { display: flex; gap: 6px; flex-wrap: wrap; }
hr { border: 0; border-top: 1px solid var(--brand-border); margin: 16px 0; }
.searchbar { display: flex; gap: 8px; align-items: center; }
.searchbar input { flex: 1; }
.kv { display: grid; grid-template-columns: 140px 1fr; gap: 6px 16px; font-size: 13px; }
.kv dt { color: var(--brand-muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.8px; padding-top: 2px; }
.kv dd { margin: 0; font-weight: 500; }

/* ---------- Action dropdown (used in toolbars) ---------- */
.action-dropdown { position: relative; display: inline-block; }
.action-dropdown summary {
  list-style: none; cursor: pointer; user-select: none;
}
.action-dropdown summary::-webkit-details-marker { display: none; }
.action-dropdown[open] > summary { background: var(--brand-bg); border-color: var(--brand-grey); }
.action-dropdown .dropdown-menu {
  position: absolute; top: calc(100% + 4px); right: 0; z-index: 50;
  min-width: 220px;
  background: var(--brand-card); border: 1px solid var(--brand-border);
  border-radius: var(--radius); box-shadow: var(--shadow-md);
  padding: 6px 0; overflow: hidden;
}
.action-dropdown .dropdown-menu button,
.action-dropdown .dropdown-menu a {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 10px 14px; text-align: left;
  background: transparent; border: 0; cursor: pointer;
  font-family: inherit; font-size: 13px; color: var(--brand-text);
  text-decoration: none;
}
.action-dropdown .dropdown-menu button:hover,
.action-dropdown .dropdown-menu a:hover { background: var(--brand-bg); }
.action-dropdown .dropdown-menu .danger { color: var(--status-overdue); }
.action-dropdown .dropdown-menu .divider { height: 1px; background: var(--brand-border); margin: 4px 0; }

/* ---------- Dashboard task rows (replaces tables on dashboard) ---------- */
.task-list { display: flex; flex-direction: column; }
.task-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 12px 4px; gap: 12px;
  border-bottom: 1px solid var(--brand-border);
  cursor: pointer; transition: background 0.1s;
}
.task-row:hover { background: var(--brand-bg); }
.task-row:last-child { border-bottom: 0; }
.task-row .task-code { font-weight: 700; color: var(--brand-red); font-size: 13px; }
/* When a pending row has already been contacted, retire the brand-red code
 * colour — red is now the signal for "not contacted", so a red code on an
 * amber-pill row reads as conflicting. Amber code = matches the row state. */
.task-row.is-contacted .task-code { color: var(--status-amber); }
.task-row .task-customer { font-size: 13px; color: var(--brand-text); margin-top: 2px; }
.task-row .task-meta { text-align: right; flex-shrink: 0; }
.task-row .task-amount { font-weight: 700; font-size: 14px; font-variant-numeric: tabular-nums; }
.task-row .task-detail { font-size: 11px; color: var(--brand-muted); margin-top: 2px; }
.task-row.urgent .task-amount { color: var(--status-overdue); }

/* Dim already-contacted applicants in the pending queue — un-contacted ones
 * float to the top via the API ordering; the visual dim reinforces that
 * "we're done with this row for now" without hiding it. */
.task-row.is-contacted,
.data-table tr.is-contacted { opacity: 0.85; }
.task-row.is-contacted:hover,
.data-table tr.is-contacted:hover { opacity: 1; }

/* ---------- Wizard / stepper ---------- */
.wizard-steps {
  display: flex; align-items: center; gap: 4px;
  margin-bottom: 20px; padding: 16px;
  background: var(--brand-card); border: 1px solid var(--brand-border);
  border-radius: var(--radius);
}
.wizard-step {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--brand-muted);
  cursor: default;
}
.wizard-step .step-circle {
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--brand-bg); color: var(--brand-muted);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px;
  border: 2px solid var(--brand-border);
  transition: all 0.15s;
}
.wizard-step.active .step-circle {
  background: var(--brand-red); color: white;
  border-color: var(--brand-red);
}
.wizard-step.done .step-circle {
  background: var(--status-done); color: white;
  border-color: var(--status-done);
}
.wizard-step.active { color: var(--brand-text); font-weight: 600; }
.wizard-step.done { cursor: pointer; }
.wizard-step.done:hover { color: var(--brand-red); }
.wizard-connector {
  flex: 1; height: 2px; background: var(--brand-border);
  min-width: 16px; margin: 0 4px;
}
.wizard-step.done + .wizard-connector,
.wizard-connector.done { background: var(--status-done); }
.wizard-step-label { display: inline; font-size: 12px; }

.wizard-panel { display: none; }
.wizard-panel.active { display: block; }
.wizard-nav {
  display: flex; justify-content: space-between;
  margin-top: 20px; gap: 12px;
}
.wizard-nav .spacer { flex: 1; }

.wizard-summary {
  background: var(--brand-bg);
  border-radius: var(--radius); padding: 12px 16px;
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 16px; font-size: 13px;
}
.wizard-summary .total { font-size: 18px; font-weight: 700; color: var(--brand-red); }

/* ---------- Compact topbar (mobile + half-screen PC) ----------
 * Applies at any width below 1024px so the nav wraps into a horizontally
 * scrollable row instead of stacking awkwardly. Half-screen PC + tablet
 * + phone all use this layout. */
@media (max-width: 1024px) {
  .topbar { padding: 10px 16px; gap: 10px; flex-wrap: wrap; align-items: center; }
  .topbar nav { margin-left: 0; gap: 4px; width: 100%; order: 3; overflow-x: auto; -webkit-overflow-scrolling: touch; flex-wrap: nowrap; }
  .topbar nav a { padding: 6px 12px; font-size: 13px; white-space: nowrap; flex-shrink: 0; }
  .topbar .brand img { height: 44px; }
  .topbar .user { font-size: 12px; gap: 6px; margin-left: auto; }
}

/* Phone-only tighter still */
@media (max-width: 600px) {
  .container { padding: 14px; }
  .topbar { padding: 8px 12px; gap: 8px; }
  .topbar nav a { padding: 6px 10px; font-size: 12px; }
  .topbar .brand img { height: 38px; }
  .topbar .user { font-size: 11px; gap: 4px; }
  .topbar .user #userLabel { display: none; }    /* the "Master Admin · admin" string eats too much width */
  .topbar .user .btn { padding: 5px 10px; }

  .stats-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; }
  .stat-card { padding: 12px; border-left-width: 3px; }
  .stat-card .value { font-size: 20px; }
  .stat-card .label { font-size: 10px; }
  .stat-card .sub { font-size: 10px; }

  .page-header h1 { font-size: 20px; }
  .page-actions { width: 100%; }
  .page-actions .btn { font-size: 12px; padding: 7px 10px; }

  .data-table { font-size: 12px; }
  .data-table th, .data-table td { padding: 8px 6px; }

  .card { padding: 14px; }
  .card-header { padding-bottom: 8px; margin-bottom: 12px; }
  .card-header h2 { font-size: 15px; }

  .wizard-steps { padding: 10px; gap: 2px; }
  .wizard-step-label { display: none !important; }
  .wizard-connector { min-width: 8px; }

  .modal { max-width: 100%; margin: 0; border-radius: 0; min-height: 100vh; }
  .modal-backdrop { padding: 0; }
}

/* ---------- Image lightbox (product zoom) ---------- */
.lightbox-backdrop {
  position: fixed; inset: 0; z-index: 1500;
  background: rgba(0, 0, 0, 0.88);
  display: flex; align-items: center; justify-content: center;
  padding: 24px; cursor: zoom-out;
  animation: fadein 0.15s ease-out;
}
@keyframes fadein { from { opacity: 0; } to { opacity: 1; } }
.lightbox-content {
  max-width: 95vw; max-height: 90vh;
  display: flex; flex-direction: column; align-items: center;
  cursor: default;
}
.lightbox-content img {
  max-width: 100%; max-height: 80vh; object-fit: contain;
  display: block; border-radius: 4px; background: white;
}
.lightbox-caption {
  color: white; text-align: center; padding: 12px 16px 0;
  font-size: 14px; font-weight: 500;
}
.lightbox-empty {
  color: white; padding: 60px 40px; font-size: 14px;
  background: rgba(255, 255, 255, 0.1); border-radius: 4px;
}
.lightbox-close {
  position: fixed; top: 16px; right: 18px;
  background: rgba(255, 255, 255, 0.15);
  color: white; border: 0; cursor: pointer;
  width: 40px; height: 40px; border-radius: 50%;
  font-size: 26px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.lightbox-close:hover { background: rgba(255, 255, 255, 0.3); }

/* Zoom button overlay on product thumbnails */
.thumb-wrap { position: relative; }
.zoom-btn {
  position: absolute; top: 6px; right: 6px;
  background: rgba(255, 255, 255, 0.94); border: 0; cursor: pointer;
  width: 28px; height: 28px; border-radius: 50%;
  font-size: 13px;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
  transition: background 0.1s, transform 0.1s;
}
.zoom-btn:hover { background: white; transform: scale(1.08); }
.thumb-placeholder {
  display: flex; align-items: center; justify-content: center;
  background: var(--brand-bg); color: var(--brand-muted);
  font-size: 28px;
}

/* ---------- Print ---------- */
@media print {
  .topbar, .page-actions, .btn, .modal-backdrop { display: none !important; }
  body { background: white; }
}

/* ============ Dashboard shell: main column + sticky action rail ============
   The dashboard used to be one long column, so the work that needs doing
   TODAY (stock to pull for laybys about to complete) sat below the fold under
   analytics. The rail pins it beside everything else. Collapses to a single
   column under 1180px — on a phone the rail stacks first, because it's the
   most actionable thing on the page. */
.dash-shell { display: grid; grid-template-columns: minmax(0, 1fr) 348px; gap: 16px; align-items: start; }
.dash-main { min-width: 0; }
.dash-rail { position: sticky; top: 14px; display: flex; flex-direction: column; gap: 14px; }
@media (max-width: 1180px) {
  .dash-shell { grid-template-columns: 1fr; }
  .dash-rail { position: static; order: -1; }
}

/* ---- Collection prep (80%+ paid) ---- */
.prep-card { padding: 0; overflow: hidden; }
.prep-head { padding: 15px 15px 13px; border-bottom: 1px solid var(--brand-border); }
.prep-title { display: flex; align-items: center; gap: 7px; font-size: 15px; font-weight: 800; letter-spacing: -0.01em; }
.prep-title .n { background: var(--status-done); color: #fff; font-size: 11px; font-weight: 800;
  padding: 1px 8px; border-radius: 999px; }
.prep-sub { font-size: 11.5px; color: var(--brand-muted); margin-top: 5px; line-height: 1.45; }
.prep-stats { display: flex; gap: 5px; margin-top: 11px; flex-wrap: wrap; }
.prep-chip { font-size: 10px; font-weight: 800; padding: 3px 9px; border-radius: 999px; letter-spacing: 0.02em; }
.prep-chip.todo      { background: var(--pill-overdue-bg); color: var(--status-overdue); }
.prep-chip.preparing { background: var(--pill-owned-bg);   color: var(--status-amber); }
.prep-chip.ready     { background: var(--pill-active-bg);  color: var(--status-done); }
.prep-list { max-height: min(62vh, 640px); overflow-y: auto; }
.prep-row { display: flex; gap: 11px; padding: 13px 14px; border-bottom: 1px solid var(--brand-border); }
.prep-row:last-child { border-bottom: 0; }
.prep-row.is-ready { background: linear-gradient(90deg, var(--pill-active-bg) 0%, transparent 70%); }
.prep-ring { width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0; display: grid; place-items: center;
  background: conic-gradient(var(--ring) calc(var(--pct) * 1%), var(--brand-border) 0); }
.prep-ring > span { width: 34px; height: 34px; border-radius: 50%; background: var(--brand-card);
  display: grid; place-items: center; font-size: 10.5px; font-weight: 800; color: var(--brand-text); }
.prep-body { flex: 1; min-width: 0; }
.prep-code { font-size: 12.5px; font-weight: 800; cursor: pointer; }
.prep-code:hover { color: var(--brand-red); }
.prep-cust { font-size: 11.5px; color: var(--brand-muted); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.prep-items { font-size: 11.5px; margin-top: 6px; line-height: 1.4; }
.prep-items b { font-weight: 700; }
.prep-bal { font-size: 11px; color: var(--brand-muted); margin-top: 4px; }
.prep-actions { display: flex; gap: 5px; margin-top: 9px; }
.prep-btn { font-family: inherit; font-size: 10.5px; font-weight: 800; padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--brand-border); background: transparent; color: var(--brand-muted); cursor: pointer; }
.prep-btn:hover { color: var(--brand-text); border-color: var(--brand-muted); }
.prep-btn.on.preparing { background: var(--status-amber); border-color: var(--status-amber); color: #fff; }
.prep-btn.on.ready     { background: var(--status-done);  border-color: var(--status-done);  color: #fff; }
.prep-empty { padding: 26px 16px; text-align: center; color: var(--brand-muted); font-size: 12.5px; line-height: 1.5; }
.prep-empty .ico { font-size: 26px; opacity: 0.5; display: block; margin-bottom: 7px; }

/* KPI grids inside the two-column shell. auto-fit measured the OLD full-width
   column, so with the rail alongside it left an orphan card on its own row.
   Fixed tracks reflow predictably: 2×2 hero on a laptop, 4-across only when
   the viewport is genuinely wide enough for it. */
.dash-main .kpi-hero  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.dash-main .kpi-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (min-width: 1580px) { .dash-main .kpi-hero { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 700px)  { .dash-main .kpi-hero, .dash-main .kpi-strip { grid-template-columns: 1fr; } }

/* Wide tables inside cards scroll instead of bleeding past the card edge.
   The two-column dashboard narrowed the main column, so the 9-column
   auto-POP table (and, on smaller laptops, Paid today) overflowed its card
   and ran under the rail. The card header stays put; only the table moves. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-scroll > .data-table { min-width: 680px; }
/* Keep the POP verify/reverse actions reachable while the wide columns
   scroll — the whole point of the card is acting on the row. */
.table-scroll .pop-table th:last-child,
.table-scroll .pop-table td:last-child {
  position: sticky; right: 0; background: var(--brand-card);
  box-shadow: -8px 0 10px -8px rgba(0, 0, 0, 0.28);
}
.table-scroll .pop-table td:nth-child(3) { white-space: nowrap; }

/* ---------- Payments report ---------- */
.pr-presets { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.pr-h { font-size: 12px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--brand-muted);
        margin: 18px 0 8px; font-weight: 800; }
.pr-split { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
@media (max-width: 900px) { .pr-split { grid-template-columns: 1fr; } }
.pr-table td, .pr-table th { padding-top: 7px; padding-bottom: 7px; }
.pr-bar { display: inline-block; width: 72px; height: 7px; border-radius: 99px;
          background: var(--brand-border); overflow: hidden; vertical-align: middle; }
.pr-bar > span { display: block; height: 100%; background: var(--brand-red); border-radius: 99px; }
/* Daily collections sparkline — bars scale to the peak day in range. */
.pr-spark { display: flex; align-items: flex-end; gap: 2px; height: 74px; padding: 6px 0;
            border-bottom: 1px solid var(--brand-border); margin-bottom: 6px; }
.pr-spark-col { flex: 1; min-width: 3px; display: flex; align-items: flex-end; height: 100%; }
.pr-spark-col > span { display: block; width: 100%; border-radius: 2px 2px 0 0;
            background: linear-gradient(180deg, var(--brand-red) 0%, var(--brand-red-dark) 100%); }
.pr-spark-col:hover > span { background: var(--status-done); }

/* ---------- Browser autofill ----------
   Chrome and Firefox paint autofilled fields with their own pale-yellow
   background, which reads as a broken input on the dark theme (and clashes on
   light). The inset box-shadow covers the UA background in both engines;
   -webkit-text-fill-color restores the text colour Chrome overrides. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active,
input:autofill,
select:-webkit-autofill,
textarea:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--brand-card) inset !important;
  box-shadow: 0 0 0 1000px var(--brand-card) inset !important;
  -webkit-text-fill-color: var(--brand-text) !important;
  caret-color: var(--brand-text);
  border-color: var(--brand-border) !important;
  /* Chrome re-applies its background on a delay; an absurd transition on
     background-color keeps ours winning without a repaint flash. */
  transition: background-color 100000s ease-in-out 0s;
}
input:-webkit-autofill:focus, input:autofill:focus { border-color: var(--brand-red) !important; }
