/* ======================================================
   CSS DESIGN SYSTEM — DentaLedger ERP — Demo Invoicing
   Professional medical/dental vendor palette.
   ====================================================== */

:root {
  /* --- Palette --- */
  /* THE PALETTE IS UNIFIED. These five tokens used to carry Tailwind teal —
     a hue that appears nowhere on the company letterhead — while the
     reporting layer used the brand accent sampled from it. Two palettes
     coexisted. They now REFERENCE the brand tokens (defined in the second
     :root block below) instead of restating a hex, so a future edit cannot
     repoint one and leave the other behind. Change the brand token; both
     move. See the sampling note above that block. */
  --color-primary:       var(--brand-accent);        /* #0f7ca4 */
  --color-primary-hover: var(--brand-accent-deep);   /* #115479 */
  --color-primary-medium:var(--brand-accent-bright); /* #0d9fca */
  --color-primary-light: var(--brand-accent-soft);   /* #eaf4f9 */
  --color-primary-glow:  rgba(15, 124, 164, 0.12);   /* the accent at 12% */
  --color-surface:       #ffffff;
  --color-bg:            #f8fafc;   /* Slate 50 background */
  --color-border:        #e2e8f0;   /* Slate 200 border */
  --color-border-light:  #f1f5f9;   /* Slate 100 border */
  --color-text:          #334155;   /* Slate 700 text */
  --color-text-dark:     #0f172a;   /* Slate 900 text */
  --color-muted:         #64748b;   /* Slate 500 muted */
  --color-danger:        #ef4444;   /* Red 500 */
  --color-danger-light:  #fef2f2;
  --color-danger-border: #fecaca;
  --color-success:       #10b981;   /* Emerald 500 */
  --color-success-light: #ecfdf5;
  --color-success-border:#a7f3d0;
  --color-row-alt:       #f8fafc;   /* Slate 50 alt row */
  /* Slightly stronger divider used inside the invoice form sections */
  --color-border-strong: #dde3ec;
  /* Draft / amber notice palette (was hardcoded inline in invoice routes) */
  --color-draft-bg:      #fefce8;
  --color-draft-border:  #fef08a;
  --color-draft-title:   #854d0e;
  --color-draft-text:    #a16207;
  /* Post action (distinct green, differentiated from primary teal) */
  --color-post:          #16a34a;   /* Green 600 */
  --color-post-hover:    #15803d;   /* Green 700 */

  /* --- Typography --- */
  --font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* --- Spacing & shape --- */
  --space:   1rem;       /* base spacing unit */
  --radius:  12px;       /* modern border radius */
  --radius-sm: 8px;      /* smaller border radius for inputs/buttons */

  /* --- Depth & Elevation --- */
  --shadow-sm: 0 1px 3px 0 rgba(15, 23, 42, 0.05);
  --shadow-md: 0 4px 12px -2px rgba(15, 23, 42, 0.06), 0 2px 6px -1px rgba(15, 23, 42, 0.06);
  --shadow-lg: 0 12px 24px -4px rgba(15, 23, 42, 0.08), 0 4px 12px -2px rgba(15, 23, 42, 0.08);
}

/* === RESET & BASE === */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: var(--font-family);
  font-size: 14px;
  line-height: 1.6;
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
}

/* === LAYOUT CONTAINER === */
.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: calc(var(--space) * 1.5) var(--space);
}

/* === HEADER === */
header {
  background: transparent;
  color: var(--color-text-dark);
  padding: 0;
  margin-bottom: calc(var(--space) * 1.5);
  border: none;
}

header .container {
  padding-top: 0;
  padding-bottom: 0;
  max-width: 100%;
  margin: 0;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
}

header h1 {
  font-size: 1.85rem;
  font-weight: 800;
  color: var(--color-text-dark);
  letter-spacing: -0.03em;
  line-height: 1.2;
}

header p {
  font-size: 0.95rem;
  color: var(--color-muted);
  margin-top: 4px;
}

/* === SECTIONS === */
section {
  background: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius);
  padding: calc(var(--space) * 1.5);
  margin-bottom: calc(var(--space) * 1.5);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.2s ease, border-color 0.2s ease;
}

section:hover {
  box-shadow: var(--shadow-md);
  border-color: rgba(13, 159, 202, 0.1);
}

section h2 {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--color-text-dark);
  margin-bottom: var(--space);
  padding-bottom: calc(var(--space) * 0.5);
  border-bottom: 1px solid var(--color-border-light);
  letter-spacing: -0.01em;
  text-transform: none;
}

/* === FORM GRID === */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: calc(var(--space) * 1);
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
}

.form-group label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-muted);
}

/* === UNIFIED FIELD STYLING ===
   One modern look for every input / select / textarea / search field,
   across the products forms, the invoice form and the search dropdowns. */
.form-group input,
.form-group select,
.form-group textarea,
.search-input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  font-family: var(--font-family);
  font-size: 0.9rem;
  color: var(--color-text-dark);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  box-shadow: var(--shadow-sm);
}

.form-group textarea,
textarea {
  height: auto;
  min-height: 80px;
  padding: 10px 12px;
  resize: vertical;
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus,
.search-input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}

.form-group input[readonly],
.form-group input[disabled],
input[readonly],
input[disabled] {
  background: var(--color-bg);
  color: var(--color-muted);
  cursor: not-allowed;
  box-shadow: none;
}

/* === CARD — primary content container (used on every page) === */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius);
  padding: calc(var(--space) * 1.5);
  margin-bottom: calc(var(--space) * 1.5);
  box-shadow: var(--shadow-sm);
}

.card h3 {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--color-text-dark);
  margin-bottom: 8px;
}

/* Small helper / caption text under fields */
.hint { font-size: 12px; color: var(--color-muted); margin-top: 4px; }

/* Opening-stock callout (product add form + add-product modal) */
.opening-stock-section { margin-top: 16px; padding: 16px; background: var(--color-bg); border: 1px dashed var(--color-border); border-radius: var(--radius-sm); }
.opening-stock-section h3 { margin: 0 0 4px; font-size: 13px; color: var(--color-text-dark); text-transform: none; letter-spacing: 0; }
.opening-stock-section .hint { font-size: 12px; color: var(--color-muted); margin: 0 0 12px; }

/* Form layout grid (auto-fit responsive columns) */
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; }

/* Sub-heading with divider (invoice form section titles) */
.form-section-head { margin-top: 16px; border-bottom: 1px solid var(--color-border-strong); padding-bottom: 8px; }

/* Definition-list grid (detail views) */
.dl-grid { display: grid; grid-template-columns: 180px 1fr; gap: 8px 16px; align-items: center; }
.dl-label { font-weight: 600; color: var(--color-muted); font-size: 13px; }
.dl-value { color: var(--color-text-dark); font-size: 14px; font-weight: 500; }
.qty-highlight { font-size: 20px; font-weight: 700; color: var(--color-primary); }

/* Section header (title + actions row) */
.section-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; border-bottom: 1px solid var(--color-border); padding-bottom: 12px; gap: 8px; }
.section-head h2 { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }

/* Inline text link */
a.link { color: var(--color-primary); text-decoration: none; font-weight: 500; }
a.link:hover { text-decoration: underline; color: var(--color-primary-hover); }

/* Empty-state cell / message */
.empty { text-align: center; color: var(--color-muted); padding: 48px 0; font-size: 14px; background: var(--color-bg); border-radius: var(--radius-sm); border: 1px dashed var(--color-border); margin: 16px 0; }

/* Totals box (invoice & product views) — scoped so it never collides with
   the dashboard .totals-grid .totals-row variant defined below. */
.totals-box { width: 320px; margin-left: auto; background: var(--color-bg); padding: 20px; border-radius: var(--radius-sm); border: 1px solid var(--color-border); margin-top: 16px; }
.totals-box .totals-row { display: flex; justify-content: space-between; margin-bottom: 10px; font-size: 14px; color: var(--color-muted); }
.totals-box .totals-row span:last-child { color: var(--color-text-dark); font-weight: 600; }
.totals-box .totals-row.grand { font-weight: 800; font-size: 18px; margin-top: 16px; padding-top: 16px; border-top: 2px solid var(--color-border); color: var(--color-primary); }
.totals-box .totals-row.grand span:last-child { color: var(--color-primary); }

/* Sortable table headers (invoice list) */
th.sortable { cursor: pointer; user-select: none; }
th.sortable a { display: inline-flex; align-items: center; gap: 6px; color: inherit; text-decoration: none; }
th.sortable:hover { color: var(--color-primary); }
th.sortable.sorted, th.sortable.sorted a { color: var(--color-primary); }
.sort-ind { font-size: 10px; line-height: 1; }

/* Product search cell keeps a usable width inside the line table */
.lines-table .product-wrapper { min-width: 200px; }

/* Invoice-list filter bar — bare fields share the unified field look */
.invoice-filter { display: flex; gap: 16px; margin-bottom: 20px; align-items: center; flex-wrap: wrap; }
.invoice-filter input[type="text"],
.invoice-filter select {
  height: 40px;
  padding: 0 12px;
  font-family: var(--font-family);
  font-size: 0.9rem;
  color: var(--color-text-dark);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.invoice-filter input[type="text"]:focus,
.invoice-filter select:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}

/* In-page validation (client-side UX layer; the server stays authoritative) */
.field-error input,
input.field-error,
.field-error .search-input {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.12);
}
.field-error-msg { color: var(--color-danger); font-size: 12px; font-weight: 600; margin-top: 4px; }

/* Draft notice block (invoice detail) */
.notice-draft { background: var(--color-draft-bg); border: 1px solid var(--color-draft-border); }
.notice-draft-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.notice-draft h3 { color: var(--color-draft-title); margin: 0; }
.notice-draft p { color: var(--color-draft-text); font-size: 13px; margin-top: 4px; }

/* Small uppercase caption (detail field labels) */
.caption { font-size: 12px; color: var(--color-muted); text-transform: uppercase; letter-spacing: 0.03em; }

/* Inline-SVG alignment helper */
.icon { display: inline-block; vertical-align: middle; }

/* Right-aligned numeric cells/fields */
.text-right { text-align: right; }

/* Horizontal button / control group */
.actions { display: flex; gap: 8px; align-items: center; }
.actions-end { display: flex; gap: 10px; align-items: center; justify-content: flex-end; }

/* Clickable table row */
.row-link { cursor: pointer; }

/* Visually-hidden label (screen-reader only) */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* === TABLE === */
.lines-table, .products-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}

.lines-table thead th, .products-table thead th {
  text-align: left;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-muted);
  padding: 10px 8px;
  border-bottom: 2px solid var(--color-border);
  white-space: nowrap;
}

.lines-table thead th.col-item-no {
  width: 110px;
}

.lines-table thead th:last-child {
  width: 44px;  /* narrow delete column */
}

.lines-table tbody tr, .products-table tbody tr {
  border-bottom: 1px solid var(--color-border-light);
  transition: background-color 0.15s ease;
}

.lines-table tbody tr:hover, .products-table tbody tr:hover {
  background-color: var(--color-primary-light);
}

.lines-table tbody td, .products-table tbody td {
  padding: 10px 8px;
  vertical-align: middle;
}

/* Empty state message (shown when no rows) */
.lines-empty {
  text-align: center;
  padding: calc(var(--space) * 2) var(--space);
  color: var(--color-muted);
  font-size: 0.88rem;
}

/* Add-line button */
#add-line {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: calc(var(--space) * 1);
  padding: 8px 18px;
  font-family: var(--font-family);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-primary);
  background: transparent;
  border: 1px dashed var(--color-primary);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

#add-line:hover {
  background: var(--color-primary-light);
  border-style: solid;
}

#add-line:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* === TOTALS === */
.totals-grid {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
}

.totals-row {
  display: flex;
  justify-content: space-between;
  width: 280px;
  padding: 6px 0;
  font-size: 0.9rem;
}

.totals-row span:first-child {
  color: var(--color-muted);
}

.totals-row span:last-child {
  font-weight: 600;
  text-align: left;
  min-width: 120px;
  color: var(--color-text-dark);
}

.totals-row.grand-total {
  border-top: 2px solid var(--color-primary);
  padding-top: 12px;
  margin-top: 4px;
}

.totals-row.grand-total span:last-child {
  font-size: 1.25rem;
  color: var(--color-primary);
  font-weight: 800;
}

/* === FOOTER === */
footer {
  background: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius);
  padding: calc(var(--space) * 1.25);
  display: flex;
  justify-content: flex-end;
  gap: calc(var(--space) * 0.75);
}

footer button {
  height: 42px;
  padding: 0 24px;
  font-family: var(--font-family);
  font-size: 0.88rem;
  font-weight: 600;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color 0.15s ease, opacity 0.15s ease, transform 0.1s ease;
}

footer button:active:not(:disabled) {
  transform: scale(0.98);
}

footer button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

#btn-save {
  background: var(--color-primary);
  color: #fff;
  box-shadow: 0 1px 2px 0 rgba(15, 124, 164, 0.2);
}

#btn-save:not(:disabled):hover {
  background: var(--color-primary-hover);
}

#btn-new {
  background: #fff;
  color: var(--color-text-dark);
  border: 1px solid var(--color-border);
}

#btn-new:not(:disabled):hover {
  background: var(--color-bg);
  border-color: var(--color-muted);
}

/* === RESPONSIVE (usable down to ~768px) === */
@media (max-width: 768px) {
  .form-grid {
    grid-template-columns: 1fr 1fr;
  }

  .totals-row {
    width: 100%;
  }

  .totals-grid {
    align-items: stretch;
  }

  footer {
    flex-direction: column;
  }

  footer button {
    width: 100%;
  }
}

@media (max-width: 480px) {
  .form-grid {
    grid-template-columns: 1fr;
  }

  .lines-table, .products-table {
    font-size: 0.8rem;
  }

  .lines-table thead th,
  .lines-table tbody td,
  .products-table thead th,
  .products-table tbody td {
    padding: 10px 8px;
  }
}

/* === LINE-ITEM INPUTS (inside table cells) === */
.line-item-no {
  width: 80px;
  height: 34px;
  padding: 0 6px;
  font-family: var(--font-family);
  font-size: 0.85rem;
  color: var(--color-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  cursor: default;
  box-shadow: none;
}

.line-product-cell {
  position: relative;
  min-width: 220px;
}

.line-product-cell input {
  width: 100%;
  height: 34px;
  padding: 0 10px;
  font-family: var(--font-family);
  font-size: 0.85rem;
  color: var(--color-text-dark);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  text-align: left;
  direction: ltr;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
  box-shadow: var(--shadow-sm);
}

.line-product-cell input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}

.line-product-cell input.has-product {
  background: var(--color-primary-light);
  border-color: var(--color-primary-medium);
  color: var(--color-primary-hover);
  font-weight: 500;
}

/* --- Search dropdown (product/customer autocomplete) ---
   The list is positioned dynamically by search-dropdown.js (it sets
   top/left/width + display inline); all static appearance lives here so the
   component no longer injects its own <style> or hardcoded hex. */
.search-dropdown-wrapper { position: relative; }

.search-dropdown-list {
  position: fixed;
  z-index: 2000;
  max-height: 250px;
  overflow-y: auto;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  list-style: none;
  margin: 4px 0 0 0;
  padding: 6px 0;
  width: 100%;
}

.search-dropdown-list li {
  padding: 8px 12px;
  font-size: 0.82rem;
  cursor: pointer;
  border-bottom: 1px solid var(--color-border-light);
  transition: background 0.1s ease, color 0.1s ease;
  color: var(--color-text);
}

.search-dropdown-list li:hover,
.search-dropdown-list li.active {
  background: var(--color-primary-light);
  color: var(--color-primary-hover);
}

.search-dropdown-list li.dd-empty,
.search-dropdown-list li.dd-empty:hover {
  color: var(--color-muted);
  font-style: italic;
  cursor: default;
  background: transparent;
}

.search-dropdown-list .dd-artno {
  font-weight: 600;
  color: var(--color-primary);
}

.search-dropdown-list .dd-cat {
  color: var(--color-muted);
  font-size: 0.78rem;
  font-weight: 500;
}

/* --- Qty / Discount / Price inputs inside table --- */
.lines-table input[type="number"],
.lines-table input[type="text"] {
  width: 100%;
  height: 34px;
  padding: 0 8px;
  font-family: var(--font-family);
  font-size: 0.85rem;
  color: var(--color-text-dark);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  text-align: left;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  box-shadow: var(--shadow-sm);
}

.lines-table input[type="number"]:focus,
.lines-table input[type="text"]:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}

/* --- Price select --- */
.lines-table select {
  width: 110px;
  height: 34px;
  padding: 0 6px;
  font-family: var(--font-family);
  font-size: 0.85rem;
  color: var(--color-text-dark);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  box-shadow: var(--shadow-sm);
}

.lines-table select:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-glow);
}

/* --- Line total (read-only) --- */
.line-total-value {
  font-weight: 700;
  text-align: left;
  white-space: nowrap;
  min-width: 90px;
  color: var(--color-text-dark);
}

/* --- Remove (×) button --- */
.btn-remove-line {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  font-size: 1.1rem;
  font-weight: 600;
  line-height: 1;
  color: var(--color-muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 50%;
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}

.btn-remove-line:hover {
  color: var(--color-danger);
  background: var(--color-danger-light);
  border-color: var(--color-danger-border);
}

/* --- Draft restoration banner --- */
.draft-banner {
  display: none;
  background: var(--color-success);
  color: #fff;
  padding: 12px 24px;
  text-align: center;
  font-weight: 600;
  font-size: 0.9rem;
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1001;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  animation: slideDownFade 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes slideDownFade {
  from { transform: translate(-50%, -20px); opacity: 0; }
  to { transform: translate(-50%, 0); opacity: 1; }
}

/* --- Validation Errors --- */
.validation-errors {
  display: none;
  background: var(--color-danger-light);
  color: var(--color-danger);
  border: 1px solid var(--color-danger-border);
  padding: 16px 20px;
  border-radius: var(--radius);
  margin-bottom: var(--space);
  font-size: 0.9rem;
  box-shadow: var(--shadow-sm);
}

.validation-errors ul {
  margin-left: 20px;
  margin-top: 6px;
}

.validation-errors li {
  margin-bottom: 4px;
}

/* --- Global Initialization Error Banner --- */
.init-error-banner {
  background: var(--color-danger-light);
  color: var(--color-danger);
  border: 1px solid var(--color-danger-border);
  padding: 16px;
  border-radius: var(--radius);
  margin-bottom: var(--space);
  font-weight: 600;
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  gap: 10px;
  box-shadow: var(--shadow-sm);
}

/* === APP LAYOUT & SIDEBAR === */
.app-layout {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: 220px;
  flex-shrink: 0;
  background: #0f172a; /* Slate 900 — professional solid dark */
  color: #fff;
  padding: 32px 16px;
  display: flex;
  flex-direction: column;
  border-right: 1px solid rgba(255, 255, 255, 0.05);
}

.sidebar-brand {
  margin-bottom: 40px;
  padding: 0 12px;
}

.sidebar-title {
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: #ffffff;
}

.sidebar-subtitle {
  font-size: 0.75rem;
  color: var(--color-primary-medium);
  font-weight: 600;
  margin-top: 2px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 16px;
  color: #94a3b8; /* Slate 400 */
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 500;
  border-radius: var(--radius-sm);
  transition: all 0.15s ease;
  border-left: 3px solid transparent;
}

.sidebar-link:hover {
  background-color: rgba(255, 255, 255, 0.03);
  color: #f8fafc;
}

.sidebar-link.active {
  background-color: rgba(255, 255, 255, 0.06);
  color: #ffffff;
  font-weight: 600;
  border-left-color: var(--color-primary-medium);
}

.sidebar-icon {
  display: inline-flex;
  opacity: 0.7;
  transition: opacity 0.15s, color 0.15s;
}

.sidebar-link:hover .sidebar-icon,
.sidebar-link.active .sidebar-icon {
  opacity: 1;
  color: var(--color-primary-medium);
}

.app-main {
  flex: 1;
  padding: 24px 24px;
  overflow-x: auto;
}

/* === DASHBOARD COMPONENTS === */
.db-metrics-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: calc(var(--space) * 1.25);
  margin-bottom: calc(var(--space) * 1.5);
}

.db-metric-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.2s ease, border-color 0.2s ease;
}

.db-metric-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: rgba(13, 159, 202, 0.15);
}

.db-metric-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--color-muted);
  letter-spacing: 0.05em;
}

.db-metric-value {
  font-size: 24px;
  font-weight: 800;
  color: var(--color-text-dark);
  line-height: 1.2;
}

.db-metric-subtext {
  font-size: 12px;
  color: var(--color-muted);
  display: flex;
  align-items: center;
  gap: 4px;
}

.db-metric-trend-up {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: var(--color-success-light);
  color: var(--color-success);
  border: 1px solid var(--color-success-border);
  padding: 1px 6px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 700;
}

.db-metric-trend-down {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: var(--color-danger-light);
  color: var(--color-danger);
  border: 1px solid var(--color-danger-border);
  padding: 1px 6px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 700;
}

/* Monthly Chart */
.db-chart-container {
  background: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius);
  padding: 24px;
  margin-bottom: calc(var(--space) * 1.5);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.2s ease;
}

.db-chart-container:hover {
  box-shadow: var(--shadow-md);
}

.db-chart-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-muted);
  margin-bottom: 28px;
}

.db-chart-canvas {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  height: 220px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--color-border-light);
  gap: 16px;
}

.db-chart-bar-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
  height: 100%;
  justify-content: flex-end;
  position: relative;
  cursor: pointer;
}

.db-chart-bar {
  width: 32px;
  background: linear-gradient(180deg, rgba(13, 159, 202, 0.15) 0%, rgba(13, 159, 202, 0.02) 100%);
  border: 1px solid rgba(13, 159, 202, 0.25);
  border-bottom: none;
  border-radius: 6px 6px 0 0;
  position: relative;
  min-height: 4px;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}

.db-chart-bar.current {
  background: linear-gradient(180deg, var(--color-primary) 0%, var(--color-primary-hover) 100%);
  border-color: var(--color-primary);
  box-shadow: 0 4px 12px rgba(15, 124, 164, 0.15);
}

.db-chart-bar-wrapper:hover .db-chart-bar {
  transform: translateY(-2px);
  background: linear-gradient(180deg, rgba(13, 159, 202, 0.3) 0%, rgba(13, 159, 202, 0.1) 100%);
  border-color: rgba(13, 159, 202, 0.5);
}

.db-chart-bar-wrapper:hover .db-chart-bar.current {
  background: linear-gradient(180deg, var(--color-primary-hover) 0%, var(--brand-accent-deep) 100%);
  box-shadow: 0 6px 16px rgba(15, 124, 164, 0.3);
}

.db-chart-bar-value {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  font-size: 10px;
  font-weight: 700;
  color: var(--color-text-dark);
  margin-bottom: 6px;
  white-space: nowrap;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  padding: 2px 6px;
  border-radius: 4px;
  box-shadow: var(--shadow-sm);
  opacity: 0;
  pointer-events: none;
  transition: all 0.15s ease;
}

.db-chart-bar-wrapper:hover .db-chart-bar-value {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.db-chart-labels {
  display: flex;
  justify-content: space-between;
  margin-top: 12px;
  gap: 16px;
}

.db-chart-label {
  flex: 1;
  text-align: center;
  font-size: 11px;
  color: var(--color-muted);
  font-weight: 600;
}

/* Side-by-Side Panels */
.db-panels-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: calc(var(--space) * 1.5);
  margin-bottom: calc(var(--space) * 1.5);
}

.db-panel {
  background: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.2s ease, border-color 0.2s ease;
}

.db-panel:hover {
  box-shadow: var(--shadow-md);
}

.db-panel-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-muted);
  margin-bottom: 20px;
  border-bottom: 1px solid var(--color-border-light);
  padding-bottom: 10px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.db-view-all-link {
  font-size: 11px;
  font-weight: 600;
  color: var(--color-primary-medium);
  text-decoration: none;
  cursor: pointer;
  text-transform: none;
  letter-spacing: normal;
  transition: color 0.15s ease;
}

.db-view-all-link:hover {
  color: var(--color-primary);
}

/* Product list with elegant soft rows */
.db-product-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.db-product-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13px;
  color: var(--color-text);
  padding: 8px 12px;
  background: var(--color-bg);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  transition: all 0.15s ease;
}

.db-product-row:hover {
  background: #ffffff;
  border-color: var(--color-border-light);
  box-shadow: var(--shadow-sm);
  transform: translateX(3px);
  color: var(--color-text-dark);
}

.db-product-name {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 260px;
}

.db-product-leader {
  display: none; /* remove old leaders */
}

.db-product-val {
  font-weight: 700;
  text-align: left;
  white-space: nowrap;
  color: var(--color-primary-medium);
}

/* Payment Method list */
.db-paymethod-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.db-paymethod-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
}

.db-paymethod-info {
  display: flex;
  justify-content: space-between;
}

.db-paymethod-name {
  font-weight: 600;
  color: var(--color-text-dark);
}

.db-paymethod-pct {
  font-weight: 700;
  color: var(--color-primary-medium);
}

.db-paymethod-bar-bg {
  height: 8px;
  background: var(--color-bg);
  border-radius: 9999px;
  overflow: hidden;
}

.db-paymethod-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--color-primary) 0%, var(--color-primary-medium) 100%);
  border-radius: 9999px;
  transition: width 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Empty state and Loading */
.db-empty-state {
  text-align: center;
  padding: 48px 24px;
  color: var(--color-muted);
  background: var(--color-surface);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius);
  font-size: 14px;
  font-style: italic;
  grid-column: 1 / -1;
  box-shadow: var(--shadow-sm);
}

.db-loading-state {
  text-align: center;
  padding: 64px 24px;
  color: var(--color-muted);
  font-size: 15px;
  font-weight: 500;
}

/* Responsive Dashboard */
/* --- Desktop Default styling for mobile components --- */
.mobile-top-bar {
  display: none;
}
.sidebar-backdrop {
  display: none;
}
.table-responsive {
  width: 100%;
}

/* --- Table Responsive Wrapper --- */
.table-responsive {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-bottom: calc(var(--space) * 1);
}

/* --- Mobile / Tablet Styles (<= 768px) --- */
@media (max-width: 768px) {
  /* Layout shifts */
  .app-layout {
    flex-direction: column;
    padding-top: 56px; /* offset for fixed top bar */
  }

  .app-main {
    padding: 16px !important;
    overflow-x: hidden;
  }

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

  /* Mobile Top Bar */
  .mobile-top-bar {
    display: flex;
    align-items: center;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 56px;
    background: #0f172a; /* Solid Slate 900 */
    color: #fff;
    padding: 0 16px;
    z-index: 1000;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
    box-shadow: var(--shadow-sm);
  }

  .hamburger-btn {
    background: transparent;
    border: none;
    color: #fff;
    cursor: pointer;
    width: 44px;
    height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: -8px;
    border-radius: var(--radius-sm);
    transition: background-color 0.15s ease;
  }

  .hamburger-btn:hover {
    background-color: rgba(255, 255, 255, 0.08);
  }

  .mobile-bar-brand {
    margin-left: 12px;
    display: flex;
    flex-direction: column;
  }

  .mobile-bar-title {
    font-size: 1.05rem;
    font-weight: 800;
    letter-spacing: -0.01em;
  }

  .mobile-bar-subtitle {
    font-size: 0.65rem;
    color: var(--color-primary-medium);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    margin-top: -2px;
  }

  /* Off-canvas Drawer */
  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: 1010;
    transform: translateX(-100%);
    transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
    box-shadow: none;
  }

  body.drawer-open .sidebar {
    transform: translateX(0);
    box-shadow: 10px 0 30px rgba(15, 23, 42, 0.25);
  }

  /* Backdrop */
  .sidebar-backdrop {
    display: block;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(15, 23, 42, 0.4);
    backdrop-filter: blur(2px);
    z-index: 1005;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.25s ease, visibility 0.25s ease;
  }

  body.drawer-open .sidebar-backdrop {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }

  body.drawer-open {
    overflow: hidden;
  }

  /* Form stack & text size prevention on focus */
  .form-grid {
    grid-template-columns: 1fr !important;
    gap: calc(var(--space) * 0.75) !important;
  }

  .form-group input,
  .form-group select,
  .form-group textarea,
  .search-input {
    font-size: 16px !important; /* iOS Zoom Prevention */
  }

  .form-group input,
  .form-group select,
  .search-input {
    height: 44px !important;    /* Touch Target Size */
  }

  /* Button touch target improvements */
  .action-btn {
    width: 44px !important;
    height: 44px !important;
  }

  .btn-remove-line {
    width: 44px !important;
    height: 44px !important;
  }

  #add-line {
    height: 44px !important;
    font-size: 0.95rem !important;
    padding: 10px 20px !important;
    width: 100% !important;
    justify-content: center;
  }

  /* Totals full-width stacking */
  .totals-grid {
    align-items: stretch !important;
  }

  .totals-row {
    width: 100% !important;
  }

  /* Footer stack */
  footer {
    flex-direction: column !important;
    gap: 10px !important;
    padding: 16px !important;
  }

  footer button {
    width: 100% !important;
    height: 48px !important;
    font-size: 0.95rem !important;
  }

  /* Dashboard Metrics 2x2 wrapping */
  .db-metrics-grid {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 12px !important;
  }

  /* Dashboard side-by-side panels stack */
  .db-panels-row {
    grid-template-columns: 1fr !important;
    gap: 16px !important;
  }

  /* Dashboard chart bar sizing on mobile */
  .db-chart-canvas {
    gap: 6px !important;
  }
  .db-chart-labels {
    gap: 6px !important;
  }
  .db-chart-bar {
    width: 24px !important;
  }
  .db-chart-label {
    font-size: 10px !important;
  }
}

/* Very Small Phones (<= 480px) */
@media (max-width: 480px) {
  .db-metrics-grid {
    grid-template-columns: 1fr !important;
  }
  .db-chart-canvas {
    gap: 4px !important;
  }
  .db-chart-labels {
    gap: 4px !important;
  }
  .db-chart-bar {
    width: 20px !important;
  }
  .db-chart-label {
    font-size: 9px !important;
  }
}

/* --- Global Elements: Buttons, Badges, Alerts, Action Icons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 42px;
  padding: 0 20px;
  font-family: var(--font-family);
  font-size: 0.88rem;
  font-weight: 600;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.15s ease, transform 0.1s ease;
  text-decoration: none;
  gap: 6px;
  box-sizing: border-box;
}

.btn:active:not(:disabled) {
  transform: scale(0.98);
}

.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--color-primary);
  color: #ffffff !important;
  box-shadow: 0 1px 2px 0 rgba(15, 124, 164, 0.2);
}

.btn-primary:hover:not(:disabled) {
  background: var(--color-primary-hover);
}

.btn-secondary {
  background: #ffffff;
  color: var(--color-text-dark) !important;
  border: 1px solid var(--color-border);
}

.btn-secondary:hover:not(:disabled) {
  background: var(--color-bg);
  border-color: var(--color-muted);
}

.btn-danger {
  background: var(--color-danger);
  color: #ffffff !important;
  box-shadow: 0 1px 2px 0 rgba(239, 68, 68, 0.2);
}

.btn-danger:hover:not(:disabled) {
  background: #dc2626;
}

.btn-dashed {
  background: transparent;
  color: var(--color-primary);
  border: 1.5px dashed var(--color-primary);
}

.btn-dashed:hover:not(:disabled) {
  background: var(--color-primary-light);
  border-style: solid;
}

.btn-success {
  background: var(--color-post);
  color: #ffffff !important;
  box-shadow: 0 1px 2px 0 rgba(22, 163, 74, 0.2);
}

.btn-success:hover:not(:disabled) {
  background: var(--color-post-hover);
}

.btn-sm {
  height: 32px;
  padding: 0 12px;
  font-size: 0.8rem;
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border: 1px solid transparent;
  white-space: nowrap;
}

.badge-active {
  background: var(--color-success-light);
  color: var(--color-success);
  border-color: var(--color-success-border);
}

.badge-inactive {
  background: var(--color-danger-light);
  color: var(--color-danger);
  border-color: var(--color-danger-border);
}

.badge-draft {
  background: #fef3c7; /* Amber 100 */
  color: #d97706;      /* Amber 600 */
  border-color: #fde68a;
}

.badge-posted {
  background: var(--color-primary-light);
  color: var(--color-primary);
  border-color: var(--brand-accent-line);
}

/* Muted VOID badge — a voided invoice reads as neutralised, not alarming. */
.badge-void {
  background: #f1f5f9; /* Slate 100 */
  color: #64748b;      /* Slate 500 */
  border-color: #e2e8f0;
}

.badge-lowstock {
  background: #fffbeb; /* Yellow 50 */
  color: #d97706;      /* Yellow 600 */
  border-color: #fde68a;
}

.badge-costmissing {
  background: #fffbeb;
  color: #ea580c;
  border-color: #fed7aa;
}

.badge-freegoods {
  background: #f0fdf4; /* Green 50 */
  color: #15803d;      /* Green 700 */
  border-color: #bbf7d0;
}

.read-only-display-price {
  height: 40px;
  padding: 0 12px;
  font-family: var(--font-family);
  font-size: 0.9rem;
  color: var(--color-muted);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  box-shadow: none;
}

.alert {
  padding: 14px 20px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 20px;
  border: 1px solid transparent;
  display: flex;
  align-items: center;
  gap: 10px;
}

.alert-success {
  background: var(--color-success-light);
  color: #065f46; /* Emerald 800 */
  border-color: var(--color-success-border);
}

.alert-error {
  background: var(--color-danger-light);
  color: #991b1b; /* Red 800 */
  border-color: var(--color-danger-border);
}

.alert-warning {
  background: #fffbeb; /* Amber 50 */
  color: #92400e;      /* Amber 800 */
  border-color: #fde68a;
}

.action-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  color: var(--color-muted);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.15s ease;
  text-decoration: none;
  box-sizing: border-box;
}

.action-btn:hover {
  color: var(--color-primary);
  background: var(--color-primary-light);
  border-color: var(--color-primary-medium);
}

/* Responsive tables and column wrapping rules */
.table-responsive {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-bottom: var(--space);
}

.products-table th, 
.products-table td,
.lines-table th,
.lines-table td {
  white-space: nowrap;
}

/* Allow description to wrap and maintain min-width on products page */
#products-table th:nth-child(2),
#products-table td:nth-child(2) {
  white-space: normal;
  min-width: 250px;
  width: auto;
}

/* Allow product description/autocomplete column in line-item table to wrap */
.lines-table th:first-child,
.lines-table td:first-child {
  white-space: normal;
}

/* Printing styles */
@media print {
  .sidebar {
    display: none !important;
  }
  /* A SCROLLING BOX IS NOT A THING PAPER HAS. `.table-responsive` scrolls on
     screen, and in print it was clipping the statement table at the right
     margin — the running-balance column came out half-drawn with a scrollbar
     rendered beside it. Releasing the overflow is what the reporting layer's
     print block already does for its own `.table-wrap`; the legacy screens
     never got the same treatment. This matters for a voided row in
     particular: a row clipped off the sheet is not "marked on paper", it is
     absent from it. */
  .table-responsive {
    overflow: visible !important;
    width: 100%;
    max-width: 100%;
  }
  .table-responsive > table {
    width: 100%;
    max-width: 100%;
    table-layout: auto;
  }
  .app-main {
    padding: 0 !important;
  }
  .mobile-top-bar,
  .sidebar-backdrop {
    display: none !important;
  }
  .app-layout {
    padding-top: 0 !important;
  }
}

/* === MODAL DIALOGS (Wave 2) === */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(15, 23, 42, 0.4);
  backdrop-filter: blur(4px);
  z-index: 3000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.modal-content {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 600px;
  max-height: 90vh;
  overflow-y: auto;
  animation: modalSlideUp 0.25s cubic-bezier(0.16, 1, 0.3, 1);
  display: flex;
  flex-direction: column;
}

@keyframes modalSlideUp {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

.modal-header {
  padding: 16px 20px;
  border-bottom: 1px solid var(--color-border-light);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.modal-header h3 {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--color-text-dark);
  margin: 0;
}

.modal-close {
  background: none;
  border: none;
  font-size: 1.5rem;
  color: var(--color-muted);
  cursor: pointer;
  padding: 4px;
  line-height: 1;
  transition: color 0.15s ease;
}

.modal-close:hover {
  color: var(--color-danger);
}

.modal-body {
  padding: 20px;
  overflow-y: auto;
}

.modal-footer {
  padding: 16px 20px;
  border-top: 1px solid var(--color-border-light);
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  background: var(--color-bg);
  border-radius: 0 0 var(--radius) var(--radius);
}

.modal-footer button {
  height: 38px;
}

/* Quick styles for table scroll in modal */
.table-scroll {
  max-height: 200px;
  overflow-y: auto;
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-sm);
  margin-top: 8px;
  margin-bottom: 8px;
}

.table-scroll table {
  width: 100%;
  border-collapse: collapse;
}

.table-scroll th {
  position: sticky;
  top: 0;
  background: var(--color-bg);
  z-index: 10;
  padding: 8px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--color-muted);
  border-bottom: 1px solid var(--color-border);
}

.table-scroll td {
  padding: 8px;
  border-bottom: 1px solid var(--color-border-light);
  font-size: 13px;
}


/* ==========================================================================
   REPORTING DESIGN LAYER — brand tokens, shared report components
   ==========================================================================

   WHERE THE COLOURS COME FROM. Every hue below was SAMPLED from the four
   letterhead PNGs that already print on every customer-facing document
   (src/public/img/letterhead/, served through src/lib/pdfAssets.js). Nothing
   here was picked from a palette generator. The sampling method and the full
   hex census are written up in the wave report; the short version:

     lh_header.png / lh_footer.png  — one horizontal gradient band, hue 194-201,
       clustering at #0D9FCA (bright) -> #0F7CA4 (dominant, ~49% of the
       chromatic pixels) -> #115479 (deep end).
     demo_stamp.png             — a single flat blue, #124BA0 (81% of its
       chromatic pixels), hue 216.
     the neutrals printed on the letterhead itself — #FFFFFF, #F2F3F3, #D1D3D4.

   THE SPLIT IS NOW CLOSED. `--color-primary` and its four companions above
   used to carry Tailwind teal (#0f766e et al), a hue sampled from nothing:
   the reporting layer used the brand accent while the other eleven screens
   used the teal, and the application had two palettes. Those five tokens now
   REFERENCE the brand tokens below, and every hardcoded teal that would have
   survived that repoint — a #f0fdfa panel, a #115e59 gradient stop, a #99f6e4
   badge border and twelve rgba() teals — was moved to the band with them.
   There is one palette. A grep of this file for a teal literal returns
   nothing, and a test asserts that against the SERVED stylesheet.
*/

:root {
  /* --- Brand accent, sampled from the letterhead band --- */
  --brand-accent:        #0f7ca4;  /* the dominant band colour */
  --brand-accent-deep:   #115479;  /* the dark end of the same gradient */
  --brand-accent-bright: #0d9fca;  /* the light end of the same gradient */
  --brand-stamp:         #124ba0;  /* the company stamp blue */
  --brand-accent-soft:   #eaf4f9;  /* accent at ~6% over white — tints, hovers */
  --brand-accent-line:   #cfe4ee;  /* accent at ~25% — borders on tinted panels */

  /* --- Neutral ramp. n-00..n-30 are the letterhead's own greys; the darker
         steps continue the same cool cast so text sits in the same family. --- */
  --brand-n-00: #ffffff;
  --brand-n-05: #f7f9fa;
  --brand-n-10: #f2f3f3;  /* letterhead */
  --brand-n-20: #e4e8ea;
  --brand-n-30: #d1d3d4;  /* letterhead */
  --brand-n-50: #8b979e;
  --brand-n-60: #6b777e;
  --brand-n-70: #4a555c;
  --brand-n-80: #2c353b;
  --brand-n-90: #161d21;

  /* --- SEMANTIC MONEY COLOURS. The two directions are never the same colour
         and never distinguished by a minus sign alone. "Due to us" is money
         a customer owes; "owed by us" is money we owe a supplier. Both are
         shown to the operator as POSITIVE magnitudes, so the COLOUR and the
         LABEL are what carry the direction. --- */
  --money-due-to-us:     #0f7ca4;  /* receivable — the brand accent itself */
  --money-due-to-us-bg:  #eaf4f9;
  --money-owed-by-us:    #a64517;  /* payable — a warm counterweight, not red */
  --money-owed-by-us-bg: #fdf1ea;
  --money-neutral:       #4a555c;  /* a figure with no direction (counts, qty) */
  --money-zero:          #8b979e;  /* an exact zero, de-emphasised */

  /* --- Chart series, derived from the same band. Ordered for the ageing
         ramp: youngest (healthy accent) to oldest (the payable warning hue). --- */
  --chart-1: #0d9fca;
  --chart-2: #0f7ca4;
  --chart-3: #115479;
  --chart-4: #a64517;
  --chart-5: #124ba0;
  --chart-grid: #e4e8ea;
  --chart-axis: #6b777e;
}

/* --- TYPOGRAPHY: system stack only, no web font, no external request. ---
   `--font-family` above is already a system stack and is reused verbatim
   rather than restated, so there is one font decision in this file. */

/* EVERY NUMERIC CELL AND EVERY MONEY FIGURE gets tabular figures, so digits
   line up in a column and a reader can compare magnitudes by eye. Applied to
   the right-aligned cells the whole app already uses, not just to new screens
   — this is the one token adoption that deliberately reaches existing pages,
   because a money column whose digits do not align is a defect everywhere. */
.text-right,
.num,
.money,
.kpi-value,
.report-table td.text-right,
.report-table th.text-right,
.products-table td.text-right,
.lines-table td.text-right {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* === THE STATEMENT SUMMARY =================================================
   The persistent total beneath a statement table, on the customer screen and
   the supplier screen alike. It is HERE rather than in either page's inline
   <style> precisely because both render it: the total used to be the fourth
   ageing cell on one screen and a bespoke totals-box on the other, and two
   copies of a figure is how they drift. The box itself is the existing
   `.totals-box` / `.totals-row` component; this only spaces it and keeps a
   subtracted figure on one line. */
.stmt-summary { margin-top: 12px; }
.stmt-summary .totals-row.subtract span:last-child { white-space: nowrap; }
.stmt-summary-note { margin-top: 8px; font-style: italic; }

/* A SUMMARY ROW THAT IS NOT PART OF THE SUM ABOVE IT.
   In FULL and PERIOD the unallocated credit is a standing POSITION, not a
   deduction: the closing balance already reflects every posted payment, so a
   figure printed flush under it would read as the third line of an
   arithmetic it takes no part in. The rule and the gap say "this is a
   separate fact" — deliberately a DASHED rule, so it cannot be mistaken for
   the solid 2px rule `.grand` draws above a total that IS a sum. */
.stmt-summary .totals-row.position {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px dashed var(--color-border);
}

/* A statement's summary must print. It is the figure the document is about. */
@media print {
  .stmt-summary { break-inside: avoid; }
}

/* === THE VOIDED-ROW STYLES — defined here, at last ========================
   `row-void` is applied TEN times and `is-voided` FOUR, across ten render
   locations in eight route files — invoices x2 (list, voided list), purchases
   (list), payments (list), SUPPLIER PAYMENTS (list), OPENING BALANCES (list),
   customers x2 (detail ledger, statement), suppliers (statement) and reports
   (product movement).

   THIS NUMBER HAS BEEN WRONG THREE TIMES RUNNING, and each time the claim
   attached to it was "that was the last one": six-and-two predated the
   product-movement report, seven-and-four predated the payments list, and
   eight-and-four was recorded alongside the claim that the payments list was
   the last document list marking a void by badge alone. It was not — the
   SUPPLIER payments list was marking one with `badge-void` and no row class,
   and the opening-balances list was doing the same for a reversed entry.
   A count that lives only in a comment is a count that drifts, so the figure
   is now PINNED BY A TEST that greps these call sites out of the source
   (tests/payment-void-row.test.js, PV5): the next miscount fails a test
   rather than a report.

   NEITHER class had a definition in any stylesheet or inline block on `main`.
   Every one of those rows was rendering as an ordinary row: a voided
   invoice in the list looked exactly like a live one.

   The two mean different things and are deliberately not the same style:
     .row-void   — THIS ROW IS THE VOID ITSELF: a voided document, or the
                   storno reversal entry that undid one.
     .is-voided  — this row BELONGS TO a document that was voided (a ledger
                   movement of a killed invoice). It is still a real row that
                   happened; it is just no longer part of the live balance.
   They can co-occur; the combined rule below keeps that legible. */
/* WHY THESE DECLARATIONS ARE `!important`, WHICH IS OTHERWISE NOT USED HERE
   FOR COLOUR. A void is a STATE OVERLAY, not a component style: it has to win
   over whatever table the row happens to sit in. It did not. `.report-table
   tbody td` sets its own `color`, and at equal specificity the later rule
   wins, so on the product-movement report a voided row rendered at FULL body
   colour with no muting at all. `.report-table tbody tr:nth-child(even) td`
   is more specific still, so on every even row the void background vanished
   too — the row was struck through and otherwise looked live.
   Measured in a real browser, not inferred: before this, that report computed
   #2c353b on #f7f9fa where every other screen computed #4a555c.
   Raising specificity or moving this block to the end of the file would both
   work until the next block is appended after it. The state must win
   unconditionally, so it says so. */
tr.row-void > td {
  color: var(--brand-n-70) !important;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  background: repeating-linear-gradient(
    135deg,
    transparent, transparent 6px,
    rgba(166, 69, 23, 0.05) 6px, rgba(166, 69, 23, 0.05) 12px
  ) !important;
}

/* A TINT ALONE CANNOT CARRY THIS STATE, and measuring it in the browser is
   how that became obvious. `.is-voided` was #f2f3f3 while the ordinary
   alternating row is #f8fafc: 1.06:1 between the two grounds — on the
   customer statement a row belonging to a voided document was indis-
   tinguishable from an ordinary even row, which is the defect this class
   exists to prevent. A deeper tint does not rescue it either (#e4e8ea
   against the stripe is 1.18:1).
   So the state gets a marker that does not depend on telling two greys
   apart: a solid rule down the leading edge of the row. It is `inset
   box-shadow` rather than `border-left` so it adds no width and cannot
   shift a column, and it is the SAME marker the print rules use, so screen
   and paper say the same thing. */
tr.is-voided > td {
  color: var(--brand-n-70) !important;
  background: var(--brand-n-20) !important;
}

tr.is-voided > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--brand-n-60);
}

tr.row-void.is-voided > td {
  /* Both: keep the strike (it is the void) over the muted ground. */
  background: var(--brand-n-20) !important;
}

/* The strike-through must not cross a link or a badge into unreadability. */
tr.row-void > td a,
tr.row-void > td .badge {
  text-decoration: none;
}

/* --- THE SAME TWO STATES, ON PAPER ----------------------------------------
   A statement or a sales log goes to a customer as a printed sheet, and a
   voided row that prints as an ordinary row is the whole defect again in a
   medium nobody can re-render. Colour is the wrong carrier here: browsers
   drop backgrounds when printing unless told not to, and the office printer
   may be mono anyway.

   So each state keeps a marker that survives the loss of colour, and the two
   markers stay DIFFERENT:
     .row-void   keeps its line-through — the strike is ink, not colour.
     .is-voided  has only a background on screen, so on paper it gains a
                 solid rule down its leading edge, plus a forced tint for the
                 printers that honour one. Without the rule it is invisible. */
@media print {
  tr.row-void > td {
    /* The diagonal stripe is a colour cue and does not survive; the strike
       carries the meaning instead. */
    background: none !important;
    text-decoration: line-through;
    text-decoration-thickness: 1px;
    color: #333 !important;
  }

  tr.is-voided > td {
    background: #ececec !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    color: #333 !important;
    text-decoration: none;
  }

  /* The marker that needs no colour at all. */
  tr.is-voided > td:first-child {
    border-left: 3pt solid #555 !important;
  }

  /* Both at once: the strike wins the row, the rule still marks the edge. */
  tr.row-void.is-voided > td {
    text-decoration: line-through;
  }
}

/* === PAGE HEAD ========================================================== */
.report-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: calc(var(--space) * 1.25);
}

.report-head h2 {
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--brand-n-90);
  letter-spacing: -0.02em;
}

.report-head .report-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* === THE DEFINITION BLOCK ==============================================
   Every report states, ON THE SCREEN, what it counts and what it leaves out —
   in particular how it treats voided and draft documents. It is not a tooltip
   and not a footnote: it is part of the report and it prints with it. */
.report-definition {
  border-left: 3px solid var(--brand-accent);
  background: var(--brand-accent-soft);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 12px 16px;
  margin-bottom: calc(var(--space) * 1.25);
  font-size: 0.85rem;
  line-height: 1.65;
  color: var(--brand-n-70);
}

.report-definition h3 {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--brand-accent-deep);
  margin-bottom: 4px;
}

.report-definition ul { margin: 4px 0 0 18px; }
.report-definition li { margin-bottom: 2px; }
.report-definition .def-excludes { color: var(--money-owed-by-us); }

/* A data-quality note is NOT an error. It is stated in the report's own voice,
   in a colour that reads as "look at this", not as "something broke". */
.report-note {
  border-left: 3px solid var(--money-owed-by-us);
  background: var(--money-owed-by-us-bg);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 12px 16px;
  margin-bottom: calc(var(--space) * 1.25);
  font-size: 0.85rem;
  line-height: 1.6;
  color: #7a3211;
}

.report-note h3 {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 4px;
}

/* === KPI TILES ========================================================== */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin-bottom: calc(var(--space) * 1.5);
}

.kpi-tile {
  display: block;
  background: var(--brand-n-00);
  border: 1px solid var(--brand-n-20);
  border-radius: var(--radius);
  padding: 16px 18px;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
  /* The accent rule at the top is the tile's only decoration and it is where
     the direction of the money is stated. */
  border-top: 3px solid var(--brand-n-30);
}

a.kpi-tile:hover {
  box-shadow: var(--shadow-md);
  border-color: var(--brand-accent-line);
  transform: translateY(-1px);
}

a.kpi-tile:focus-visible {
  outline: 2px solid var(--brand-accent);
  outline-offset: 2px;
}

.kpi-tile.kpi-due-to-us    { border-top-color: var(--money-due-to-us); }
.kpi-tile.kpi-owed-by-us   { border-top-color: var(--money-owed-by-us); }
.kpi-tile.kpi-neutral      { border-top-color: var(--brand-n-30); }

.kpi-label {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--brand-n-60);
  display: block;
  margin-bottom: 6px;
}

.kpi-value {
  font-size: 1.7rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--brand-n-90);
  display: block;
  word-break: break-word;
}

.kpi-tile.kpi-due-to-us  .kpi-value { color: var(--money-due-to-us); }
.kpi-tile.kpi-owed-by-us .kpi-value { color: var(--money-owed-by-us); }
.kpi-value.is-zero { color: var(--money-zero); }

.kpi-unit {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--brand-n-50);
  margin-left: 4px;
  letter-spacing: 0;
}

.kpi-sub {
  display: block;
  margin-top: 6px;
  font-size: 0.78rem;
  color: var(--brand-n-60);
  line-height: 1.45;
}

/* === FILTER BAR ========================================================= */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
  background: var(--brand-n-05);
  border: 1px solid var(--brand-n-20);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: calc(var(--space) * 1.25);
}

.filter-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.filter-field > label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--brand-n-60);
}

.filter-field input,
.filter-field select {
  height: 36px;
  padding: 0 10px;
  border: 1px solid var(--brand-n-30);
  border-radius: var(--radius-sm);
  background: var(--brand-n-00);
  font-family: inherit;
  font-size: 0.875rem;
  color: var(--brand-n-90);
  min-width: 140px;
  max-width: 100%;
}

.filter-field input:focus,
.filter-field select:focus {
  outline: none;
  border-color: var(--brand-accent);
  box-shadow: 0 0 0 3px rgba(15, 124, 164, 0.12);
}

.filter-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.preset-link {
  font-size: 0.78rem;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--brand-n-30);
  background: var(--brand-n-00);
  color: var(--brand-n-70);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.preset-link:hover {
  border-color: var(--brand-accent);
  color: var(--brand-accent-deep);
  background: var(--brand-accent-soft);
}

.preset-link[aria-current="true"] {
  background: var(--brand-accent);
  border-color: var(--brand-accent);
  color: #fff;
  font-weight: 600;
}

.filter-actions { display: flex; gap: 8px; align-items: flex-end; }

/* === DATA TABLE ========================================================= */
.table-wrap {
  border: 1px solid var(--brand-n-20);
  border-radius: var(--radius);
  overflow-x: auto;
  background: var(--brand-n-00);
  -webkit-overflow-scrolling: touch;
}

table.report-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.report-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--brand-n-05);
  color: var(--brand-n-70);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  text-align: left;
  padding: 10px 12px;
  white-space: nowrap;
  border-bottom: 1px solid var(--brand-n-20);
}

.report-table thead th.text-right { text-align: right; }

/* A sortable heading is a LINK, so it works without JavaScript and is
   keyboard-reachable for free. */
.report-table thead th a.sort-link {
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.report-table thead th a.sort-link:hover { color: var(--brand-accent-deep); }

.report-table thead th[aria-sort] a.sort-link { color: var(--brand-accent-deep); }

.sort-caret { font-size: 0.65em; opacity: 0.85; }

.report-table tbody td {
  padding: 9px 12px;
  border-bottom: 1px solid var(--brand-n-10);
  color: var(--brand-n-80);
  vertical-align: top;
}

.report-table tbody tr:last-child td { border-bottom: none; }
.report-table tbody tr:nth-child(even) td { background: var(--brand-n-05); }
.report-table tbody tr:hover td { background: var(--brand-accent-soft); }

.report-table td.text-right { text-align: right; white-space: nowrap; }
.report-table td.wrap { white-space: normal; min-width: 200px; }

.report-table tfoot td {
  padding: 11px 12px;
  background: var(--brand-n-10);
  font-weight: 700;
  color: var(--brand-n-90);
  border-top: 2px solid var(--brand-n-30);
}

.report-table tfoot td.text-right { text-align: right; white-space: nowrap; }

.report-table .money-due-to-us  { color: var(--money-due-to-us); font-weight: 600; }
.report-table .money-owed-by-us { color: var(--money-owed-by-us); font-weight: 600; }
.report-table .money-zero       { color: var(--money-zero); }

.report-table a.link-cell {
  color: var(--brand-accent-deep);
  text-decoration: none;
  font-weight: 600;
}
.report-table a.link-cell:hover { text-decoration: underline; }

/* === EMPTY STATE ========================================================
   Designed, not blank. A new install sees these before it sees anything else,
   so each one says what the screen will show and how to make it show it. */
.empty-state {
  text-align: center;
  padding: 44px 24px;
  color: var(--brand-n-60);
}

.empty-state .empty-mark {
  width: 46px;
  height: 46px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: var(--brand-accent-soft);
  border: 1px solid var(--brand-accent-line);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--brand-accent);
}

.empty-state h3 {
  font-size: 1rem;
  font-weight: 700;
  color: var(--brand-n-80);
  margin-bottom: 6px;
}

.empty-state p {
  font-size: 0.86rem;
  max-width: 44ch;
  margin: 0 auto 14px;
  line-height: 1.6;
}

.empty-state .empty-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
}

/* === CHART CONTAINER ====================================================
   The height is set on the WRAPPER, not on the <canvas>: Chart.js with
   `maintainAspectRatio:false` sizes the canvas to its parent, and a canvas
   with its own height attribute and a responsive chart fight each other and
   grow on every resize. */
.chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 14px;
  margin-bottom: calc(var(--space) * 1.5);
}

.chart-card {
  background: var(--brand-n-00);
  border: 1px solid var(--brand-n-20);
  border-radius: var(--radius);
  padding: 16px 18px;
  box-shadow: var(--shadow-sm);
  min-width: 0;
}

.chart-card h3 {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--brand-n-60);
  margin-bottom: 2px;
}

.chart-card .chart-sub {
  font-size: 0.78rem;
  color: var(--brand-n-50);
  margin-bottom: 12px;
}

.chart-frame {
  position: relative;
  width: 100%;
  height: 240px;
}

.chart-frame canvas { display: block; width: 100% !important; height: 100% !important; }

/* The fallback shown when a chart has nothing to draw. It replaces the frame
   entirely rather than leaving an empty box with axes and no data. */
.chart-empty {
  height: 240px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border: 1px dashed var(--brand-n-30);
  border-radius: var(--radius-sm);
  background: var(--brand-n-05);
  color: var(--brand-n-50);
  font-size: 0.85rem;
  text-align: center;
  padding: 16px;
}

/* === REPORT INDEX CARDS ================================================= */
.report-index {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
}

.report-card {
  display: block;
  background: var(--brand-n-00);
  border: 1px solid var(--brand-n-20);
  border-left: 3px solid var(--brand-accent);
  border-radius: var(--radius);
  padding: 16px 18px;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}

.report-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.report-card:focus-visible { outline: 2px solid var(--brand-accent); outline-offset: 2px; }

.report-card h3 {
  font-size: 0.98rem;
  font-weight: 700;
  color: var(--brand-accent-deep);
  margin-bottom: 4px;
}

.report-card p {
  font-size: 0.83rem;
  color: var(--brand-n-60);
  line-height: 1.55;
}

/* A qualification the report must carry in its own title — the gross-profit
   screen's "goods only, before operating expenses". Rendered as part of the
   report, never as a tooltip. */
.report-qualifier {
  display: block;
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--money-owed-by-us);
  margin-top: 4px;
  letter-spacing: 0;
  text-transform: none;
}

/* === RESPONSIVE — down to a tablet, and usable on a phone ================ */
@media (max-width: 1024px) {
  .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
  .kpi-value { font-size: 1.45rem; }
  .chart-grid { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  .report-head { flex-direction: column; align-items: stretch; }
  .report-head .report-actions { justify-content: flex-start; }
  .filter-bar { flex-direction: column; align-items: stretch; }
  .filter-field input,
  .filter-field select { min-width: 0; width: 100%; }
  .filter-actions { justify-content: flex-start; }
  .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
  .kpi-tile { padding: 13px 14px; }
  .kpi-value { font-size: 1.25rem; }
  .report-table { font-size: 0.82rem; }
  .report-table thead th,
  .report-table tbody td { padding: 8px 9px; }
  /* A sticky header inside a horizontally scrolling table is more trouble
     than it is worth on a small screen. */
  .report-table thead th { position: static; }
  .chart-frame, .chart-empty { height: 210px; }
}

/* === PRINT ==============================================================
   Every report prints legibly straight from the browser. The nav, the filter
   bar and every button come off; the definition block stays, because a
   printed report without its definition is a page of numbers whose rules
   nobody can check. */
@media print {
  .filter-bar,
  .report-actions,
  .report-head .btn,
  .print-hide { display: none !important; }

  body { background: #fff; font-size: 11pt; }
  .container { max-width: none; padding: 0; }

  section, .card, .chart-card, .table-wrap, .kpi-tile {
    box-shadow: none !important;
    border-color: #bbb !important;
    break-inside: avoid;
  }

  .kpi-grid { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .kpi-value { font-size: 1.15rem; }

  /* THE TABLE MUST FIT THE PAGE, not scroll inside a box that paper does not
     have. `.table-wrap` scrolls on screen; on paper the overflow is released
     and the table is forced to the printable width. Without the three
     `white-space` overrides below a wide report is silently CLIPPED at the
     right margin — the low-stock report lost its Value column, which is a
     figure, not decoration. */
  .table-wrap {
    overflow: visible !important;
    border: none;
    width: 100%;
    max-width: 100%;
  }
  .report-table {
    font-size: 8pt;
    width: 100%;
    max-width: 100%;
    table-layout: auto;
  }
  .report-table thead { display: table-header-group; }  /* repeat on each page */
  /* NOT `table-footer-group`, which is its default and which REPEATS the row
     on every page: the grand total would then sit under a partial list of
     rows on every sheet but the last. `table-row-group` prints it once, at
     the end, where it is true. This is the same mistake the PDF builder makes
     if `showFoot` is left at its default. */
  .report-table tfoot { display: table-row-group; }
  .report-table thead th {
    position: static;
    background: #eee !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
    /* Headings wrap AT SPACES rather than setting a floor width. Deliberately
       NOT `word-break: break-word`, which splits "REORDER POINT" into a
       vertical column of letters and an SKU like 123.4567 across two lines —
       both tried, both worse than the clipping they fixed. */
    white-space: normal;
  }
  .report-table td { white-space: normal; }
  /* A money cell must not wrap at all: a figure broken across two lines is
     unreadable, and these are short enough to never need it. */
  .report-table td.text-right,
  .report-table tfoot td.text-right { white-space: nowrap; }
  /* The link-only trailing column carries no information on paper. */
  .report-table a.link-cell[href*="product-movement"] { display: none; }
  .report-table tbody tr { break-inside: avoid; }
  .report-table tbody tr:nth-child(even) td { background: transparent; }
  .report-table tfoot td { background: #eee !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  .report-definition, .report-note {
    background: none !important;
    border-left: 2pt solid #666 !important;
    break-inside: avoid;
  }

  .chart-frame { height: 170pt; break-inside: avoid; }
  .report-print-footer { display: block !important; }
}

/* The screen never shows the print footer; print turns it on (above). */
.report-print-footer { display: none; font-size: 9pt; color: #555; margin-top: 10pt; }

/* ── Audit log screen ──────────────────────────────────────────────────────
   ADDITIVE ONLY. Every selector below is new and scoped to `.audit-*`; no
   rule above this comment is modified, so no existing screen can shift. */
.audit-when { white-space: nowrap; font-variant-numeric: tabular-nums; }
.audit-action {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  background: var(--color-surface-alt, rgba(0, 0, 0, 0.04));
  border-radius: 4px;
  padding: 2px 6px;
  white-space: nowrap;
}
.audit-fields { display: flex; flex-wrap: wrap; gap: 4px 14px; }
.audit-field { display: inline-flex; gap: 6px; align-items: baseline; font-size: 12px; }
.audit-field-label { color: var(--color-muted); }
.audit-field-value { font-weight: 600; }
.audit-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
}
/* The four columns get cramped below ~480px; the details column is the one
   that can afford to wrap rather than force a horizontal scroll. */
@media (max-width: 480px) {
  .audit-fields { flex-direction: column; gap: 2px; }
  .audit-pager { flex-wrap: wrap; }
}

/* UI round: compact, persistent navigation with a separately anchored logout. */
.sidebar { position:fixed; inset:0 auto 0 0; height:100dvh; padding:20px 12px 12px; z-index:100; }
.sidebar-brand { margin-bottom:20px; }
.sidebar-nav { flex:1; min-height:0; overflow-y:auto; gap:6px; scrollbar-width:thin; }
.sidebar-link { padding:8px 10px; font-size:13px; gap:8px; }
.sidebar-group { border-top:1px solid #ffffff12; padding:5px 0; }
.sidebar-group summary { cursor:pointer; padding:8px 10px; color:#cbd5e1; font-size:12px; font-weight:700; letter-spacing:.025em; }
.sidebar-group .sidebar-link { margin-left:7px; }
.sidebar-logout { flex:none; margin-top:8px; padding-top:8px; border-top:1px solid rgba(255,255,255,0.08); }
.sidebar-nav { overscroll-behavior:contain; }
.sidebar-group summary:focus-visible { outline:2px solid var(--color-primary-medium); outline-offset:2px; border-radius:var(--radius-sm); }
.app-main { margin-left:220px; min-width:0; }
.settings-tabs { display:flex; gap:4px; border-bottom:1px solid var(--color-border); margin-bottom:24px; }
.settings-tabs a { padding:12px 20px; color:var(--color-muted); text-decoration:none; border-bottom:3px solid transparent; }
.settings-tabs a.active { color:var(--color-primary); border-color:var(--color-primary); font-weight:700; }
.settings-fields { border:0; padding:0; margin:0; }
.settings-fields legend { font-size:18px; font-weight:700; margin-bottom:20px; }
.account-card { max-width:600px; }
.account-card p { margin-bottom:20px; }
.expense-form { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:16px; align-items:end; }
.expense-form .form-group { margin:0; display:flex; flex-direction:column; gap:6px; }
.expense-filters { display:flex; gap:14px; align-items:end; flex-wrap:wrap; margin-bottom:18px; }
.expense-filters .form-group { display:flex; flex-direction:column; gap:6px; margin:0; }
#products-table { table-layout:fixed; width:100%; min-width:0; }
#products-table th, #products-table td { white-space:normal; overflow-wrap:anywhere; padding:12px 10px; }
#products-table th:nth-child(1) { width:14%; }
#products-table th:nth-child(2) { width:35%; }
#products-table th:nth-child(3) { width:10%; }
#products-table th:nth-child(4) { width:12%; }
#products-table th:nth-child(5) { width:11%; }
#products-table th:nth-child(6) { width:18%; }
#products-table .cell-actions { white-space:normal; }
.product-extra-content { display:flex; flex-wrap:wrap; gap:24px; padding:6px; color:var(--color-muted); }
.product-extra[hidden], [hidden] { display:none!important; }
.statement-applied { display:block; font-size:11px; line-height:1.5; color:var(--color-muted); margin-top:4px; }
.stmt-ageing .form-row { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); }
.pdf-print-message { display:none; }
@media (max-width:768px) { .app-main { margin-left:0; } .expense-form { grid-template-columns:1fr; } .sidebar { height:100dvh; } .stmt-ageing .form-row { grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media print {
  body.has-pdf-export > * { display:none!important; }
  body.has-pdf-export > .pdf-print-message { display:block!important; font:12pt sans-serif; margin:20mm; color:#000; }
  .app-main { margin-left:0; }
}
#stmt-table { width:100%; min-width:0; table-layout:fixed; }
#stmt-table th, #stmt-table td { white-space:normal; overflow-wrap:anywhere; }
#stmt-table th:first-child { width:13%; }
#stmt-table:has(th:nth-child(5):last-child) th:nth-child(2) { width:42%; }
#stmt-table:has(th:nth-child(5):last-child) th:nth-child(5) { width:18%; }

/* C4 (final round): header and summary grids never leave one item alone on a
   row at desktop widths. Columns follow the number of items instead of a
   minimum width: 3 -> 3, 4 -> 4 (2 x 2 on narrower screens), 5 -> 5,
   6 -> 3 x 2; KPI grids the same up to 8 tiles; the report index 4 across. */
@media (min-width: 769px) {
  .form-row:has(> :nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .form-row:has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form-row:has(> :nth-child(5):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .form-row:has(> :nth-child(6):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .form-grid:has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi-grid:has(> :nth-child(4):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi-grid:has(> :nth-child(5):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kpi-grid:has(> :nth-child(6):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kpi-grid:has(> :nth-child(7):last-child),
  .kpi-grid:has(> :nth-child(8):last-child) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .report-index { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .expense-form > button { grid-column: 1 / -1; justify-self: start; }
}
@media (min-width: 1200px) {
  .form-row:has(> :nth-child(4):last-child) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .form-row:has(> :nth-child(5):last-child) { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .kpi-grid:has(> :nth-child(4):last-child) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .kpi-grid:has(> :nth-child(5):last-child) { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .report-index { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* r3: the quotation / purchase-order cancellation reason and the expense
   reversal form use the app's field styling, in line with their buttons. */
.form-group.cancel-reason { flex-direction:row; align-items:center; gap:8px; margin:0; }
.form-group.cancel-reason input { width:240px; }
.expense-reverse-form { display:flex; gap:14px; align-items:end; flex-wrap:wrap; padding:4px 0; }
.expense-reverse-form .form-group { display:flex; flex-direction:column; gap:6px; margin:0; min-width:220px; }

/* r3: the purchases report's nine columns fit the content width at 1280 and
   1440 without sideways scrolling. Headings wrap at their spaces, the
   supplier name may wrap, and figures still never wrap. */
.report-purchases .report-table thead th { white-space: normal; vertical-align: bottom; }
.report-purchases .report-table td.wrap { min-width: 140px; }
.report-purchases .report-table thead th,
.report-purchases .report-table tbody td,
.report-purchases .report-table tfoot td { padding-left: 10px; padding-right: 10px; }

/* r3: ordinary browser printing of a page without Export PDF. Paper gets the
   title and the content: no sidebar, buttons, filters or form controls. A
   card or table longer than a sheet flows on to the next one instead of
   leaving the title alone on the first. Pages with Export PDF still print
   only the guidance line (above). */
@media print {
  .sidebar, .btn, button, input, select, textarea,
  .filter-bar, .invoice-filter, .expense-filters { display: none !important; }
  .app-main { margin-left: 0 !important; }
  section, .card, .table-wrap, .table-responsive { break-inside: auto !important; box-shadow: none !important; }
  .card { padding: 0 !important; border: 0 !important; margin-bottom: 10pt !important; }
  header { padding-top: 0 !important; padding-bottom: 6pt !important; margin-bottom: 0 !important; }
  h1, h2, h3 { break-after: avoid; }
  table thead { display: table-header-group; }
  table tr { break-inside: avoid; }
  table th, table td { padding: 3pt 5pt !important; font-size: 8.5pt; }
  #products-table th:nth-child(6), #products-table td:nth-child(6) { display: none; }
  #products-table th:nth-child(2) { width: 52%; }
  #products-table th:nth-child(4), #products-table th:nth-child(5) { width: 11%; }
}
