/* Elenserve Solar Rooftop Calculator — design tokens + components.
   Adapted from the Elenserve "Modernist" design system used in the original
   calculator mockup, extended into a normal responsive website (the mockup
   was built inside a phone-frame preview; this is the real, deployable
   layout). Retune colors/spacing here — every component below reads from
   these custom properties. */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('../fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('../fonts/archivo-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+2020, U+2113;
}

:root {
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-surface-2: #ffffff;
  --color-text: #201e1d;
  --color-accent: #ec3013;
  --color-accent-2: #e15b47;
  --color-divider: rgba(32,30,29,0.14);

  --color-neutral-100: #f8f4f4;
  --color-neutral-200: #eae7e7;
  --color-neutral-300: #d7d3d3;
  --color-neutral-400: #bab6b6;
  --color-neutral-500: #9b9797;
  --color-neutral-600: #7d7979;
  --color-neutral-700: #605d5d;
  --color-neutral-800: #444141;
  --color-neutral-900: #2d2b2b;

  --color-accent-100: #fff2ef;
  --color-accent-200: #ffe0d9;
  --color-accent-300: #ffc4b8;
  --color-accent-400: #ff9783;
  --color-accent-500: #ff563c;
  --color-accent-600: #dd2b0f;
  --color-accent-700: #ae1800;
  --color-accent-800: #7c1405;
  --color-accent-900: #4d170e;

  --font-heading: "Archivo", system-ui, sans-serif;
  --font-heading-weight: 800;
  --font-body: "Archivo", system-ui, sans-serif;

  --space-1: 4px;  --space-2: 8px;  --space-3: 12px;
  --space-4: 16px; --space-6: 24px; --space-8: 32px;

  --radius-sm: 6px; --radius-md: 10px; --radius-lg: 16px;

  --shadow-sm: 0 1px 2px rgba(45,43,43,0.14);
  --shadow-md: 0 3px 10px rgba(45,43,43,0.16);
  --shadow-lg: 0 12px 32px rgba(45,43,43,0.22);
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* The plain HTML `hidden` attribute is only ever honored via the browser's
 * own default (user-agent) stylesheet rule `[hidden] { display: none }` —
 * and that origin always loses to ANY author rule that sets `display` on
 * the same element, no matter how low that rule's specificity is (e.g.
 * .card below sets `display: flex`). Without this override, toggling
 * `.hidden = true` on an element that also carries an author class with
 * its own `display` (the follow-up summary panel is exactly this: class
 * "card" + the `hidden` attribute) silently does nothing visually — the
 * element's `hidden` DOM property flips to true, but it stays fully
 * visible on screen. This one rule guarantees `hidden` always actually
 * hides, everywhere in the app, regardless of what other classes an
 * element carries.
 */
[hidden] { display: none !important; }
body {
  background: var(--color-neutral-200);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 15px; line-height: 1.55; font-weight: 400;
}
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.15; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 32px; } h2 { font-size: 24px; } h3 { font-size: 19px; }
h4 { font-size: 17px; } h5 { font-size: 15px; }
p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent); text-decoration: none; }
a:hover { color: var(--color-accent-700); text-decoration: underline; }
img { display: block; max-width: 100%; }
hr.hr { height: 1px; border: 0; margin: var(--space-4) 0; background: var(--color-divider); }
.text-muted { color: rgba(32,30,29,0.6); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* — layout — */
.topbar {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-6);
  background: var(--color-surface-2); border-bottom: 2px solid var(--color-divider);
}
.topbar .brand { display: flex; align-items: center; gap: 10px; margin-right: auto; }
.topbar .brand img { height: 24px; width: auto; }
.topbar .brand-fallback { font-family: var(--font-heading); font-weight: 800; font-size: 18px; }
.topbar .user-chip { font-size: 13px; opacity: 0.75; }
.topbar .spacer { flex: 1; }

/* Briefly widened to 1400px in response to "why only half screen" — the
   user tried it live and preferred the original narrower column back
   (a wide wizard stretches the paired-field rows uncomfortably far apart
   on a big desktop screen), so this is back to 720px. */
.page {
  max-width: 720px; margin: 0 auto; padding: var(--space-6) var(--space-4) 60px;
}
.page-narrow { max-width: 460px; }
/* Dashboard — the team's proposal list, not the wizard, so it's not
   affected by the step-scoped .page-full toggle above; applied statically
   in dashboard.php's markup instead of via JS. Wide enough that the new
   Proposal No./Consumer/Consumer No./Phone/System/Savings/Status/Updated
   table reads comfortably without every column being squeezed. */
.page-wide { max-width: 1400px; }
/* Step 7 (Estimated charges) only — toggled onto .page by calculator.js's
   render() while state.step === 6. That table has 11 columns and stayed
   cramped/scrolly at the standard 720px width, so just this step widens to
   the full window; every other step stays at the narrower 720px above
   (the user explicitly preferred that narrower column for the input-heavy
   steps — see the note below). */
.page.page-full { max-width: 1600px; }

.auth-shell {
  min-height: 100vh; display: flex; flex-direction: column;
  align-items: center; justify-content: center; padding: var(--space-4);
  background: var(--color-neutral-200);
}
.auth-card {
  width: 100%; max-width: 420px; background: var(--color-surface-2);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  padding: var(--space-8) var(--space-6);
}
.auth-card .brand-row { display: flex; justify-content: center; margin-bottom: var(--space-4); }
.auth-card .brand-row img { height: 28px; }
.auth-card h1 { font-size: 22px; text-align: center; }
.auth-card .subtitle { text-align: center; font-size: 13px; opacity: 0.65; margin-bottom: var(--space-6); }

/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text);
  background: transparent; border: 1px solid transparent;
  padding: 10px 18px; border-radius: var(--radius-md);
  transition: background 0.15s ease;
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary { background: var(--color-accent); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--color-accent-600); }
.btn-primary:active:not(:disabled) { background: var(--color-accent-700); }
.btn-secondary { border-color: var(--color-divider); background: var(--color-surface-2); }
.btn-secondary:hover:not(:disabled) { background: rgba(32,30,29,0.06); }
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); background: none; }
.btn-ghost:hover:not(:disabled) { background: rgba(236,48,19,0.08); }
.btn-block { width: 100%; }
.btn-row { display: flex; gap: 10px; }
.btn-row .btn { flex: 1; }

/* — forms — */
.field { margin-bottom: var(--space-4); }
.field > label { display: block; font-size: 12px; margin-bottom: 5px; color: rgba(32,30,29,0.7); }
.input, textarea.input, select.input {
  width: 100%; min-height: 42px; padding: 8px 12px; font: inherit;
  font-size: 15px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.input:hover { border-color: rgba(32,30,29,0.45); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
/* 2026-10-01: make the field being typed in (and its text cursor) easy to see */
.input:focus, textarea.input:focus, select.input:focus { border-color: var(--color-accent); box-shadow: 0 0 0 3px rgba(212, 55, 30, 0.18); background: #fffdf7; }
.input, textarea.input { caret-color: #000; }
textarea.input { min-height: 80px; resize: vertical; }

/* Flags a required field that's still empty — border + tint make it obvious
   at a glance which field is blocking Continue, instead of leaving the user
   to guess (e.g. a placeholder that looks like a real value can otherwise
   be mistaken for one). */
.input-missing { border-color: var(--color-accent) !important; background: var(--color-accent-100); }
.input-missing::placeholder { color: var(--color-accent-700); opacity: 0.7; }

/* Brief highlight when jumping back to a BOM line from the "Review &
   confirm costing" table's Category link (added 2026-09-16) — see
   scrollToBomRow() in calculator.js. The class is removed by JS after
   1.5s; the transition just makes that removal fade rather than cut. */
.bom-row-flash { outline: 2px solid var(--color-accent); outline-offset: 2px; transition: outline-color 1.2s ease; }

.otp-input-row { display: flex; gap: 8px; }
.otp-box {
  width: 42px; height: 48px; text-align: center; font-size: 20px; font-weight: 700;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
  background: var(--color-surface);
}
.otp-box:focus-visible { border-color: var(--color-accent); }

.field-hint { font-size: 11px; opacity: 0.6; margin-top: 4px; }
.field-error { font-size: 12px; color: var(--color-accent-700); margin-top: 4px; }

.alert {
  padding: 10px 14px; border-radius: var(--radius-md); font-size: 13px; margin-bottom: var(--space-4);
}
.alert-error { background: var(--color-accent-100); color: var(--color-accent-800); }
.alert-success { background: #eaf6ea; color: #1c6b2a; }
.alert-info { background: var(--color-neutral-100); color: var(--color-neutral-800); }

/* Bill auto-read progress indicator (see assets/js/bill-reader.js). */
.spinner {
  width: 14px; height: 14px; flex: none; border-radius: 50%;
  border: 2px solid rgba(32,30,29,0.25); border-top-color: var(--color-accent);
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Full-screen camera barcode scanner (serials.php / assets/js/serials.js)
 * — currently unused (live camera scanning removed for now, see the
 * project doc); left in place in case it's brought back. */
.scan-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(10,10,10,0.94);
  display: flex; align-items: center; justify-content: center; padding: var(--space-4);
}
.scan-overlay-inner { width: 100%; max-width: 480px; }
.scan-overlay-header {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 10px; color: #fff; font-weight: 700; font-size: 14px;
}
#scanReader { width: 100%; border-radius: var(--radius-md); overflow: hidden; background: #000; }

.demo-otp-banner {
  background: #fffbe6; border: 1px dashed #d6b13a; color: #6b5300;
  padding: 10px 14px; border-radius: var(--radius-md); font-size: 12px; margin-bottom: var(--space-4);
  line-height: 1.5;
}
.demo-otp-banner strong { font-size: 15px; letter-spacing: 2px; }

/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-4); border-radius: var(--radius-md); background: var(--color-surface-2);
  box-shadow: var(--shadow-sm);
}
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
.card-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 18px; line-height: 1.2; }
.card-body { margin: 0; font-size: 13px; opacity: 0.8; }
.card-meta { display: flex; align-items: center; gap: 6px; font-size: 11px; color: rgba(32,30,29,0.5); }

/* — tags — */
.tag { display: inline-flex; align-items: center; font-size: 11px; letter-spacing: 0.02em; padding: 4px 10px; border-radius: 999px; }
.tag-accent { background: var(--color-accent-100); color: var(--color-accent-800); }

/* — segmented control — */
.seg { display: inline-flex; overflow: hidden; border: 1px solid var(--color-divider); border-radius: var(--radius-md); }
.seg-opt { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; font-size: 13px; cursor: pointer; background: var(--color-surface-2); }
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt.active { background: var(--color-accent); color: #fff; }
.seg-opt input { display: none; }

/* — wizard shell — */
.wizard-shell {
  background: var(--color-surface-2); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); overflow: hidden;
  display: flex; flex-direction: column; min-height: 560px;
}
.wizard-header { padding: var(--space-4) var(--space-6); border-bottom: 2px solid var(--color-divider); }
.wizard-header .brand-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.wizard-header .brand-row img { height: 20px; }
.wizard-header .step-title { font-family: var(--font-heading); font-weight: 800; font-size: 18px; }
.wizard-header .step-sub { font-size: 11px; opacity: 0.6; margin-top: 2px; }
.wizard-header .step-sub .step-ref { opacity: 0.85; font-weight: 600; }
/* Progress bar segments are clickable tabs (added 2026-09-20, enlarged to
   show each step's name the same day after feedback that the thin bar
   gave no clue which step was which without hovering) — each one jumps
   straight to that step, same as clicking a breadcrumb; see render()'s
   wizard-progress markup and its data-goto-step wiring. Horizontally
   scrollable rather than shrinking 11 labels to illegibility on a narrow
   phone screen — the current step is kept in view by adjusting this
   strip's own scrollLeft on render (see render()'s comment — deliberately
   NOT scrollIntoView(), which used to yank the whole page back up to here
   on every BOM-step edit). Number badge (.seg-num) removed 2026-09-20 per
   feedback — label text only now. */
.wizard-progress {
  display: flex; gap: 4px; margin-top: 10px; overflow-x: auto; padding-bottom: 2px;
  -webkit-overflow-scrolling: touch; scrollbar-width: thin;
}
.wizard-progress .seg-tab {
  flex: 0 0 auto; min-width: 62px; max-width: 92px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 3px; background: var(--color-neutral-100); border: none;
  border-radius: 8px; padding: 7px 6px; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background 0.15s ease;
}
.wizard-progress .seg-tab .seg-label {
  font-size: 10.5px; font-weight: 600; line-height: 1.2; text-align: center;
  opacity: 0.65; word-break: break-word;
}
.wizard-progress .seg-tab.done .seg-label { opacity: 0.85; }
.wizard-progress .seg-tab.current { background: var(--color-accent-100); }
.wizard-progress .seg-tab.current .seg-label { opacity: 1; color: var(--color-accent-800); }
.wizard-progress .seg-tab:hover { background: var(--color-accent-100); }
.wizard-progress .seg-tab:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
/* 4-stage wizard (2026-09-25) — Customer Data / Design Input / BOM Review /
   Output. Only 4 tabs now, so they share the full width instead of scrolling. */
.wizard-progress .seg-tab.stage-tab { flex: 1 1 0; max-width: none; min-width: 0; padding: 9px 6px; }
.wizard-progress .seg-tab.stage-tab .seg-label { font-size: 12px; }
/* Collapsible section cards inside a stage */
details.stage-section {
  border: 1px solid var(--color-divider); border-radius: 10px; background: var(--color-surface-2, #fff);
}
details.stage-section > summary.stage-section-head {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 10px 14px; font-weight: 700; font-size: 14px; user-select: none;
}
details.stage-section > summary.stage-section-head::-webkit-details-marker { display: none; }
details.stage-section > summary.stage-section-head::before {
  content: '\25B8'; font-size: 12px; opacity: 0.6; transition: transform 0.15s ease; margin-right: 2px;
}
details.stage-section[open] > summary.stage-section-head::before { transform: rotate(90deg); }
.stage-section-title { flex: 1; }
.stage-badge { font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.stage-badge.ok { background: #e6f4ea; color: #1e6b34; }
.stage-badge.todo { background: #fdecea; color: #a4281c; }
details.stage-section > .stage-section-body {
  padding: 4px 14px 14px; display: flex; flex-direction: column; gap: var(--space-4);
  border-top: 1px solid var(--color-divider);
}
/* Silent-autosave indicator (added 2026-09-20) — see persistProposal()'s
   own comment for why this is updated by writing straight into this one
   element's textContent rather than a full render(). Empty/hidden until
   the first autosave actually fires. */
.autosave-status { font-size: 10px; opacity: 0.5; margin-top: 4px; text-align: right; min-height: 12px; }
.wizard-body { flex: 1; overflow: auto; padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-4); }
.wizard-footer { flex: none; padding: var(--space-4) var(--space-6); border-top: 2px solid var(--color-divider); display: flex; gap: 10px; }
.wizard-footer .btn-back { flex: 1; }
.wizard-footer .btn-next { flex: 2; }

.upload-drop {
  border: 2px dashed var(--color-divider); border-radius: var(--radius-md);
  padding: 44px 16px; display: flex; flex-direction: column; align-items: center; gap: 10px;
  cursor: pointer; text-align: center;
}
.upload-drop:hover { border-color: var(--color-accent); background: var(--color-accent-100); }

.entry-card, .panel-card { padding: 14px; gap: 10px; }
.entry-row, .kv-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.kv-row + .kv-row { margin-top: 6px; }
.entry-row .input { width: 130px; text-align: right; }

/* BOM step (added 2026-09-20) — same stacked card on mobile as every other
   step (nothing changes below this breakpoint), but on a wide-enough
   screen (this step's .page-full toggle already widens the page shell —
   see render() in calculator.js) each line's fields lay out as a denser,
   table-like row instead of one field per line. Purely a layout change:
   every input/select/button keeps the exact same id/data-attribute and
   event wiring, just arranged differently. .bom-field-wide covers a
   paired sub-row (Make+Type, Capacity+Phase, Unit+Qty, Cost+GST) or the
   Saved product field, both of which need more than one grid column's
   worth of room; .bom-field-full covers a hint line, the rate/amount
   summary, or the Save/Remove button row, none of which make sense
   squeezed into a single column next to another field. */
@media (min-width: 860px) {
  .bom-line-card {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    align-items: start;
  }
  .bom-line-card > .field { margin: 0; min-width: 0; }
  .bom-line-card > .bom-field-wide { grid-column: span 2; min-width: 0; }
  .bom-line-card > .bom-field-full { grid-column: 1 / -1; }
}

.bignum { font-family: var(--font-heading); font-weight: 800; font-size: 36px; color: var(--color-accent); }

.chart-row { display: flex; align-items: flex-end; gap: 10px; height: 140px; padding: 0 4px; }
.chart-bar-group { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; height: 100%; justify-content: flex-end; }
.chart-bars { display: flex; align-items: flex-end; gap: 2px; height: 100%; }
.chart-bars .bar { width: 10px; }
.chart-bars .bar-before { background: var(--color-neutral-400); }
.chart-bars .bar-after { background: var(--color-accent); }
.chart-legend { display: flex; gap: 16px; font-size: 11px; opacity: 0.7; }
.chart-legend .swatch { width: 8px; height: 8px; display: inline-block; margin-right: 4px; }

/* Only used inside #print-report (the printed proposal) — colors here
   follow the report's navy/amber palette rather than the live wizard's
   red-orange theme. */
.table { width: 100%; border-collapse: collapse; font-size: 13px; font-family: var(--rpt-font-body, inherit); }
.table th { text-align: left; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--rpt-muted, rgba(32,30,29,0.6)); padding: 8px; border-bottom: 2px solid var(--rpt-line, var(--color-divider)); }
.table td { padding: 8px; border-bottom: 1px solid var(--rpt-line, var(--color-divider)); }

/* Editable Bill history table (Step 2) — used to be stacked cards with
   page-size pagination ("takes multiple pages"); now compact table rows
   instead, all entries visible at once with no pagination. table-layout:
   fixed with explicit % column widths, since auto layout stretches every
   <input> to its browser default ~170px width and overflows a 3-column
   table well past 720px. (BOM lines, Step 5, were briefly tried as a
   table too but the user asked for the card layout back — see stepBOM().) */
.entry-table { table-layout: fixed; }
.entry-table th:nth-child(1), .entry-table td:nth-child(1) { width: 36%; }
.entry-table th:nth-child(2), .entry-table td:nth-child(2) { width: 25%; }
.entry-table th:nth-child(3), .entry-table td:nth-child(3) { width: 25%; }
.entry-table th:nth-child(4), .entry-table td:nth-child(4) { width: 14%; }
.entry-table td, .entry-table th { padding: 6px; vertical-align: middle; }
.entry-table input.input { min-height: 36px; padding: 6px 8px; font-size: 13px; width: 100%; min-width: 0; }

/* — dashboard — */
.dash-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-6); flex-wrap: wrap; gap: 10px; }
.calc-list { display: flex; flex-direction: column; gap: 10px; }
.calc-item { display: flex; justify-content: space-between; align-items: center; padding: 14px 16px; }
.calc-item .meta { font-size: 12px; opacity: 0.6; margin-top: 2px; }
.calc-item .actions { display: flex; gap: 8px; }
.empty-state { text-align: center; padding: 60px 20px; opacity: 0.6; }
/* Dashboard table (replaces the old stacked-card list — see dashboard.php).
   Wrapped in the shared white .card-like surface via .card-2/etc. isn't
   used here; a plain bordered/striped table reads better at this width. */
.dash-table { background: var(--color-surface-2); border-radius: var(--radius-md); overflow: hidden; box-shadow: var(--shadow-sm); }
.dash-table th { background: var(--color-neutral-100); }
.dash-table tbody tr:hover { background: var(--color-neutral-100); }
.dash-proposal-no { font-family: var(--rpt-font-mono, 'JetBrains Mono', monospace); font-size: 12px; opacity: 0.75; white-space: nowrap; }
.dash-status-select { background: var(--color-surface-2); font-family: inherit; cursor: pointer; }
/* Row "⋮" actions menu (added 2026-09-07) — replaces the row's old row of
   separate Open/Open (last stage)/Installation details/Clone/Clone BOM/
   Delete buttons with one kebab button per row plus a single shared
   dropdown (see #rowActionsMenu, `position:fixed` and repositioned by JS
   next to whichever kebab was clicked — see dashboard.php). */
.row-menu-btn { font-size: 18px; line-height: 1; font-weight: 800; padding: 6px 12px; letter-spacing: 1px; }
.row-actions-menu {
  position: fixed; z-index: 60; min-width: 210px;
  background: var(--color-surface-2); border: 1px solid var(--color-divider);
  border-radius: var(--radius-md); box-shadow: var(--shadow-md); padding: 6px;
}
.row-actions-menu a, .row-actions-menu button {
  display: block; width: 100%; text-align: left; padding: 8px 10px; font-size: 13px;
  border-radius: var(--radius-sm); background: none; border: none;
  color: var(--color-text); text-decoration: none; cursor: pointer;
  font-family: inherit; line-height: 1.3;
}
.row-actions-menu a:hover, .row-actions-menu button:hover:not(:disabled) { background: var(--color-neutral-100); }
.row-actions-menu .row-actions-menu-danger { color: var(--color-accent); }
/* "Push to Zoho Books" result overlay (added 2026-09-13) — a plain centered
   card over a dimmed backdrop, same border-radius/shadow tokens as every
   other .card on this page, just floated above everything else. Closed by
   its own Close button, clicking the dimmed backdrop, or Escape. */
.zoho-push-overlay {
  position: fixed; inset: 0; z-index: 300; background: rgba(0, 0, 0, 0.45);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.zoho-push-modal {
  max-width: 560px; width: 100%; max-height: 82vh; overflow-y: auto;
  box-shadow: var(--shadow-md);
}
/* Panel/Inverter Make & Type quick-pick popup (added 2026-09-15, calculator.js
   equipPickerOverlayHtml()) — same centered-card-over-dimmed-backdrop pattern
   as the Zoho push overlay just above, kept as its own class rather than
   reusing .zoho-push-overlay/.zoho-push-modal so the two features (a
   dashboard-only result popup vs. a calculator-wizard question popup) stay
   independent if either is changed later. */
.equip-picker-overlay {
  position: fixed; inset: 0; z-index: 300; background: rgba(0, 0, 0, 0.45);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.equip-picker-modal {
  max-width: 420px; width: 100%; max-height: 82vh; overflow-y: auto;
  box-shadow: var(--shadow-md);
}
/* Step-intro "welcome to this step" popup (added 2026-09-15,
   calculator.js stepIntroOverlayHtml()) — same centered-card-over-dimmed-
   backdrop mechanism as .equip-picker-overlay just above, but deliberately
   bigger and bolder: this is a big plain-language question with a single
   large OK button, meant to read clearly at a glance for someone with
   little project knowledge, not a compact form control. Kept as its own
   class rather than reused, so this and the equip-picker popup can each
   be restyled independently later. */
.step-intro-overlay {
  position: fixed; inset: 0; z-index: 310; background: rgba(0, 0, 0, 0.55);
  display: flex; align-items: center; justify-content: center; padding: 20px;
}
.step-intro-modal {
  max-width: 480px; width: 100%; max-height: 86vh; overflow-y: auto;
  box-shadow: var(--shadow-md); text-align: center; gap: var(--space-3);
  padding: var(--space-6) var(--space-4);
}
.step-intro-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 26px; line-height: 1.25; }
.step-intro-body { margin: 0; font-size: 15px; line-height: 1.5; opacity: 0.85; }
.step-intro-ok { font-size: 16px; font-weight: 700; padding: 14px 20px; margin-top: var(--space-2); }
/* Follow-up date/remarks quick-edit fields, moved into the top of this
   menu 2026-09-07 (previously the table's own Follow-up column) — a plain
   block of label+input pairs, not menu-item rows, so they don't inherit
   the hover/click-to-navigate styling above. */
.row-actions-menu-followup { padding: 4px 6px 6px; }
.row-actions-menu-followup label { display: block; font-size: 10.5px; font-weight: 700; color: var(--color-neutral-600); text-transform: uppercase; letter-spacing: 0.03em; margin: 6px 0 3px; }
.row-actions-menu-followup label:first-child { margin-top: 0; }
.row-actions-menu-followup input { display: block; width: 100%; min-height: 30px; padding: 4px 8px; font-size: 12.5px; box-sizing: border-box; }
.row-actions-menu-divider { height: 1px; background: var(--color-divider); margin: 6px 2px; }

/* — print report — */
/* Report visual language (2026-08-21): adopts the "solar-savings-proposal"
   mockup's palette/typography — navy cover, amber/green accents, Bricolage
   Grotesque display + Public Sans body + JetBrains Mono for figures —
   scoped entirely to #print-report so the live wizard UI (still Archivo /
   red-orange accent) is untouched. Google Fonts are loaded in calculator.php
   the same way pdf.js/tesseract.js already are (external CDN, already an
   established pattern in this app); every family falls back to the
   self-hosted Archivo or a system font stack, so a blocked/offline font
   fetch degrades the look but never breaks layout or makes the report
   unreadable. The charges-table column structure/widths and the A4/A5
   page-break logic below are untouched from the tested implementation —
   only colors/fonts change on those. */
#print-report { display: none; }
#print-report {
  --rpt-navy: #16324F;
  --rpt-navy-deep: #0e2338;
  --rpt-amber: #E8A33D;
  --rpt-amber-pale: #F6DDB0;
  --rpt-green: #2F7D5D;
  --rpt-green-pale: #CFE8DC;
  --rpt-paper: #F3F6F8;
  --rpt-line: #D7E0E7;
  --rpt-muted: #5A7186;
  --rpt-chart-yellow: #F2C230;
  --rpt-chart-red: #D64545;
  --rpt-highlight-bg: #FCE94F;
  --rpt-highlight-text: #C21807;
  --rpt-font-display: 'Bricolage Grotesque', var(--font-heading), system-ui, sans-serif;
  --rpt-font-body: 'Public Sans', var(--font-body), system-ui, sans-serif;
  --rpt-font-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace;
  font-family: var(--rpt-font-body);
  color: var(--rpt-navy);
  /* Crisper glyph rendering — the previous render looked soft/blurred in the
     exported PDF because small print-table text had no explicit smoothing
     hints, so some renderers fell back to a fuzzier antialiasing pass. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Cover — a clean light card (was a dark navy banner, then a dark red
   banner; both read as "not good looking" against print) with a slim amber
   accent border and a soft paper-to-white gradient, matching the white
   .rpt-card sections below it instead of fighting them with a heavy dark
   block. Customer name/address/consumer no./sanctioned load read as the
   proposal's headline in dark navy text — easy to read, no contrast fights.
   All cover text colors below are scoped to .rpt-cover only. */
.rpt-cover {
  background: linear-gradient(135deg, #ffffff, var(--rpt-paper));
  color: var(--rpt-navy); border: 1px solid var(--rpt-line); border-left: 5px solid var(--rpt-amber);
  border-radius: 14px; padding: 12px 18px; margin-bottom: 7px;
  position: relative; overflow: hidden;
}
.rpt-cover::after {
  content: ""; position: absolute; right: -50px; top: -50px; width: 180px; height: 180px;
  border-radius: 50%; background: radial-gradient(circle, rgba(232,163,61,.14), transparent 70%);
}
.rpt-cover-top { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; position: relative; z-index: 1; flex-wrap: wrap; }
.rpt-eyebrow { font-size: 13px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--rpt-amber); margin-bottom: 6px; font-weight: 700; }
/* Group 1 — customer info: name, address, consumer no. / sanctioned load.
   Bumped back up (2026-09-03, "aligns page 1 neat & clean, bigger fonts,
   most customers are 50+") from the earlier shrunk-for-long-names sizes —
   the name wraps onto a second line naturally (flex-wrap + min-width:0)
   rather than overflowing, so it stays readable even for long names. */
.rpt-cover-group1 { flex: 1; min-width: 0; }
/* overflow-wrap:break-word is a safety net for a long unbroken surname
   (e.g. "Rathinasabhapathy") on a narrow column — without it, a single
   word wider than the shrunk flex column overflows past its box instead
   of wrapping, which is exactly what happened on the mobile format's
   narrow cover (real bug, caught on that render). */
.rpt-cover h1.rpt-cover-name { font-family: var(--rpt-font-display); font-size: 17px; font-weight: 700; margin: 0 0 4px; line-height: 1.22; color: var(--rpt-navy); overflow-wrap: break-word; }
.rpt-cover .rpt-sub { color: var(--rpt-muted); font-size: 12.5px; overflow-wrap: break-word; }
.rpt-cover-logo { height: 26px; opacity: 0.95; }
/* Group 2 — logo with the report date and contact numbers directly beneath it. */
.rpt-cover-group2 { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: none; position: relative; z-index: 1; }
.rpt-cover-logo-box { background: #fff; border: 1px solid var(--rpt-line); border-radius: 8px; padding: 7px 12px; display: inline-flex; align-items: center; }
.rpt-cover-date-contact { text-align: right; }
.rpt-cover-date-contact div { margin-top: 3px; }
.rpt-cover-date-contact span { display: block; font-size: 10.5px; color: var(--rpt-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.rpt-cover-date-contact strong { font-family: var(--rpt-font-mono); font-size: 13.5px; font-weight: 600; white-space: nowrap; color: var(--rpt-navy); }
.rpt-meta-row { display: flex; gap: 18px; margin-top: 6px; flex-wrap: wrap; position: relative; z-index: 1; }
.rpt-meta-row div span { display: block; font-size: 10px; color: var(--rpt-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.rpt-meta-row div strong { font-family: var(--rpt-font-mono); font-size: 13.5px; font-weight: 600; color: var(--rpt-navy); }

/* Section card — replaces the old bare section-label + table sequence with
   a bordered, rounded card per section (Bill before/after, generation
   chart, consumer details, bill history, snapshot, proposed system,
   charges, long-term savings), matching the mockup's .card. */
.rpt-card { background: #fff; border: 1px solid var(--rpt-line); border-radius: 12px; padding: 7px 14px; margin-bottom: 5px; break-inside: avoid; page-break-inside: avoid; }
.rpt-card h2 { font-family: var(--rpt-font-display); font-size: 14px; margin: 0 0 2px; color: var(--rpt-navy); font-weight: 700; letter-spacing: 0.01em; }
.rpt-card .rpt-desc { font-size: 10.5px; color: var(--rpt-muted); margin-bottom: 4px; }

/* Page-1-only cards (before/after, long-term savings, coverage) — bigger
   heading/description type than the shared .rpt-card default above, per
   the 2026-09-03 request to make page 1 read "neat, clean, impressive"
   with bigger fonts for customers 50+. Scoped to .rpt-card-p1 specifically
   so page 2 onward (Bill History, Bill at a Glance, Proposed System,
   charges table, Why go solar) keeps the untouched default sizing. */
.rpt-card-p1 { padding: 10px 16px 12px; margin-bottom: 9px; }
.rpt-card-p1 h2 { font-size: 17px; margin-bottom: 3px; }
.rpt-card-p1 .rpt-desc { font-size: 12px; margin-bottom: 7px; }

/* Forces the card carrying this class to start on a fresh printed page —
   used on "Your Bill History" so page 1 (cover + before/after + savings +
   coverage) stays self-contained and page 2 always starts cleanly with
   Bill History, regardless of how tall the enlarged page-1 cards above
   grow (even if that pushes the report to a 3rd page overall, which the
   user explicitly accepted). break-before covers modern engines; the
   page-break-before duplicate is the older/wider-supported alias used
   elsewhere in this file for the same reason. */
.rpt-page-break { break-before: page; page-break-before: always; }

/* Bill before/after — power-flow diagram (electricity -> house, then
   electricity+solar -> house), styled after the team's SOLAR VECTOR
   reference graphic but condensed to fit the report's tight page budget:
   an icon row + dashed "Powering" connector, with the You Consume/Spend/
   Pay/Save figures as compact stat chips beside it rather than a full
   separate poster layout. */
/* Row height/fonts scaled ~50% up from the original pass per user
   feedback that this card should read bigger and bolder overall. */
.rpt-flow-row { display: flex; align-items: center; gap: 14px; padding: 8px 0; }
.rpt-flow-row.after { border-top: 1px solid var(--rpt-line); margin-top: 5px; padding-top: 11px; }
/* Wraps the label pill + icon diagram as one unit, separate from the
   vec-stats figures beside it — on A4 this is a no-op (same side-by-side
   layout as before, just with an extra wrapper level); on A5 the row
   below switches to a column layout and this wrapper becomes its own
   top line, so it needs its own internal flex row + gap. */
.rpt-flow-head { display: flex; align-items: center; gap: 14px; flex: 0 0 auto; }
.rpt-flow-label { flex: 0 0 auto; writing-mode: horizontal-tb; font-size: 12.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; padding: 5px 11px; border-radius: 12px; white-space: nowrap; }
.rpt-flow-label.now { background: #FCEFE0; color: #B5651D; }
.rpt-flow-label.with-solar { background: var(--rpt-green-pale); color: var(--rpt-green); }
.rpt-flow-diagram { flex: 0 0 auto; display: flex; align-items: center; width: 260px; }
.rpt-flow-icons { display: flex; align-items: center; justify-content: center; line-height: 0; }
.rpt-flow-icons.stack { flex-direction: column; gap: 2px; }
.rpt-flow-arrow { flex: 1; position: relative; height: 0; border-top: 2px dashed var(--rpt-amber); margin: 0 8px; }
.rpt-flow-arrow span { position: absolute; top: -10px; left: 50%; transform: translateX(-50%); background: #fff; padding: 0 5px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--rpt-amber); white-space: nowrap; }
.rpt-flow-row.after .rpt-flow-arrow { border-top-color: var(--rpt-green); }
.rpt-flow-row.after .rpt-flow-arrow span { color: var(--rpt-green); }

/* Stat boxes beside each power-flow row — bordered box, colored kicker
   label, big bold black figure, YEARLY caption, and a colored up/down
   arrow badge, matching the team's SOLAR VECTOR reference graphic (orange
   up-arrow boxes for "spending now", green down-arrow boxes for "with
   solar"). Only the figures themselves change per proposal — the box
   style, colors and arrows stay fixed. */
.rpt-vec-stats { flex: 1; display: flex; gap: 9px; }
.rpt-vec-stat { flex: 1; display: flex; align-items: center; justify-content: space-between; gap: 10px; background: #fff; border: 1.8px solid; border-radius: 10px; padding: 13px 14px; min-width: 0; }
.rpt-vec-body { min-width: 0; }
.rpt-vec-label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 3px; }
.rpt-vec-value { font-family: var(--rpt-font-mono); font-size: 23px; font-weight: 800; color: #14181c; line-height: 1.15; white-space: nowrap; }
.rpt-vec-value .unit { font-size: 15px; font-weight: 700; }
.rpt-vec-cadence { font-size: 11px; color: var(--rpt-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.rpt-vec-arrow { flex: none; line-height: 0; }
/* A5's narrower content width can't fit a 3-box "with solar" row at the
   full A4-scale sizing above (it overflowed off the card in testing) —
   step everything down one notch specifically for A5 (icon sizes are
   handled in JS via the isA5 branches in buildPrintReport()).
   2026-09-03: page 1 (cover + these 3 cards) was leaving a large blank
   gap at the bottom of A5's page 1 — Bill History's forced page-2 break
   means that space can't be reclaimed by flowing more content up, so
   these three cards (NOT the cover, which the user asked to leave alone)
   were sized up further — more padding/gaps/margins and bigger fonts —
   to use that vertical room properly instead of leaving it empty, while
   staying on the label+diagram+stats single-row layout (a column-stacked
   layout was tried and tested, but it pushed the "with solar" row's
   stacked icon pair tall enough to spill the whole report onto a 4th A5
   page — reverted). The 3-box "with solar" row's box padding/font is
   kept one notch below the 2-box "now" row's — pushing it to match
   caused the 3rd box's value text to spill past its own border, a real
   bug caught on that render (the row itself had room; the fixed-size text
   inside a narrower box didn't). */
#print-report.pdf-a5 .rpt-flow-row { gap: 13px; padding: 11px 0; }
#print-report.pdf-a5 .rpt-flow-row.after { padding-top: 13px; }
#print-report.pdf-a5 .rpt-flow-label { font-size: 11px; padding: 6px 11px; }
/* Trimmed from 195px — the stacked pole+solar pair in the "with solar"
   row (and the side-by-side pole+house in the "now" row) don't need the
   full width the earlier pass gave them; the freed space goes to the
   stat boxes beside it, which is the tighter constraint (see below). */
#print-report.pdf-a5 .rpt-flow-diagram { width: 160px; }
#print-report.pdf-a5 .rpt-flow-arrow { margin: 0 6px; }
#print-report.pdf-a5 .rpt-flow-arrow span { font-size: 9px; }
#print-report.pdf-a5 .rpt-vec-stats { gap: 8px; }
#print-report.pdf-a5 .rpt-vec-stat { padding: 12px 10px; gap: 7px; border-width: 1.6px; }
#print-report.pdf-a5 .rpt-vec-label { font-size: 10.5px; }
#print-report.pdf-a5 .rpt-vec-value { font-size: 19px; }
/* "kWh" dropped to its own line below the number (rather than staying
   inline after it) — "4,936 kWh" together is wider than the 3-box "with
   solar" row's box, and since the value has white-space:nowrap the
   overflow was invisibly spilling past the card's (and the page's)
   right edge instead of wrapping — a real clipping bug caught on this
   render. The ₹ figures have no unit suffix so are unaffected and stay
   on one line. */
#print-report.pdf-a5 .rpt-vec-value .unit { display: block; font-size: 12.5px; margin-top: 1px; }
#print-report.pdf-a5 .rpt-vec-cadence { font-size: 9px; }
/* Same overflow problem hits the PM Surya Ghar / 3-5-10-Year Savings tiles
   on A5's narrower auto-fit grid columns — Indian-formatted ₹ figures have
   no space to wrap at, so an oversized font just runs past the box border
   instead of breaking. Stepped up (2026-09-03) from the earlier A5 sizing
   to help fill page 1's leftover vertical space, still short of A4's size
   to stay safely inside each tile's border. */
#print-report.pdf-a5 .report-stat-tile { padding: 16px 9px; }
#print-report.pdf-a5 .report-stat-tile-kicker { font-size: 11px; }
#print-report.pdf-a5 .report-stat-tile-value { font-size: 23px; }
/* Page-1 card heading/description and cover text — A5's narrower content
   width can't carry the full A4-scale bump above without wrapping headings
   awkwardly, so step down one notch (still bigger than the pre-2026-09-03
   sizes on every page-2+ card, which are untouched). Padding/margin
   stepped up further on 2026-09-03 (see comment above) to fill A5 page
   1's blank space. */
#print-report.pdf-a5 .rpt-card-p1 { padding: 19px 20px 21px; margin-bottom: 20px; }
#print-report.pdf-a5 .rpt-card-p1 h2 { font-size: 17px; }
#print-report.pdf-a5 .rpt-card-p1 .rpt-desc { font-size: 11.5px; margin-bottom: 11px; }
#print-report.pdf-a5 .rpt-coverage-row { margin-top: 12px; }
#print-report.pdf-a5 .rpt-coverage-bar { height: 30px; }
#print-report.pdf-a5 .rpt-coverage-pct { font-size: 20px; }
#print-report.pdf-a5 .rpt-legend { margin-top: 12px; font-size: 11.5px; }
#print-report.pdf-a5 .rpt-eyebrow { font-size: 10px; }
#print-report.pdf-a5 .rpt-cover h1.rpt-cover-name { font-size: 13.5px; }
#print-report.pdf-a5 .rpt-cover .rpt-sub { font-size: 10px; }
#print-report.pdf-a5 .rpt-cover-date-contact span,
#print-report.pdf-a5 .rpt-meta-row div span { font-size: 8.5px; }
#print-report.pdf-a5 .rpt-cover-date-contact strong,
#print-report.pdf-a5 .rpt-meta-row div strong { font-size: 11px; }

/* "How much of your bill solar covers" — a single overall coverage bar
   (real self-consumed units ÷ real total consumption, summed across every
   billing entry) instead of a denser per-entry, multi-series bar chart —
   simplified per user feedback that the previous chart was hard to read
   at a glance. */
.rpt-coverage-row { display: flex; align-items: center; gap: 10px; margin-top: 4px; }
.rpt-coverage-bar { flex: 1; height: 20px; border-radius: 10px; background: var(--rpt-paper); overflow: hidden; }
.rpt-coverage-fill { height: 100%; border-radius: 10px; background: linear-gradient(90deg, var(--rpt-chart-yellow), var(--rpt-green)); }
.rpt-coverage-pct { flex: none; font-family: var(--rpt-font-mono); font-size: 15px; font-weight: 800; color: var(--rpt-navy); }
.rpt-legend { display: flex; gap: 14px; margin-top: 6px; font-size: 10.5px; color: var(--rpt-muted); flex-wrap: wrap; }
.rpt-legend .rpt-dot { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 5px; }

/* Payback timeline — a simple 0-to-25-year track (25 years = typical
   rooftop panel lifespan) shaded red before break-even, green after, with
   a marker at the actual break-even point. Only rendered when the team has
   entered a system cost on the Panel Config step (v.paybackYears != null
   in buildPrintReport()) — there's no assumed/default cost, so this whole
   block is simply omitted rather than showing a guessed number. */
.rpt-payback { margin: 4px 0 6px; }
.rpt-payback-track { position: relative; height: 8px; border-radius: 4px; }
.rpt-payback-marker { position: absolute; top: -2.5px; width: 3px; height: 13px; background: #1a1a1a; border-radius: 2px; transform: translateX(-50%); }
.rpt-payback-scale { position: relative; height: 11px; margin-top: 3px; font-size: 8.5px; color: var(--rpt-muted); }
.rpt-payback-start { position: absolute; left: 0; }
.rpt-payback-end { position: absolute; right: 0; }
.rpt-payback-mid { position: absolute; transform: translateX(-50%); font-weight: 700; color: var(--rpt-navy); white-space: nowrap; }

/* "Why go solar with Elenserve" closing pitch — a trust/credibility card
   plus a clear call-to-action, placed right before the footer so the
   report ends on a persuasive note rather than a bare numbers table. */
.rpt-cta { background: var(--rpt-green-pale); border-color: var(--rpt-green); }
.rpt-cta h2 { color: #16324F; }
.rpt-cta-list { margin: 0 0 8px; padding-left: 16px; font-size: 11px; color: #16324F; }
.rpt-cta-list li { margin-bottom: 3px; }
.rpt-cta-action { font-size: 12px; font-weight: 700; color: var(--rpt-green); }

/* "Commercial terms & conditions" card — user-entered payment terms, a
   fixed scope-of-customer bullet list, and a fixed 3-stage project
   timeline. Sits right after "Itemized quotation" in the DOM order (see
   buildPrintReport() in calculator.js). */
.rpt-terms-block { margin-bottom: 6px; break-inside: avoid; page-break-inside: avoid; }
.rpt-terms-block:last-child { margin-bottom: 0; }
.rpt-terms-label { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--rpt-muted); margin-bottom: 2px; }
.rpt-terms-payment { font-size: 11px; color: #16324F; white-space: pre-line; }
.rpt-terms-list { margin: 0; padding-left: 16px; font-size: 11px; color: var(--rpt-highlight-text, #C21807); }
.rpt-terms-list li { margin-bottom: 2px; }
.rpt-timeline { display: flex; gap: 8px; break-inside: avoid; page-break-inside: avoid; }
.rpt-timeline-step { flex: 1; background: var(--rpt-green-pale); border: 1px solid var(--rpt-line); border-radius: 8px; padding: 5px 8px; text-align: center; break-inside: avoid; page-break-inside: avoid; }
.rpt-timeline-step strong { display: block; font-size: 10px; color: var(--rpt-navy); }
.rpt-timeline-step span { display: block; font-size: 10.5px; font-weight: 700; color: var(--rpt-green); margin-top: 1px; }

.rpt-footer { text-align: left; font-size: 10.5px; color: var(--rpt-muted); border-top: 1px solid var(--rpt-line); padding-top: 6px; }
/* Savings disclaimer — sits just above the footer, on its own line, red
   and bold per the user's request. Deliberately NOT given a break-before
   or any break-inside rule of its own: it's one short line at the very
   end of the report (nothing prints after it but the footer), so it can
   never cause a card to spill or a page to split differently than
   before — it just adds a couple of extra print lines at the bottom. */
.rpt-savings-disclaimer { text-align: left; font-size: 10.5px; font-weight: 700; color: #C21807; margin-top: 8px; }
#print-report.pdf-mobile .rpt-savings-disclaimer { font-size: 14px; margin-top: 10px; }
/* Tighter row padding for the plain (non-charges) tables inside the report
   only — the panel-spec table, Bill History — scoped to #print-report so
   the wizard's own on-screen tables elsewhere in the app keep their normal,
   more touch-friendly padding. Explicitly excludes both charges-table
   variants: as an ID selector this would otherwise outrank their own
   (intentionally tighter/narrower) padding rules below and silently win —
   which is exactly what happened here 2026-08-22 — it re-widened the A4
   table's cell padding enough to wrap "₹5,953" mid-digit into "₹5,95"/"3",
   a table the user asked to leave untouched. Caught by re-screenshotting
   the A4 output after finishing the A5 work, not by the A5-focused testing
   that had been driving these edits. */
#print-report .table:not(.report-charges-table):not(.report-charges-table-a5) th,
#print-report .table:not(.report-charges-table):not(.report-charges-table-a5) td { padding: 6px 8px; }
@media print {
  /* `body` normally carries the app's neutral-gray backdrop (--color-neutral-200,
     visible around the white on-screen wizard card). Hiding body's *children*
     with visibility:hidden doesn't clear body's own background-color, and
     the print-color-adjust:exact rule below forces browsers to keep it —
     so without this override the exported PDF shows that gray filling the
     whole page behind/around the white report content. Found 2026-08-18 by
     rendering the report inside the real page shell (topbar + .page +
     #print-report) instead of an isolated snippet, which is what let it
     slip through the earlier A4/A5 testing. */
  body { background: #fff; }
  /* Scoped with :not(.print-plain) — this "hide everything, then show only
     the dedicated report overlay" mechanism is for calculator.php/
     serials.php's print-to-PDF flow (#print-report/#print-agreement/
     #print-tneb-letter, further down). layout-designer.php has no such
     overlay — it prints its own visible page directly — so it opts out via
     body.print-plain and instead just hides `.no-print`-flagged elements
     (see the Rooftop Layout Designer print block near the end of this
     file). Without this exclusion, EVERY page's `body *` (including
     layout-designer.php's, which has no #print-report to re-reveal) went
     to visibility:hidden, so its "Print / Save PDF" produced a blank page
     — found and fixed 2026-09-09. */
  body:not(.print-plain) * { visibility: hidden; }
  #print-report, #print-report * { visibility: visible; }
  #print-report { display: block; position: absolute; top: 0; left: 0; width: 100%; }
  /* The Vendor & Consumer Agreement (buildAgreementReport()) is a second,
     independent print target sharing this same window.print() pipeline —
     onPrintAgreement() adds body.printing-agreement right before printing
     and removes it again on 'afterprint', so exactly one of the two ever
     shows for a given print regardless of which one happened to be built
     into the DOM most recently. */
  body.printing-agreement #print-report { display: none !important; visibility: hidden !important; }
  body.printing-agreement #print-agreement, body.printing-agreement #print-agreement * { visibility: visible; }
  body.printing-agreement #print-agreement { display: block; position: absolute; top: 0; left: 0; width: 100%; }
  /* The TNEB Installation Letter (buildTnebLetterReport()) is a third,
     independent print target on this same window.print() pipeline —
     onPrintTnebLetter() adds body.printing-tneb-letter right before
     printing and removes it again on 'afterprint', same pattern as
     printing-agreement above; exactly one of the three ever shows for a
     given print regardless of which happen to be built into the DOM. */
  body.printing-tneb-letter #print-report, body.printing-tneb-letter #print-agreement { display: none !important; visibility: hidden !important; }
  body.printing-tneb-letter #print-tneb-letter, body.printing-tneb-letter #print-tneb-letter * { visibility: visible; }
  body.printing-tneb-letter #print-tneb-letter { display: block; position: absolute; top: 0; left: 0; width: 100%; }
  /* 2026-11-14: the letter printed as 2 pages (second one empty). The hidden wizard behind it (visibility:hidden
     still keeps its height) was taller than one A4 page on the Save & share step, so the browser added a blank
     page for it. For this print everything else on the page is taken out of the layout and the letter flows
     normally from the top - it is always exactly as long as the letter itself. */
  body.printing-tneb-letter > *:not(#print-tneb-letter) { display: none !important; }
  body.printing-tneb-letter #print-tneb-letter { position: static; }
  body.printing-tneb-letter .tnl-page { break-inside: avoid; page-break-inside: avoid; }
  /* The Simple Quotation (buildSimpleQuotationReport()) is a fourth,
     independent print target on this same window.print() pipeline —
     onPrintQuotation() adds body.printing-quotation right before printing
     and removes it again on 'afterprint', same pattern as
     printing-agreement/printing-tneb-letter above; exactly one of the four
     ever shows for a given print regardless of which happen to be built
     into the DOM. Added 2026-09-17. */
  body.printing-quotation #print-report, body.printing-quotation #print-agreement, body.printing-quotation #print-tneb-letter { display: none !important; visibility: hidden !important; }
  body.printing-quotation #print-quotation, body.printing-quotation #print-quotation * { visibility: visible; }
  body.printing-quotation #print-quotation { display: block; position: absolute; top: 0; left: 0; width: 100%; }
  /* The report's column widths/font sizes were measured against a portrait
     page's content width — printing landscape would overflow/squash the
     10-column charges table. Setting size here makes Chrome/Edge pre-select
     Portrait in the print dialog's orientation dropdown by default, instead
     of leaving it at whatever the browser last used. */
  /* Static fallback only — as of 2026-08-18 this is normally overridden by
     a <style id="pdfPageStyle"> tag that applyPdfPageSize() in
     calculator.js inserts right before window.print(), based on the
     A4/A5 choice made on the Save & share step. A later <style> in
     document order wins over this one for the same @page property, so the
     JS override always takes effect when present; this rule only matters
     if that injection somehow didn't run. Margin trimmed from 14mm to
     10mm so the reclaimed width lets the charges table run at a larger,
     phone-legible font size below without overflowing. */
  @page { size: A4 portrait; margin: 10mm; }
  /* Without this, some browsers silently drop background colors/shading on
     print (or require the user to manually enable "background graphics"),
     which would make the colored stat tiles below print as plain white. */
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* Estimated-charges table has 10 columns (incl. Carry Forward and
   Observation) — narrower font/padding and fixed per-column widths keep it
   inside the printable page width instead of overflowing or shrinking
   unpredictably. Font sizes were bumped from 8.5/10.5px to 10.5/12.5px
   (2026-08-18) — most customers open this "printed" proposal as a saved PDF
   on a phone rather than on paper, and a page sized for A4 shrinks a lot to
   fit a phone screen, so text needs to start larger to stay readable
   without pinching to zoom. The @page margin above was trimmed to 10mm to
   reclaim the width this costs, keeping all 10 columns on one page. */
.report-charges-table { table-layout: fixed; width: 100%; font-size: 12.5px; }
.report-charges-table th, .report-charges-table td { padding: 6px 5px; }
.report-charges-table th { letter-spacing: normal; white-space: normal; word-break: keep-all; font-size: 10.5px; line-height: 1.35; color: var(--rpt-navy); background: var(--rpt-paper); }
.report-charges-table td { overflow-wrap: break-word; line-height: 1.35; }
.report-charges-table th:nth-child(1), .report-charges-table td:nth-child(1) { width: 13%; }
.report-charges-table th:nth-child(2), .report-charges-table td:nth-child(2) { width: 8%; }
.report-charges-table th:nth-child(3), .report-charges-table td:nth-child(3) { width: 8%; }
.report-charges-table th:nth-child(4), .report-charges-table td:nth-child(4) { width: 7%; }
.report-charges-table th:nth-child(5), .report-charges-table td:nth-child(5) { width: 9%; }
.report-charges-table th:nth-child(6), .report-charges-table td:nth-child(6) { width: 12%; }
.report-charges-table th:nth-child(7), .report-charges-table td:nth-child(7) { width: 9%; }
.report-charges-table th:nth-child(8), .report-charges-table td:nth-child(8) { width: 10%; }
.report-charges-table th:nth-child(9), .report-charges-table td:nth-child(9) { width: 8%; }
.report-charges-table th:nth-child(10), .report-charges-table td:nth-child(10) { width: 16%; }

/* Stat-tile rows (EB spending/after-solar/savings/subsidy, and the 3/5/10
   year projections) — auto-fit grid instead of a fixed 4-across flex row,
   so tiles wrap to fewer per row on A5's narrower content width instead of
   squeezing four tight tiles into ~130mm. On A4's wider content area this
   still comfortably fits 4 (or 3) per row, same as the old layout. */
/* minmax lowered from 150px to 110px on 2026-08-18: at 150px, A5's ~124mm
   content width only fit 3 of the 4 before/after/savings/subsidy tiles per
   row, orphaning the 4th onto its own mostly-empty extra page — which also
   pushed the user's requested "Long-term savings starts on page 3" forced
   break to page 4. At 110px all 4 fit in one row on A5 too; on A4's wider
   content area the 4 tiles still simply stretch to fill the row exactly
   as before (auto-fit + 1fr fills available width regardless of the
   minimum), so this is a no-op visually for A4. */
.report-stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 10px; }
/* Without this, a tile that lands right at a print page boundary can split
   — kicker label on one page, ₹ value on the next (seen in A5 testing). */
/* Solid filled backgrounds (navy/green tiles) read as too heavy per
   feedback — swapped for a white card with a thick 2px colored outline,
   same "bordered box, colored label, big dark figure" language as the
   .rpt-vec-stat boxes above, so the whole report reads as one system. */
.report-stat-tile { background: #fff; border: 2px solid; border-radius: 8px; padding: 9px 8px; text-align: center; break-inside: avoid; page-break-inside: avoid; font-family: var(--rpt-font-body); }
.report-stat-tile-kicker { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 4px; }
.report-stat-tile-value { font-family: var(--rpt-font-mono); font-size: 27px; font-weight: 800; color: #14181c; line-height: 1.15; }
/* Optional small caveat line inside a stat tile (added 2026-09-22 for the
   Tamil Nadu State Subsidy tile's remark — moved here from a separate line
   below the whole stat-tile row, per request, so the caveat reads as part
   of that specific figure rather than a generic footnote under all of
   them). Unused/absent for every other tile. */
.report-stat-tile-note { font-size: 8.5px; color: var(--rpt-muted); margin-top: 3px; line-height: 1.25; }

/* The A5-only forced page breaks that used to live here (before
   "Proposed solar system" and "Long-term savings") were removed
   2026-08-22: fitting the new cover content plus the design changes below
   into 3 A5 pages needed every card free to pack tightly wherever it
   actually fits (each still protected from splitting mid-card by
   .rpt-card's page-break-inside:avoid above) — the old fixed 2-cards-then-
   break/1-card-then-break split repeatedly orphaned a card onto its own
   near-empty 4th page once the cover grew. Natural flow packs to 3 pages
   for both the sample dataset and a real customer's data (verified via
   headless render — see render_test.js / render_test_real.js). */

/* A5 (mobile-friendly) charges table — 7 columns (Date, Units, Net, Carry
   Fwd, Solar, After Solar, Savings) instead of the A4 table's 10. Dropping
   "Bill Charges"/"Network" as separate columns (they sum to "After Solar",
   which stays) and folding "Observation" into a subtext line under the
   date (.rcc-a5-obs) rather than its own column buys back enough width to
   run at nearly the same font size as the A4 table despite A5 being ~30%
   narrower. Replaced an earlier per-entry-card layout on 2026-08-18 — the
   user tried it and preferred a table for scanning all entries at a glance.
   table-layout:fixed here for the same overflow-safety reason as the A4
   table above. */
.report-charges-table-a5 { table-layout: fixed; width: 100%; font-size: 12px; }
.report-charges-table-a5 th, .report-charges-table-a5 td { padding: 4px 4px; }
.report-charges-table-a5 th { letter-spacing: normal; white-space: normal; word-break: keep-all; font-size: 10px; line-height: 1.25; color: var(--rpt-navy); background: var(--rpt-paper); }
/* Only the Date column's cell (and its wrapping observation subtext) should
   ever wrap — every other column holds a short number or ₹ amount, and
   letting those wrap via overflow-wrap:break-word was splitting values
   mid-digit (e.g. "₹1,29" / "5") once the columns got narrower. nowrap
   keeps every number on one line; widths below were rebalanced (Carry Fwd
   only ever holds 1-2 digits, so it gives width back to the ₹ columns). */
.report-charges-table-a5 td { line-height: 1.25; white-space: nowrap; }
.report-charges-table-a5 td:nth-child(1) { white-space: normal; overflow-wrap: break-word; }
.report-charges-table-a5 th:nth-child(1), .report-charges-table-a5 td:nth-child(1) { width: 22%; }
.report-charges-table-a5 th:nth-child(2), .report-charges-table-a5 td:nth-child(2) { width: 11%; }
.report-charges-table-a5 th:nth-child(3), .report-charges-table-a5 td:nth-child(3) { width: 11%; }
.report-charges-table-a5 th:nth-child(4), .report-charges-table-a5 td:nth-child(4) { width: 10%; }
.report-charges-table-a5 th:nth-child(5), .report-charges-table-a5 td:nth-child(5) { width: 9%; }
.report-charges-table-a5 th:nth-child(6), .report-charges-table-a5 td:nth-child(6) { width: 19%; }
.report-charges-table-a5 th:nth-child(7), .report-charges-table-a5 td:nth-child(7) { width: 18%; }
.rcc-a5-obs { font-size: 9.5px; font-style: italic; opacity: 0.6; margin-top: 1px; font-weight: 400; }
.rcc-a5-note { font-size: 9px; font-style: italic; color: var(--rpt-muted); padding: 5px; text-align: left; background: var(--rpt-paper); border-top: 1px solid var(--rpt-line); }

/* Itemized quotation (BOM & pricing step) — the GST-wise summary block
   under the item table/cards. Kept as one atomic unit so a page break
   never falls between a GST group line and the grand total below it. */
.rpt-bom-summary { break-inside: avoid; page-break-inside: avoid; color: var(--rpt-navy); }
#print-report.pdf-a5 .rpt-bom-summary, #print-report.pdf-a5 .rpt-bom-summary > div { font-size: 11px; }
#print-report.pdf-mobile .rpt-bom-summary, #print-report.pdf-mobile .rpt-bom-summary > div { font-size: 15px; }
/* Item names under each GST group line, one bullet per BOM line item
   (see gstGroupLine() in calculator.js) — was a single comma-separated
   run-on line; em-sized off the group wrapper above so it still scales
   correctly with the A5/mobile overrides there without its own media
   queries. */
.rpt-bom-items { margin: 3px 0 0; padding-left: 14px; opacity: 0.7; font-size: 0.8em; }
.rpt-bom-items li { margin-bottom: 1px; }

/* Bill snapshot (lowest/average/highest) mini bar rows — same visual
   language as the wizard's before/after bar chart, laid out as labelled
   horizontal bars so a layman can read the spread at a glance. */
.stat-bar-row { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; break-inside: avoid; page-break-inside: avoid; }
.stat-bar-label { width: 56px; flex: none; font-size: 11px; opacity: 0.7; }
.stat-bar-track { flex: 1; background: var(--rpt-paper, var(--color-neutral-200)); border-radius: 4px; height: 12px; overflow: hidden; }
.stat-bar-fill { height: 100%; border-radius: 4px; }
.stat-bar-value { width: 96px; flex: none; text-align: right; font-size: 12px; font-weight: 700; line-height: 1.3; }

/* "Your bill at a glance" — two side-by-side comparison columns (was
   inline-styled; pulled into classes here so the pdf-mobile block below
   can stack them without needing !important). */
.rpt-glance-row { display: flex; gap: 20px; break-inside: avoid; page-break-inside: avoid; }
.rpt-glance-col { flex: 1; break-inside: avoid; page-break-inside: avoid; }
.rpt-glance-col-title { font-size: 11px; opacity: 0.6; margin-bottom: 6px; }

/* ── "WhatsApp · Mobile-friendly" PDF format (added 2026-09-03; sized up
   again 2026-09-03 — "200%" pass) ──
   A4/A5 are standard paper sizes — pinch-zoom is expected on a phone
   screen when the page is A4/A5-wide. This format instead uses a
   deliberately narrow custom page (100mm, see applyPdfPageSize() in
   calculator.js) with much bigger fonts throughout, on the theory that a
   PDF viewer's default "fit to width" zoom maps the page's full width to
   the phone's full screen width — a narrower page means the same (or
   bigger) font sizes render proportionally larger on-screen with no
   zoom needed. Unlike the .pdf-a5 rules above (which only touch the 3
   page-1 cards, keeping every page-2+ card pixel-identical per an
   earlier round's explicit request), this format rewrites EVERY card,
   because the whole point is nothing on any page needs zooming. Several
   elements also get real layout changes, not just bigger fonts — the
   before/after icon diagram moves to its own line above the stat boxes
   (via the .rpt-flow-head wrapper already in the HTML) and every stat
   box stacks full-width one-per-row, the savings tiles go one-per-row
   instead of a multi-column grid, the "bill at a glance" two columns
   stack vertically, the proposed-system table becomes one card per
   panel, and the charges table becomes one card per billing entry
   (report-charges-cards/.rcc-card, built in buildPrintReport()'s
   chargesCardHtml) — none of A4/A5's multi-column tables fit a ~300px
   content width at a size anyone can read without zooming.

   The whole page is also now ONE continuous page (see applyPdfPageSize())
   instead of splitting across ~5 pages, so the customer just scrolls down
   on their phone. Page WIDTH is unchanged (100mm — that's what drives the
   zoom effect above); every size below is roughly doubled from the
   original mobile pass so the report reads noticeably bigger/bolder at
   that same fit-to-width zoom, per the follow-up request to make it
   "200%". A few spots (the flow diagram's icon row, the panel/charges
   card grids) get more like +50-80% rather than a literal 2x, specifically
   where a full double risked overflowing the fixed ~296px card content
   width — verified by rendering and visually inspecting every element at
   these sizes rather than doubling blindly. */
#print-report.pdf-mobile .rpt-cover { padding: 22px 22px; }
/* At A4/A5 widths, the name/address column and the logo+date+contact
   column comfortably sit side by side. At mobile's ~300px content width
   they don't — group1's flex-shrink let it get so narrow that the
   customer's surname overflowed straight through the logo/date column
   (real bug, caught on this render). Stack them instead: name/address on
   top (full width, so the name has real room to wrap), logo+date+contact
   as a full-width row underneath. */
#print-report.pdf-mobile .rpt-cover-top { flex-direction: column; gap: 16px; }
#print-report.pdf-mobile .rpt-cover-group2 { flex-direction: row; align-items: center; justify-content: space-between; width: 100%; }
#print-report.pdf-mobile .rpt-eyebrow { font-size: 16px; }
#print-report.pdf-mobile .rpt-cover h1.rpt-cover-name { font-size: 26px; }
#print-report.pdf-mobile .rpt-cover .rpt-sub { font-size: 16px; }
#print-report.pdf-mobile .rpt-cover-date-contact span,
#print-report.pdf-mobile .rpt-meta-row div span { font-size: 13px; }
#print-report.pdf-mobile .rpt-cover-date-contact strong,
#print-report.pdf-mobile .rpt-meta-row div strong { font-size: 18px; }

/* Every card (not just page 1 — see note above) gets bigger heading/body
   type. Higher specificity than both .rpt-card and .rpt-card-p1 so this
   applies uniformly regardless of which class a given card also carries. */
#print-report.pdf-mobile .rpt-card { padding: 18px 16px; margin-bottom: 16px; }
#print-report.pdf-mobile .rpt-card h2 { font-size: 22px; margin-bottom: 7px; }
#print-report.pdf-mobile .rpt-card .rpt-desc { font-size: 15px; margin-bottom: 11px; }
/* .rpt-card's base rule (further up) keeps a whole card from ever
   splitting across a page break — fine at A4/A5 sizes, but this round's
   ~2x bigger mobile cards can now genuinely exceed a single page's height
   (the charges-card list grows with every billing entry; the closing
   "Why go solar" card is a long fixed list). Relaxed back to auto for
   mobile so a tall card can flow across a page boundary instead of either
   forcing an oversized page to fit it whole or getting silently clipped.
   The actual visual units that must stay intact (one flow-row, one
   charges/panel card, one savings tile) each carry their own
   break-inside:avoid below/elsewhere, so this only allows a break
   *between* those units, never through the middle of one. h2/.rpt-desc
   are kept glued to whatever follows so a heading is never orphaned alone
   at the bottom of a page. */
#print-report.pdf-mobile .rpt-card { break-inside: auto; page-break-inside: auto; }
#print-report.pdf-mobile .rpt-card h2,
#print-report.pdf-mobile .rpt-card .rpt-desc { break-after: avoid; page-break-after: avoid; break-inside: avoid; page-break-inside: avoid; }
/* Forced page 2/4 starts for the fixed mobile layout described above
   (cover / Now / With solar / investment onward) — the "With solar" side
   of this boundary is handled by .rpt-flow-row.after above, since "Now"
   and "With solar" are two rows inside this same card, not two cards. */
#print-report.pdf-mobile .rpt-card-beforeafter { break-before: page; page-break-before: always; }
#print-report.pdf-mobile .rpt-card-payback { break-before: page; page-break-before: always; }
/* Commercial terms & conditions card (added 2026-09-22, "avoid split
   view") — an exception to the mobile break-inside:auto relaxation two
   rules up. That relaxation exists for cards tall enough to genuinely
   exceed one page (the charges list, "Why go solar"); this card is never
   that tall, so it's put back to avoid — the whole card (Payment terms +
   Scope of customer + timeline) moves to the next page as one unit rather
   than splitting between its Payment-terms and Scope-of-customer blocks,
   which is what was producing a large trailing blank gap on the previous
   page. Same fix applies at A4/A5 too, where .rpt-card's own base
   break-inside:avoid already covers it — this rule only needed adding for
   mobile specifically. */
#print-report.pdf-mobile .rpt-terms-card { break-inside: avoid; page-break-inside: avoid; }

/* Coverage card ("How much of your bill solar covers") — same reasoning
   as .rpt-terms-card above: it's short (heading + one description line +
   the bar/pct row + a 2-item legend), so rather than let the general
   .rpt-card break-inside:auto rule split it mid-card (bar/pct landing on
   one page, the legend or the pct number spilling to the next), keep it
   as one atomic block that moves to the next page as a whole if it
   doesn't fit in what's left of the current one. 2026-09-22. */
#print-report.pdf-mobile .rpt-card-coverage { break-inside: avoid; page-break-inside: avoid; }

/* Payback timeline — bigger track/labels; the "Break-even" label's
   position is widened away from "Today"/"25 yrs" specifically for
   mobile in JS (paybackLabelPct), since this bar's small base font size
   left almost no margin before the two collided on a real render — the
   dead zone was widened further this round since the label font grew
   again and the track's absolute width didn't. */
#print-report.pdf-mobile .rpt-payback-track { height: 13px; border-radius: 7px; }
#print-report.pdf-mobile .rpt-payback-marker { height: 19px; top: -3px; width: 5px; }
#print-report.pdf-mobile .rpt-payback-scale { font-size: 12.5px; margin-top: 7px; }

/* Before/after: label+diagram move to their own line (flow-row becomes a
   column of [head, stats] instead of a row of [label, diagram, stats] —
   see .rpt-flow-head in the HTML), and every stat box stacks full-width
   one-per-row below it. This round also stacks the label ABOVE the
   diagram (flow-head itself becomes a column) and lets the diagram take
   the full card width, so the now much taller icons (see mainIconH/
   houseIconH in calculator.js) have real room instead of competing with
   the label for a shared row. */
/* Now that the parent .rpt-card can break across a page (see above), the
   flow-row itself (label + diagram + 3 stacked stat boxes) needs to be
   splittable too — on the 130x185mm page this round settled on, "Now"/
   "With solar" plus all 3 of its full-width stat boxes together can be
   taller than an entire page, so break-inside:avoid on the row was
   actually being ignored by the browser (nowhere it COULD go without
   splitting) and a stat box got cut in half mid-box — real bug, caught by
   rendering and inspecting the actual page-break points, not just page
   count. Fixed by moving "must stay intact" down to the two things that
   are actually small enough to guarantee it: the head (label+diagram)
   and each individual stat box — a page break can now only fall between
   the head and the first box, or between two boxes, never through one. */
/* display:block, not flex — Chrome's print pagination doesn't reliably
   fragment a flex container's children at all: even after the stats
   sub-container was switched to grid (below), the 3 boxes still moved
   together as one block, because the ROW ITSELF was still flex
   (flex-direction:column) and that outer flex context was what was
   actually blocking fragmentation, not the stats container. A plain
   block-flow row lets the browser paginate between its children
   (head / stats) freely. gap doesn't apply in block layout, so the
   spacing gap previously provided by the row is replaced with a
   margin-bottom on .rpt-flow-head below. */
#print-report.pdf-mobile .rpt-flow-row { display: block; padding: 14px 0; }
/* User asked for a fixed, predictable page layout on mobile: page 1 the
   cover, page 2 "Now", page 3 "With solar", page 4 "Your investment pays
   off" onward. Natural flow put those in roughly the right place for one
   test customer but isn't guaranteed for every name/address length, so
   these three boundaries are forced explicitly rather than left to
   chance — see .rpt-card-beforeafter and .rpt-card-payback below for the
   other two. */
#print-report.pdf-mobile .rpt-flow-row.after { padding-top: 22px; break-before: page; page-break-before: always; }
#print-report.pdf-mobile .rpt-flow-head { flex-direction: column; align-items: flex-start; gap: 12px; width: 100%; margin-bottom: 18px; break-inside: avoid; page-break-inside: avoid; }
#print-report.pdf-mobile .rpt-flow-label { font-size: 15px; padding: 8px 14px; }
#print-report.pdf-mobile .rpt-flow-diagram { width: 100%; }
#print-report.pdf-mobile .rpt-flow-arrow { margin: 0 10px; }
#print-report.pdf-mobile .rpt-flow-arrow span { font-size: 12px; }
/* display:block, not flex or grid — switching the row from flex to block
   (see .rpt-flow-row above) made no difference on its own, which proved
   the atomic container blocking fragmentation was actually THIS element
   (still display:grid at that point), not the row. Chrome's print
   pagination does not reliably fragment a grid container's children
   either (grid items default to align-items:stretch, which apparently
   forces Chrome to lay the grid out as one sized block before deciding
   where it can break, so all 3 stat boxes kept moving together as one
   unit regardless of break-inside on the individual boxes — confirmed by
   rendering and checking the actual page-break points, twice). Plain
   block layout is the one display mode Chrome's paginator reliably
   fragments between children, so each stat box becomes an ordinary block
   with a margin-bottom standing in for the removed grid gap. */
/* break-inside:avoid on the group itself is safe to re-add now that the
   page (see applyPdfPageSize in calculator.js, 130x215mm this round) is
   sized with real headroom over this group's measured height — with that
   headroom in place "avoid" holds and the 3 boxes stay together as one
   visual unit instead of each drifting onto whichever page has room, per
   the user's page-by-page layout request. */
#print-report.pdf-mobile .rpt-vec-stats { display: block; break-inside: avoid; page-break-inside: avoid; }
#print-report.pdf-mobile .rpt-vec-stat { display: flex; padding: 14px 15px; gap: 10px; border-width: 2px; margin-bottom: 10px; break-inside: avoid; page-break-inside: avoid; }
#print-report.pdf-mobile .rpt-vec-stat:last-child { margin-bottom: 0; }
#print-report.pdf-mobile .rpt-vec-label { font-size: 13px; }
#print-report.pdf-mobile .rpt-vec-value { font-size: 26px; }
#print-report.pdf-mobile .rpt-vec-value .unit { font-size: 15px; }
#print-report.pdf-mobile .rpt-vec-cadence { font-size: 11.5px; }

/* Long-term savings tiles — one per row instead of the auto-fit grid, so
   the long "PM Surya Ghar Subsidy" label never has to wrap into a
   cramped column. Sizing trimmed 2026-09-22 so this card's description +
   payback bar + all 5 tiles fit on a single mobile page (previously ran
   just over the page-1 content budget, spilling the coverage card and
   Bill History onto extra pages behind it). */
#print-report.pdf-mobile .report-stat-row { grid-template-columns: 1fr; gap: 9px; }
#print-report.pdf-mobile .report-stat-tile { padding: 12px 13px; text-align: left; }
#print-report.pdf-mobile .report-stat-tile-kicker { font-size: 12px; }
#print-report.pdf-mobile .report-stat-tile-value { font-size: 25px; }
#print-report.pdf-mobile .report-stat-tile-note { font-size: 9px; }

#print-report.pdf-mobile .rpt-coverage-bar { height: 40px; }
#print-report.pdf-mobile .rpt-coverage-pct { font-size: 26px; }
#print-report.pdf-mobile .rpt-legend { font-size: 15px; margin-top: 12px; }

/* "Your bill at a glance" — stacked instead of side-by-side; each bar
   row's fixed label/value column widths (sized for A4/A5's wider cards)
   get more breathing room and a bigger font now that they're not
   sharing the row with a second comparison block. */
#print-report.pdf-mobile .rpt-glance-row { flex-direction: column; gap: 20px; }
#print-report.pdf-mobile .rpt-glance-col-title { font-size: 16px; }
#print-report.pdf-mobile .stat-bar-row { gap: 12px; margin-bottom: 12px; }
#print-report.pdf-mobile .stat-bar-label { width: 82px; font-size: 15px; }
#print-report.pdf-mobile .stat-bar-track { height: 22px; }
#print-report.pdf-mobile .stat-bar-value { width: 134px; font-size: 17px; }

/* Bill History (the simple 3-column table) just needs bigger type — it's
   narrow enough to stay a table even at 300px. */
#print-report.pdf-mobile .table th { font-size: 15px; padding: 13px 9px; }
#print-report.pdf-mobile .table td { font-size: 17px; padding: 13px 9px; }

/* Proposed solar system — one card per panel instead of a 5-column
   table (Type values like "Mono PERC Half-Cut" don't fit a table column
   at this width without wrapping badly). Kept as a 3-across grid (Wp/Qty/
   kWp are always short numbers, so it doesn't need to stack) but sized
   up alongside everything else. */
#print-report .rpt-panel-cards { display: flex; flex-direction: column; gap: 14px; }
#print-report .rpt-panel-card { border: 1px solid var(--rpt-line); border-radius: 12px; padding: 18px 20px; break-inside: avoid; page-break-inside: avoid; }
#print-report .rpt-panel-card-make { font-weight: 700; font-size: 19px; color: var(--rpt-navy); }
#print-report .rpt-panel-card-make span { display: block; font-weight: 400; font-size: 15px; color: var(--rpt-muted); margin-top: 3px; }
#print-report .rpt-panel-card-grid { display: flex; gap: 18px; margin-top: 14px; }
#print-report .rpt-panel-card-grid div { flex: 1; }
#print-report .rpt-panel-card-grid span { display: block; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--rpt-muted); margin-bottom: 3px; }
#print-report .rpt-panel-card-grid strong { font-family: var(--rpt-font-mono); font-size: 21px; color: var(--rpt-navy); }

/* Charges breakdown — one card per billing entry instead of any
   multi-column table (built as chargesCardHtml in buildPrintReport(),
   used only when isMobile). Kept as a 2-column grid (each value is a
   short number, so a single-column stack would just waste vertical
   space) but every figure/label sized up alongside the rest. */
#print-report .report-charges-cards { display: flex; flex-direction: column; gap: 14px; margin-bottom: 6px; }
#print-report .rcc-card { border: 1px solid var(--rpt-line); border-radius: 12px; padding: 18px 20px; break-inside: avoid; page-break-inside: avoid; }
#print-report .rcc-card-head { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 8px 12px; margin-bottom: 13px; padding-bottom: 10px; border-bottom: 1px solid var(--rpt-line); }
#print-report .rcc-card-date { font-family: var(--rpt-font-mono); font-weight: 700; font-size: 19px; color: var(--rpt-navy); }
#print-report .rcc-card-obs { font-size: 14px; font-style: italic; color: var(--rpt-muted); }
#print-report .rcc-card-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 20px; }
#print-report .rcc-card-grid div span { display: block; font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--rpt-muted); margin-bottom: 3px; }
#print-report .rcc-card-grid div strong { font-family: var(--rpt-font-mono); font-size: 19px; font-weight: 700; color: var(--rpt-navy); }
#print-report .rcc-card-grid div strong i { font-style: normal; font-size: 14.5px; font-weight: 600; }
#print-report .rcc-card-save { color: var(--rpt-green) !important; }

/* "Why go solar" trust card sized down from the generic mobile enlargement
   above specifically because it now shares page 1 with the cover (moved
   there 2026-09-03 to fill the blank gap below the cover — see the
   ctaCardHtml comment in buildPrintReport()). Every other mobile card
   keeps the full 2026-09-03 "200%" sizing; only this one card is trimmed,
   and only enough to fit the two of them on one page together. */
#print-report.pdf-mobile .rpt-cta { padding: 18px 18px; margin-bottom: 22px; }
#print-report.pdf-mobile .rpt-cta h2 { font-size: 21px; margin-bottom: 6px; }
#print-report.pdf-mobile .rpt-cta-list { font-size: 14.5px; margin: 0 0 6px; }
#print-report.pdf-mobile .rpt-cta-list li { margin-bottom: 2px; }
#print-report.pdf-mobile .rpt-cta-action { font-size: 14.5px; }
#print-report.pdf-mobile .rpt-terms-label { font-size: 13px; }
#print-report.pdf-mobile .rpt-terms-payment { font-size: 14.5px; }
#print-report.pdf-mobile .rpt-terms-list { font-size: 14.5px; }
#print-report.pdf-mobile .rpt-timeline { flex-direction: column; gap: 6px; }
#print-report.pdf-mobile .rpt-timeline-step { text-align: left; padding: 8px 12px; }
#print-report.pdf-mobile .rpt-timeline-step strong { font-size: 13px; display: inline; }
#print-report.pdf-mobile .rpt-timeline-step span { font-size: 14px; display: inline; margin-left: 6px; }
#print-report.pdf-mobile .rpt-footer { font-size: 15px; }
/* The forced page-2 break before Bill History was an A4/A5-specific
   requirement from an earlier round (keeping their page count to a
   predictable 2-3). Mobile is now a single continuous page, so there is
   no "page 2" to break to — kept as auto (harmless no-op) rather than
   removed, so nothing forces a break if this ever goes back to a
   multi-page layout. */
#print-report.pdf-mobile .rpt-page-break { break-before: auto; page-break-before: auto; }

@media (max-width: 560px) {
  .wizard-header, .wizard-body, .wizard-footer { padding-left: var(--space-4); padding-right: var(--space-4); }
  .auth-card { padding: var(--space-6) var(--space-4); }
  .entry-row .input { width: 100px; }
}

/* — Vendor & Consumer Agreement (buildAgreementReport() in calculator.js) —
   A separate print target from #print-report (the customer proposal),
   see the body.printing-agreement rules in the @media print block above.
   Deliberately plain/legal-document styling (black text, generous line
   height, no color accents) rather than the proposal's navy/amber report
   look — this is a document meant to be signed and filed, not a sales
   piece. Uses the same Google Fonts already loaded in calculator.php
   (Bricolage Grotesque for the title, Public Sans for body text), each
   with its own fallback stack, independent of the #print-report-scoped
   --rpt-font-* variables. */
#print-agreement { display: none; }
#print-agreement {
  font-family: 'Public Sans', var(--font-body), system-ui, sans-serif;
  color: #111;
  font-size: 12.5px;
  line-height: 1.55;
}
.agr-doc { width: 100%; }
/* Each .agr-page is one physical printed sheet — break-after: page on all
   but the last one. Plain A4 padding (top/right/bottom 14mm/4mm/4mm, left
   4mm) on every page — the 2026-09-05 150mm-top-offset / 50mm-left-margin
   experiment for pages 1-2 (the stamp-paper pages) was reverted the same
   day per the team's own feedback ("agreement print not good and replace
   with initial one"); pages 1-2 now print exactly like every other page
   again, with only the adjustable stampOffsetTop1/2 padding-top (default
   0mm, set inline per-page from state — see buildAgreementReport()) left
   in place for lining a page up against pre-printed stamp-paper stock. */
.agr-page { break-after: page; page-break-after: always; padding: 14mm 4mm 4mm; }
.agr-page:last-child { break-after: auto; page-break-after: auto; }
.agr-title { font-family: 'Bricolage Grotesque', var(--font-heading), system-ui, sans-serif; font-size: 16px; font-weight: 700; line-height: 1.35; text-align: center; margin: 0 0 18px; }
.agr-para { margin: 0 0 10px; }
.agr-para.agr-strong { font-weight: 700; margin-top: 16px; }
.agr-clause { margin: 0 0 9px; break-inside: avoid; page-break-inside: avoid; }
.agr-clause.agr-note { font-style: italic; font-size: 11.5px; opacity: 0.8; }
.agr-spec-row { display: flex; gap: 14px; flex-wrap: wrap; margin: 4px 0 12px; padding: 8px 10px; border: 1px solid #999; border-radius: 4px; background: #f7f7f5; font-size: 12px; }
.agr-spec-row > div { flex: 1; min-width: 140px; }
.agr-spec-label { display: block; font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; opacity: 0.65; margin-bottom: 2px; }
.agr-signature-grid { display: flex; gap: 30px; margin-top: 40px; break-inside: avoid; page-break-inside: avoid; }
.agr-sig-col { flex: 1; }
.agr-sig-label { font-weight: 700; margin-bottom: 22px; }
.agr-sig-line { margin-bottom: 22px; border-bottom: 1px solid #444; padding-bottom: 2px; min-width: 160px; }
/* 2026-10-13: ~25 mm clear space above the signature line to sign in. */
.agr-sig-space { margin-top: 25mm; border-top: 1px solid #444; padding-top: 4px; font-size: 11px; opacity: 0.7; }

/* — TNEB Installation Letter (buildTnebLetterReport() in calculator.js) —
   A third print target, alongside #print-report and #print-agreement
   above (see the body.printing-tneb-letter rules in the @media print
   block). A single plain A4 page reproducing the team's own 1-page letter
   template (uploaded reference: "Letter to TNEB_Narayanee.docx") — same
   plain black-text/no-color-accent treatment as the agreement, since this
   too is a document meant to be printed on letterhead and handed to a
   DISCOM official, not a sales piece. Reuses the same fonts as
   #print-agreement.
   Spacing here is deliberately tight (compact table rows, small section/
   closing margins) — the first version (14mm page padding, 1.65 line
   height, 32/46px closing/address margins) measured out to just over one
   A4 page's usable height once the two spec tables were both filled in,
   spilling a couple of lines onto a second page ("make it single page",
   2026-09-05). Verified back down to exactly one page via
   render_test.js's page.pdf() + pdfinfo page-count check. */
#print-tneb-letter { display: none; }
#print-tneb-letter {
  font-family: 'Public Sans', var(--font-body), system-ui, sans-serif;
  color: #111;
  font-size: 12px;
  line-height: 1.4;
}
.tnl-page { padding: 10mm 10mm; }
/* Letterhead logo at the top of the printed letter — same
 * assets/img/elenserve-logo.png used on the proposal cover/header, just
 * sized for a single-page A4 business letter. */
.tnl-letterhead { margin-bottom: 12px; }
.tnl-letterhead img { height: 28px; object-fit: contain; display: block; }
.tnl-to-date { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 10px; gap: 20px; }
.tnl-para { margin: 0 0 5px; }
.tnl-subject { font-weight: 700; margin: 8px 0 8px; }
.tnl-strong { font-weight: 700; }
.tnl-section-title { font-weight: 700; margin: 10px 0 5px; }
.tnl-table { width: 100%; border-collapse: collapse; margin: 0 0 10px; }
.tnl-table td { border: 1px solid #999; padding: 3px 8px; font-size: 12px; line-height: 1.3; vertical-align: top; }
.tnl-table td:first-child { font-weight: 600; width: 46%; background: #f7f7f5; }
.tnl-closing { margin-top: 14px; }
.tnl-closing-line { margin: 0 0 3px; }
/* Blank room for a physical (or stamped) signature between "For elenserve
 * technologies" and the registered-address line below it — requested
 * 2026-09-06: "give space after for elenserve technologies in eb letter". */
.tnl-sig-space { height: 50px; }
.tnl-address { text-align: center; margin-top: 16px; font-size: 11px; }

/* — Simple Quotation (buildSimpleQuotationReport() in calculator.js) —
   A fourth print target, alongside #print-report/#print-agreement/
   #print-tneb-letter above (see the body.printing-quotation rules in the
   @media print block). Added 2026-09-17, requested directly: "give option
   to print Items only simple quotation only" — a plain, itemized bill of
   every BOM line, unlike #print-report's own itemized-quotation section
   which deliberately collapses to two GST-group totals. Same plain
   black-text/no-color-accent business-document treatment and fonts as
   #print-agreement/#print-tneb-letter, since this too is meant to be
   printed and handed over, not a sales piece. */
#print-quotation { display: none; }
#print-quotation {
  font-family: 'Public Sans', var(--font-body), system-ui, sans-serif;
  color: #111;
  font-size: 12.5px;
  line-height: 1.45;
}
.qot-page { padding: 12mm 10mm; }
.qot-letterhead { margin-bottom: 14px; }
.qot-letterhead img { height: 28px; object-fit: contain; display: block; }
.qot-to-date { display: flex; justify-content: space-between; gap: 20px; margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid #999; }
.qot-subject { font-weight: 700; margin: 0 0 12px; }
.qot-table { width: 100%; border-collapse: collapse; margin: 0 0 14px; }
.qot-table th, .qot-table td { border: 1px solid #999; padding: 6px 8px; font-size: 12px; vertical-align: top; }
.qot-table th { background: #f7f7f5; font-weight: 700; text-align: left; }
.qot-totals { margin-left: auto; width: 260px; }
.qot-totals > div { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; }
.qot-totals .qot-grand { border-top: 1.5px solid #333; margin-top: 4px; padding-top: 8px; font-size: 14px; font-weight: 700; }
/* Central + state subsidy and estimated bi-monthly generation (added
   2026-09-22) — plain label/value rows, full width unlike the
   right-aligned .qot-totals box above, so the longer subsidy labels never
   have to wrap awkwardly in a narrow column. */
.qot-subsidy-gen { margin-top: 14px; padding-top: 10px; border-top: 1px solid #999; }
.qot-subsidy-gen > div { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: 12px; }
.qot-subsidy-gen strong { font-weight: 700; }
/* GST-rate groups (added 2026-09-17 — "Items format as per proposal 5 %
   and 18 % tax group with details") — each group is its own titled
   mini-table + subtotal, same idea as buildPrintReport()'s bomSummaryHtml
   but with full item pricing detail rather than a name-only bullet list. */
.qot-group { margin-bottom: 16px; }
.qot-group-title { font-weight: 700; margin-bottom: 6px; padding-bottom: 4px; border-bottom: 1px solid #ccc; }
.qot-group-totals { display: flex; justify-content: space-between; gap: 12px; font-size: 12px; margin-top: -6px; }
.qot-group-totals strong { font-size: 13px; }
/* Payment terms / Scope of customer (added 2026-09-17) — same content as
   buildPrintReport()'s "Commercial terms & conditions" card. */
.qot-terms { margin-top: 16px; }
.qot-terms-title { font-weight: 700; margin-bottom: 4px; }
.qot-terms-text { white-space: pre-wrap; }
.qot-terms-list { margin: 4px 0 0; padding-left: 18px; color: #C21807; }
.qot-terms-list li { margin-bottom: 2px; }
/* "Why go solar with Elenserve" (added 2026-09-17) — same content as
   buildPrintReport()'s ctaCardHtml, styled plainly to match this document's
   business-letter tone rather than the glossy proposal's card look. */
.qot-why { margin-top: 16px; padding-top: 10px; border-top: 1px solid #999; }
.qot-why-title { font-weight: 700; margin-bottom: 4px; }
.qot-why-list { margin: 4px 0 0; padding-left: 18px; }
.qot-why-list li { margin-bottom: 2px; }
.qot-footnote { margin-top: 18px; font-size: 10.5px; opacity: 0.75; }
.qot-savings-disclaimer { margin-top: 6px; font-size: 10.5px; font-weight: 700; color: #C21807; }

/* ─────────────────────────────────────────────────────────────────────
 * Rooftop Layout Designer (layout-designer.php / assets/js/layout-designer.js)
 * Added 2026-09-08. Reuses the app's existing .btn/.card/.field/.input/
 * .table/.tag/.empty-state/.alert/.dash-header classes wherever they
 * already fit; everything below is either a new small button/badge
 * modifier (kept generic, not ld-prefixed, in case it's useful
 * elsewhere) or specific to this page's own layout (ld- prefixed so it
 * can't collide with any other page's classes). Colors are drawn from
 * the shared --color-* tokens via the --ld-* custom properties below,
 * so the drawings/stat tiles follow the app's Archivo + red-orange
 * theme instead of the tool's original standalone Elenserve-blue/amber
 * palette — the --ld-* indirection exists only so the SVG-building JS
 * can reference one set of stable names.
 * ───────────────────────────────────────────────────────────────────── */
.btn-danger { border-color: var(--color-accent-300); color: var(--color-accent-700); background: var(--color-surface-2); }
.btn-danger:hover:not(:disabled) { background: var(--color-accent-100); }
.btn-sm { padding: 6px 12px; font-size: 12.5px; border-radius: var(--radius-sm); }

.ld-wrap {
  --ld-accent: var(--color-accent);
  --ld-accent-line: var(--color-accent-700);
  --ld-ink: var(--color-text);
  --ld-muted: var(--color-neutral-600);
  --ld-line: var(--color-neutral-500);
  --ld-hatch: var(--color-neutral-300);
  --ld-obstruction: var(--color-neutral-300);
  --ld-obstruction-line: var(--color-neutral-600);
  --ld-walkway: #dcefe7;
  --ld-walkway-line: #1c6b2a;
  --ld-danger: var(--color-accent-700);
  --ld-good: #1c6b2a;
  --ld-paper: #ffffff;
  /* Placed panels — deliberately NOT tied to --color-accent (unlike the
     rest of this page's red-orange theme): a real rooftop PV module reads
     as a blue cell field behind a black aluminium frame, so the drawing
     uses that actual-equipment coloring instead of the app's brand
     accent, on request (2026-09-09). Lightened from an initial dark navy
     (#163a63) the same day — "not good to see" at panel-cell scale. */
  --ld-panel: #4f95d1;
  --ld-panel-line: #05070a;
}
.ld-topline { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; margin-bottom: var(--space-4); }
.ld-saved-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.ld-saved-bar select.input { width: auto; min-width: 220px; }
.ld-save-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: var(--space-4); }
.ld-save-row input.input { max-width: 320px; }
.ld-status { font-size: 12px; min-height: 16px; margin: -4px 0 var(--space-2); }
.ld-status.is-error { color: var(--ld-danger); }
.ld-status.is-ok { color: var(--ld-good); }

.ld-grid { display: grid; gap: var(--space-3) var(--space-4); margin-bottom: var(--space-2); }
.ld-grid.cols-2 { grid-template-columns: 1fr 1fr; }
.ld-grid.cols-3 { grid-template-columns: 1fr 1fr 1fr; }
.ld-grid.cols-4 { grid-template-columns: 1fr 1fr 1fr 1fr; }
@media (max-width: 760px) { .ld-grid.cols-2, .ld-grid.cols-3, .ld-grid.cols-4 { grid-template-columns: 1fr; } }

.ld-hint { font-size: 11.5px; color: var(--ld-muted); margin: 4px 0 0; line-height: 1.5; }
.ld-checkline { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 500; color: var(--ld-ink); }
.ld-checkline input { width: auto; }
.ld-handrail-grid { display: grid; grid-template-columns: repeat(4, auto); gap: 14px; margin-top: 4px; }
@media (max-width: 640px) { .ld-handrail-grid { grid-template-columns: 1fr 1fr; } }

.ld-section-card { border: 1.5px solid var(--color-divider); border-radius: var(--radius-md); padding: 18px 20px; margin-bottom: 16px; background: var(--color-surface-2); }
.ld-sec-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; gap: 10px; flex-wrap: wrap; }
.ld-sec-head input[type=text] { font-family: var(--font-heading); font-weight: 800; font-size: 16px; color: var(--color-accent); border: none; border-bottom: 1.5px solid transparent; background: transparent; padding: 2px 0; width: auto; min-width: 180px; min-height: auto; }
.ld-sec-head input[type=text]:focus { outline: none; border-bottom-color: var(--color-accent); }
.ld-sec-name-print { display: none; }
@media print { .ld-sec-name-print { display: block; font-family: var(--font-heading); font-weight: 800; font-size: 16px; color: var(--color-text); margin: 0 0 14px; } }

.ld-obstruction-row { display: grid; grid-template-columns: 1.2fr .7fr .7fr .7fr .7fr .8fr auto; gap: 8px; align-items: end; margin-bottom: 8px; }
@media (max-width: 780px) { .ld-obstruction-row { grid-template-columns: 1fr 1fr; } }
.ld-obstruction-row .field { margin-bottom: 0; }
.ld-obstruction-card { border: 1px solid var(--color-divider); border-radius: var(--radius-md); padding: 10px 12px; margin-bottom: 10px; }
.ld-obstruction-card .ld-obstruction-row:last-child { margin-bottom: 0; }
.ld-obstruction-row.ld-ob-r1 { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.ld-obstruction-row.ld-ob-r2 { grid-template-columns: 1fr .8fr 1fr .8fr auto; }
@media (max-width: 780px) { .ld-obstruction-row.ld-ob-r1, .ld-obstruction-row.ld-ob-r2 { grid-template-columns: 1fr 1fr; } }
.ld-side-box { margin: 4px 0 10px; }
.ld-side-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .3px; color: var(--ld-muted, rgba(32,30,29,0.6)); margin-bottom: 4px; }
.ld-side-head .ld-checkline { text-transform: none; letter-spacing: 0; font-weight: 500; }
.ld-side-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.ld-side-grid.is-same { grid-template-columns: minmax(140px, 220px); }
.ld-side-grid .field { margin-bottom: 0; }
@media (max-width: 640px) { .ld-side-grid { grid-template-columns: 1fr 1fr; } }
.ld-neighbor-box { border: 1px dashed var(--color-divider); border-radius: var(--radius-md); padding: 12px 14px; margin-top: 10px; }

.ld-output { margin-top: 16px; padding-top: 16px; border-top: 1px dashed var(--color-divider); }
/* Section body split (2026-09-23): design inputs on the left, drawing +
   stats on the right (sticky), so the drawing is visible while typing.
   Reports (obstruction table, hourly shadow report) run full width below. */
.ld-sec-body { display: grid; grid-template-columns: minmax(330px, 4fr) minmax(0, 7fr); gap: 16px; align-items: start; }
.ld-sec-body.inputs-hidden { grid-template-columns: minmax(0, 1fr); }
.ld-sec-body.inputs-hidden .ld-sec-inputs { display: none; }
.ld-sec-visual .ld-roof-svg { max-height: calc(100vh - 170px); }
.ld-sec-body.inputs-hidden .ld-svg-shell { max-width: 1100px; margin-left: auto; margin-right: auto; }
.ld-sec-head-actions { display: inline-flex; gap: 8px; align-items: center; }
/* compact inputs (2026-09-23) */
.ld-sec-inputs .field { margin-bottom: 0; }
.ld-sec-inputs .field label { font-size: 11px; margin-bottom: 2px; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ld-sec-inputs .input { min-height: 30px; height: 30px; padding: 3px 8px; font-size: 13px; }
.ld-sec-inputs select.input { padding-right: 22px; }
.ld-sec-inputs .ld-grid { gap: 6px 8px; margin-bottom: 0; }
.ld-sec-inputs .ld-grid.ld-c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ld-sec-inputs .ld-hint-sm { font-size: 11.5px; margin: 0 0 6px; }
.ld-sec-inputs .btn-sm { padding: 4px 10px; font-size: 12px; }
.ld-sec-inputs .ld-obstruction-card { padding: 6px 8px; margin-bottom: 6px; }
.ld-sec-inputs .ld-obstruction-row { gap: 6px 8px; margin-bottom: 6px; }
.ld-sec-inputs .ld-obstruction-row.ld-ob-r1, .ld-sec-inputs .ld-obstruction-row.ld-ob-r2 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.ld-sec-inputs .ld-side-box { margin: 0 0 6px; }
.ld-sec-inputs .ld-side-head { margin-bottom: 2px; font-size: 11px; }
.ld-sec-inputs .ld-side-grid { gap: 6px; }
.ld-sec-inputs .ld-handrail-grid { gap: 10px; }
.ld-grp { border: 1px solid var(--color-divider); border-radius: var(--radius-md); margin-bottom: 6px; background: var(--color-surface, #fff); }
.ld-grp > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px; padding: 7px 10px; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px; user-select: none; }
.ld-grp > summary::-webkit-details-marker { display: none; }
.ld-grp > summary::before { content: '▸'; font-size: 11px; color: var(--ld-muted); transition: transform .15s; }
.ld-grp[open] > summary::before { transform: rotate(90deg); }
.ld-grp-title { color: var(--color-text); }
.ld-grp-sum { margin-left: auto; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--ld-muted); font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 55%; }
.ld-grp-body { padding: 2px 10px 10px; }
.ld-grp-tools { text-align: right; font-size: 11.5px; color: var(--ld-muted); margin: 0 0 4px; }
.ld-linkbtn { background: none; border: 0; padding: 0; color: var(--color-accent); cursor: pointer; font-size: 11.5px; }
.ld-sec-inputs .ld-grid.cols-2 { gap: 10px 12px; }
.ld-sec-visual { position: sticky; top: 10px; max-height: calc(100vh - 20px); overflow: auto; }
.ld-sec-visual .ld-output { margin-top: 0; padding-top: 0; border-top: 0; }
.ld-sec-visual .ld-svg-shell { max-width: none; }
.ld-sec-visual .ld-stat-grid { grid-template-columns: repeat(3, 1fr); }
.ld-sec-reports:not(:empty) { margin-top: 16px; padding-top: 12px; border-top: 1px dashed var(--color-divider); }
.ld-sec-inputs .ld-side-grid { grid-template-columns: repeat(4, minmax(0,1fr)); }
.ld-subhead { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .3px; color: var(--ld-muted, rgba(32,30,29,0.6)); margin: 12px 0 6px; }
@media (max-width: 1000px) {
  .ld-sec-body { grid-template-columns: 1fr; }
  .ld-sec-visual { position: static; max-height: none; overflow: visible; }
}
.ld-rowshadow { margin-top: 12px; border: 1px solid var(--color-divider); border-radius: var(--radius-md); padding: 10px 12px; background: var(--ld-paper); }
.ld-rowshadow.is-warn { border-color: var(--ld-danger); }
.ld-side-svg { width: 100%; max-width: 460px; height: auto; display: block; margin: 4px 0 8px; }
.ld-kv { width: 100%; border-collapse: collapse; font-size: 12px; }
.ld-kv td { padding: 3px 6px; border-bottom: 1px solid var(--color-divider); vertical-align: top; }
.ld-kv td:first-child { color: var(--ld-muted); width: 38%; }
.ld-muted-inline { color: var(--ld-muted); font-size: 11px; }
.print-only { display: none; }
.ld-svg-shell { background: var(--ld-paper); border: 1px solid var(--color-divider); border-radius: var(--radius-md); padding: 14px; max-width: 780px; margin: 0 auto 14px; }
.ld-roof-svg { width: 100%; height: auto; display: block; }
.ld-svg-caption { text-align: center; font-size: 11.5px; color: var(--ld-muted); margin-top: 6px; }
.ld-legend { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; font-size: 11px; color: var(--ld-muted); margin-top: 8px; }
.ld-legend .sw { display: inline-block; width: 11px; height: 11px; border-radius: 2px; margin-right: 5px; vertical-align: -1.5px; }

.ld-stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 4px; }
@media (max-width: 780px) { .ld-stat-grid { grid-template-columns: 1fr 1fr; } }
.ld-stat { background: var(--color-surface-2); border: 1px solid var(--color-divider); border-radius: var(--radius-md); padding: 10px 12px; }
.ld-stat .k { font-size: 10.5px; color: var(--ld-muted); text-transform: uppercase; letter-spacing: .3px; font-weight: 600; }
.ld-stat .v { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 16px; font-weight: 600; color: var(--color-text); margin-top: 2px; font-variant-numeric: tabular-nums; }
.ld-stat.highlight .v { color: var(--color-accent); }
.ld-stat.warn { border-color: var(--ld-danger); background: var(--color-accent-100); }
.ld-stat.warn .v { color: var(--ld-danger); }

.ld-titleblock { border: 1.5px solid var(--color-accent); border-radius: var(--radius-md); overflow: hidden; margin-bottom: 18px; }
.ld-titleblock .tb-head { background: var(--color-accent); color: #fff; padding: 8px 16px; font-family: var(--font-heading); font-weight: 800; font-size: 13px; letter-spacing: .4px; text-transform: uppercase; }
.ld-titleblock .tb-body { display: grid; grid-template-columns: repeat(4, 1fr); background: var(--color-surface-2); }
@media (max-width: 720px) { .ld-titleblock .tb-body { grid-template-columns: 1fr 1fr; } }
.ld-titleblock .tb-cell { padding: 9px 14px; border-top: 1px solid var(--color-divider); border-left: 1px solid var(--color-divider); }
.ld-titleblock .tb-cell:nth-child(-n+4) { border-top: none; }
.ld-titleblock .tb-cell .k { font-size: 10px; color: var(--ld-muted); text-transform: uppercase; letter-spacing: .3px; font-weight: 600; }
.ld-titleblock .tb-cell .v { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 13px; color: var(--color-text); margin-top: 2px; word-break: break-word; font-variant-numeric: tabular-nums; }
/* Special requirements / notes, shown on the title block only when the
   customer form's notes field has content (2026-09-09) — kept inside
   .ld-titleblock so it prints on page 1 right along with the rest of the
   customer/title-block data. */
.ld-titleblock .tb-notes { padding: 9px 14px; border-top: 1px solid var(--color-divider); background: var(--color-surface-2); }
.ld-titleblock .tb-notes .k { font-size: 10px; color: var(--ld-muted); text-transform: uppercase; letter-spacing: .3px; font-weight: 600; }
.ld-titleblock .tb-notes .v { font-size: 12.5px; color: var(--color-text); margin-top: 3px; white-space: pre-line; }

.ld-summary-card { border: 2px solid var(--color-accent); }
.ld-summary-card .ld-stat .v { font-size: 19px; }
.ld-summary-table td:first-child { font-family: var(--font-heading); font-weight: 700; color: var(--color-accent); }

/* Obstruction/neighbour details + hourly (all-3-season) shadow report,
   printed under each rooftop section's drawing (2026-09-10). Not no-print
   — these are the durable record of what's blocking the layout and when,
   so they belong in both the on-screen output and the PDF. break-inside:
   avoid keeps each report block itself from splitting mid-table across a
   page — the section card that contains it is now allowed to break across
   pages when it doesn't fit on one (2026-09-10 pagination fix, see @media
   print below), so this is what stops the split from landing awkwardly
   inside one of these two blocks specifically. */
.ld-obstruction-report, .ld-shadow-report { margin-top: 16px; break-inside: avoid; page-break-inside: avoid; }
.ld-report-title { font-family: var(--font-heading); font-weight: 800; font-size: 12.5px; letter-spacing: .3px; text-transform: uppercase; color: var(--color-accent); margin: 0 0 8px; }
.ld-report-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.ld-report-table th, .ld-report-table td { border: 1px solid var(--color-divider); padding: 6px 10px; text-align: left; vertical-align: top; }
.ld-report-table th { background: var(--color-surface-2); font-size: 10px; text-transform: uppercase; letter-spacing: .3px; color: var(--ld-muted); font-weight: 600; }
/* Explicit column widths for the obstruction/neighbour table (2026-09-10)
   — its "Position" cells run long ("5.5 m from left, 5.0 m from top",
   "West side, 20.0 m away") and were wrapping onto 2-3 cramped lines under
   the browser's default auto column sizing, while "Item" sat mostly
   empty. table-layout:fixed + these percentages give Position the room
   its content actually needs. */
.ld-obstruction-report .ld-report-table { table-layout: fixed; }
.ld-obstruction-report .ld-report-table th:nth-child(1), .ld-obstruction-report .ld-report-table td:nth-child(1) { width: 21%; }
.ld-obstruction-report .ld-report-table th:nth-child(2), .ld-obstruction-report .ld-report-table td:nth-child(2) { width: 35%; }
.ld-obstruction-report .ld-report-table th:nth-child(3), .ld-obstruction-report .ld-report-table td:nth-child(3) { width: 19%; }
.ld-obstruction-report .ld-report-table th:nth-child(4), .ld-obstruction-report .ld-report-table td:nth-child(4) { width: 25%; }
.ld-extra-report .ld-report-table th:nth-child(1), .ld-extra-report .ld-report-table td:nth-child(1) { width: 14%; }
.ld-extra-report .ld-report-table th:nth-child(2), .ld-extra-report .ld-report-table td:nth-child(2) { width: 30%; }
.ld-extra-report .ld-report-table th:nth-child(3), .ld-extra-report .ld-report-table td:nth-child(3) { width: 22%; }
.ld-extra-report .ld-report-table th:nth-child(4), .ld-extra-report .ld-report-table td:nth-child(4) { width: 16%; }
.ld-extra-report .ld-report-table th:nth-child(5), .ld-extra-report .ld-report-table td:nth-child(5) { width: 18%; }
.ld-warn-cell { color: var(--ld-danger, #c62828); font-weight: 600; }
.ld-report-table tr.ld-low-energy td { opacity: .55; }
.ld-edge-heights { font-size: 12.5px; margin: 8px 0 4px; padding: 6px 10px; border-radius: var(--radius-md); background: var(--color-surface-2, #f6f6f4); }
.ld-edgeh { color: var(--color-text); }
.ld-extra-card { border-color: var(--ld-overhang, #0e7c86); }
.ld-shadow-report .ld-report-table td { font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums; color: var(--color-text); }
.ld-shadow-report .ld-report-table td:first-child { font-weight: 600; }
.ld-shadow-report .ld-report-table td.muted { color: var(--ld-muted); font-weight: 400; }
.ld-shadow-report .ld-report-table td.warn-cell { color: var(--ld-danger); font-weight: 700; background: var(--color-accent-100); }
/* Panel Nos. line under the shaded-panel count in each report cell
   (2026-09-10) — lighter weight than the count above it so the number
   ("8 panels") still reads first at a glance, with the actual panel list
   as a supporting line rather than competing with it. */
.ld-report-panel-nos { font-weight: 500; font-size: 10.5px; opacity: .85; }
.ld-report-note { font-size: 11px; color: var(--ld-muted); margin: 6px 0 0; }
/* Small supporting line under a stat tile's main value (2026-09-10) — used
   for the "Panel No. 1-3, 9-11" reference under the live shaded-panel-count
   stat tile, mirroring the report table's own count+Nos. pattern above. */
.ld-stat-sub { font-size: 11px; color: var(--ld-muted); margin-top: 3px; font-weight: 500; }
.ld-stat.warn .ld-stat-sub { color: var(--ld-danger); opacity: .85; }
@media (max-width: 780px) {
  .ld-report-table { font-size: 11px; }
  .ld-report-table th, .ld-report-table td { padding: 5px 6px; }
}

/* Shadow Simulation card (hour-by-hour obstruction/neighbouring-building
   shadow check) — reuses .seg/.seg-opt (built for <label>+radio elsewhere)
   with plain <button>s instead, so it needs a small reset here. */
.ld-wrap button.seg-opt { border: none; font: inherit; color: var(--color-text); }
.ld-wrap button.seg-opt.active { color: #fff; }
.ld-shadowsim-row { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; margin-top: 6px; }
.ld-shadowsim-time { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 220px; }
.ld-shadowsim-time label { font-size: 12.5px; color: var(--ld-muted); }
.ld-shadowsim-time label strong { color: var(--color-text); font-family: 'JetBrains Mono', ui-monospace, monospace; }
.ld-shadowsim-time input[type="range"] {
  width: 100%; height: 4px; border-radius: 2px; background: var(--color-divider);
  appearance: none; -webkit-appearance: none; outline: none; cursor: pointer;
}
.ld-shadowsim-time input[type="range"]::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none; width: 16px; height: 16px; border-radius: 50%;
  background: var(--color-accent); border: 2px solid #fff; box-shadow: 0 0 0 1px var(--color-accent); cursor: pointer;
}
.ld-shadowsim-time input[type="range"]::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%; background: var(--color-accent);
  border: 2px solid #fff; box-shadow: 0 0 0 1px var(--color-accent); cursor: pointer;
}

@media print {
  /* body.print-plain opts this page out of the shared "hide everything"
     rule above, so its whole visible page prints by default — this is
     what actually hides every no-print-flagged editing control (inputs,
     add/remove buttons, the obstruction/neighbour forms, the whole
     Customer/Panel/Mounting Structure cards, etc.) plus the outer topbar,
     leaving only the drawings/stats/summary. Before this rule existed
     `.no-print` had no effect at all in print — layout-designer.php's
     "Print / Save PDF" was printing a blank page instead (see the
     body:not(.print-plain) note above), not this. */
  body.print-plain .topbar,
  body.print-plain .no-print,
  body.print-plain #ldSaveCard { display: none !important; }
  .ld-topline, .ld-save-row, .ld-status, #ldTopActions { display: none !important; }
  .page { max-width: 100%; padding: 10px 14px; }
  .card { break-inside: avoid; }
  /* .ld-section-card (2026-09-10): deliberately NOT break-inside:avoid,
     unlike .card above. A section with a full obstruction list plus the
     3-season hourly shadow report can easily run taller than one printed
     page — forcing the whole card to avoid breaking just pushed it
     wholesale onto a fresh page, leaving the page before it mostly blank
     (seen in a real proposal: the "Rooftop Sections" heading landed alone
     at the top of a page with nothing else on it). Letting the card break
     normally fills each page before continuing onto the next; the
     finer-grained avoid rules just below (drawing shell, individual stat
     tiles, section heading, report table rows) keep the actual content
     from being sliced mid-item, and box-decoration-break:clone keeps the
     card's border/background looking correct on both sides of the break
     instead of just stopping dead at the page edge. */
  .ld-section-card {
    break-inside: auto; page-break-inside: auto;
    box-decoration-break: clone; -webkit-box-decoration-break: clone;
  }
  .ld-svg-shell, .ld-stat, .ld-report-table tr { break-inside: avoid; page-break-inside: avoid; }
  /* One page per section: name + drawing + design parameters kept
     together (2026-09-23); stats / row-shadow box / reports follow. */
  .print-only { display: block !important; }
  .ld-sec-body { display: block; }
  .ld-sec-visual { position: static; max-height: none; overflow: visible; }
  .ld-section-card + .ld-section-card { break-before: page; page-break-before: always; }
  .ld-print-sheet { break-inside: avoid; page-break-inside: avoid; }
  .ld-section-card .ld-output { break-inside: auto; }
  .ld-svg-shell { padding: 6px; margin-bottom: 6px; }
  .ld-roof-svg { max-height: 150mm; width: 100%; }
  .ld-params { break-before: avoid; page-break-before: avoid; break-inside: avoid; page-break-inside: avoid; margin-bottom: 8px; }
  .ld-params-table { font-size: 10.5px; }
  .ld-params-table td { padding: 2px 5px; }
  .ld-rowshadow { break-inside: avoid; page-break-inside: avoid; }
  .ld-sec-name-print { break-after: avoid; page-break-after: avoid; }

  /* Project Summary requested right after the customer/title-block data,
     ahead of the individual rooftop section drawings (2026-09-09) — this
     only reorders the *printed* output; on screen the summary still comes
     last, after the sections it totals, which is the natural place while
     actively building a layout. #ldSaveCard/no-print elements above are
     display:none so they're removed from this flex flow entirely — no
     order needed for those. */
  .ld-wrap { display: flex; flex-direction: column; }
  #ld_titleblock { order: 1; }
  #summaryContainer { order: 2; }
  #rooftopSectionsCard { order: 3; }
  .ld-wrap > p.ld-hint { order: 4; break-before: avoid; page-break-before: avoid; }

  /* Logo header + address/footer repeated on every printed page (2026-09-09).
     Chromium only repeats a real HTML thead/tfoot on every printed page —
     position:fixed clips to the page's content box and does not repeat
     correctly across pages, and display:table-header-group on a plain div
     does not trigger repetition either (both tried and confirmed not to
     work). So layout-designer.php wraps the whole page in a real
     <table class="ld-print-table"> with the logo in <thead> and the
     address/contact in <tfoot> — this only takes on table display roles
     here, under print; on screen (see the unconditional block below) it's
     reset to plain stacked divs so it's invisible to the normal editor. */
  body.print-plain .ld-print-table { display: table; }
  body.print-plain .ld-print-table thead { display: table-header-group; }
  body.print-plain .ld-print-table > tbody { display: table-row-group; }
  body.print-plain .ld-print-table tfoot { display: table-footer-group; }
  body.print-plain .ld-print-table tr { display: table-row; }
  body.print-plain .ld-print-table td { display: table-cell; }
  body.print-plain .ld-print-header, body.print-plain .ld-print-footer { display: block; }
  body.print-plain .ld-print-header {
    padding: 4mm 10mm 8mm; box-sizing: border-box;
  }
  body.print-plain .ld-print-header img { height: 24px; object-fit: contain; display: block; }
  body.print-plain .ld-print-footer {
    padding: 6mm 10mm 4mm; box-sizing: border-box; text-align: center;
    font-size: 9.5px; color: var(--color-neutral-700); font-family: 'Archivo', sans-serif;
    border-top: 1px solid var(--color-divider);
  }
}
/* Direct children only (2026-09-27) — the old descendant selectors also
   turned every table INSIDE the page (report tables, cable table) into
   stacked blocks on screen. */
.ld-print-table, .ld-print-table > thead, .ld-print-table > tbody, .ld-print-table > tfoot,
.ld-print-table > * > tr, .ld-print-table > * > tr > td { display: block; width: 100%; margin: 0; padding: 0; border: 0; }
.ld-print-header, .ld-print-footer { display: none; }

/* — Dispatch list: manual verification checkboxes (2026-09-11) — print-only,
   nothing saved: an empty box the dispatch team ticks with a pen against
   each BOM/accessory/tool line while physically loading it. A styled
   <span>, not a real <input type="checkbox">, so it looks identical on
   screen and on the printed sheet across browsers instead of depending on
   each browser's own checkbox-in-print rendering. */
.verify-checkbox {
  display: inline-block;
  width: 14px; height: 14px;
  border: 1.5px solid var(--color-text);
  border-radius: 2px;
  flex-shrink: 0;
  vertical-align: middle;
}
.dispatch-verify-col { width: 44px; text-align: center; }
.dispatch-verify-list { display: flex; flex-direction: column; gap: 8px; }
.dispatch-verify-row { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }

@media print {
  /* Dispatch list: let the BOM/accessories tables break across pages
     instead of jumping to a fresh one (2026-09-11 — a real printed
     proposal showed 4 pages with a huge blank gap under each card). The
     shared ".card { break-inside: avoid; }" rule above is right for a
     short card, but these two grow with the proposal and can easily be
     taller than the *remaining* room on the current page while still
     shorter than a full page — avoid-inside then pushes the whole card to
     a fresh page, leaving whatever room was left on the page before it
     blank. This is the exact "page-1 packing" class of bug fixed for the
     customer proposal report several times (see build-notes.md).
     Scoped to .dispatch-card-table specifically (added alongside .card,
     only on the BOM/accessories cards — NOT the short special-tools/notes
     cards below, which stay on the plain .card avoid-whole-card behavior:
     they're always short enough that avoiding a split and jumping intact
     is the better (and gap-free, see below) choice for them, whereas a
     first attempt at also fragmenting them left an empty bordered sliver
     behind on the previous page when their heading had nothing to pair
     with in the remaining space). Same-specificity tie with the earlier
     .card rule resolved by this block coming later in the file.
     box-decoration-break:clone keeps the border/background correct on
     both sides of a break; the two rules below stop a break from landing
     mid-table-row or right after the heading with nothing following it. */
  .dispatch-card-table {
    break-inside: auto; page-break-inside: auto;
    box-decoration-break: clone; -webkit-box-decoration-break: clone;
  }
  .dispatch-card-table table tr { break-inside: avoid; page-break-inside: avoid; }
  .dispatch-card-table > .card-kicker {
    break-after: avoid; page-break-after: avoid;
    break-inside: avoid; page-break-inside: avoid;
  }
}

/* — Home page (Zoho-style sidebar + greeting + stat cards), added 2026-09-10 — */
.home-shell { display: flex; align-items: flex-start; min-height: calc(100vh - 61px); }
.home-sidebar {
  width: 220px; flex: 0 0 220px; background: var(--color-surface-2);
  border-right: 1px solid var(--color-divider); padding: var(--space-4) 0;
  position: sticky; top: 0; align-self: flex-start; min-height: calc(100vh - 61px);
}
.home-nav-group { margin-bottom: var(--space-4); }
.home-nav-heading {
  display: flex; align-items: center; justify-content: space-between; width: 100%;
  font-family: var(--font-heading); font-size: 15.6px; font-weight: 700; text-transform: none; letter-spacing: 0.01em;
  color: var(--color-neutral-600); background: none; border: none; cursor: pointer; text-align: left;
  padding: 5px var(--space-4); margin-bottom: 2px; border-radius: var(--radius-sm);
}
.home-nav-heading:hover { background: var(--color-neutral-100); }
/* Icon + label, grouped so the chevron (::after) stays the button's only
   other flex child and keeps landing flush right via justify-content. */
.home-nav-heading-label { display: inline-flex; align-items: center; gap: 9px; }
.home-nav-heading::after {
  content: '▸'; font-size: 9px; opacity: 0.6; margin-left: 8px; transition: transform 0.15s ease;
}
.home-nav-group.expanded .home-nav-heading::after { transform: rotate(90deg); }
.home-nav-links { display: none; }
.home-nav-group.expanded .home-nav-links { display: block; }
.home-nav-icon { width: 15px; height: 15px; flex: 0 0 auto; opacity: 0.7; }
.home-nav-link {
  display: flex; align-items: center; gap: 9px; padding: 9px var(--space-4); font-size: 14px; color: var(--color-text);
  border-left: 3px solid transparent;
}
.home-nav-link > .home-nav-icon { opacity: 0.75; }
.home-nav-link.active > .home-nav-icon { opacity: 1; }
.home-nav-link:hover { background: var(--color-neutral-100); text-decoration: none; }
.home-nav-link.active { border-left-color: var(--color-accent); color: var(--color-accent); font-weight: 700; background: var(--color-accent-100); }
.home-nav-soon { color: var(--color-neutral-600); }
.home-nav-soon::after {
  content: 'Soon'; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--color-neutral-500); background: var(--color-neutral-100); border-radius: 999px;
  padding: 1px 6px; margin-left: 8px; vertical-align: middle;
}

.home-main { flex: 1; min-width: 0; padding: var(--space-6) var(--space-8) 60px; }
.home-greeting h1 { margin-bottom: 2px; }
.home-welcome { color: rgba(32,30,29,0.65); font-size: 15px; margin-bottom: var(--space-6); }

.quick-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: var(--space-6); }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; margin-bottom: var(--space-6); }
.stat-card {
  background: var(--color-surface-2); border-left: 4px solid var(--color-accent);
  border-radius: var(--radius-md); box-shadow: var(--shadow-sm); padding: 14px 16px;
}
.stat-card-label { font-size: 12px; color: rgba(32,30,29,0.6); font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em; }
.stat-card-value { font-family: var(--font-heading); font-weight: 800; font-size: 24px; margin-top: 4px; }

.home-panels { display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--space-4); align-items: start; }
.home-panel-card { padding: var(--space-4) var(--space-4) var(--space-6); }

.pipeline-chart { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.pipeline-row { display: grid; grid-template-columns: 130px 1fr 28px; align-items: center; gap: 10px; font-size: 12.5px; }
.pipeline-row-label { color: rgba(32,30,29,0.75); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pipeline-row-track { background: var(--color-neutral-200); border-radius: 999px; height: 10px; overflow: hidden; }
.pipeline-row-fill { height: 100%; border-radius: 999px; }
.pipeline-row-count { text-align: right; font-weight: 700; }

.recent-list { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.recent-row {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: var(--radius-sm); color: var(--color-text);
}
.recent-row:hover { background: var(--color-neutral-100); text-decoration: none; }
.recent-row-name { font-weight: 700; font-size: 13.5px; }
.recent-row-meta { font-size: 11.5px; color: rgba(32,30,29,0.55); margin-top: 1px; }
.recent-row-status {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  border: 1px solid; border-radius: 999px; padding: 2px 8px; white-space: nowrap;
}

/* — Customers page (follow-up summary per customer), added 2026-09-10 — */
.followup-summary { display: flex; flex-direction: column; gap: 10px; padding: 10px 0; }
.followup-item {
  background: var(--color-surface-2); border: 1px solid var(--color-divider);
  border-radius: var(--radius-sm); padding: 10px 12px;
}
.followup-item-main { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-weight: 600; font-size: 13px; }
.followup-item-meta { font-size: 12px; color: rgba(32,30,29,0.6); margin-top: 4px; }
.followup-item-remarks { font-size: 12.5px; color: rgba(32,30,29,0.75); font-style: italic; margin-top: 4px; }
.followup-log-form { display: flex; gap: 8px; align-items: flex-end; margin-top: 8px; }
.followup-log-form textarea { flex: 1; min-height: 46px; resize: vertical; }

/* Explicit open/close follow-up card (2026-09-10, round 2) — replaces the
   old inferred-status .followup-item-main/-meta/-remarks layout above
   (left in place, unused, per this project's convention of not deleting
   superseded CSS) with a labeled-rows layout plus toggleable open/close
   forms and an on-demand history log. Used only on customers.php now that
   follow-ups have moved off the Proposals dashboard entirely. */
.followup-status-pill {
  font-size: 10.5px; font-weight: 700; border-radius: 999px; padding: 2px 9px;
  text-transform: uppercase; letter-spacing: 0.03em;
}
.followup-item-top { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-weight: 600; font-size: 13px; margin-bottom: 6px; }
.followup-item-body { display: flex; flex-direction: column; gap: 3px; margin-bottom: 8px; }
.followup-row { font-size: 12.5px; display: flex; gap: 6px; }
.followup-row-label { color: rgba(32,30,29,0.55); min-width: 78px; flex: 0 0 auto; }
.followup-row-muted { color: rgba(32,30,29,0.4); font-style: italic; }
.followup-item-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.followup-history-toggle {
  background: none; border: none; padding: 5px 4px; font-size: 12px; font-weight: 600;
  color: var(--color-accent); cursor: pointer;
}
.followup-history-toggle:hover { text-decoration: underline; }
.followup-form {
  margin-top: 10px; padding: 10px; background: var(--color-surface); border: 1px solid var(--color-divider);
  border-radius: var(--radius-sm); display: flex; flex-direction: column; gap: 6px;
}
.followup-form label { font-size: 11.5px; font-weight: 700; color: rgba(32,30,29,0.6); }
.followup-form-actions { display: flex; gap: 8px; margin-top: 2px; }
.followup-history {
  margin-top: 10px; padding: 10px; background: var(--color-surface); border: 1px solid var(--color-divider);
  border-radius: var(--radius-sm); display: flex; flex-direction: column; gap: 8px; max-height: 260px; overflow-y: auto;
}
.followup-history-entry { font-size: 12px; border-bottom: 1px dashed var(--color-divider); padding-bottom: 6px; }
.followup-history-entry:last-child { border-bottom: none; padding-bottom: 0; }
.followup-history-kind {
  display: inline-block; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  border-radius: 999px; padding: 1px 8px; margin-right: 6px;
}
.followup-history-kind-open { background: rgba(41,128,185,0.12); color: #1f6391; }
.followup-history-kind-close { background: rgba(60,150,90,0.14); color: #2f7a4d; }
.followup-history-date { font-weight: 600; }
.followup-history-remarks { font-size: 12px; color: rgba(32,30,29,0.75); margin-top: 3px; }
.followup-history-when { font-size: 10.5px; color: rgba(32,30,29,0.45); margin-top: 3px; }

/* Highlight animation for a customer row deep-linked from the Proposals
   dashboard's "Follow-up →" row-menu link (see focusFromQuery() in
   customers.php's script). Brief, not persistent — removed after 2s. */
@keyframes custRowFlash {
  0% { background: rgba(201,138,31,0.28); }
  100% { background: transparent; }
}
.cust-row-flash { animation: custRowFlash 2s ease-out; }

.cust-section-heading {
  font-size: 15px; font-weight: 800; font-family: var(--font-heading); color: var(--color-text);
  display: flex; align-items: center; gap: 8px; margin-bottom: var(--space-3);
  width: 100%; background: none; border: none; padding: 4px 0; cursor: pointer; text-align: left;
}
.cust-section-heading:hover { color: var(--color-accent); }
.cust-section-chevron { font-size: 12px; color: rgba(32,30,29,0.45); width: 12px; display: inline-block; }
.cust-section-count {
  font-size: 11.5px; font-weight: 700; color: rgba(32,30,29,0.55);
  background: var(--color-neutral-100); border-radius: 999px; padding: 1px 9px;
}

/* Next-7-days ribbon — a horizontal strip of day blocks under the
   Follow-up customers heading, added 2026-09-10. */
.followup-ribbon-wrap { margin-bottom: var(--space-5); }
.followup-ribbon-title {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: rgba(32,30,29,0.55); margin-bottom: 6px;
}
.followup-ribbon { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 6px; }
.ribbon-day {
  flex: 0 0 168px; background: var(--color-surface-2); border: 1px solid var(--color-divider);
  border-radius: var(--radius-md); padding: 10px 12px; min-height: 90px;
}
.ribbon-day.is-today { border-color: var(--color-accent); box-shadow: 0 0 0 1px var(--color-accent) inset; }
.ribbon-day-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.ribbon-day-label { font-size: 12px; font-weight: 700; }
.ribbon-day.is-today .ribbon-day-label { color: var(--color-accent); }
.ribbon-day-count {
  font-size: 10.5px; font-weight: 700; color: #fff; background: #c98a1f;
  border-radius: 999px; padding: 1px 7px;
}
.ribbon-day-items { display: flex; flex-direction: column; gap: 6px; }
.ribbon-item { font-size: 11.5px; }
.ribbon-item-name { font-weight: 600; line-height: 1.25; }
.ribbon-item-phone { display: block; color: rgba(32,30,29,0.6); font-size: 11px; }
.ribbon-empty { font-size: 11.5px; color: rgba(32,30,29,0.4); font-style: italic; }

@media (max-width: 900px) {
  .home-shell { flex-direction: column; }
  .home-sidebar {
    width: 100%; flex: none; position: static; min-height: 0; border-right: none;
    border-bottom: 1px solid var(--color-divider); display: flex; overflow-x: auto;
  }
  .home-nav-group { margin-bottom: 0; margin-right: var(--space-4); white-space: nowrap; }
  .home-panels { grid-template-columns: 1fr; }
  .followup-log-form { flex-direction: column; align-items: stretch; }
  .ribbon-day { flex-basis: 140px; }
}

/* BOM auto-fill card (2026-09-25) */
.bom-autofill-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; }
.bom-autofill-list li { line-height: 1.45; }
.bom-autofill-list .stage-badge { margin-right: 4px; }

/* Simple Quotation — proposal-style grouped list, no table (2026-09-25) */
.qot-group-head { display: flex; justify-content: space-between; gap: 12px; font-weight: 700; font-size: 13px; padding-bottom: 3px; border-bottom: 1px solid #ccc; }
.qot-group-sub { font-size: 11.5px; opacity: 0.7; margin-top: 3px; }
.qot-items { margin: 5px 0 0; padding-left: 16px; font-size: 12px; opacity: 0.85; }
.qot-items li { margin-bottom: 2px; }

/* Direct PDF download (2026-09-25) — pdf-download.js adds body.pdf-rendering
   while html2pdf captures a print-only container, so it has real layout. */
body.pdf-rendering #print-report, body.pdf-rendering #print-quotation { display: block !important; background: #fff; }

/* Stage sections — colour-coded status + collapsed by default (2026-09-25) */
.stage-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.stage-legend { font-size: 11.5px; opacity: 0.75; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.stage-legend .dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-left: 6px; }
.stage-legend .dot:first-child { margin-left: 0; }
.dot.ok { background: #2e7d32; } .dot.todo { background: #c62828; } .dot.opt { background: #e0a100; }
.stage-expand-btn { padding: 4px 10px; font-size: 12px; }
details.stage-section { border-left-width: 5px; }
details.stage-section.status-ok { border-left-color: #2e7d32; }
details.stage-section.status-todo { border-left-color: #c62828; }
details.stage-section.status-opt { border-left-color: #e0a100; }
details.stage-section.status-info { border-left-color: #9e9e9e; }
.stage-badge.opt { background: #fff4d6; color: #7a5600; }
.stage-badge.info { background: #eeeeee; color: #555; }
.stage-badge { max-width: 60%; overflow: hidden; text-overflow: ellipsis; }

/* ─────────────────────────────────────────────────────────────────────
 * Layout Designer — proposal link, panel pick, Cable route & earthing
 * (2026-09-27). See assets/js/layout-designer.js.
 * ───────────────────────────────────────────────────────────────────── */
.ld-link-bar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 8px; }
.ld-link-bar .input { width: auto; min-width: 320px; flex: 0 1 420px; }
.ld-link-label { margin: 0; font-size: 11.5px; color: var(--ld-muted, rgba(32,30,29,0.6)); text-transform: uppercase; letter-spacing: .3px; font-weight: 600; }
.ld-link-chip { display: inline-flex; align-items: center; gap: 4px; padding: 4px 10px; border-radius: 999px; background: var(--color-accent-100, #fde9e2); color: var(--color-accent-700, #a33); font-size: 12.5px; font-weight: 700; }
.ld-hint-inline { font-size: 11.5px; color: var(--ld-muted, rgba(32,30,29,0.6)); }
.ld-src { font-size: 10px; font-weight: 700; text-transform: none; letter-spacing: 0; padding: 1px 6px; border-radius: 999px; margin-left: 4px; vertical-align: 1px; }
.ld-src:empty { display: none; }
.ld-src.is-locked { background: #e8eef6; color: #2c4f7c; }
.ld-src.is-from { background: #e6f2ea; color: #1c6b2a; }
.ld-src.is-edited { background: #fff1d6; color: #8a5a00; }
.input.is-locked { background: transparent; border: 1px dashed var(--color-neutral-500, #999); color: var(--color-neutral-700, #555); cursor: not-allowed; }
.ld-link-banner { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: var(--space-4); padding: 10px 14px; border-radius: var(--radius-md); font-size: 13px; }
.ld-link-banner.is-changed { background: #fff6e0; border: 1px solid #f0cf85; color: #5c4200; }
.tb-linked { float: right; font-size: 11px; font-weight: 600; opacity: .85; text-transform: none; letter-spacing: 0; }
.ld-panel-pick { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: -4px 0 12px; }
.ld-panel-pick label { margin: 0; font-size: 12px; font-weight: 600; }
.ld-panel-pick select.input { width: auto; min-width: 280px; max-width: 520px; }

.ld-cable-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.ld-unit-seg .seg-opt { padding: 5px 12px; }
.ld-cable-body { display: grid; grid-template-columns: minmax(330px, 4fr) minmax(0, 7fr); gap: 16px; align-items: start; }
.ld-cable-inputs .field { margin-bottom: 0; }
.ld-cable-inputs .field label { font-size: 11px; margin-bottom: 2px; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ld-cable-inputs .input { min-height: 30px; height: 30px; padding: 3px 8px; font-size: 13px; }
.ld-cable-inputs .ld-grid { gap: 6px 8px; margin-bottom: 6px; }
.ld-cable-inputs .ld-grid.ld-c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ld-cable-inputs .ld-hint-sm { font-size: 11.5px; margin: 4px 0 6px; }
.ld-cable-inputs .ld-grp-sum { max-width: 50%; }
.ld-pit-row { padding-top: 4px; border-top: 1px dashed var(--color-divider); }
.ld-cable-warn { background: #fff6e0; border: 1px solid #f0cf85; color: #5c4200; border-radius: var(--radius-md); padding: 8px 12px; font-size: 12.5px; margin-bottom: 10px; line-height: 1.5; }
.ld-cable-draw { display: grid; gap: 10px; }
.ld-cable-draw .ld-svg-shell { width: 100%; box-sizing: border-box; }
.ld-cable-svg { cursor: crosshair; width: 100%; max-height: 520px; }
.ld-side-svg.ld-elev-svg { width: 100%; max-width: none; height: auto; }
.ld-click-mode { font-size: 12px; display: flex; gap: 14px; flex-wrap: wrap; align-items: center; margin: 6px 0; color: var(--ld-muted); }
.ld-click-mode label { display: inline-flex; gap: 4px; align-items: center; color: var(--color-text); cursor: pointer; }
.ld-cable-tots { margin: 10px 0 6px; }
.ld-cable-table-wrap { overflow-x: auto; }
.ld-cable-results { margin-top: 12px; }
.ld-cable-table td { vertical-align: middle; }
.ld-cable-table td.num, .ld-cable-table th { text-align: right; white-space: nowrap; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12px; }
.ld-cable-table th:first-child, .ld-cable-table td:first-child { text-align: left; font-family: inherit; white-space: normal; min-width: 220px; }
.ld-cab-sw { display: inline-block; width: 12px; height: 4px; border-radius: 2px; margin-right: 6px; vertical-align: middle; }
.ld-cab-sw-dc { background: #d32f2f; } .ld-cab-sw-ac { background: #1565c0; } .ld-cab-sw-earth { background: #2e7d32; }
.ld-cab-sw-la { background: repeating-linear-gradient(90deg, #795548 0 4px, transparent 4px 7px); }
.ld-ov-input { width: 74px; min-height: 28px; height: 28px; padding: 2px 6px; text-align: right; display: inline-block; }
.ld-ov-cell { white-space: nowrap; }
.ld-print-inline { display: none; }
@media (max-width: 900px) {
  .ld-cable-body { grid-template-columns: minmax(0, 1fr); }
  .ld-link-bar .input { min-width: 0; flex: 1 1 100%; }
}
@media print {
  #cableRouteCard { order: 4; break-before: page; page-break-before: always; }
  .ld-wrap > p.ld-hint { order: 5; }
  #cableRouteCard .ld-cable-empty, #cableRouteCard.ld-cable-empty, #ldLinkBanner, .ld-link-bar { display: none !important; }
  .ld-cable-body { display: block; }
  .ld-cable-card { border: 0; box-shadow: none; padding: 0; }
  .ld-cable-sheet { break-inside: avoid; page-break-inside: avoid; }
  .ld-cable-sheet .ld-svg-shell { padding: 4px; margin-bottom: 4px; }
  .ld-cable-svg { max-height: 115mm; }
  .ld-elev-svg { max-height: 70mm; }
  .ld-cable-table { font-size: 9.5px; }
  .ld-cable-table td, .ld-cable-table th { padding: 2px 4px; }
  .ld-cable-table td.num { font-size: 9.5px; }
  .ld-print-inline { display: inline; }
  .ld-cable-warn { font-size: 10px; padding: 4px 8px; }
  .ld-src.is-locked, .ld-src.is-from { display: none; }
}

/* ─────────────────────────────────────────────────────────────────────
 * Layout Designer — 3-step flow (2026-09-27): ① Site & building →
 * ② Panels → ③ Wiring & earthing, as numbered collapsible stages.
 * ───────────────────────────────────────────────────────────────────── */
.ld-stage-tools { font-size: 12.5px; color: var(--ld-muted); margin: 0 0 8px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.ld-stage { border: 1px solid var(--color-divider); border-radius: var(--radius-lg, 12px); background: var(--color-surface, #fff); margin-bottom: var(--space-4); }
.ld-stage > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; padding: 12px 16px; user-select: none; flex-wrap: wrap; }
.ld-stage > summary::-webkit-details-marker { display: none; }
.ld-stage > summary::after { content: '▸'; margin-left: 4px; color: var(--ld-muted); transition: transform .15s; order: 9; }
.ld-stage[open] > summary::after { transform: rotate(90deg); }
.ld-stage[open] > summary { border-bottom: 1px solid var(--color-divider); }
.ld-stage-no { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 50%; background: var(--color-accent); color: #fff; font-weight: 800; font-size: 14px; flex-shrink: 0; }
.ld-stage-title { font-family: var(--font-heading, inherit); font-weight: 800; font-size: 18px; color: var(--color-text); }
.ld-stage-sub { font-size: 12px; color: var(--ld-muted); flex: 1 1 260px; }
.ld-stage > summary .stage-badge { margin-left: auto; max-width: 45%; }
.ld-stage-body { padding: 14px 16px 16px; }
.ld-stage-body > .card:last-of-type { margin-bottom: 0; }
.ld-stage-next { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.ld-site-body { display: grid; grid-template-columns: minmax(330px, 4fr) minmax(0, 7fr); gap: 16px; align-items: start; }
.ld-site-inputs .field { margin-bottom: 0; }
.ld-site-inputs .field label { font-size: 11px; margin-bottom: 2px; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ld-site-inputs .input { min-height: 30px; height: 30px; padding: 3px 8px; font-size: 13px; }
.ld-site-inputs .ld-grid { gap: 6px 8px; margin-bottom: 6px; }
.ld-site-inputs .ld-grid.ld-c3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ld-site-inputs .ld-hint-sm { font-size: 11.5px; margin: 2px 0 6px; }
.ld-site-inputs .btn-sm { padding: 4px 10px; font-size: 12px; }
.ld-site-inputs .ld-obstruction-card { padding: 6px 8px; margin-bottom: 6px; }
.ld-site-inputs .ld-obstruction-row { gap: 6px 8px; margin-bottom: 6px; }
.ld-site-inputs .ld-obstruction-row.ld-ob-r1, .ld-site-inputs .ld-obstruction-row.ld-ob-r2 { grid-template-columns: repeat(3, minmax(0,1fr)); }
.ld-site-inputs .ld-side-box { margin: 0 0 6px; }
.ld-site-inputs .ld-side-head { margin-bottom: 2px; font-size: 11px; }
.ld-site-sec { border: 1px solid var(--color-divider); border-radius: var(--radius-md); padding: 8px; margin: 10px 0; background: var(--color-surface-2, #faf8f6); }
.ld-site-sec .ld-sec-head { margin-bottom: 6px; }
.ld-building-grp > summary .ld-grp-title { font-size: 12.5px; }
.ld-bld-unit { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; margin-bottom: 8px; }
.ld-site-visual { position: sticky; top: 8px; }
.ld-site-visual .ld-svg-shell { margin-bottom: 10px; }
.ld-site-svg { width: 100%; max-height: 520px; }
.ld-site-empty { padding: 40px 20px; text-align: center; color: var(--ld-muted); font-size: 13px; }
.ld-sec-title { font-weight: 800; font-size: 15px; margin-right: 8px; }
@media (max-width: 900px) { .ld-site-body { grid-template-columns: minmax(0, 1fr); } .ld-site-visual { position: static; } }
@media print {
  .ld-stage-tools, .ld-stage-next, .ld-stage-sub, .ld-stage > summary .stage-badge, .ld-stage > summary::after { display: none !important; }
  .ld-stage { border: 0; margin: 0; background: none; }
  .ld-stage > summary { padding: 0 0 6px; border: 0 !important; }
  .ld-stage-no { width: 22px; height: 22px; font-size: 12px; }
  .ld-stage-title { font-size: 16px; }
  .ld-stage-body { padding: 0; }
  #stage1 { order: 3; break-before: page; page-break-before: always; }
  #stage2 { order: 4; break-before: page; page-break-before: always; }
  #stage3 { order: 5; break-before: page; page-break-before: always; }
  #stage3 #cableRouteCard { break-before: auto; page-break-before: auto; }
  #stage2 #rooftopSectionsCard, #stage3 .ld-cable-card { break-inside: auto; page-break-inside: auto; }
  .ld-stage > summary { break-after: avoid; page-break-after: avoid; }
  .ld-wrap > p.ld-hint { order: 6; }
  .ld-site-body { display: block; }
  .ld-site-visual { position: static; }
  .ld-site-sheet { break-inside: avoid; page-break-inside: avoid; }
  .ld-site-svg { max-height: 120mm; }
  .ld-site-sheet .ld-elev-svg { max-height: 60mm; }
  .ld-site-sheet .ld-sec-name-print { display: none; }
  #stage3 .ld-sec-name-print { display: none; }
}

/* ─────────────────────────────────────────────────────────────────────
 * Layout Designer — guided wizard, North setting, floor-wise wiring view
 * (2026-09-27, round 5).
 * ───────────────────────────────────────────────────────────────────── */
.ld-wiz-cta { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; background: #fff6e0; border: 1px solid #f0cf85; border-radius: var(--radius-md); padding: 10px 14px; margin-bottom: 10px; font-size: 13px; }
.ld-wiz-overlay { position: fixed; inset: 0; background: rgba(20,18,16,.55); z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 16px; }
.ld-wiz { background: var(--color-surface, #fff); border-radius: 14px; width: min(900px, 100%); max-height: calc(100vh - 32px); display: flex; flex-direction: column; box-shadow: 0 20px 60px rgba(0,0,0,.35); overflow: hidden; }
.ld-wiz-top { display: flex; align-items: center; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--color-divider); }
.ld-wiz-dots { display: flex; gap: 4px; flex: 1; flex-wrap: wrap; }
.ld-wiz-dots i { width: 18px; height: 5px; border-radius: 3px; background: var(--color-neutral-300, #ddd); }
.ld-wiz-dots i.done { background: #9fcfae; } .ld-wiz-dots i.on { background: var(--color-accent); }
.ld-wiz-x { border: 0; background: none; font-size: 24px; line-height: 1; cursor: pointer; color: var(--ld-muted, #777); }
.ld-wiz-body { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 20px; padding: 18px 20px; overflow: auto; }
.ld-wiz-q h3 { margin: 0 0 6px; font-size: 20px; }
.ld-wiz-help { font-size: 13.5px; color: var(--color-neutral-700, #555); margin: 0 0 14px; line-height: 1.5; }
.ld-wiz-fields { display: flex; flex-direction: column; gap: 10px; }
.ld-wiz-flabel { font-size: 12px; font-weight: 700; margin-bottom: -4px; }
.ld-wiz-choices { display: flex; flex-wrap: wrap; gap: 8px; }
.ld-wiz-choice { border: 2px solid var(--color-divider); background: var(--color-surface-2, #f6f4f2); border-radius: 10px; padding: 10px 14px; font-size: 14px; font-weight: 700; cursor: pointer; min-width: 90px; }
.ld-wiz-choice.on { border-color: var(--color-accent); background: #fff1ec; color: var(--color-accent-700, #a33); }
.ld-wiz-check { display: inline-flex; gap: 6px; align-items: center; font-size: 14px; padding: 6px 10px; border: 1px solid var(--color-divider); border-radius: 8px; }
.ld-wiz-num { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; font-weight: 600; }
.ld-wiz-num .input { max-width: 200px; font-size: 16px; }
.ld-wiz-obs { display: grid; grid-template-columns: 1.4fr repeat(5, minmax(0,1fr)) auto; gap: 6px; align-items: end; font-size: 11px; }
.ld-wiz-obs label { display: flex; flex-direction: column; gap: 2px; }
.ld-wiz-obs .input { min-height: 30px; height: 30px; padding: 3px 6px; font-size: 13px; }
.ld-wiz-pic { background: #faf8f5; border: 1px solid var(--color-divider); border-radius: 12px; display: flex; align-items: center; justify-content: center; padding: 10px; min-height: 220px; }
.ld-wiz-svg { width: 100%; max-width: 360px; height: auto; }
.ld-wiz-foot { display: flex; justify-content: space-between; padding: 12px 16px; border-top: 1px solid var(--color-divider); }
.ld-wiz-err { color: var(--ld-danger, #c62828); font-weight: 700; font-size: 13px; }
.ld-wiz-sum { margin: 0; padding-left: 18px; font-size: 13.5px; line-height: 1.7; }
@media (max-width: 720px) { .ld-wiz-body { grid-template-columns: minmax(0,1fr); } .ld-wiz-pic { order: -1; min-height: 160px; } .ld-wiz-obs { grid-template-columns: repeat(3, minmax(0,1fr)); } }
.ld-north-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; font-size: 12px; }
.ld-north-row label { font-weight: 700; margin: 0; }
.ld-north-row select.input { width: auto; min-height: 30px; height: 30px; padding: 3px 24px 3px 8px; }
.ld-floor-svg { width: 100%; height: auto; display: block; }
.ld-cab-more { border: 1px solid var(--color-divider); border-radius: var(--radius-md); margin: 10px 0; background: var(--color-surface, #fff); }
.ld-cab-more > summary { cursor: pointer; padding: 8px 12px; font-weight: 700; font-size: 13px; }
.ld-cab-more > *:not(summary) { padding: 0 10px 10px; }
.ld-cab-list { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
.ld-cab-line { display: flex; justify-content: space-between; gap: 14px; padding: 10px 12px; border: 1px solid var(--color-divider); border-left: 5px solid #999; border-radius: var(--radius-md); background: var(--color-surface, #fff); flex-wrap: wrap; }
.ld-cab-line.ld-cab-dc { border-left-color: #d32f2f; } .ld-cab-line.ld-cab-ac { border-left-color: #1565c0; } .ld-cab-line.ld-cab-earth { border-left-color: #2e7d32; } .ld-cab-line.ld-cab-la { border-left-color: #795548; }
.ld-cab-line-main { display: flex; gap: 8px; flex: 1 1 380px; font-size: 13px; }
.ld-cab-route { font-size: 12px; color: var(--ld-muted); margin-top: 2px; }
.ld-cab-math { font-size: 12.5px; margin-top: 3px; }
.ld-cab-line-total { text-align: right; font-size: 15px; min-width: 170px; }
.ld-cab-ov { font-size: 11.5px; color: var(--ld-muted); margin-top: 4px; }
@media print {
  .ld-wiz-cta, .ld-cab-ov { display: none !important; }
  .ld-cab-more { border: 0; } .ld-cab-more > summary { padding: 4px 0; }
  .ld-cab-line { break-inside: avoid; page-break-inside: avoid; padding: 5px 8px; }
  .ld-cab-math, .ld-cab-line-main { font-size: 10.5px; }
  .ld-floor-svg { max-height: 120mm; }
}
/* wizard — manual table placement (2026-09-27) */
.ld-wiz-count { font-size: 13.5px; padding: 6px 10px; background: #eef5fb; border-radius: 8px; }
.ld-wiz-tbl { display: grid; grid-template-columns: auto repeat(4, minmax(0,1fr)); gap: 6px 8px; align-items: end; font-size: 11px; padding: 6px 8px; border: 1px solid var(--color-divider); border-radius: 8px; }
.ld-wiz-tbl:has(select) { grid-template-columns: auto repeat(5, minmax(0,1fr)); }
.ld-wiz-tbl label { display: flex; flex-direction: column; gap: 2px; }
.ld-wiz-tbl .input { min-height: 30px; height: 30px; padding: 3px 6px; font-size: 13px; }
.ld-wiz-tbl > b { align-self: center; font-size: 12.5px; }
.ld-wiz-tbl > .ld-muted-inline, .ld-wiz-tbl > .ld-linkbtn { grid-column: span 2; align-self: center; }
@media (max-width: 720px) { .ld-wiz-tbl, .ld-wiz-tbl:has(select) { grid-template-columns: repeat(2, minmax(0,1fr)); } }

/* ---- Layout Designer round 8 (2026-09-27): structure tables + 3D cable view ---- */
.ld-struct-box{margin-top:10px;padding:10px 12px;border:1px dashed var(--ld-line,#d8d2c8);border-radius:8px;background:#fcfbf9}
.ld-struct-box .ld-hint{margin:6px 0 0}
.ld-struct-order{margin-top:8px;font-size:13px}
.ld-struct-order ul,.ld-struct-order-list{margin:4px 0 0 18px;padding:0}
.ld-struct-order li,.ld-struct-order-list li{margin:2px 0;font-size:13px}
.ld-wiz-tsize{display:flex;flex-direction:column;gap:6px;margin-bottom:6px}
.ld-wiz-tsize-row{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.ld-wiz-tsize-r{width:40px;font-size:11px;font-weight:700;color:#777}
.ld-wiz-choice.ld-wiz-tcell{display:flex;align-items:center;gap:6px;padding:5px 8px;min-width:96px}
.ld-wiz-tcell svg{flex:none}
.ld-wiz-tcell span{display:flex;flex-direction:column;line-height:1.15;font-weight:800;font-size:13px}
.ld-wiz-tcell small{font-weight:500;font-size:10.5px;color:#777}
.ld-cab-views{display:flex;gap:0;margin:0 0 8px}
.ld-seg{border:1px solid var(--ld-line,#d8d2c8);background:#fff;padding:5px 12px;font:inherit;font-size:12.5px;font-weight:700;cursor:pointer;color:#444}
.ld-seg:first-child{border-radius:6px 0 0 6px}.ld-seg:last-child{border-radius:0 6px 6px 0}
.ld-seg+.ld-seg{border-left:0}
.ld-seg.on{background:#1d4f7a;border-color:#1d4f7a;color:#fff}
.ld-iso-ctl{display:flex;align-items:center;flex-wrap:wrap;gap:0;margin:0 0 6px;font-size:12.5px}
.ld-iso-ctl>span{margin-right:6px;font-weight:700;color:#555}
.ld-iso-ctl .ld-iso-sep{margin-left:14px}
.ld-iso-chk{display:inline-flex;align-items:center;gap:4px;margin-right:10px;cursor:pointer}
.ld-iso-chk .sw{display:inline-block;width:14px;height:4px;border-radius:2px}
.ld-iso-svg{width:100%;height:auto;display:block;background:#fff}
.ld-print-only{display:none}
@media print{.ld-print-only{display:block !important}.ld-cab-views,.ld-iso-ctl{display:none !important}}
@media (max-width:640px){.ld-wiz-choice.ld-wiz-tcell{min-width:80px;padding:4px 6px}.ld-iso-ctl{gap:4px}}
@media print{.ld-iso-svg{max-height:125mm}}
details.share-sec { background: #fff; }
/* Guided calculation (2026-09-27) — live system panel */
.cg-pic { align-items: stretch; justify-content: flex-start; }
.cg-live { width: 100%; font-size: 13px; }
.cg-live-h { font-weight: 800; font-size: 13.5px; margin-bottom: 6px; }
.cg-row { display: flex; justify-content: space-between; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--color-divider); }
.cg-row span { color: var(--color-neutral-700, #666); }
.cg-row b { text-align: right; }
.cg-muted { font-weight: 400; opacity: .65; }
@media (max-width: 700px) { .ld-wiz-body { grid-template-columns: 1fr; } }

/* ---- Quotation blocks + Elenserve scope of work (2026-09-27, round 10) —
   assets/js/quote-blocks.js; used in the proposal's Itemized quotation and
   in the Simple quotation. ---- */
.qb-wrap, .qb-scope { --qb-ink: #16324F; --qb-muted: #5A7186; --qb-line: #D7E0E7; --qb-gen: #E8A33D; --qb-gen-pale: #FDF1DC; --qb-bos: #2F7D5D; --qb-bos-pale: #E4F2EB; color: var(--qb-ink); }
.qb-wrap { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.qb-block { border: 1px solid var(--qb-line); border-radius: 10px; overflow: hidden; background: #fff; }
.qb-head { display: flex; align-items: center; gap: 10px; padding: 7px 10px; }
.qb-block-gen .qb-head { background: linear-gradient(90deg, var(--qb-gen-pale), #fff); border-bottom: 2px solid var(--qb-gen); }
.qb-block-bos .qb-head { background: linear-gradient(90deg, var(--qb-bos-pale), #fff); border-bottom: 2px solid var(--qb-bos); }
.qb-num { flex: none; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; color: #fff; }
.qb-block-gen .qb-num { background: var(--qb-gen); } .qb-block-bos .qb-num { background: var(--qb-bos); }
.qb-head-t { flex: 1; min-width: 0; }
.qb-title { font-weight: 800; font-size: 1.08em; line-height: 1.2; }
.qb-sub { font-size: 0.82em; color: var(--qb-muted); }
.qb-price { text-align: right; }
.qb-total { font-weight: 800; font-size: 1.15em; }
.qb-tax { font-size: 0.74em; color: var(--qb-muted); white-space: nowrap; }
.qb-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; padding: 7px; }
.qb-block-gen .qb-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.qb-card { border: 1px solid var(--qb-line); border-radius: 8px; padding: 6px 8px; background: #fbfcfd; break-inside: avoid; page-break-inside: avoid; display: flex; flex-direction: column; gap: 3px; }
.qb-card-top { display: flex; gap: 8px; align-items: flex-start; }
.qb-ico { flex: none; width: 26px; height: 26px; padding: 3px; border-radius: 7px; }
.qb-block-gen .qb-ico { color: #b06f10; background: var(--qb-gen-pale); } .qb-block-bos .qb-ico { color: var(--qb-bos); background: var(--qb-bos-pale); }
.qb-card-title { min-width: 0; }
.qb-cat { font-size: 0.72em; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--qb-muted); }
.qb-name { font-weight: 700; font-size: 0.88em; line-height: 1.25; }
.qb-qty { font-weight: 600; color: var(--qb-muted); white-space: nowrap; }
.qb-feats { list-style: none; margin: 0; padding: 0; font-size: 0.8em; line-height: 1.3; }
.qb-feats li { display: flex; gap: 4px; align-items: flex-start; margin: 1px 0; }
.qb-tick { flex: none; width: 11px; color: var(--qb-bos, #2F7D5D); font-weight: 800; line-height: 1.3; }
.qb-warranty { margin-top: auto; font-size: 0.74em; font-weight: 700; padding: 2px 7px; border-radius: 999px; align-self: flex-start; }
.qb-block-gen .qb-warranty { background: var(--qb-gen-pale); color: #8a5a0e; } .qb-block-bos .qb-warranty { background: var(--qb-bos-pale); color: #22603f; }
.qb-grand { display: flex; justify-content: space-between; align-items: center; padding: 7px 12px; border-radius: 10px; background: var(--qb-ink); color: #fff; font-weight: 700; }
.qb-grand strong { font-size: 1.2em; }
.qb-scope { margin-top: 2px; }
.qb-scope-h { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.qb-scope-badge { background: var(--qb-ink); color: #fff; font-weight: 800; padding: 3px 12px; border-radius: 999px; font-size: 1em; }
.qb-scope-sub { font-size: 0.85em; color: var(--qb-muted); }
.qb-scope-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.qb-step { display: flex; gap: 6px; align-items: flex-start; border: 1px solid var(--qb-line); border-radius: 8px; padding: 6px; background: linear-gradient(180deg, #fff, #f4f8fa); break-inside: avoid; page-break-inside: avoid; }
.qb-step-ico { position: relative; flex: none; }
.qb-step-ico .qb-ico { color: var(--qb-ink); background: #e8eef3; }
.qb-step-n { position: absolute; right: -4px; top: -5px; width: 14px; height: 14px; border-radius: 50%; background: var(--qb-gen); color: #fff; font-size: 9px; font-weight: 800; display: flex; align-items: center; justify-content: center; }
.qb-step-t { font-weight: 800; font-size: 0.82em; line-height: 1.2; }
.qb-step-x { font-size: 0.74em; color: var(--qb-muted); line-height: 1.3; }
/* the quotation card may run over a page — keep each item card whole instead */
#print-report .rpt-quote-card { break-inside: auto; page-break-inside: auto; }
#print-report.pdf-a5 .qb-wrap, #print-report.pdf-a5 .qb-scope { font-size: 10.5px; }
#print-report.pdf-a5 .qb-scope-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#print-report.pdf-mobile .qb-wrap, #print-report.pdf-mobile .qb-scope { font-size: 15px; }
#print-report.pdf-mobile .qb-grid, #print-report.pdf-mobile .qb-scope-grid { grid-template-columns: 1fr; }
#print-report.pdf-mobile .qb-head { flex-wrap: wrap; } #print-report.pdf-mobile .qb-price { text-align: left; width: 100%; padding-left: 34px; }
#print-quotation .qb-wrap { margin-bottom: 12px; font-size: 12.5px; }
#print-quotation .qb-scope { margin: 14px 0 4px; font-size: 12.5px; }
.handover-tag { display: inline-block; margin-top: 4px; font-size: 10.5px; font-weight: 700; color: #0e7490; background: #e0f2fe; border-radius: 999px; padding: 1px 8px; }

/* ---- Installation details walk-through (2026-09-27) — serials.php + assets/js/install-walk.js ---- */
.iw-steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin-bottom: var(--space-4); position: sticky; top: 0; z-index: 5; background: var(--color-bg, #f5f3f0); padding: 6px 0; }
.iw-step-btn { display: flex; align-items: center; gap: 8px; border: 2px solid var(--color-divider); background: #fff; border-radius: 10px; padding: 8px 10px; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; text-align: left; color: inherit; }
.iw-step-btn.on { border-color: var(--color-accent); background: #fff1ec; }
.iw-dot { flex: none; width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: #e5e1dc; font-size: 12px; font-weight: 800; }
.iw-step-btn.on .iw-dot { background: var(--color-accent); color: #fff; }
.iw-step-btn.ok .iw-dot { background: #2f7d5d; color: #fff; }
.iw-h { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.iw-hint { font-size: 13.5px; background: #eef5fb; border-radius: 8px; padding: 8px 12px; margin-bottom: 10px; }
.iw-count { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 13.5px; font-weight: 700; padding: 6px 10px; background: #eef5fb; border-radius: 8px; margin-bottom: 6px; }
.iw-group { font-size: 11.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; opacity: .6; margin: 10px 0 4px; }
.iw-item { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border: 1px solid var(--color-divider); border-radius: 8px; margin-bottom: 5px; cursor: pointer; background: #fff; }
.iw-item input { width: 20px; height: 20px; flex: none; accent-color: #2f7d5d; }
.iw-item.ok { background: #eef7f1; border-color: #b9dcc7; }
.iw-item-name { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.iw-item-name small { font-size: 11.5px; opacity: .6; }
.iw-item-qty { font-weight: 700; white-space: nowrap; font-size: 13px; }
.iw-app { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.35fr); gap: 10px; margin-top: 10px; }
.iw-app .field { display: flex; flex-direction: column; gap: 3px; margin: 0; font-size: 12.5px; font-weight: 600; }
.iw-pw { display: flex; gap: 4px; align-items: center; } .iw-pw .input { flex: 1; min-width: 0; }
.iw-nav { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: var(--space-4); padding-top: 10px; border-top: 1px solid var(--color-divider); }
.iw-progress { font-size: 13px; opacity: .7; }
.iw-sheet { display: none; }
@media (max-width: 700px) {
  .iw-steps { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .iw-step-btn { flex-direction: column; gap: 3px; font-size: 11px; padding: 6px 4px; text-align: center; }
  .iw-app { grid-template-columns: 1fr; }
}
/* customer handover sheet — printed alone */
@media print {
  body.iw-printing > *:not(#iwSheet) { display: none !important; }
  body.iw-printing .page > *:not(#iwSheet) { display: none !important; }
  body.iw-printing .page { padding: 0 !important; margin: 0 !important; }
  body.iw-printing #iwSheet { display: block !important; }
  body.iw-printing #iwSheet, body.iw-printing #iwSheet * { visibility: visible !important; }
}
.iws-page { font-family: 'Public Sans', system-ui, sans-serif; color: #16324F; padding: 10mm; font-size: 12.5px; }
.iws-top { display: flex; align-items: center; justify-content: space-between; border-bottom: 3px solid #E8A33D; padding-bottom: 8px; margin-bottom: 12px; }
.iws-top img { height: 30px; }
.iws-title { font-size: 20px; font-weight: 800; }
.iws-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 16px; margin-bottom: 12px; }
.iws-grid > div { display: flex; flex-direction: column; } .iws-grid span { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: #5A7186; }
.iws-wide { grid-column: 1 / -1; }
.iws-app { border: 2px solid #2F7D5D; border-radius: 10px; padding: 10px 12px; background: #E4F2EB; margin-bottom: 12px; }
.iws-app .iws-grid { grid-template-columns: repeat(3, 1fr); margin: 6px 0; } .iws-app b { font-size: 15px; }
.iws-h { font-weight: 800; font-size: 14px; margin: 8px 0 4px; }
.iws-note { font-size: 11px; color: #5A7186; }
.iws-ser { font-size: 11px; line-height: 1.5; word-break: break-word; margin-bottom: 4px; }
.iws-care { margin: 0; padding-left: 18px; line-height: 1.6; }
.iws-foot { margin-top: 16px; padding-top: 8px; border-top: 1px solid #D7E0E7; font-weight: 700; }
/* quotation item pictures (2026-09-27) */
.qb-art { flex: none; width: 52px; height: 52px; border-radius: 10px; background: #fff; border: 1px solid var(--qb-line, #D7E0E7); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.qb-art svg { width: 44px; height: 44px; }
.qb-art-photo img { width: 100%; height: 100%; object-fit: contain; }
.qb-block-gen .qb-art { width: 64px; height: 64px; } .qb-block-gen .qb-art svg { width: 54px; height: 54px; }
#print-report.pdf-a5 .qb-art { width: 40px; height: 40px; } #print-report.pdf-a5 .qb-art svg { width: 34px; height: 34px; }
.qb-spec { font-size: 0.74em; color: var(--qb-muted, #5A7186); line-height: 1.35; border-top: 1px dashed var(--qb-line, #D7E0E7); padding-top: 3px; }

/* pictures are <img> now (html2canvas PDF download draws them) */
.qb-art .qb-art-img { width: 44px; height: 44px; display: block; }
.qb-block-gen .qb-art .qb-art-img { width: 54px; height: 54px; }
#print-report.pdf-a5 .qb-art .qb-art-img { width: 34px; height: 34px; }
img.qb-ico { box-sizing: border-box; object-fit: contain; }
/* no split blocks in print / PDF (2026-09-27): each quotation block, the
   scope strip and the grand total stay whole on one page when they fit */
.qb-block, .qb-scope, .qb-grand, .qb-step { break-inside: avoid; page-break-inside: avoid; }
.qb-grand { break-before: avoid; page-break-before: avoid; }
/* A5: page 1 (cover, before/after, savings, coverage) doesn't fit one A5
   sheet, so the forced break before Bill History left page 2 almost empty
   (2026-09-27). Let A5 flow like the mobile layout. */
#print-report.pdf-a5 .rpt-page-break { break-before: auto; page-break-before: auto; }
/* BOS cards 3 across on A4 (report) and the simple quotation, so the whole
   BOS block fits on one page next to / after the panel & inverter block */
#print-quotation .qb-block-bos .qb-grid,
#print-report:not(.pdf-a5):not(.pdf-mobile) .qb-block-bos .qb-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#print-quotation .qb-wrap, #print-report:not(.pdf-a5):not(.pdf-mobile) .qb-wrap { font-size: 11.5px; }
.rpt-quote-card > h2 { break-after: avoid; page-break-after: avoid; }
#print-quotation .qot-savings-disclaimer, #print-quotation .qot-footnote { break-before: avoid; page-break-before: avoid; }
.qot-totals, .qot-subsidy-gen, .qot-terms, .qot-why, .qot-to-date { break-inside: avoid; page-break-inside: avoid; }

/* 2026-09-27 (live test): Guided calculation / layout wizard on Android
   phones — the one-column grid squeezed the "Your system so far" panel over
   the question. On phones the body is a plain scrolling column instead, the
   calculation summary goes below the question, and the height uses the
   dynamic viewport so the Back / Next bar stays above the browser toolbar. */
.ld-wiz { max-height: calc(100vh - 32px); max-height: calc(100dvh - 32px); }
.ld-wiz-body { min-height: 0; }
@media (max-width: 720px) {
  .ld-wiz-overlay { padding: 8px; }
  .ld-wiz { max-height: calc(100vh - 16px); max-height: calc(100dvh - 16px); border-radius: 12px; }
  .ld-wiz-top { padding: 10px 12px; gap: 8px; }
  .ld-wiz-top b, .ld-wiz-top strong { font-size: 14px; }
  .ld-wiz-dots { gap: 3px; }
  .ld-wiz-dots i { width: 8px; height: 4px; }
  .ld-wiz-body { display: flex; flex-direction: column; gap: 14px; padding: 14px; flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; }
  .ld-wiz-body > * { flex: 0 0 auto; min-width: 0; }
  .ld-wiz-pic { min-height: 0; }
  .ld-wiz-pic.cg-pic { order: 2; }
  .ld-wiz-q h3 { font-size: 17px; }
  .ld-wiz-foot { padding: 10px 12px; flex: none; }
  .ld-wiz-choice { min-width: 0; padding: 9px 12px; }
  .cg-row { font-size: 12.5px; }
}

/* Commercial summary card (2026-09-27) — price, tax, subsidy and payment
   terms first, specifications after (quote-blocks.js commercialSummaryHtml). */
.cs-card { border: 1.5px solid #16324F; border-radius: 12px; padding: 14px 16px; background: #fff; break-inside: avoid; page-break-inside: avoid; font-family: var(--rpt-font-body, inherit); color: #14181c; }
.rpt-cs-card { padding: 0; border: 0; background: none; box-shadow: none; }
.cs-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 10px; }
.cs-kicker { font-size: 10px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: #E8491D; }
.cs-title { font-size: 18px; font-weight: 800; color: #16324F; line-height: 1.2; }
.cs-size { text-align: right; font-size: 18px; font-weight: 800; color: #1F7A4D; line-height: 1.1; white-space: nowrap; }
.cs-size small { display: block; font-size: 10px; font-weight: 600; color: #6b7280; }
.cs-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.cs-table th { text-align: right; font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; font-weight: 700; padding: 4px 6px; border-bottom: 1.5px solid #16324F; }
.cs-table th:first-child, .cs-table td:first-child { text-align: left; }
.cs-table td { text-align: right; padding: 7px 6px; border-bottom: 1px solid #e5e7eb; vertical-align: top; white-space: nowrap; }
.cs-table td:first-child { white-space: normal; font-weight: 700; color: #16324F; }
.cs-table td small { font-size: 10px; color: #6b7280; }
.cs-table td:last-child { font-weight: 800; }
.cs-table tfoot td { background: #16324F; color: #fff; font-weight: 800; font-size: 13px; border: 0; }
.cs-table tfoot td:first-child { color: #fff; border-radius: 8px 0 0 8px; }
.cs-table tfoot td:last-child { border-radius: 0 8px 8px 0; font-size: 14px; }
.cs-n { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; background: #E8491D; color: #fff; font-size: 10.5px; margin-right: 7px; vertical-align: 1px; }
.cs-sub { margin-top: 10px; background: #F0F8F3; border: 1px solid #cfe7d8; border-radius: 10px; padding: 8px 12px; font-size: 12px; }
.cs-sub > div { display: flex; justify-content: space-between; gap: 10px; padding: 2px 0; }
.cs-sub b { color: #1F7A4D; white-space: nowrap; }
.cs-sub .cs-net { border-top: 1px dashed #9cc9ae; margin-top: 4px; padding-top: 6px; font-size: 14px; font-weight: 800; color: #16324F; }
.cs-sub .cs-net b { font-size: 16px; }
.cs-sub .cs-note { display: block; font-size: 9.5px; color: #6b7280; padding-top: 4px; }
.cs-bottom { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; margin-top: 10px; }
.cs-label { font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: #6b7280; margin-bottom: 4px; }
.cs-pay { border: 1px solid #f3c9b8; background: #FFF5F0; border-radius: 10px; padding: 8px 12px; }
.cs-pay-t { font-size: 12.5px; font-weight: 700; color: #16324F; white-space: pre-line; }
.cs-time { border: 1px solid #e5e7eb; border-radius: 10px; padding: 8px 12px; }
.cs-steps { display: flex; gap: 6px; }
.cs-steps > div { flex: 1; text-align: center; background: #F0F8F3; border-radius: 8px; padding: 4px 4px; }
.cs-steps strong { display: block; font-size: 9.5px; color: #16324F; line-height: 1.15; }
.cs-steps span { display: block; font-size: 11px; font-weight: 800; color: #1F7A4D; }
.cs-spec-h { font-weight: 800; font-size: 14px; color: #16324F; margin: 16px 0 8px; }
#print-quotation .cs-card { margin: 0 0 4px; }
#print-report.pdf-mobile .cs-bottom { grid-template-columns: minmax(0, 1fr); }
#print-report.pdf-mobile .cs-table { font-size: 13px; }
#print-report.pdf-mobile .cs-head { flex-direction: column; }
#print-report.pdf-mobile .cs-size { text-align: left; }

/* A5 report (2026-09-27): the "Now / With solar" rows were wider than the
   A5 page — the icons sat beside three stat boxes and the last box was cut
   off in the PDF. On A5 the icons now sit above the boxes. */
#print-report.pdf-a5 .rpt-flow-row { display: block; }
#print-report.pdf-a5 .rpt-flow-head { margin-bottom: 8px; }
#print-report.pdf-a5 .rpt-flow-diagram { width: 240px; }
#print-report.pdf-a5 .rpt-vec-stats { display: flex; gap: 8px; }
/* Savings / subsidy tiles: the big ₹ figure shrinks to fit its tile instead
   of spilling over the border (seen on print with 7-digit savings). */
.report-stat-tile { container-type: inline-size; min-width: 0; }
.report-stat-tile-value { white-space: nowrap; font-size: min(27px, 14cqi); }
#print-report.pdf-a5 .report-stat-tile-value { font-size: min(23px, 14cqi); }
#print-report.pdf-mobile .report-stat-tile-value { font-size: min(25px, 14cqi); }

/* ── View-only lock for saved proposals (2026-09-28) ── */
.view-only-banner { display: flex; gap: 10px; align-items: flex-start; background: #FFF6E5; border: 1px solid #F1C27D; color: #5A3B00; border-radius: 10px; padding: 10px 12px; margin: 0 0 12px; font-size: 13px; line-height: 1.45; }
.view-only-banner .view-only-ico { font-size: 18px; line-height: 1; }
.view-only-banner a { color: #1F4E79; font-weight: 700; }
.wizard-body .view-only-field { opacity: 0.8; cursor: not-allowed; }

/* Simple quote: units next to subsidy, over-sanctioned-load flag (2026-09-28) */
.cs-sub .cs-units { border-top: 1px dashed #9cc9ae; margin-top: 4px; padding-top: 6px; font-weight: 700; color: #16324F; }
.cs-sub .cs-units b { color: #1F4E79; }
.qot-overload { margin: 8px 0 10px; padding: 8px 12px; border: 1.5px solid #C0392B; background: #FDECEA; color: #8E1B10; border-radius: 8px; font-size: 12.5px; font-weight: 700; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.qot-terms-list li.qot-overload-li { color: #B42318; }

/* Sidebar → Installation proposal picker (2026-09-29) */
.install-pick-overlay { position: fixed; inset: 0; background: rgba(20, 24, 31, 0.45); z-index: 1000; display: flex; align-items: flex-start; justify-content: center; padding: 8vh 16px 16px; }
.install-pick-overlay[hidden] { display: none; }
.install-pick-box { background: #fff; width: 100%; max-width: 560px; border-radius: 14px; box-shadow: 0 18px 50px rgba(0,0,0,.25); padding: 14px; display: flex; flex-direction: column; gap: 10px; max-height: 80vh; }
.install-pick-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 15px; }
.install-pick-x { background: none; border: none; font-size: 24px; line-height: 1; cursor: pointer; color: #666; padding: 0 4px; }
.install-pick-input { width: 100%; }
.install-pick-list { overflow-y: auto; display: flex; flex-direction: column; gap: 4px; min-height: 60px; }
.install-pick-row { text-align: left; background: #fff; border: 1px solid #e6e2dc; border-radius: 10px; padding: 9px 12px; cursor: pointer; display: flex; flex-direction: column; gap: 2px; font: inherit; }
.install-pick-row:hover, .install-pick-row.hi { border-color: var(--color-accent, #e8552d); background: #FFF6F2; }
.install-pick-row .ip-name { font-weight: 700; font-size: 14px; }
.install-pick-row .ip-meta { font-size: 12px; opacity: .7; }
.install-pick-empty { padding: 14px; text-align: center; opacity: .6; font-size: 13px; }
/* View-only banner Edit button + focus flash for quick links */
.view-only-banner { align-items: center; }
.view-only-banner > div { flex: 1; }
.view-only-banner .view-only-edit { white-space: nowrap; text-decoration: none; }
.focus-flash { box-shadow: 0 0 0 3px var(--color-accent, #e8552d); border-radius: 12px; transition: box-shadow .4s; }

/* ── Smart check / price insights / verified BOS kits (2026-09-29, assets/js/smart-check.js) ── */
.sc-card { border: 1px solid var(--color-divider); border-left: 5px solid #2F7D5D; border-radius: var(--radius-md, 10px); background: var(--color-surface-2); margin-bottom: 14px; }
.sc-card.sc-tone-warn { border-left-color: #d49500; }
.sc-card.sc-tone-err { border-left-color: #c62828; }
.sc-head { display: flex; align-items: center; gap: 10px; padding: 10px 12px; cursor: pointer; list-style: none; }
.sc-head::-webkit-details-marker { display: none; }
.sc-badge { flex: 0 0 auto; min-width: 26px; height: 26px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; background: #e6f4ea; color: #1e6b34; }
.sc-tone-warn .sc-badge { background: #fff4d6; color: #7a5600; }
.sc-tone-err .sc-badge { background: #fdecea; color: #a4281c; }
.sc-title { flex: 1; font-size: 14px; line-height: 1.35; }
.sc-title span { color: var(--color-neutral-700); }
.sc-tone-err .sc-title span { color: #a4281c; font-weight: 600; }
.sc-content { padding: 0 12px 12px; }
.sc-list { list-style: none; margin: 0; padding: 0; }
.sc-item { display: flex; align-items: flex-start; gap: 8px; padding: 8px 0; border-top: 1px solid var(--color-divider); font-size: 13px; line-height: 1.4; }
.sc-ico { flex: 0 0 auto; width: 20px; text-align: center; }
.sc-body { flex: 1; min-width: 0; }
.sc-area { display: inline-block; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; padding: 1px 6px; border-radius: 4px; background: var(--color-neutral-200); color: var(--color-neutral-800); margin-right: 4px; }
.sc-err .sc-area { background: #fdecea; color: #a4281c; }
.sc-warn .sc-area { background: #fff4d6; color: #7a5600; }
.sc-rule { font-size: 12px; color: var(--color-neutral-600); margin-top: 2px; }
.sc-fix { flex: 0 0 auto; white-space: nowrap; }
.sc-okline { margin: 4px 0 0; font-size: 13px; color: #1e6b34; }
.sc-foot { margin: 8px 0 0; font-size: 11.5px; color: var(--color-neutral-600); }
.sc-prices { margin-top: 10px; }
.sc-prices > summary { cursor: pointer; font-size: 13px; font-weight: 600; }
.sc-table-wrap { overflow-x: auto; margin-top: 6px; }
.sc-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.sc-table th, .sc-table td { padding: 5px 6px; border-bottom: 1px solid var(--color-divider); text-align: left; vertical-align: top; }
.sc-table .num { text-align: right; white-space: nowrap; font-family: 'JetBrains Mono', ui-monospace, monospace; }
.sc-table small { display: block; color: var(--color-neutral-600); }
.sc-tag { font-size: 11px; padding: 1px 6px; border-radius: 999px; background: var(--color-neutral-200); white-space: nowrap; }
.sc-tag-ok { background: #e6f4ea; color: #1e6b34; }
.sc-tag-warn { background: #fff4d6; color: #7a5600; }
.sc-kits { margin-bottom: 14px; }
.sc-kit-row { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px; margin-top: 10px; }
.sc-kit { text-align: left; border: 1px solid var(--color-divider); border-radius: 10px; background: var(--color-surface-2); padding: 10px 12px; cursor: pointer; display: flex; flex-direction: column; gap: 2px; font: inherit; color: inherit; }
.sc-kit:hover { border-color: #2F7D5D; }
.sc-kit-match { border: 2px solid #2F7D5D; background: #f1f8f4; }
.sc-kit b { font-size: 14px; } .sc-kit span { font-size: 12.5px; } .sc-kit small { font-size: 11px; color: var(--color-neutral-600); }
.sc-kit:disabled { opacity: .6; cursor: default; }
.sc-loaded { margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: #e6f4ea; color: #1e6b34; font-size: 13px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sc-other, .sc-save { margin-top: 10px; }
.sc-other > summary, .sc-save > summary { cursor: pointer; font-size: 13px; font-weight: 600; }
.sc-check { display: flex; gap: 8px; align-items: flex-start; font-size: 12.5px; margin-top: 10px; }
.sc-save-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; margin-top: 8px; }
.sc-save-row .field { margin: 0; display: flex; flex-direction: column; gap: 4px; font-size: 12px; }
.sc-kit-admin { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12px; margin-top: 6px; }
@media (max-width: 600px) { .sc-item { flex-wrap: wrap; } .sc-fix { margin-left: 28px; } }
@media print { .sc-card, .sc-kits { display: none !important; } }
/* Layout designer trees (2026-09-29) */
.ld-tree-card { border-color: #9cc98d; background: #f5faf2; }
.ld-tree-hint { margin: 6px 0 0 !important; color: #3f7a35 !important; }
/* Commissioning checklist step + handover page 2 (2026-09-29) */
.iw-steps { grid-template-columns: repeat(5, minmax(0, 1fr)); }
@media (max-width: 700px) { .iw-steps { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.iw-item.ic-reading { cursor: default; }
.iw-item.bad { background: #fdecea; border-color: #f0b4ae; }
.ic-in { display: flex; align-items: center; gap: 6px; flex: none; }
.ic-in .input { width: 110px; text-align: right; }
.ic-in span { font-size: 12.5px; font-weight: 700; min-width: 26px; }
.ic-sign { display: grid; grid-template-columns: 1fr 180px; gap: 10px; margin-top: 12px; }
.ic-sign .field { display: flex; flex-direction: column; gap: 3px; margin: 0; font-size: 12.5px; font-weight: 600; }
.ic-sign .ic-wide { grid-column: 1 / -1; }
@media (max-width: 600px) { .ic-sign { grid-template-columns: 1fr; } .ic-in .input { width: 84px; } }
.iws-page2 { page-break-before: always; break-before: page; }
.iws-ic { width: 100%; border-collapse: collapse; font-size: 11.5px; margin-bottom: 10px; }
.iws-ic th, .iws-ic td { border: 1px solid #D7E0E7; padding: 4px 6px; text-align: left; vertical-align: top; }
.iws-ic th { background: #F1F5F8; font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; }
.iws-ic td:nth-child(2), .iws-ic td:nth-child(3), .iws-ic td:nth-child(4) { white-space: nowrap; width: 1%; }
.iws-ic-g td { background: #E4F2EB; font-weight: 800; }
.iws-blank { min-width: 90px; }
.iws-signs { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 22px; }
.iws-signs > div { display: flex; flex-direction: column; gap: 2px; }
.iws-signs span { font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: #5A7186; }
.iws-signs i { display: block; border-bottom: 1px solid #16324F; height: 34px; }
/* commissioning-checklist.php admin editor (2026-09-29) */
.ica-list { display: flex; flex-direction: column; gap: 8px; max-width: 1100px; }
.ica-row { display: flex; flex-direction: row; gap: 12px; align-items: flex-start; padding: 10px 12px; }
.ica-row.ica-off { opacity: .6; }
.ica-on { display: flex; gap: 6px; align-items: center; font-weight: 700; font-size: 13px; padding-top: 22px; white-space: nowrap; }
.ica-fields { flex: 1; display: grid; grid-template-columns: 2fr 1.1fr 1fr repeat(3, 0.6fr); gap: 8px; min-width: 0; }
.ica-fields .field { display: flex; flex-direction: column; gap: 3px; margin: 0; font-size: 12px; font-weight: 600; min-width: 0; }
.ica-fields .ica-label:last-child { grid-column: 1 / -1; }
.ica-btns { display: flex; gap: 2px; padding-top: 20px; }
@media (max-width: 800px) { .ica-row { flex-wrap: wrap; } .ica-fields { grid-template-columns: 1fr 1fr; } .ica-fields .ica-label { grid-column: 1 / -1; } .ica-on, .ica-btns { padding-top: 0; } }
.iws-page2 { padding-top: 6mm; padding-bottom: 4mm; }
.iws-page2 .iws-top { margin-bottom: 8px; }
.iws-page2 .iws-grid { margin-bottom: 8px; gap: 4px 16px; }
.iws-page2 .iws-ic th, .iws-page2 .iws-ic td { padding: 3px 6px; line-height: 1.3; }
.iws-page2 .iws-signs { margin-top: 14px; }
.iws-page2 .iws-foot { margin-top: 10px; }
/* Serial numbers full at BOM qty (2026-09-29) */
.serial-full { margin-top: 10px; padding: 8px 10px; border-radius: 8px; background: #e6f4ea; color: #1e6b34; font-size: 13px; font-weight: 600; }
/* Automation settings + WhatsApp follow-up button (2026-09-29) */
.btn.btn-wa { background: #25D366; color: #fff; border-color: #25D366; padding: 5px 12px; font-size: 12.5px; text-decoration: none; }
.btn.btn-wa:hover { background: #1ebe5a; }
.au-card { max-width: 900px; margin-bottom: var(--space-4); }
.au-line { display: flex; gap: 10px; align-items: flex-start; padding: 6px 0; font-size: 13.5px; }
.au-line input { width: 18px; height: 18px; margin-top: 2px; flex: none; }
.au-line span { display: flex; flex-direction: column; } .au-line small { color: var(--color-neutral-600); font-size: 12px; }
.au-fu { border-top: 1px solid var(--color-divider); padding-top: 8px; margin-top: 4px; }
.au-grid { display: grid; grid-template-columns: 110px 1fr; gap: 8px; margin: 4px 0 8px 28px; }
.au-card .field { display: flex; flex-direction: column; gap: 3px; margin: 0; font-size: 12px; font-weight: 600; }
.au-wide { grid-column: 1 / -1; }
@media (max-width: 640px) { .au-grid { grid-template-columns: 1fr; margin-left: 0; } }
/* stage moved automatically — toast (install walk-through / serials) */
.auto-toast { position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); background: #16324F; color: #fff; padding: 10px 16px; border-radius: 10px; font-size: 13.5px; z-index: 9999; box-shadow: 0 6px 20px rgba(0,0,0,.25); max-width: 92vw; }

/* Offer comparison (2026-09-29, assets/js/offer-compare.js) — a separate,
   optional print target: only what changed in Offer 2 vs Offer 1. */
#print-offer-compare { display: none; font-family: 'Public Sans', var(--font-body), system-ui, sans-serif; color: #111; font-size: 12.5px; line-height: 1.45; }
body.pdf-rendering-oc #print-offer-compare { display: block !important; background: #fff; }
@media print {
  body.printing-offer-compare #print-report, body.printing-offer-compare #print-agreement,
  body.printing-offer-compare #print-tneb-letter, body.printing-offer-compare #print-quotation { display: none !important; visibility: hidden !important; }
  body.printing-offer-compare #print-offer-compare, body.printing-offer-compare #print-offer-compare * { visibility: visible; }
  body.printing-offer-compare #print-offer-compare { display: block; position: absolute; top: 0; left: 0; width: 100%; }
}
.oc-summary { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; border: 1px solid #cfd8e3; background: #f4f7fb; border-radius: 8px; padding: 10px 12px; margin: 0 0 10px; }
.oc-summary > div span { display: block; font-size: 11px; opacity: 0.7; }
.oc-summary > div b { font-size: 14px; }
.oc-summary .oc-arrow { font-size: 18px; opacity: 0.6; }
.oc-summary .oc-head { margin-left: auto; font-weight: 700; }
.oc-intro { font-size: 12px; margin: 0 0 12px; opacity: 0.85; }
.oc-sec { margin: 0 0 14px; }
.oc-sec-title { font-weight: 700; font-size: 13.5px; margin: 0 0 6px; padding-bottom: 3px; border-bottom: 1.5px solid #16324F; color: #16324F; break-after: avoid; page-break-after: avoid; }
.oc-table { width: 100%; border-collapse: collapse; font-size: 12px; }
/* 2026-10-12: 3-offer PDF cut off the last column — long unbroken text
   (e.g. "17.2X1220mmx100microns,Chemical") widened the table past the page.
   Fixed layout + wrap anywhere keeps every column inside the page width. */
.oc-table { table-layout: fixed; max-width: 100%; }
.oc-table th, .oc-table td { overflow-wrap: anywhere; word-break: break-word; }
.oc-table th:first-child { width: 17%; }
.oc-com th:last-child { width: 14%; }
.oc-table th, .oc-table td { border: 1px solid #c9c9c9; padding: 5px 7px; vertical-align: top; text-align: left; }
.oc-table th { background: #f2f4f7; font-weight: 700; }
.oc-table th small { display: block; font-weight: 400; opacity: 0.7; font-size: 10.5px; }
.oc-table td:first-child { font-weight: 600; }
.oc-table td.oc-old { color: #555; }
.oc-table td.oc-new { font-weight: 600; background: #fffbe8; }
.oc-table tr { break-inside: avoid; page-break-inside: avoid; }
.oc-com td:last-child { font-weight: 600; }
.oc-table tr.oc-strong td { font-weight: 700; font-size: 12.5px; }
.oc-good { color: #1e6b34; }
.oc-bad { color: #a4281c; }
.oc-note { font-size: 10.5px; opacity: 0.7; margin-top: 4px; }
.oc-none { font-size: 12px; opacity: 0.75; margin: 4px 0; }
.oc-preview:not(:empty) { margin-top: 10px; overflow-x: auto; }
.oc-preview-sum { font-size: 12.5px; font-weight: 600; margin-bottom: 8px; }

/* Fixed PC save folder (2026-09-29, assets/js/pc-save-folder.js) */
.pc-folder-box { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 8px; margin: 8px 0; padding: 8px 10px; border: 1px dashed #b9c6d6; border-radius: 8px; background: #f6f9fc; font-size: 12.5px; }
.pc-folder-box .pcf-text { flex: 1 1 220px; }
.pc-folder-box .btn-sm { padding: 4px 10px; font-size: 12px; min-height: 0; }
.pcf-toast { position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%) translateY(20px); background: #16324F; color: #fff; padding: 10px 16px; border-radius: 8px; font-size: 13px; box-shadow: 0 6px 20px rgba(0,0,0,.2); opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; z-index: 9999; max-width: 92vw; }
.pcf-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
@media print { .pcf-toast, .pc-folder-box { display: none !important; } }

/* Per-stage Save / Edit bar (2026-09-30) */
.stage-save-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin: 16px 0 4px; padding: 12px 14px; border: 1px solid var(--color-neutral-300, #ddd); border-radius: 10px; background: #F7FAF7; font-size: 13px; }
.stage-save-bar.locked { background: #FFF6E5; border-color: #F1C27D; color: #5A3B00; }
.stage-save-bar.editing { background: #EAF4FF; border-color: #9CC3EA; color: #123B63; }
.stage-save-bar > span { flex: 1 1 220px; }
.stage-save-bar .btn { white-space: nowrap; }
.bom-verify-out { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--color-neutral-300, #ddd); }
.bom-verify-out .field-hint { flex: 1 1 220px; }
.micro-dc-note { background: #EAF4FF; border-radius: 8px; padding: 8px 10px; }
@media print { .stage-save-bar, .bom-verify-out, .earth-kit-warn { display: none !important; } }

/* Customers page — 3-stage proposal follow-ups + phone layout (2026-09-30) */
.fu-stage-chip { display: inline-block; font-size: 10.5px; font-weight: 700; border-radius: 999px; padding: 2px 9px; background: #16324F14; color: #16324F; text-transform: uppercase; letter-spacing: 0.03em; }
.fu-interest { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 8px; }
.fu-int-btn { border: 1px solid var(--color-divider); background: var(--color-surface-2, #fff); border-radius: 999px; padding: 6px 12px; font-size: 13px; font-weight: 600; cursor: pointer; }
.fu-int-btn.active { background: #16324F; color: #fff; border-color: #16324F; }
.fu-next { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 8px; }
.fu-next label { margin: 0; }
.btn.btn-wa-row { padding: 3px 10px; font-size: 12px; margin-left: 6px; vertical-align: middle; }
@media (max-width: 760px) {
  #custListContainer .dash-table, #custListContainer .dash-table tbody { display: block; width: 100%; overflow: visible; }
  #custListContainer .dash-table thead { display: none; }
  #custListContainer .dash-table tr.cust-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; padding: 10px 8px; border-bottom: 1px solid var(--color-divider); }
  #custListContainer .dash-table tr.cust-row td { display: block; border: none; padding: 0; }
  #custListContainer .dash-table tr.cust-row td:first-child { width: 14px; }
  #custListContainer .dash-table tr.cust-row td[data-label="Customer"] { flex: 1 1 calc(100% - 30px); }
  #custListContainer .dash-table tr.cust-row td[data-label="Phone"] { flex: 1 1 100%; padding-left: 24px; }
  #custListContainer .dash-table tr.cust-row td[data-label="Status"], #custListContainer .dash-table tr.cust-row td[data-label="Follow-up"] { padding-left: 24px; }
  #custListContainer .dash-table tr.cust-row td[data-label="Follow-up"] { padding-left: 0; }
  #custListContainer .cust-col-email, #custListContainer .cust-col-count { display: none !important; }
  #custListContainer .dash-table tr.cust-detail-row:not([hidden]) { display: block; }
  #custListContainer .dash-table tr.cust-detail-row td.cust-detail-spacer { display: none; }
  #custListContainer .dash-table tr.cust-detail-row td.cust-detail-cell { display: block; padding: 0 6px 8px; }
  #custListContainer .followup-item-actions .btn { flex: 1 1 auto; text-align: center; }
  #custListContainer .btn.btn-wa-row { margin-left: 8px; padding: 6px 12px; font-size: 13px; }
}
/* Either/or commissioning reading (2026-09-30) */
.iw-item .ic-alt { display: block; font-style: normal; font-size: 11.5px; color: #1F4E79; font-weight: 600; margin-top: 1px; }
.iw-item.alt-done { opacity: 0.85; }
/* Phones (2026-09-30): .home-shell's align-items:flex-start let the main
   column grow to its widest content (the 7-day follow-up ribbon), so the
   whole page became ~1100 px wide on Android and the follow-up buttons
   (Close / WhatsApp) sat off-screen. Stretch the column to the screen. */
@media (max-width: 900px) {
  .home-shell { align-items: stretch; }
  .home-main { width: 100%; max-width: 100vw; box-sizing: border-box; padding-left: 14px; padding-right: 14px; }
  .followup-ribbon-wrap { max-width: 100%; }
}
/* Proposal report: solar more than sanctioned load (2026-09-30) */
.rpt-overload { margin: 10px 0 0; max-width: 520px; }
.rpt-terms-list li.qot-overload-li { color: #B42318; }

/* Mobile report (2026-10-04): "What you'll pay after going solar" as a vertical label | value table per bill entry. */
.rcc-vtable { width: 100%; border-collapse: collapse; margin-top: 4px; }
.rcc-vtable th, .rcc-vtable td { padding: 5px 4px; border-bottom: 1px solid rgba(0,0,0,0.08); font-size: 1em; vertical-align: baseline; }
.rcc-vtable th { text-align: left; font-weight: 500; opacity: 0.7; width: 55%; }
.rcc-vtable td { text-align: right; font-weight: 700; }
.rcc-vtable tr:last-child th, .rcc-vtable tr:last-child td { border-bottom: 0; }
.rcc-vtable .rcc-v-save th, .rcc-vtable .rcc-v-save td { color: var(--rpt-green, #2e7d32); opacity: 1; }

/* 2026-10-04: 3-option segmented controls (PDF layout) stack on phones instead of running off the screen. */
@media (max-width: 640px) {
  .seg.seg-stack { display: flex; flex-direction: column; width: 100%; }
  .seg.seg-stack .seg-opt { padding: 11px 14px; font-size: 14px; }
  .seg.seg-stack .seg-opt + .seg-opt { border-left: 0; border-top: 1px solid var(--color-divider); }
}
/* 2026-10-04: offer comparison "Everything side by side" — identical rows are plain, differing rows keep the highlight. */
.oc-table tr.oc-same td { background: transparent; color: #555; font-weight: 400; }
.oc-table tr.oc-same td:first-child { font-weight: 600; color: inherit; }

/* ── Horizontal status tabs (2026-10-09, assets/js/section-tabs.js) ──────────
   Default layout for every multi-section page: one tab per section, coloured
   by status — green completed, red pending, amber optional, grey view only.
   Only the selected section shows; the card's own header is hidden because
   the tab already names it. */
.sec-tabs { display: flex; gap: 6px; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin;
  padding: 4px 2px 8px; margin: 0 0 2px; }
.sec-tab { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; padding: 8px 12px; border-radius: 999px;
  border: 2px solid transparent; font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap;
  background: #eeeeee; color: #444; line-height: 1.2; }
.sec-tab .sec-tab-ico { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%;
  font-size: 11px; font-weight: 800; color: #fff; background: #9e9e9e; flex: 0 0 auto; }
.sec-tab.st-ok   { background: #e6f4ea; color: #1e6b34; } .sec-tab.st-ok .sec-tab-ico   { background: #2e7d32; }
.sec-tab.st-todo { background: #fdecea; color: #a4281c; } .sec-tab.st-todo .sec-tab-ico { background: #c62828; }
.sec-tab.st-opt  { background: #fff4d6; color: #7a5600; } .sec-tab.st-opt .sec-tab-ico  { background: #e0a100; }
.sec-tab.st-info { background: #eeeeee; color: #555; }
.sec-tab.active { border-color: currentColor; box-shadow: 0 2px 6px rgba(0,0,0,.12); }
.sec-tab.active.st-ok   { background: #2e7d32; color: #fff; } .sec-tab.active.st-ok .sec-tab-ico   { background: #fff; color: #2e7d32; }
.sec-tab.active.st-todo { background: #c62828; color: #fff; } .sec-tab.active.st-todo .sec-tab-ico { background: #fff; color: #c62828; }
.sec-tab.active.st-opt  { background: #b98500; color: #fff; } .sec-tab.active.st-opt .sec-tab-ico  { background: #fff; color: #b98500; }
.sec-tab.active.st-info { background: #555; color: #fff; }    .sec-tab.active.st-info .sec-tab-ico { background: #fff; color: #555; }
.sec-tab:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.sec-tab[disabled] { opacity: 1; cursor: pointer; }
/* The tab names the section — hide the card's own collapsible header. */
.sec-tabbed > details.stage-section > summary.stage-section-head,
.sec-tabbed > div > details.stage-section > summary.stage-section-head { display: none; }
.sec-tabbed > details.stage-section > .stage-section-body,
.sec-tabbed > div > details.stage-section > .stage-section-body { border-top: 0; padding-top: 14px; }
.sec-tabbed > [hidden] { display: none !important; }
@media (max-width: 640px) { .sec-tab { padding: 8px 10px; font-size: 12.5px; } }
@media print { .sec-tabs { display: none !important; } }

/* ── 2026-10-09 round 2: "not to scroll — like reading a book" ─────────────
   Compact sticky stage header (stages always visible), Guided calculation in
   the header, compact lock bar, sized fields, ‹ Previous / Next › pager. */
.wizard-shell { overflow: clip; }
.wizard-header.is-sticky { position: sticky; top: 0; z-index: 40; background: var(--color-surface-2, #fff);
  padding: 10px var(--space-6) 8px; box-shadow: 0 2px 8px rgba(0,0,0,.06); }
.wizard-header .wh-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.wizard-header .wh-titles { min-width: 0; }
.wizard-header.is-sticky .step-title { font-size: 16px; line-height: 1.2; }
.wizard-header .wh-guide-btn { white-space: nowrap; padding: 7px 12px; font-size: 13px; }
.wizard-header.is-sticky .wizard-progress { margin-top: 8px; }
.wizard-header.is-sticky .wizard-progress .seg-tab.stage-tab { padding: 7px 6px; }
.wizard-header .autosave-status:empty { display: none; }
@media (max-width: 640px) {
  .wizard-header.is-sticky { padding: 8px 12px 6px; }
  .wizard-header .wh-guide-btn { padding: 6px 10px; font-size: 12px; }
  .wizard-header.is-sticky .step-title { font-size: 14px; }
}

/* Wider page on a computer for every stage. */
@media (min-width: 900px) { .page.page-wizard-wide { max-width: 1240px; } .page.page-wizard-wide.page-full { max-width: 1600px; } }

/* Compact lock bar — details only on tap of ⓘ. */
.view-only-banner.vob-compact { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 6px 10px; margin: 0 0 10px; font-size: 13px; line-height: 1.3; }
.vob-compact .vob-text { flex: 1 1 auto; min-width: 0; }
.vob-compact .vob-info { width: 26px; height: 26px; border-radius: 50%; border: 1px solid #F1C27D; background: #fff; color: #5A3B00; font-size: 14px; line-height: 1; cursor: pointer; padding: 0; flex: 0 0 auto; }
.vob-compact .view-only-edit { padding: 5px 12px; font-size: 12.5px; flex: 0 0 auto; }
.vob-compact .vob-help { flex: 1 1 100%; font-size: 12px; opacity: .9; padding-top: 2px; }

/* Field sizes follow the data (2026-10-09: "long grey box for 2 letters"). */
.wizard-shell input.input[type="number"] { max-width: 150px; }
.wizard-shell select.input { max-width: 360px; }
.wizard-shell input.input[type="text"], .wizard-shell input.input[type="tel"], .wizard-shell input.input[type="email"], .wizard-shell input.input:not([type]) { max-width: 520px; }
.wizard-shell #quoteSubjectInput { max-width: 100%; }
.wizard-shell textarea.input { max-width: 760px; }
.wizard-shell :not(.cf-row):not(.bom-line-card):not(.bom-field-wide) > .field:has(> input.input[type="number"]) { flex: 0 1 auto !important; min-width: 130px !important; }
.wizard-shell div.input { max-width: 520px; }

/* ‹ Previous / Next › — turn the page like a book. */
.sec-pager { display: flex; align-items: center; gap: 8px; margin-top: 14px; padding-top: 12px; border-top: 1px dashed var(--color-divider); }
.sec-pager .sec-pg-count { font-size: 12px; opacity: .6; margin-right: auto; white-space: nowrap; flex: 0 0 auto; }
.sec-pager > span:not(.sec-pg-count) { display: none; }
.sec-pager .sec-pg-btn { padding: 8px 14px; font-size: 13px; min-width: 0; max-width: 46%; flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 640px) { .sec-pager { gap: 6px; } .sec-pager .sec-pg-btn { padding: 8px 10px; font-size: 12.5px; flex: 1 1 0; max-width: none; } }
/* Hints under a sized field sit on their own line. */
.wizard-shell .field > span.field-hint { display: block; margin-top: 4px; }
@media (max-width: 640px) { .wizard-header.is-sticky .step-sub { display: none; } }
@media print { .sec-pager, .vob-compact, .wh-guide-btn { display: none !important; } }
/* Computer: plain fields sit side by side (2–3 per row) so a section fits
   the screen instead of one long column; everything else stays full width. */
@media (min-width: 900px) {
  .wizard-shell .stage-section-body { display: grid !important; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); column-gap: 18px; }
  .wizard-shell .stage-section-body > :not(.field) { grid-column: 1 / -1; }
  .wizard-shell .stage-section-body > .field { margin-bottom: 0; }
}

/* ── 2026-10-09 round 3: one tidy line for tabs + tools + lock ───────────── */
.sec-tabs-row { display: flex; align-items: center; gap: 10px; margin: 0 0 4px; }
.sec-tabs-row > .sec-tabs { flex: 1 1 auto; min-width: 0; margin: 0; }
.sec-tabs-row .sec-tabs-extras { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; padding-bottom: 6px; }
.sec-tabs-row.solo { justify-content: flex-end; }
@media (max-width: 760px) {
  .sec-tabs-row { flex-wrap: wrap; gap: 4px; }
  .sec-tabs-row .sec-tabs-extras { order: -1; flex: 1 1 100%; justify-content: flex-end; padding-bottom: 2px; }
}
.tool-chip { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 11px; border-radius: 999px; border: 1px solid var(--color-divider);
  background: #fff; color: #333; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.tool-chip:hover { border-color: #999; }
.tool-chip.on { background: #201e1d; color: #fff; border-color: #201e1d; }
.tool-chip .tc-badge { min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; color: #fff; background: #9e9e9e; }
.tool-chip.tc-err .tc-badge { background: #c62828; } .tool-chip.tc-warn .tc-badge { background: #e0a100; } .tool-chip.tc-ok .tc-badge { background: #2e7d32; }
.tool-chip[disabled] { opacity: 1; }
.lock-chip { position: relative; display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 4px 0 10px; border-radius: 999px;
  background: #FFF6E5; border: 1px solid #F1C27D; color: #5A3B00; font-size: 12.5px; font-weight: 600; white-space: nowrap; }
.lock-chip.editing { background: #EAF4FF; border-color: #9CC3EA; color: #123B63; }
.lock-chip.plain { background: transparent; border-color: transparent; padding: 0; }
.lock-chip .vob-info { width: 24px; height: 24px; border-radius: 50%; border: 1px solid currentColor; background: #fff; color: inherit; font-size: 13px; line-height: 1; cursor: pointer; padding: 0; opacity: .8; }
.lock-chip.plain .vob-info { border-color: var(--color-divider); color: #666; }
.lock-chip .lock-edit-btn { height: 26px; padding: 0 12px; font-size: 12px; border-radius: 999px; min-height: 0; }
.lock-chip .lock-help { position: absolute; right: 0; top: calc(100% + 6px); z-index: 60; width: min(320px, 86vw); white-space: normal; font-weight: 400;
  background: #fff; color: #333; border: 1px solid var(--color-divider); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.15); padding: 10px 12px; font-size: 12.5px; line-height: 1.5; }
/* Drawers under the tab row (one open at a time). */
.stage-drawers { margin: 4px 0 10px; }
.stage-drawer { position: relative; border: 1px solid var(--color-divider); border-radius: 12px; background: #fafafa; padding: 8px 40px 8px 8px; }
.stage-drawer > .card, .stage-drawer > div > .card, .stage-drawer .sc-card { margin: 0 !important; box-shadow: none; }
.stage-drawer-close { position: absolute; top: 8px; right: 8px; width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--color-divider); background: #fff; cursor: pointer; font-size: 13px; }
/* The tab already names the section — hide each step's repeated title tag. */
.sec-tabbed .stage-section-body > .tag.tag-accent:first-child { display: none; }
/* Table inputs (bill history etc.) sized to their data. */
.wizard-shell table .input { max-width: 170px; min-height: 36px; padding: 6px 10px; font-size: 14px; }
@media print { .sec-tabs-row, .stage-drawers { display: none !important; } }
/* Desktop: every tab visible (wraps to a 2nd line rather than hiding). */
@media (min-width: 761px) { .sec-tabs-row > .sec-tabs { flex-wrap: wrap; overflow: visible; } .sec-tabs-row { align-items: flex-start; } .sec-tabs-row .sec-tabs-extras { padding-top: 4px; } }
@media (max-width: 760px) {
  .sec-tabs-row .sec-tabs-extras { gap: 5px; }
  .tool-chip { height: 30px; padding: 0 9px; font-size: 12px; }
}
@media (max-width: 480px) { .tool-chip .tc-label, .lock-chip .tc-label { display: none; } }
.wizard-shell table input.input[type="text"], .wizard-shell table input.input[type="number"], .wizard-shell table input.input:not([type]) { max-width: 170px; }
@media (min-width: 761px) {
  .wizard-shell .entry-table { width: auto; table-layout: auto; }
  .wizard-shell .entry-table th, .wizard-shell .entry-table td { width: auto !important; padding-right: 18px; }
  .wizard-shell .entry-table input.input { width: 160px; }
}
.stage-drawers:not(:has(.stage-drawer:not([hidden]))) { display: none; }

/* ── 2026-10-09 round 4: boxes sized to their data, short fields in one line ── */
.bom-compact-card { padding: 12px 14px; margin-bottom: 10px; }
.cf-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 14px; }
.cf-row > .field { margin: 0 !important; flex: 0 0 auto !important; min-width: 0 !important; }
.cf-row > .field > label { white-space: nowrap; }
.cf-row > .field > label small { font-size: 10.5px; opacity: .6; font-weight: 400; margin-left: 2px; }
.wizard-shell .cf-row .cf-num input.input { width: 92px; }
.wizard-shell .cf-row .cf-sel select.input { width: 104px; }
.cf-row > .cf-grow { flex: 1 1 220px !important; }
.wizard-shell .cf-row .cf-grow input.input { width: 100%; max-width: 420px; }
.mini-help { position: relative; align-self: center; }
.mini-help > summary { list-style: none; width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--color-divider); display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 13px; color: #666; background: #fff; }
.mini-help > summary::-webkit-details-marker { display: none; }
.mini-help[open] > div { position: absolute; right: 0; top: calc(100% + 6px); z-index: 50; width: min(340px, 80vw); background: #fff; border: 1px solid var(--color-divider); border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.15); padding: 10px 12px; font-size: 12.5px; line-height: 1.5; }
.cf-link { font-size: 11.5px; margin-left: 8px; font-weight: 600; }
.cf-terms { align-items: flex-start; flex-wrap: nowrap; }
.cf-terms > textarea.input { flex: 1 1 auto; min-height: 58px; max-width: none !important; }
.cf-terms-side { flex: 0 0 auto; display: flex; flex-direction: column; gap: 6px; }
.wizard-shell .cf-terms-side select.input { width: 230px; }
.cf-mini { padding: 4px 8px !important; font-size: 11.5px !important; white-space: nowrap; }
@media (max-width: 640px) { .cf-terms { flex-wrap: wrap; } .cf-terms-side { flex: 1 1 100%; } .wizard-shell .cf-terms-side select.input { width: 100%; } }

/* BOM line: on a computer every field sits inline at the width its data needs. */
@media (min-width: 860px) {
  .bom-line-card { display: flex !important; flex-direction: row !important; flex-wrap: wrap; align-items: flex-end !important; justify-content: flex-start !important; gap: 8px 12px; padding: 12px 14px; }
  .bom-line-card > * { flex: 0 0 auto; min-width: 0; }
  .bom-line-card > .bom-field-full { flex: 1 1 100%; }
  .bom-line-card > .bom-field-wide:not(.field) { display: flex; flex-direction: row; gap: 8px 12px !important; align-items: flex-end; }
  .bom-line-card > .field.bom-field-wide { display: block; }
  .bom-line-card .field { margin: 0 !important; flex: 0 0 auto !important; min-width: 0 !important; }
  .bom-line-card .field > label { white-space: nowrap; font-size: 11.5px; margin-bottom: 3px; }
  .bom-line-card .input { min-height: 36px; padding: 6px 10px; font-size: 14px; }
  .wizard-shell .bom-line-card [data-field="category"] { width: 180px; }
  .wizard-shell .bom-line-card [data-field="productSelect"] { width: 280px; flex: 0 0 auto !important; }
  .wizard-shell .bom-line-card [data-field="make"] { width: 140px; }
  .wizard-shell .bom-line-card [data-field="type"] { width: 190px; }
  .wizard-shell .bom-line-card [data-field="capacity"] { width: 100px; }
  .wizard-shell .bom-line-card [data-field="phase"] { width: 130px; }
  .wizard-shell .bom-line-card [data-field="ioWays"] { width: 120px; }
  .wizard-shell .bom-line-card [data-field="name"] { width: 100%; max-width: 560px; }
  .bom-line-card > .field.bom-field-full:has([data-field="name"]) { flex: 1 1 320px; }
  .wizard-shell .bom-line-card [data-field="unit"] { width: 72px; }
  .wizard-shell .bom-line-card [data-field="qty"], .wizard-shell .bom-line-card [data-field="qtyShow"] { width: 80px; }
  .wizard-shell .bom-line-card [data-field="wpShow"] { width: 76px; }
  .wizard-shell .bom-line-card [data-field="costPrice"] { width: 110px; }
  .wizard-shell .bom-line-card [data-field="gstShow"] { width: 64px; }
  .bom-line-card .field > .field-hint { display: block; max-width: 200px; font-size: 11px; line-height: 1.3; margin-top: 3px; }
  .bom-line-card > p.field-hint.bom-field-full { margin: 0 !important; font-size: 11px; }
}
@media (min-width: 860px) {
  /* Rate / amount and Save / Remove share one line. */
  .bom-line-card > .bom-field-full:has([data-bom-rate]) { flex: 1 1 380px; gap: 24px; justify-content: flex-start !important; }
  .bom-line-card > .bom-field-full:has([data-save-bom]) { flex: 0 0 auto; margin-left: auto; }
  .bom-line-card .field.bom-field-wide > p.field-hint { max-width: 280px; font-size: 11px; line-height: 1.3; }
}
@media (min-width: 860px) {
  /* Hints go to the end of the card so the fields flow in one or two lines. */
  .bom-line-card > p.field-hint.bom-field-full { order: 90; }
  .bom-line-card > .bom-field-full:has([data-bom-rate]) { order: 95; }
  .bom-line-card > .bom-field-full:has([data-save-bom]) { order: 96; }
  .bom-line-card > div.bom-field-full:not(:has([data-bom-rate])):not(:has([data-save-bom])):not(.field) { order: 97; }
}
@media (min-width: 860px) {
  .bom-line-card, .bom-line-card > .bom-field-wide:not(.field) { align-items: flex-start !important; }
  .bom-line-card .field > .field-hint[data-bom-floor-msg] { max-width: 150px; }
  .bom-line-card > .bom-field-full:has([data-bom-rate]), .bom-line-card > .bom-field-full:has([data-save-bom]) { align-self: center; }
}
@media (max-width: 859px) {
  /* Phone: short values get short boxes too. */
  .wizard-shell .bom-line-card [data-field="wpShow"], .wizard-shell .bom-line-card [data-field="unit"],
  .wizard-shell .bom-line-card [data-field="qty"], .wizard-shell .bom-line-card [data-field="qtyShow"] { width: 90px; }
  .wizard-shell .bom-line-card [data-field="gstShow"] { width: 70px; }
  .wizard-shell .bom-line-card [data-field="costPrice"] { width: 130px; }
  .wizard-shell .bom-line-card [data-field="capacity"] { width: 110px; }
  .bom-line-card .field:has(> [data-field="wpShow"]) { display: inline-block; }
}

/* ── 2026-10-09 round 5: compact, workflow-grouped layout ───────────────────
   Computer: each section is a 6-column grid — plain fields take 2 columns
   (3 per row), cards take 3 (2 side by side) when a section has several,
   wide things (tables, BOM lines, alerts, hints) take the full row. */
@media (min-width: 900px) {
  .wizard-shell .stage-section-body { grid-template-columns: repeat(6, minmax(0, 1fr)) !important; column-gap: 14px; row-gap: 12px; }
  .wizard-shell .stage-section-body > * { grid-column: 1 / -1; }
  .wizard-shell .stage-section-body > .field { grid-column: span 2; }
  .wizard-shell .stage-section-body:has(> .card ~ .card) > .card { grid-column: span 3; margin: 0 !important; }
  .wizard-shell .stage-section-body > .card:has(table), .wizard-shell .stage-section-body > .bom-line-card,
  .wizard-shell .stage-section-body > .bom-compact-card, .wizard-shell .stage-section-body > .bh-card { grid-column: 1 / -1 !important; }
  .wizard-shell .stage-section-body > hr.hr { display: none; }
}
.wizard-shell .card { padding: 12px 14px; }
.wizard-shell .seg { width: fit-content; max-width: 100%; align-self: flex-start; }
/* Bill upload: compact drop zone. */
.upload-card { display: flex; flex-direction: column; gap: 8px; }
.upload-card .upload-drop { padding: 16px 12px !important; min-height: 0 !important; gap: 4px; }
/* Bill history across (one column per bill). */
.bh-table { width: auto; border-collapse: collapse; }
.bh-table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; opacity: .65; padding: 4px 10px 4px 0; white-space: nowrap; font-weight: 600; }
.bh-table td { padding: 3px 4px; vertical-align: middle; }
.wizard-shell .bh-table input.input { width: 112px !important; max-width: none !important; min-height: 34px; padding: 5px 8px; font-size: 13.5px; }
.bh-table .bh-rm td { text-align: center; }
.bh-table .bh-add { padding-left: 10px; vertical-align: middle; }
.bh-table tr { border: 0; }
/* Smaller stage footer — the ‹ › pager does most of the moving now. */
.wizard-footer .btn { min-height: 0; padding: 9px 18px; font-size: 14px; }
@media (min-width: 900px) { .wizard-footer { justify-content: space-between; } .wizard-footer .btn { flex: 0 0 auto !important; width: auto !important; min-width: 160px; } }
/* Drawer content tidy. */
.stage-drawer .bom-verify-out { border-top: 0; margin: 0 !important; padding: 6px 4px; }
/* Output: action buttons compact. */
.wizard-shell .stage-section-body .btn.btn-secondary[style*="flex:1 1 140px"] { min-height: 0; padding: 9px 12px; font-size: 13.5px; }

/* Compact save bar + footer (round 5). */
.stage-save-bar { margin: 10px 0 0; padding: 8px 12px; }
.stage-save-bar .btn { padding: 7px 14px; font-size: 13px; min-height: 0; }
.wizard-footer { padding-top: 10px; padding-bottom: 10px; }
@media (min-width: 900px) {
  .wizard-shell .stage-section-body > .card.c3 { grid-column: span 2 !important; }
  /* Plain fields inside a card sit side by side. */
  .wizard-shell .stage-section-body .card > .field { display: inline-block; vertical-align: top; margin: 0 14px 10px 0 !important; }
  .wizard-shell .stage-section-body .card > .field > label { white-space: nowrap; }
}
/* The ‹ › pager does the stage moving — hide the duplicate footer buttons
   (kept in the page, so Continue's checks still run from the pager). */
.wizard-shell:has(.sec-pager) .wizard-footer { display: none; }
@media (min-width: 900px) {
  .wizard-shell .stage-section-body .card:not(.bom-line-card):has(> .field + .field) { display: flex !important; flex-direction: row !important; flex-wrap: wrap; column-gap: 14px; align-items: flex-start; }
  .wizard-shell .stage-section-body .card:not(.bom-line-card):has(> .field + .field) > :not(.field) { flex: 1 1 100%; }
  .wizard-shell .stage-section-body .card:not(.bom-line-card):has(> .field + .field) > .field { flex: 0 0 auto !important; }
}
@media (min-width: 900px) {
  .wizard-shell .stage-section-body > .card.c4 { grid-column: span 4 !important; }
  .wizard-shell .stage-section-body > .card.c2 { grid-column: span 2 !important; }
}

@media (max-width: 640px) { .sec-pager { flex-wrap: wrap; } .sec-pager .sec-pg-count { flex: 1 1 100%; } .sec-pager .sec-pg-btn { flex: 1 1 0; min-width: 0; } }

/* ── 2026-10-09 round 6: two-column stage layouts, vertical Output tabs ── */
.two-col { display: flex; flex-direction: column; gap: 12px; }
.two-col > .col { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.two-col > .col > .card { margin: 0 !important; }
@media (min-width: 900px) {
  .two-col { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; align-items: start; }
  .two-col.two-col-wide-left { grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); }
  .wl-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 4px 20px; }
  .wl-grid .wl-col + .wl-col { border-left: 1px dashed var(--color-divider); padding-left: 18px; }
}
.wl-col > .field, .wl-col > div > .field { margin-bottom: 8px !important; }
.wl-col label { white-space: normal !important; }
tr.focus-flash td { background: #fff4d6 !important; transition: background .4s; }
/* Output → Print & share: tabs as a column on the left (computer). */
@media (min-width: 900px) {
  .sec-tabbed.sec-vertical { display: grid; grid-template-columns: 230px minmax(0, 1fr); gap: 0 14px; align-items: start; }
  .sec-tabbed.sec-vertical > .sec-tabs, .sec-tabbed.sec-vertical > .sec-tabs-row { grid-column: 1; grid-row: 1 / span 20; flex-direction: column; flex-wrap: nowrap; overflow: visible; align-items: stretch; align-self: start; position: static; }
  .sec-tabbed.sec-vertical > .sec-tabs .sec-tab { white-space: normal; text-align: left; border-radius: 10px; justify-content: flex-start; }
  .sec-tabbed.sec-vertical > :not(.sec-tabs):not(.sec-tabs-row) { grid-column: 2; }
}
.wizard-shell .stage-section-body .wl-col div[style*="display:flex"] > .field.field.field { flex: 1 1 0 !important; min-width: 0 !important; }
.wl-col div[style*="display:flex"] > .field > input.input { width: 100%; max-width: 150px; }
/* 💾 Save proposal chip on the Output tab row (round 7). */
.save-chip { display: inline-flex; align-items: center; gap: 8px; height: 32px; padding: 0 10px 0 4px; border-radius: 999px; border: 1px solid #c8e6c9; background: #f1f8f1; font-size: 12px; white-space: nowrap; }
.save-chip.unsaved { border-color: #f5c2bd; background: #fdecea; font-weight: 600; }
.save-chip .save-chip-btn { height: 26px; min-height: 0; padding: 0 12px; font-size: 12.5px; border-radius: 999px; }
.save-chip.saved .save-chip-text { color: #1e6b34; }
.save-chip:not(:has(.save-chip-btn)) { padding-left: 10px; }
@media (max-width: 480px) { .save-chip .save-chip-text { display: none; } }
/* Print & share layout (round 8). */
.ps-top { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.ps-top > div:first-child { margin: 0 !important; }
.ps-top .pc-folder-box { flex: 1 1 320px; margin: 0; padding: 5px 8px; }
.ps-top .pc-folder-box .pcf-text { font-size: 11.5px; }
.ps-grid { display: flex; flex-direction: column; gap: 12px; }
.seg.seg-vert { display: flex; flex-direction: column; width: 100%; max-width: 260px; }
.seg.seg-vert .seg-opt { padding: 9px 12px; }
.seg.seg-vert .seg-opt + .seg-opt { border-left: 0; border-top: 1px solid var(--color-divider); }
.ps-actions > div[style*="display:flex"] { display: grid !important; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
@media (min-width: 900px) {
  .ps-grid { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: 18px; align-items: start; }
  .ps-actions > div[style*="display:flex"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.ps-actions .btn { min-height: 0; padding: 10px 10px; font-size: 13.5px; }
.wl-summary { background: #f6f9fc; border: 1px dashed #b9c6d6; border-radius: 8px; padding: 8px 10px; font-size: 11.5px; line-height: 1.45; }
/* Consumer details — 3 compact rows on a computer (round 9):
   Name · Consumer No. · Load · Tariff | Address · Pincode · Phone · Email | Salesperson · Name · Number */
@media (min-width: 900px) {
  .wizard-shell .stage-section-body:has(> .field > #cName) { grid-template-columns: repeat(12, minmax(0, 1fr)) !important; }
  :where(.wizard-shell .stage-section-body:has(> .field > #cName)) > .field { grid-column: span 3; }
  .wizard-shell .stage-section-body > .field:has(> #cName) { grid-column: span 4; }
  .wizard-shell .stage-section-body > .field:has(> #cNumber) { grid-column: span 3; }
  .wizard-shell .stage-section-body > .field:has(> #cLoad) { grid-column: span 2; }
  .wizard-shell .stage-section-body > .field:has(#cTariffCode) { grid-column: span 3; }
  .wizard-shell .stage-section-body > .field:has(> #cAddress) { grid-column: span 5; }
  .wizard-shell .stage-section-body > .field:has(> #cPincode) { grid-column: span 2; }
  .wizard-shell .stage-section-body > .field:has(> #cPhone) { grid-column: span 2; }
  .wizard-shell .stage-section-body > .field:has(> #cEmail) { grid-column: span 3; }
  .wizard-shell .stage-section-body > .field:has(#cSalesPersonPicker),
  .wizard-shell .stage-section-body > .field:has(> #cSalesPersonName),
  .wizard-shell .stage-section-body > .field:has(> #cSalesPersonNumber) { grid-column: span 4; }
  .wizard-shell .stage-section-body > .field:has(> #lm51RateField) { grid-column: span 3; }
  .wizard-shell #cLoad, .wizard-shell #cPincode { max-width: 130px; }
  .wizard-shell #cPhone { max-width: 170px; }
  .wizard-shell #cAddress { min-height: 42px; height: 42px; resize: vertical; }
  .wizard-shell .stage-section-body > .field:has(#cTariffCode) .field-hint { font-size: 11px; margin-top: 3px !important; }
}

@media (min-width: 900px) { .sec-tabbed.sec-vertical { grid-auto-rows: min-content; } .sec-tabbed.sec-vertical > .sec-tabs { padding-top: 0; } }
/* Round 10: Output buttons — Report (print + PDF) | Quotation (print + PDF) | WhatsApp. */
@media (min-width: 640px) {
  .ps-actions > div[style*="display:flex"] { display: grid !important; grid-template-columns: repeat(3, minmax(0, 1fr)) !important; grid-template-rows: auto auto; grid-auto-flow: column; }
  .ps-actions #shareWhatsappBtn { grid-row: span 2; height: 100%; }
}
/* Consumer details: tariff hint on one line (full text on hover) so Address moves up; Address shows 2 lines. */
@media (min-width: 900px) {
  .wizard-shell #tariffCategoryHint { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 3px 0 0 !important; }
  .wizard-shell #cAddress { height: 58px !important; min-height: 58px !important; line-height: 1.35; padding: 6px 10px; font-size: 14px; }
  .wizard-shell .stage-section-body:has(> .field > #cName) { row-gap: 8px; }
}
/* TNEB letter: Panel | Inverter side by side (round 11). */
.tl-cols .tl-card { padding: 12px 14px; }
.tl-cols .tl-card > div:first-child { margin-top: 0 !important; }
.tl-cols .tl-card .field { min-width: 120px !important; }
@media (min-width: 900px) {
  .tl-cols .col:first-child .tl-card > div[style*="display:flex"] { display: grid !important; grid-template-columns: 1fr 1fr; gap: 10px; }
  .tl-cols .col:last-child .tl-card > div[style*="display:flex"] { display: grid !important; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px 10px; }
  .tl-cols .tl-card label { font-size: 11.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}

/* ── 2026-10-10: ＋ New menu link, wizard More ▾ menu ───────────────── */
.home-nav-link.home-nav-new { font-weight: 700; color: var(--color-accent, #e8590c); }
.home-nav-plus { display: inline-flex; width: 20px; justify-content: center; font-weight: 800; margin-right: 6px; }
.more-wrap { position: relative; display: inline-flex; }
.more-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 60; min-width: 230px; background: #fff; border: 1px solid var(--color-divider, #ddd);
  border-radius: 12px; box-shadow: 0 8px 24px rgba(0,0,0,.14); padding: 6px; display: flex; flex-direction: column; gap: 2px; }
.more-menu[hidden] { display: none; }
.more-item { text-align: left; background: none; border: 0; border-radius: 8px; padding: 9px 10px; font-size: 13px; cursor: pointer; white-space: nowrap; }
.more-item:hover { background: #f3f3f3; }
.more-item.on { background: #201e1d; color: #fff; }
@media (max-width: 600px) { .more-menu { right: auto; left: 0; } .more-item { padding: 12px 10px; font-size: 14px; } }

/* ═════════════════════════════════════════════════════════════════════
   Phone layout pass (2026-10-15) — one menu on every page, bottom tab bar,
   no sideways scrolling, 16 px inputs (stops iPhone zoom), 44 px taps.
   Desktop (> 900 px) is unchanged except .nav-drawer-only staying hidden.
   ═════════════════════════════════════════════════════════════════════ */
.m-drawer-head, .m-drawer-foot, .m-tabbar, .m-nav-scrim { display: none; }
.home-sidebar.nav-drawer-only { display: none; }
@media screen and (max-width: 900px) {
  html, body { overflow-x: hidden; }
  body.has-m-tabbar { padding-bottom: calc(70px + env(safe-area-inset-bottom, 0px)); }
  /* Drawer */
  .home-sidebar, .home-sidebar.nav-drawer-only {
    display: block !important; position: fixed !important; top: 0; left: 0; bottom: 0; z-index: 1001;
    width: min(86vw, 330px) !important; max-width: none; min-height: 0 !important; overflow-y: auto; overflow-x: hidden;
    border-right: 0; border-bottom: 0; padding: 0 0 24px; background: #fff;
    transform: translateX(-104%); transition: transform .22s ease; box-shadow: 8px 0 28px rgba(0,0,0,.18);
  }
  body.m-nav-open .home-sidebar { transform: none; }
  body.m-nav-open { overflow: hidden; }
  .m-nav-scrim { display: block; position: fixed; inset: 0; background: rgba(32,30,29,.45); z-index: 1000; }
  .m-nav-scrim[hidden] { display: none; }
  .m-drawer-head { display: flex; align-items: center; gap: 12px; padding: 16px 10px 14px 16px; border-bottom: 1px solid var(--color-divider); position: sticky; top: 0; background: #fff; z-index: 1; }
  .m-drawer-avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--color-accent-100, #fde6e1); color: var(--color-accent); display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 16px; flex: none; }
  .m-drawer-name { flex: 1; min-width: 0; font-weight: 700; font-size: 15px; display: flex; flex-direction: column; }
  .m-drawer-name small { font-weight: 500; font-size: 12.5px; opacity: .65; }
  .m-drawer-x { width: 44px; height: 44px; border: 0; background: transparent; display: flex; align-items: center; justify-content: center; color: var(--color-text); cursor: pointer; }
  .m-drawer-foot { display: block; padding: 14px 16px 0; }
  .m-drawer-foot .btn { width: 100%; min-height: 44px; }
  .home-sidebar .home-nav-group { margin: 0 !important; white-space: normal; padding: 4px 8px; }
  /* Collapsible groups in the phone drawer (2026-10-16): tap a heading to open / close it; only the group
     holding the current page starts open, so the whole menu fits and the drawer itself scrolls if needed. */
  .home-sidebar .home-nav-links { display: none; padding-left: 26px; }
  .home-sidebar .home-nav-group.expanded .home-nav-links { display: block; }
  .home-sidebar .home-nav-heading { min-height: 46px; padding: 0 12px; font-size: 15px; font-weight: 700; text-transform: none; letter-spacing: 0;
    color: var(--color-text); border-radius: 10px; }
  .home-sidebar .home-nav-heading::after { content: '▸'; font-size: 13px; opacity: .55; transition: transform .15s ease; }
  .home-sidebar .home-nav-group.expanded .home-nav-heading::after { transform: rotate(90deg); }
  .home-sidebar .home-nav-group.expanded .home-nav-heading { background: #f6f4f1; }
  .home-sidebar, .home-sidebar.nav-drawer-only { height: 100vh; height: 100dvh; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
  .home-sidebar .home-nav-link { min-height: 42px; padding: 0 12px; border-radius: 10px; border-left: 0; font-size: 15px; }
  .home-sidebar .home-nav-link.active { background: var(--color-accent-100, #fde6e1); }
  /* Bottom tab bar */
  .m-tabbar { display: grid; grid-template-columns: repeat(var(--m-tabs, 5), minmax(0, 1fr)); position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
    background: #fff; border-top: 1px solid var(--color-divider); padding-bottom: env(safe-area-inset-bottom, 0px); }
  .m-tab { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-height: 60px; font: inherit; font-size: 11px; font-weight: 600;
    color: var(--color-neutral-700); text-decoration: none !important; background: transparent; border: 0; cursor: pointer; }
  .m-tab.on { color: var(--color-text); font-weight: 800; }
  .m-tab.on .m-tab-ic { color: var(--color-accent); }
  .m-tab-new .m-tab-ic { background: var(--color-accent); color: #fff !important; border-radius: 10px; width: 40px; height: 28px; display: flex; align-items: center; justify-content: center; }
  .m-tab-new .m-tab-ic svg { width: 20px; height: 20px; }
  /* Top bar: logo + page actions only; Home / Log out live in the tab bar & drawer */
  .topbar { padding: 8px 12px; gap: 8px; flex-wrap: nowrap; min-height: 52px; box-sizing: border-box; }
  body.has-m-tabbar .topbar .user-chip, body.has-m-tabbar .topbar .topbar-home, body.has-m-tabbar .topbar a.btn[href="home.php"], body.has-m-tabbar .topbar a.btn[href="layout-designer.php"], body.has-m-tabbar .topbar #logoutBtn { display: none !important; }
  @media print { .m-tabbar, .m-nav-scrim { display: none !important; } }
  .topbar .brand img { height: 22px; }
  /* Content */
  .home-shell { display: block; }
  .home-main { padding: 16px 14px 24px !important; }
  input.input, select.input, textarea.input, .input { font-size: 16px; }
  .btn { min-height: 40px; }
  .stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .stat-card { padding: 10px 12px; }
  .stat-card-value { font-size: 20px; }
  h1 { font-size: 26px; line-height: 1.15; }
  .home-main img, .home-main video { max-width: 100%; }
}
/* Customers follow-ups (2026-10-15): overdue column in the 7-day strip, next follow-up on each row */
.ribbon-day.is-overdue { border-color: #dc2626; background: #fef2f2; }
.ribbon-day.is-overdue .ribbon-day-label { color: #b91c1c; }
.cust-next-what { font-size: 12px; color: rgba(32,30,29,.7); margin-top: 3px; max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media screen and (max-width: 900px) {
  #custListContainer .dash-table tr.cust-row { background: #fff; border-radius: 14px; margin-bottom: 8px; border: 1px solid var(--color-divider); }
  #custListContainer .dash-table tr.cust-row td[data-label="Next"] { flex: 1 1 100%; padding-left: 24px; }
  .followup-ribbon { -webkit-overflow-scrolling: touch; }
}
@media screen and (max-width: 900px) { .cust-intro { display: none; } }
/* BOM Review compact lines (2026-10-15) — see assets/js/bom-compact.js */
.bom-line-card.bom-cmp:not(.bom-open) > :not(.bom-sum) { display: none !important; }
.bom-line-card.bom-cmp:not(.bom-open) { padding: 0 !important; }
.bom-line-card.bom-cmp.bom-open { box-shadow: 0 0 0 2px var(--color-accent) inset; }
.bom-sum { grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; width: 100%; min-height: 54px; padding: 8px 12px; border: 0; background: transparent;
  font: inherit; text-align: left; cursor: pointer; color: var(--color-text); border-radius: inherit; }
.bom-line-card.bom-open > .bom-sum { border-bottom: 1px solid var(--color-divider); margin-bottom: 6px; border-radius: 0; }
.bs-dot { width: 22px; height: 22px; flex: none; border-radius: 50%; background: #e5e1db; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 800; }
.bs-dot.ok { background: #2e7d32; } .bs-dot.miss { background: #c62828; }
.bs-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.bs-cat { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--color-neutral-600); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bs-cat b { color: #c62828; }
.bs-name { font-size: 14.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bs-qty { flex: none; font-size: 13.5px; font-weight: 700; white-space: nowrap; }
.bs-amt { flex: none; font-size: 13px; color: var(--color-neutral-700); white-space: nowrap; min-width: 84px; text-align: right; }
.bs-chev { flex: none; opacity: .55; }
.bom-cmp-bar { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 12.5px; color: var(--color-neutral-700); margin: 2px 0 6px; }
@media screen and (max-width: 560px) { .bs-amt { display: none; } }
/* Proposal wizard on a phone (2026-10-15): full-width content, no boxes inside boxes, big touch targets */
@media screen and (max-width: 900px) {
  .page { padding-left: 10px !important; padding-right: 10px !important; }
  details.stage-section, .stage-section { margin-left: 0 !important; margin-right: 0 !important; }
  details.stage-section > .card, .stage-section .card .card { padding-left: 10px; padding-right: 10px; }
  .bom-line-card select.input, .bom-line-card input.input { min-width: 0; width: 100%; }
  .bom-line-card .bom-field-wide { flex-wrap: wrap; }
  .bom-line-card .field > div[style*="display:flex"] { flex-wrap: wrap; }
  .bom-line-card [data-field="productSelect"] { flex: 1 1 100% !important; }
  .bom-line-card .bom-field-wide > .field { flex: 1 1 120px !important; }
  .bom-line-card [data-remove-bom], .bom-line-card [data-make-inactive-bom], .bom-line-card [data-goto-review], .bom-line-card [data-save-bom] { min-height: 40px; padding: 0 12px !important; font-size: 13px !important; border: 1px solid var(--color-divider) !important; border-radius: 10px; }
  .bom-line-card [data-remove-bom] { color: #b42318; }
  .stage-toolbar, .sec-tabs, .section-tabs { overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
}
/* Layout Designer tidy (2026-10-15) — see assets/js/ld-tidy.js */
@media screen { #ld_titleblock { display: none; } }
.ld-req .ld-req-bar { display: flex; align-items: center; gap: 12px; width: 100%; border: 0; background: transparent; padding: 0; font: inherit; text-align: left; cursor: pointer; color: var(--color-text); min-height: 40px; }
.ld-req-t { font-family: var(--font-heading); font-weight: 800; font-size: 17px; white-space: nowrap; }
.ld-req-sum { flex: 1; min-width: 0; font-size: 13.5px; color: var(--color-neutral-700); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ld-req-act { flex: none; font-weight: 700; font-size: 13px; color: var(--color-accent); }
.ld-req:not(.ld-req-open) > :not(.ld-req-bar) { display: none !important; }
.ld-req.ld-req-open > h2.card-title { display: none; }
.ld-req.ld-req-open > .ld-req-bar { margin-bottom: 12px; }
@media screen and (max-width: 700px) { .ld-req .ld-req-bar { flex-wrap: wrap; } .ld-req-sum { flex-basis: 100%; order: 3; } .ld-req-act { margin-left: auto; } }
/* Dispatch list on a phone (2026-10-15): one card per item instead of a 6-column table (print unchanged) */
@media screen and (max-width: 700px) {
  #dispatchBomTable table, #dispatchBomTable tbody, #dispatchAccessoriesView table, #dispatchAccessoriesView tbody { display: block; width: 100%; }
  #dispatchBomTable thead, #dispatchAccessoriesView thead { display: none; }
  #dispatchBomTable tr, #dispatchAccessoriesView tr { display: grid; grid-template-columns: 28px minmax(0,1fr) auto; gap: 2px 10px; align-items: center; padding: 10px 4px; border-bottom: 1px solid var(--color-divider); }
  #dispatchBomTable td, #dispatchAccessoriesView td { display: block; border: 0 !important; padding: 0 !important; }
  #dispatchBomTable td:nth-child(1) { grid-row: 1 / 3; }
  #dispatchBomTable td:nth-child(2) { grid-column: 2; grid-row: 1; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; opacity: .65; }
  #dispatchBomTable td:nth-child(3) { grid-column: 2; grid-row: 2; font-weight: 600; overflow-wrap: anywhere; }
  #dispatchBomTable td:nth-child(4) { display: none; }
  #dispatchBomTable td:nth-child(5) { grid-column: 3; grid-row: 1 / 3; font-weight: 800; white-space: nowrap; }
  #dispatchBomTable td:nth-child(6) { grid-column: 3; grid-row: 2; font-size: 12px; opacity: .7; text-align: right; display: none; }
  #dispatchAccessoriesView td:nth-child(3) { font-weight: 800; white-space: nowrap; }
  #dispatchAccessoriesView td:nth-child(4) { display: none; }
  .page { max-width: 100% !important; box-sizing: border-box; }
  .iw-item { overflow-wrap: anywhere; }
}
@media screen and (max-width: 480px) { .iw-step-btn { font-size: 11px; overflow-wrap: anywhere; hyphens: auto; } .iw-step-btn span:last-child { overflow-wrap: anywhere; } }

/* ===== PDF / print tidy (2026-10-15) — "no cut blocks and no empty pages" =====
   The closing disclaimer + "Prepared by" footer must never sit alone on an extra page:
   they stay with the card before them (the browser moves that card over with them). */
@media print {
  #print-report .rpt-savings-disclaimer, #print-report .rpt-footer { break-before: avoid; page-break-before: avoid; break-inside: avoid; }
  #print-report table tr, #print-quotation table tr, #print-agreement table tr, #print-tneb-letter table tr { break-inside: avoid; page-break-inside: avoid; }
  #print-report thead, #print-quotation thead { display: table-header-group; }
}
/* A5: cover + "Your bill, before and after Solar" fit together on page 1 (they were 845px on a
   733px page, which left page 1 with the cover only). Same content, slightly smaller icons and spacing. */
@media print {
  #print-report.pdf-a5 .rpt-card-p1 { padding: 12px 14px 12px; margin-bottom: 10px; }
  #print-report.pdf-a5 .rpt-cover { margin-bottom: 8px; }
  #print-report.pdf-a5 .rpt-flow-icons img { height: 42px !important; width: auto !important; }
  #print-report.pdf-a5 .rpt-flow-row { padding: 6px 0; gap: 10px; }
  #print-report.pdf-a5 .rpt-flow-row.after { padding-top: 8px; }
  #print-report.pdf-a5 .rpt-flow-head { margin-bottom: 4px; }
  #print-report.pdf-a5 .rpt-vec-stat { padding: 8px 9px; }
  #print-report.pdf-a5 .rpt-card-p1 .rpt-desc { margin-bottom: 6px; }
}
/* Dispatch list print (2026-10-15): a long BOM / accessories card left an empty bordered sliver at the
   bottom of page 1. Plain (slice) border at the break + no break before the card's first line fixes it;
   the table header repeats on the next page. */
@media print {
  .dispatch-card-table { box-decoration-break: slice; -webkit-box-decoration-break: slice; }
  .dispatch-card-table > :first-child { break-before: avoid; page-break-before: avoid; }
}
/* Layout PDF (2026-10-15): the "Top view (plan) — click it…" fold heading is a screen instruction; in the
   PDF it was left alone at the bottom of a page with its plan on the next one. */
@media print {
  .ld-cab-more > summary { display: none; }
  .ld-cab-more { break-before: auto; }
}
/* Items list (PC review 2026-10-15): the 10-column table ran past the screen edge — scroll it inside its card. */
#itemListContainer { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ═════════════════════════════════════════════════════════════════════
   2026-10-16 — Total cost on the proposal, phone fit for BOM / Review /
   Output (no sideways scrolling), collapsible menu with a sliding bar.
   ═════════════════════════════════════════════════════════════════════ */
/* Investment summary on the proposal PDF (total → subsidy → net). */
#print-report .rpt-invest { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 8px; margin-top: 12px; break-inside: avoid; page-break-inside: avoid; }
#print-report .rpt-invest .ri-cell { border: 1.5px solid var(--rpt-line); border-radius: 10px; padding: 8px 10px; display: flex; flex-direction: column; gap: 1px; background: #fff; }
#print-report .rpt-invest .ri-cell span { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--rpt-muted); }
#print-report .rpt-invest .ri-cell strong { font-family: var(--rpt-font-display); font-size: 18px; font-weight: 800; color: var(--rpt-navy); line-height: 1.15; }
#print-report .rpt-invest .ri-cell small { font-size: 10px; color: var(--rpt-muted); }
#print-report .rpt-invest .ri-minus strong { color: var(--rpt-green); }
#print-report .rpt-invest .ri-net { border-color: var(--rpt-navy); background: var(--rpt-paper); }
#print-report .rpt-invest .ri-cell:first-child strong { color: var(--rpt-navy-deep); }
#print-report.pdf-mobile .rpt-invest { grid-template-columns: 1fr 1fr; gap: 10px; }
#print-report.pdf-mobile .rpt-invest .ri-cell span { font-size: 13px; }
#print-report.pdf-mobile .rpt-invest .ri-cell strong { font-size: 24px; }
#print-report.pdf-mobile .rpt-invest .ri-cell small { font-size: 12px; }
#print-report.pdf-a5 .rpt-invest { gap: 6px; margin-top: 8px; }
#print-report.pdf-a5 .rpt-invest .ri-cell { padding: 6px 8px; }
#print-report.pdf-a5 .rpt-invest .ri-cell strong { font-size: 15px; }
/* Same figures on the Output stage's Proposal summary card. */
.ps-cost { margin: 10px 0 6px; border: 1px solid var(--color-divider); border-radius: 12px; overflow: hidden; max-width: 420px; }
.ps-cost > div { display: flex; justify-content: space-between; gap: 12px; padding: 7px 12px; font-size: 14px; }
.ps-cost > div + div { border-top: 1px solid var(--color-divider); }
.ps-cost > div b { white-space: nowrap; }
.ps-cost > .net { background: var(--color-accent-100, #fde6e1); font-weight: 700; }

/* ── Collapsible menu (☰ in every top bar — see includes/sidebar.php) ── */
.nav-burger { flex: none; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--color-divider);
  border-radius: 10px; background: #fff; color: var(--color-text); cursor: pointer; padding: 0; margin-right: -6px; }
.nav-burger:hover { border-color: #999; }
@media print { .nav-burger { display: none !important; } }
@media screen and (min-width: 901px) {
  .home-sidebar { transition: width .2s ease, flex-basis .2s ease; overflow-x: hidden; }
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) { width: 62px; flex: 0 0 62px; }
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) .home-nav-links,
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) .home-nav-heading::after { display: none !important; }
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) .home-nav-heading-label { font-size: 0; gap: 0; }
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) .home-nav-link > span:not(.home-nav-plus) { display: none; }
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) .home-nav-heading,
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) .home-nav-link { justify-content: center; padding-left: 0; padding-right: 0; }
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) .home-nav-icon { width: 20px; height: 20px; opacity: .85; }
  body.nav-collapsed .home-sidebar:not(.nav-drawer-only) .home-nav-group { margin-bottom: 6px; }
  /* Full-width pages (calculator…): the menu slides in over the page from the ☰ button. */
  .home-sidebar.nav-drawer-only { display: block; position: fixed; top: 0; left: 0; bottom: 0; z-index: 1001; width: 290px; min-height: 0; overflow-y: auto;
    background: #fff; padding: 0 0 24px; transform: translateX(-104%); transition: transform .22s ease; box-shadow: 8px 0 28px rgba(0,0,0,.18); }
  body.m-nav-open .home-sidebar.nav-drawer-only { transform: none; }
  body.m-nav-open:has(.nav-drawer-only) .m-nav-scrim { display: block; position: fixed; inset: 0; background: rgba(32,30,29,.35); z-index: 1000; }
  body.m-nav-open .m-nav-scrim[hidden] { display: none; }
  .home-sidebar.nav-drawer-only .m-drawer-head { display: flex; align-items: center; gap: 12px; padding: 14px 8px 12px 16px; border-bottom: 1px solid var(--color-divider); margin-bottom: 8px; }
  .home-sidebar.nav-drawer-only .m-drawer-avatar { width: 36px; height: 36px; border-radius: 50%; background: var(--color-accent-100, #fde6e1); color: var(--color-accent); display: flex; align-items: center; justify-content: center; font-weight: 800; flex: none; }
  .home-sidebar.nav-drawer-only .m-drawer-name { flex: 1; min-width: 0; font-weight: 700; display: flex; flex-direction: column; }
  .home-sidebar.nav-drawer-only .m-drawer-name small { font-weight: 500; font-size: 12px; opacity: .65; }
  .home-sidebar.nav-drawer-only .m-drawer-x { width: 40px; height: 40px; border: 0; background: transparent; display: flex; align-items: center; justify-content: center; cursor: pointer; }
  .home-sidebar.nav-drawer-only .m-drawer-foot { display: block; padding: 12px 16px 0; }
  .home-sidebar.nav-drawer-only .m-drawer-foot .btn { width: 100%; }
}
@media screen and (max-width: 900px) { .nav-burger { width: 38px; height: 38px; margin-right: 0; } }

/* ── Menu ribbon with its own scroll bar (2026-10-18) ──
   The left menu scrolls by itself, separate from the page: when groups like Admin are open and the menu
   is taller than the screen, scroll the menu without moving the page (and the page without moving the menu). */
@media screen and (min-width: 901px) {
  .home-sidebar:not(.nav-drawer-only) {
    position: sticky; top: 0; align-self: flex-start;
    height: 100vh; height: 100dvh; min-height: 0; max-height: 100vh; max-height: 100dvh;
    overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; box-sizing: border-box;
  }
}
.home-sidebar { scrollbar-width: thin; scrollbar-color: #c9c2b8 transparent; scrollbar-gutter: stable; }
.home-sidebar::-webkit-scrollbar { width: 8px; }
.home-sidebar::-webkit-scrollbar-track { background: transparent; }
.home-sidebar::-webkit-scrollbar-thumb { background: #c9c2b8; border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; }
.home-sidebar::-webkit-scrollbar-thumb:hover { background: #9e958a; background-clip: padding-box; }

/* ── Phone fit for the proposal wizard (BOM / Review / Output) ── */
@media screen and (max-width: 900px) {
  .wizard-body { padding: 10px 8px !important; overflow-x: hidden; }
  .wizard-body .stage-section-body { padding-left: 10px !important; padding-right: 10px !important; }
  .wizard-body .card .card { padding-left: 8px; padding-right: 8px; }
  .wizard-body > *, .wizard-body .stage-section, .wizard-body .stage-section-body > * { min-width: 0; max-width: 100%; }
  /* Section tabs: wrap onto lines — every tab visible, nothing hidden off to the right. */
  .sec-tabs, .sec-tabs-row > .sec-tabs, .sec-tabbed.sec-vertical > .sec-tabs { flex-wrap: wrap !important; overflow: visible !important; gap: 5px; }
  .sec-tabs .sec-tab { padding: 6px 10px; font-size: 12px; max-width: 100%; white-space: normal; text-align: left; line-height: 1.2; min-height: 32px; }
  .sec-tabs .sec-tab .sec-tab-ico { width: 16px; height: 16px; font-size: 10px; flex: none; }
  /* Smart check / More / lock / Edit row: wraps instead of pushing Edit off-screen. */
  .sec-tabs-row .sec-tabs-extras { flex-wrap: wrap; justify-content: flex-start !important; max-width: 100%; row-gap: 6px; }
  .sec-tabs-row .sec-tabs-extras .lock-chip { margin-left: auto; flex: none; }
  .sec-tabbed.sec-vertical { display: block; }
  .ps-grid, .ps-top { display: flex !important; flex-direction: column; gap: 10px; }
}
@media screen and (max-width: 700px) {
  /* Wide tables become one card per row (labels from the column headings — assets/js/mobile-fit.js). */
  #wizardRoot .m-cards-wrap { overflow: visible !important; max-width: 100%; }
  #wizardRoot table.m-cards { display: block; width: 100% !important; min-width: 0 !important; border: 0; }
  #wizardRoot table.m-cards > thead { display: none; }
  #wizardRoot table.m-cards > tbody, #wizardRoot table.m-cards > tfoot { display: block; width: 100%; }
  #wizardRoot table.m-cards tr { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 5px 10px; padding: 9px 11px; margin: 0 0 8px;
    border: 1px solid var(--color-divider); border-radius: 12px; background: #fff; }
  #wizardRoot table.m-cards > tfoot tr { background: var(--color-neutral-100, #f4f4f4); font-weight: 700; }
  #wizardRoot table.m-cards td { display: block; min-width: 0; width: auto !important; padding: 0 !important; border: 0 !important; text-align: left !important;
    font-size: 13.5px; overflow-wrap: anywhere; white-space: normal !important; }
  #wizardRoot table.m-cards td::before { content: attr(data-label); display: block; font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    color: var(--color-neutral-600, #777); margin-bottom: 1px; }
  #wizardRoot table.m-cards td[data-label=""]::before, #wizardRoot table.m-cards td.m-span::before { display: none; }
  #wizardRoot table.m-cards td.m-span, #wizardRoot table.m-cards td.m-wide { grid-column: 1 / -1; }
  #wizardRoot table.m-cards td.m-wide2 { grid-column: span 2; }
  #wizardRoot table.m-cards td.m-wide { font-weight: 600; font-size: 14px; }
  #wizardRoot table.m-cards td:empty { display: none; }
  #wizardRoot table.m-cards td .input { max-width: 100% !important; width: 100%; }
}

/* ── Slide-in menu scroll fix (2026-10-28) ──
   On full-width pages (calculator, sticker maker, dispatch, installation details…) and on phones, the
   slide-in menu grew taller than the screen, so its lower items (Accounts, Admin…) were cut off with no
   scroll bar. Pin it to the screen height so it always scrolls on its own. */
.home-sidebar.nav-drawer-only,
body.m-nav-open .home-sidebar.nav-drawer-only {
  height: 100vh; height: 100dvh; max-height: 100vh; max-height: 100dvh; box-sizing: border-box;
  overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}
@media screen and (max-width: 900px) {
  .home-sidebar {
    height: 100vh; height: 100dvh; max-height: 100vh; max-height: 100dvh; box-sizing: border-box;
    overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
  }
}
.home-sidebar.nav-drawer-only .m-drawer-head { position: sticky; top: 0; background: #fff; z-index: 1; margin-bottom: 0; }
.home-sidebar.nav-drawer-only .m-drawer-foot { padding-bottom: 16px; }

/* Apartment sharing (2026-10-30): bold red note under the price card (items + qty only, no prices) and a
   small red tag on each shared spec card. .qb-first keeps the "specifications" heading with its first block. */
.qb-shared { border: 2px solid #c00000; background: #fff5f5; border-radius: 10px; padding: 8px 12px; margin: 8px 0; color: #c00000; font-weight: 700; font-size: 12px; line-height: 1.4; break-inside: avoid; page-break-inside: avoid; }
.qb-shared-h { font-size: 14px; font-weight: 800; margin-bottom: 2px; }
.qb-shared-s { font-weight: 600; }
.qb-shared-l { margin: 5px 0; padding: 0 0 0 16px; columns: 2; column-gap: 18px; }
.qb-shared-l li { break-inside: avoid; margin: 0 0 2px; }
.qb-shared-l li span { font-weight: 600; white-space: nowrap; }
.qb-shared-tag { display: inline-block; margin-left: 4px; padding: 0 6px; border-radius: 999px; background: #c00000; color: #fff; font-size: 0.82em; font-weight: 800; letter-spacing: .02em; white-space: nowrap; vertical-align: 1px; }
.qb-first { break-inside: avoid; page-break-inside: avoid; }
.qb-first > h2, .qb-first > .cs-spec-h { margin-top: 0; }
.rpt-shared-card { padding: 0; border: 0; background: none; box-shadow: none; }
#print-report.pdf-mobile .qb-shared { font-size: 15px; }
#print-report.pdf-mobile .qb-shared-h { font-size: 17px; }
#print-report.pdf-mobile .qb-shared-l { columns: 1; }


/* 2026-10-31 — PDF layout fixes (quotation header, item names, savings table) */
.qot-to-date > div:first-child { flex: 1 1 auto; min-width: 0; }
.qot-to-date > div:last-child { flex: 0 0 auto; white-space: nowrap; }
.qb-nb { white-space: nowrap; }
/* money / unit figures never split over two lines ("₹37,87 / 9", "-2,37 / 8") */
.report-charges-table td:not(:first-child):not(:last-child) { white-space: nowrap; overflow-wrap: normal; }
.rpt-la1d-note { margin-top: -2px; font-size: 11px; color: var(--rpt-navy, #1e3a5f); }
/* "You pay / You save" boxes beside the pictures: drop below them when there is no room
   (the A4 savings PDF had the third box running off the page) */
#print-report .rpt-flow-row { flex-wrap: wrap; }
#print-report .rpt-vec-stats { flex: 1 1 400px; min-width: 0; }
