/*
 * app.css — the app's FIRST stylesheet (02-UI-SPEC contract, 02-03 / D-13).
 *
 * Provenance: the editorial palette + type system is ported from the offer-comparison
 * skill's build_comparison.py CSS, then NORMALIZED to this phase's design contract:
 *   - EXACTLY 4 font sizes: 12 / 14 / 18 / 30px (the ported 8.5-24px values are snapped
 *     up/into this scale — chips/legends/eyebrows -> 12px; card price -> 18px).
 *   - Two weights only: 400 (regular) / 600 (semibold). Italic 400 for disclaimers.
 *   - 8pt spacing scale: 4 / 8 / 16 / 24 / 32 / 48 / 64.
 *
 * Supply-chain (CLAUDE.md, PII app): EVERYTHING is vendored under /static. There is NO
 * remote Google-Fonts <link> and NO CDN reference anywhere — the skill's hosted-font
 * <link> is intentionally NOT ported. As of 05-03 the real editorial faces (Spectral,
 * Inter 400/600, IBM Plex Mono 600) are SELF-HOSTED as latin-subset .woff2 under
 * /static/fonts/ and declared via @font-face below (D-06); the system stacks
 * (Georgia / system-sans / system-mono) remain as graceful fallbacks. A CSP middleware
 * (app/main.py) forbids any external font/script/style origin (D-07, DASH-03/05).
 *
 * The "Due to Seller" total is NEVER styled as an editable input and is NEVER computed in
 * JS (CLAUDE.md §4) — it is server-rendered into .ns-total and OOB-swapped on every mutation.
 */

/* ----------------------------------------------------------------------------
 * Tokens (palette + type stacks + spacing) — :root custom properties.
 * -------------------------------------------------------------------------- */
:root {
  /* Editorial palette (ported from build_comparison.py, D-13). */
  --ink: #1F2A38;
  --ink-soft: #44505C;
  --paper: #F5F2EC;
  --line: #D8D3C7;
  --brass: #B08529;
  --sage: #E7EEDF;
  --sage-line: #9DBE8C;
  --sage-tx: #3F6B33;
  --clay: #F6E5D2;
  --clay-tx: #9A5A18;
  --white: #ffffff;
  --mute: #6B7682;
  --wash: #E9E5DC; /* page background wash */

  /* Font stacks — the real self-hosted faces (declared via @font-face below) lead,
   * with the system-stack fallbacks retained for graceful FOUT/degradation (05-03 / D-06). */
  --serif: "Spectral", Georgia, "Times New Roman", serif;
  --sans: "Inter", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;

  /* The ONLY four font sizes permitted this phase (UI-SPEC Typography). */
  --fs-label: 12px;   /* Label: chips, eyebrows, column heads, footnotes (min size) */
  --fs-body: 14px;    /* Body: default text, table cells, line amounts (mono) */
  --fs-heading: 18px; /* Heading: section titles, headline money, the live total */
  --fs-display: 30px; /* Display: page H1 */

  /* 8pt spacing scale (all multiples of 4). */
  --sp-xs: 4px;
  --sp-sm: 8px;
  --sp-md: 16px;
  --sp-lg: 24px;
  --sp-xl: 32px;
  --sp-2xl: 48px;
  --sp-3xl: 64px;

  /* Shell layout dimensions (05-04 / D-13) — multiples of 4, layout dims not spacing tokens. */
  --sidebar-w: 240px;
  --sidebar-w-collapsed: 64px;

  /* Status-state pill tints (DASH-02). Derived IN-FAMILY from the existing sage/clay/mute/ink
   * pairs so the pills read as the same editorial system — no new hues introduced. */
  --status-active: var(--sage-tx);     /* on --sage  : "Active" */
  --status-active-bg: var(--sage);
  --status-review: var(--clay-tx);     /* on --clay  : "In review" */
  --status-review-bg: var(--clay);
  --status-pending: var(--mute);       /* on --paper : "Pending" */
  --status-pending-bg: var(--paper);
  --status-closed: #EFE9DC;            /* on --ink   : "Closed" */
  --status-closed-bg: var(--ink);
}

/* Alpine x-cloak: hide elements (e.g. the user-menu dropdown) until Alpine initialises so
 * there is no flash of the open menu on first paint. Alpine removes the attribute on init. */
[x-cloak] { display: none !important; }

/* Self-hosted editorial faces (05-03 / D-06, D-07). Latin subset, vendored under
 * /static/fonts/ — NEVER a remote Google-Fonts / static-CDN origin (no-external-origin gate).
 * font-display:swap → FOUT over invisible text; the --serif/--sans/--mono fallback
 * stacks below already match, so degradation is graceful if a file is missing.
 * Weights mirror the phase's 2-weight scale: Inter 400 (body) + 600 (semibold money/
 * emphasis), Spectral 600 (headings/H1), IBM Plex Mono 600 (ALL money). */
@font-face { font-family:"Spectral"; src:url("/static/fonts/spectral-600.woff2") format("woff2"); font-weight:600; font-style:normal; font-display:swap; }
@font-face { font-family:"Inter"; src:url("/static/fonts/inter-400.woff2") format("woff2"); font-weight:400; font-style:normal; font-display:swap; }
@font-face { font-family:"Inter"; src:url("/static/fonts/inter-600.woff2") format("woff2"); font-weight:600; font-style:normal; font-display:swap; }
@font-face { font-family:"IBM Plex Mono"; src:url("/static/fonts/ibmplexmono-600.woff2") format("woff2"); font-weight:600; font-style:normal; font-display:swap; }

/* ----------------------------------------------------------------------------
 * Base
 * -------------------------------------------------------------------------- */
* { box-sizing: border-box; }
html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
body {
  margin: 0;
  background: var(--wash);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: 1.5;
}

main { max-width: 1080px; margin: var(--sp-lg) auto; padding: 0 var(--sp-md); }

h1 { font-family: var(--serif); font-weight: 600; font-size: var(--fs-display); line-height: 1.1; margin: 0 0 var(--sp-sm); letter-spacing: -.01em; }
h2 { font-family: var(--serif); font-weight: 600; font-size: var(--fs-heading); line-height: 1.2; margin: 0 0 var(--sp-sm); }
h3 { font-family: var(--serif); font-weight: 600; font-size: var(--fs-heading); line-height: 1.2; margin: 0 0 var(--sp-xs); }

a { color: var(--ink); }

/* ----------------------------------------------------------------------------
 * Topbar / nav (Phase-1 chrome; print-hidden)
 * -------------------------------------------------------------------------- */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-md);
  background: var(--ink); color: #EFE9DC;
  padding: var(--sp-md) var(--sp-lg);
}
.topbar .brand { font-family: var(--serif); font-weight: 600; font-size: var(--fs-heading); color: #EFE9DC; text-decoration: none; }
.topbar nav { display: flex; align-items: center; gap: var(--sp-md); }
.topbar .user { font-size: var(--fs-label); color: #B9BFC7; }
.topbar a { color: #EFE9DC; }
.topbar .logout-form { margin: 0; }

/* ----------------------------------------------------------------------------
 * SaaS shell — sidebar + topbar (05-04 / D-13).
 *
 * base.html wraps the unchanged {% block content %} in a fixed --ink sidebar (240px,
 * collapse->64px via Alpine + localStorage) + a 64px --ink topbar. One continuous dark
 * chrome. The content column (.app-main) is offset by the sidebar width. @media print
 * hides BOTH so the printable ESTIMATE survives (see the print block at the bottom).
 * Composed entirely from existing tokens — NO new font size/weight (UI-SPEC Typography).
 * -------------------------------------------------------------------------- */
.app-sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 20;
  width: var(--sidebar-w);
  display: flex; flex-direction: column;
  background: var(--ink); color: #EFE9DC;
  border-right: 1px solid var(--ink-soft);
  overflow-x: hidden;
}
.app-sidebar.collapsed { width: var(--sidebar-w-collapsed); }

.app-sidebar-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-sm);
  min-height: var(--sp-3xl); /* 64px — aligns with the topbar height */
  padding: 0 var(--sp-md);
  border-bottom: 1px solid var(--ink-soft);
}
.app-brand {
  font-family: var(--serif); font-weight: 600; font-size: var(--fs-heading);
  color: #EFE9DC; text-decoration: none; white-space: nowrap;
}
.app-sidebar.collapsed .app-brand { font-size: var(--fs-heading); overflow: hidden; }
.app-collapse {
  display: inline-flex; align-items: center; justify-content: center;
  padding: var(--sp-xs); min-width: 32px; min-height: 32px;
  background: transparent; border: 1px solid var(--ink-soft); border-radius: 3px;
  color: #EFE9DC; cursor: pointer;
}
.app-collapse:hover { border-color: #EFE9DC; }
.app-sidebar.collapsed .app-collapse .ic { transform: rotate(180deg); }

.app-nav { display: flex; flex-direction: column; padding: var(--sp-sm) 0; }
.app-nav-item {
  display: flex; align-items: center; gap: var(--sp-md);
  min-height: 48px; padding: 0 var(--sp-md);
  font-size: var(--fs-label); font-weight: 600; letter-spacing: .04em;
  color: #B9BFC7; text-decoration: none; white-space: nowrap;
  border-left: 3px solid transparent; /* reserves the active brass-rule gutter */
}
.app-nav-item:hover { color: #EFE9DC; background: rgba(255,255,255,.04); }
.app-nav-item .ic { flex: none; }
.app-nav-label { overflow: hidden; }
/* Active item — the 3px brass left-rule is the ONLY "you are here" signal (D-13, brass reserved). */
.app-nav-item.active { color: #EFE9DC; border-left: 3px solid var(--brass); background: rgba(176,133,41,.10); }
/* Collapsed rail: icon-only, labels hidden. */
.app-sidebar.collapsed .app-nav-label { display: none; }

/* Content column offset by the sidebar. */
.app-main { margin-left: var(--sidebar-w); min-height: 100vh; transition: none; }

/* Topbar — 64px --ink chrome continuous with the sidebar. */
.app-topbar {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-md);
  min-height: var(--sp-3xl); /* 64px */
  padding: 0 var(--sp-lg);
  background: var(--ink); color: #EFE9DC;
  border-bottom: 1px solid var(--ink-soft);
}
.app-topbar-title { display: flex; align-items: center; gap: var(--sp-sm); min-width: 0; }
.app-topbar-brand {
  font-family: var(--serif); font-weight: 600; font-size: var(--fs-heading);
  color: #EFE9DC; text-decoration: none;
}

/* User menu (Alpine dropdown — client-only sugar). */
.app-usermenu { position: relative; }
.app-usermenu-trigger {
  display: inline-flex; align-items: center; gap: var(--sp-sm);
  background: transparent; border: 1px solid var(--ink-soft); border-radius: 3px;
  color: #EFE9DC; padding: var(--sp-sm) var(--sp-md); cursor: pointer;
  font-size: var(--fs-label); font-weight: 600;
}
.app-usermenu-trigger:hover { border-color: #EFE9DC; }
.app-usermenu-trigger .user { color: #EFE9DC; font-size: var(--fs-label); }
.app-usermenu-caret .ic { transform: rotate(-90deg); transition: transform .12s ease; }
.app-usermenu-caret.is-open .ic { transform: rotate(90deg); }
.app-usermenu-pop {
  position: absolute; right: 0; top: calc(100% + var(--sp-xs)); z-index: 30;
  min-width: 180px;
  display: flex; flex-direction: column; gap: var(--sp-xs);
  background: var(--white); color: var(--ink);
  border: 1px solid var(--line); border-radius: 3px;
  box-shadow: 0 8px 28px rgba(31,42,56,.18);
  padding: var(--sp-sm);
}
.app-usermenu-link {
  display: block; padding: var(--sp-sm) var(--sp-md);
  font-size: var(--fs-body); font-weight: 600; color: var(--ink); text-decoration: none;
  border-radius: 3px;
}
.app-usermenu-link:hover { background: var(--paper); }
.app-usermenu-pop .logout-form { margin: 0; }
.app-usermenu-pop .logout-form button { width: 100%; }

/* Responsive: under 760px the sidebar shrinks to the icon-rail; under 480px it tucks away. */
@media (max-width: 760px) {
  .app-sidebar { width: var(--sidebar-w-collapsed); }
  .app-sidebar .app-nav-label, .app-sidebar .app-brand { display: none; }
  .app-main { margin-left: var(--sidebar-w-collapsed); }
}

/* ----------------------------------------------------------------------------
 * Status pills (DASH-02) — a .chip variant, NOT a new component family.
 * 12px mono uppercase, 600, 2px radius, 1px border (same anatomy as .chip).
 * -------------------------------------------------------------------------- */
.status-pill {
  display: inline-block; font-family: var(--mono); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase;
  border-radius: 2px; padding: 0 var(--sp-xs); border: 1px solid transparent; vertical-align: middle;
}
.status-pill.is-active  { color: var(--status-active);  background: var(--status-active-bg);  border-color: var(--sage-line); }
.status-pill.is-review  { color: var(--status-review);  background: var(--status-review-bg);  border-color: #E3B488; }
.status-pill.is-pending { color: var(--status-pending); background: var(--status-pending-bg); border-color: var(--line); }
.status-pill.is-closed  { color: var(--status-closed);  background: var(--status-closed-bg);  border-color: var(--ink); }

/* ----------------------------------------------------------------------------
 * KPI card (DASH-01) + 4-up grid. White surface, --line border, 16px pad, min-h 96px.
 * Every VALUE is server-rendered — NEVER summed in JS (Pitfall 3 / acceptance gate).
 * -------------------------------------------------------------------------- */
.kpi-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-md);
  margin: var(--sp-lg) 0;
}
.kpi-card {
  background: var(--white); border: 1px solid var(--line); border-radius: 3px;
  padding: var(--sp-md); min-height: 96px;
  box-shadow: 0 1px 0 var(--line);
  display: flex; flex-direction: column; gap: var(--sp-xs);
}
.kpi-card .kpi-label {
  font-family: var(--mono); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--mute); margin: 0;
}
.kpi-card .kpi-value { font-size: var(--fs-heading); font-weight: 600; margin: 0; }
.kpi-card .kpi-value.money { font-family: var(--mono); }
.kpi-card .kpi-sub { font-size: var(--fs-label); font-weight: 600; color: var(--mute); margin: 0; }
@media (max-width: 760px) { .kpi-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .kpi-grid { grid-template-columns: 1fr; } }

/* ----------------------------------------------------------------------------
 * Page chrome shared across the restyled pages (VISUAL-only, 05-04). Section headers,
 * the plain listing/auth/form surfaces — composed from existing tokens. No money math.
 * -------------------------------------------------------------------------- */
.page-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-md); margin: 0 0 var(--sp-lg); flex-wrap: wrap; }

/* Listings index + listing detail */
.listings-header, .listing-header, .offers-header, .listings-table { /* hooks for the restyle */ }
.listings-header, .listing-header { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-md); margin: 0 0 var(--sp-lg); flex-wrap: wrap; }
.offers-header { display: flex; align-items: center; gap: var(--sp-sm); margin: 0 0 var(--sp-md); flex-wrap: wrap; }
.offers-header h2 { margin: 0; margin-right: auto; }

table.listings-table, table.offers-table {
  width: 100%; border-collapse: collapse; font-size: var(--fs-body);
  background: var(--white); box-shadow: 0 1px 0 var(--line);
}
table.listings-table th, table.offers-table th {
  text-align: left; padding: var(--sp-sm); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft);
  border-bottom: 1.5px solid var(--ink);
}
table.listings-table td, table.offers-table td { padding: var(--sp-sm); border-bottom: 1px solid #ECE8DE; vertical-align: middle; }
table.listings-table a, table.offers-table a { font-weight: 600; }

.listing-fields { display: grid; grid-template-columns: max-content 1fr; gap: var(--sp-xs) var(--sp-lg); background: var(--white); border: 1px solid var(--line); padding: var(--sp-lg); margin: 0 0 var(--sp-xl); max-width: 560px; }
.listing-fields dt { font-size: var(--fs-label); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--mute); margin: 0; }
.listing-fields dd { margin: 0; font-weight: 600; }

.empty { color: var(--ink-soft); padding: var(--sp-lg) 0; }

/* Auth / form cards (login, set-password, invite, listing form) */
.auth-card, .listing-form {
  background: var(--white); border: 1px solid var(--line);
  box-shadow: 0 1px 0 var(--line), 0 18px 50px rgba(31,42,56,.08);
  max-width: 480px; margin: var(--sp-2xl) auto; padding: var(--sp-xl) var(--sp-lg);
}
.listing-form { max-width: 560px; }
.auth-card h1, .listing-form h1 { margin: 0 0 var(--sp-lg); }
.auth-card form label, .listing-form form label { display: block; font-size: var(--fs-label); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-soft); margin: 0 0 var(--sp-md); }
.auth-card input[type="email"], .auth-card input[type="password"],
.auth-card select, .listing-form input, .listing-form select {
  display: block; width: 100%; margin-top: var(--sp-xs);
  font-family: var(--sans); font-size: var(--fs-body); font-weight: 400;
  padding: var(--sp-sm); border: 1px solid var(--line); border-radius: 3px; color: var(--ink);
}
.listing-form input[name="list_price"], .listing-form input[type="number"] { font-family: var(--mono); }
.error { color: var(--clay-tx); background: var(--clay); border: 1px solid #E3B488; border-radius: 3px; padding: var(--sp-sm) var(--sp-md); font-size: var(--fs-body); font-weight: 600; }
.form-actions { display: flex; align-items: center; gap: var(--sp-md); margin-top: var(--sp-lg); }
.invite-result { background: var(--paper); border: 1px solid var(--line); border-radius: 3px; padding: var(--sp-md); margin: 0 0 var(--sp-lg); }
.invite-link { font-family: var(--mono); font-size: var(--fs-body); padding: var(--sp-sm); border: 1px solid var(--line); border-radius: 3px; }

/* Net-sheet "back" link + page footer link */
.ns-back, .cmp-back { padding: 0 var(--sp-lg) var(--sp-lg); margin: var(--sp-md) 0 0; }

/* Review queue (Phase-4 surface, restyled into the shell — VISUAL only; _review_diff frozen) */
.review-block { margin: 0 0 var(--sp-xl); }
.review-header { margin: 0 0 var(--sp-lg); }
.review-header h1 { margin: 0 0 var(--sp-xs); }
.review-sub { font-size: var(--fs-body); color: var(--mute); margin: 0; max-width: 640px; }
.review-queue { display: flex; flex-direction: column; gap: var(--sp-lg); }
.review-empty { color: var(--ink-soft); padding: var(--sp-lg) 0; }
.review-card { background: var(--white); border: 1px solid var(--line); box-shadow: 0 1px 0 var(--line); padding: var(--sp-lg); }
.review-card-head { display: flex; align-items: baseline; gap: var(--sp-sm); flex-wrap: wrap; margin: 0 0 var(--sp-md); }
.review-kind { font-family: var(--mono); font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--brass); }
.review-prov, .review-when { font-size: var(--fs-label); color: var(--mute); }
.review-total { display: flex; align-items: baseline; gap: var(--sp-sm); padding: var(--sp-md); background: var(--paper); border-top: 1.5px solid var(--ink); margin: 0 0 var(--sp-md); }
.review-total-label { font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft); }
.review-total-value { font-family: var(--mono); font-size: var(--fs-heading); font-weight: 600; }
.review-total-delta { font-family: var(--mono); font-size: var(--fs-label); color: var(--mute); }
table.review-fields { width: 100%; border-collapse: collapse; font-size: var(--fs-body); margin: 0 0 var(--sp-md); }
table.review-fields th { text-align: left; padding: var(--sp-sm); font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft); border-bottom: 1.5px solid var(--ink); }
table.review-fields td { padding: var(--sp-sm); border-bottom: 1px solid #ECE8DE; vertical-align: top; }
tr.low-confidence td { background: var(--clay); }
.lc-flag { font-family: var(--mono); font-size: var(--fs-label); font-weight: 600; color: var(--clay-tx); margin-left: var(--sp-xs); }
.review-citations h4, .review-ambiguities h4 { font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--mute); margin: var(--sp-md) 0 var(--sp-xs); }
.review-citations ul, .review-ambiguities ul { margin: 0; padding-left: var(--sp-lg); font-size: var(--fs-body); }
.cit-snippet { font-style: italic; color: var(--ink-soft); }
.cit-field { font-weight: 600; }
.review-actions { display: flex; gap: var(--sp-sm); margin-top: var(--sp-md); }
.review-actions form { margin: 0; }
.btn-confirm { border-top: 3px solid var(--brass); color: var(--ink); font-weight: 600; }
.btn-discard { color: var(--clay-tx); border-color: #E3B488; background: var(--clay); }

/* ----------------------------------------------------------------------------
 * Buttons
 * -------------------------------------------------------------------------- */
button, .btn {
  font-family: var(--sans); font-size: var(--fs-body); font-weight: 600;
  color: var(--ink); background: var(--white);
  border: 1px solid var(--line); border-radius: 3px;
  padding: var(--sp-sm) var(--sp-md);
  cursor: pointer;
}
button:hover, .btn:hover { border-color: var(--ink-soft); }

/* Primary CTA "Add line" — the ONLY general place --brass touches a button (accent rule). */
.btn-primary {
  border-top: 3px solid var(--brass);
  color: var(--ink); font-weight: 600;
}
.btn-primary:hover { border-color: var(--brass); }

/* Secondary / row-action buttons use ink, never brass. Touch target >= 48px. */
.btn-sm {
  font-size: var(--fs-label); font-weight: 600;
  padding: var(--sp-sm) var(--sp-md);
  min-height: 48px; min-width: 48px;
  border: 1px solid var(--line); background: var(--white); color: var(--ink-soft);
}
.btn-reset {
  color: var(--sage-tx); border-color: var(--sage-line); background: var(--sage);
}
.btn-reset:hover { border-color: var(--sage-tx); }
.btn-delete { color: var(--clay-tx); border-color: #E3B488; background: var(--clay); }
.btn-delete:hover { border-color: var(--clay-tx); }

/* ----------------------------------------------------------------------------
 * Eyebrow + page header chrome (brass reserved here, per Color contract)
 * -------------------------------------------------------------------------- */
.eyebrow {
  font-family: var(--mono); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase; color: var(--brass);
  margin: 0 0 var(--sp-sm);
}

/* ----------------------------------------------------------------------------
 * Net-sheet block — the headline editable table
 * -------------------------------------------------------------------------- */
.ns-block { background: var(--white); box-shadow: 0 1px 0 var(--line), 0 18px 50px rgba(31,42,56,.10); margin: var(--sp-xl) 0; }
.ns-header { padding: var(--sp-lg) var(--sp-lg) var(--sp-md); border-bottom: 1px solid var(--line); }
.ns-header h2 { margin: 0 0 var(--sp-xs); }
.ns-sub { font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--mute); margin: 0; }
.ns-actions { padding: var(--sp-md) var(--sp-lg); display: flex; gap: var(--sp-sm); }

table.ns-table { width: 100%; border-collapse: collapse; font-size: var(--fs-body); }
table.ns-table th {
  text-align: left; padding: var(--sp-sm); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft);
  border-bottom: 1.5px solid var(--ink);
}
table.ns-table th.amount, table.ns-table td.amount { text-align: right; padding: var(--sp-sm) var(--sp-md); }
table.ns-table td { padding: var(--sp-sm); border-bottom: 1px solid #ECE8DE; vertical-align: middle; }

/* Category group sub-header row (paper tint). */
tr.ns-group td {
  background: var(--paper); color: var(--ink-soft);
  font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  border-bottom: 1px solid var(--line);
}

/* Money: mono, right-aligned, semibold, penny precision. */
.money { font-family: var(--mono); font-weight: 600; }
td.amount .money { white-space: nowrap; }

/* Row label + chips. */
td.label .ns-label { color: var(--ink); }
.chip {
  display: inline-block; font-family: var(--mono); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .04em; border-radius: 2px; padding: 0 var(--sp-xs); margin-left: var(--sp-sm);
  vertical-align: middle; border: 1px solid transparent;
}
.chip.auto { color: var(--mute); border-color: var(--line); background: var(--paper); }
.chip.custom { color: var(--mute); border-color: var(--line); background: var(--paper); }
.chip.override { color: var(--sage-tx); border-color: var(--sage-line); background: var(--sage); }

/* Override row: sage left accent rule on the amount cell (D-09, color-encoded). */
tr.ns-row.is-override td.amount { border-left: 3px solid var(--sage-line); }

td.actions { white-space: nowrap; text-align: right; }
td.actions .btn-sm { margin-left: var(--sp-xs); }

/* Inline-edit row form. */
tr.ns-row-edit td { background: var(--paper); }
tr.ns-row-edit input[type="text"],
tr.ns-row-edit input[type="number"] {
  font-family: var(--sans); font-size: var(--fs-body);
  padding: var(--sp-xs) var(--sp-sm); border: 1px solid var(--line); border-radius: 3px; width: 100%;
}
tr.ns-row-edit input.amount-input { font-family: var(--mono); text-align: right; }

/* The live "Due to Seller" total band — paper, top hairline, mono 18px 600. */
tfoot.ns-total td { background: var(--paper); border-top: 1.5px solid var(--ink); padding: var(--sp-md) var(--sp-sm); }
tfoot.ns-total .ns-total-label { font-size: var(--fs-label); font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-soft); }
tfoot.ns-total .ns-total-value { font-family: var(--mono); font-size: var(--fs-heading); font-weight: 600; text-align: right; }

/* Empty state. */
.ns-empty { padding: var(--sp-lg); text-align: center; color: var(--ink-soft); }
.ns-empty h3 { color: var(--ink); }
.ns-empty p { font-size: var(--fs-body); margin: var(--sp-sm) 0 var(--sp-md); }

/* Inline save-error slot (HTMX error swap). */
.ns-error { color: var(--clay-tx); font-size: var(--fs-label); font-weight: 600; }

/* ----------------------------------------------------------------------------
 * Offer comparison (per listing) — port of build_comparison.py (02-04 / D-13).
 *
 * Reuses the palette + 4-size scale + .eyebrow + .money already defined above.
 * The ported skill CSS used many sub-12px sizes (8.5-11.5px chips/labels and a 24px
 * price); those are SNAPPED to this phase's scale: labels/tags/chips -> --fs-label (12px),
 * the card price + net-band value -> --fs-heading (18px). No sub-12px values appear here.
 * --cmp-cols (one per offer) is set inline on .cmp-block so .glance / .net-row are one
 * equal column per offer; both collapse to a single column under 760px.
 * -------------------------------------------------------------------------- */
.cmp-block { background: var(--white); box-shadow: 0 1px 0 var(--line), 0 18px 50px rgba(31,42,56,.10); margin: var(--sp-xl) 0; }

.cmp-header { background: var(--ink); color: #EFE9DC; padding: var(--sp-lg) var(--sp-lg) var(--sp-md); }
.cmp-header h1 { color: #EFE9DC; }
.cmp-header .cmp-meta { font-size: var(--fs-body); color: #B9BFC7; margin: 0; }
.cmp-header .cmp-meta b { color: #EFE9DC; font-weight: 600; }
.cmp-header .money { color: #EFE9DC; }

/* Glance: one card per offer (equal columns; collapse under 760px). */
.glance { display: grid; grid-template-columns: repeat(var(--cmp-cols, 1), 1fr); border-bottom: 1px solid var(--line); }
.card { padding: var(--sp-md) var(--sp-lg); border-right: 1px solid var(--line); }
.card:last-child { border-right: none; }
.card.card-top { background: var(--sage); }
.card .tag { font-family: var(--mono); font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--mute); margin: 0 0 var(--sp-xs); }
.card h2 { margin: 0 0 var(--sp-xs); }
.card .who { font-size: var(--fs-label); font-weight: 600; color: var(--ink-soft); margin: 0 0 var(--sp-md); min-height: 30px; }
.card .price { font-family: var(--mono); font-size: var(--fs-heading); font-weight: 600; line-height: 1.1; }
.card .price .pct { display: block; font-family: var(--sans); font-size: var(--fs-label); font-weight: 600; color: var(--mute); margin-top: var(--sp-xs); }

/* "Top net" badge (sage), snapped to the 12px label size. */
.lead { display: inline-block; font-family: var(--mono); font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--sage-tx); background: var(--sage); border: 1px solid var(--sage-line); border-radius: 2px; padding: 0 var(--sp-xs); margin-left: var(--sp-xs); vertical-align: middle; }

/* KPI grid inside a card. */
.kpis { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-sm) var(--sp-md); margin-top: var(--sp-md); }
.kpi { border-top: 1px solid var(--line); padding-top: var(--sp-xs); }
.kpi .l { font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--mute); margin: 0 0 var(--sp-xs); line-height: 1.3; }
.kpi .v { font-size: var(--fs-body); font-weight: 600; margin: 0; }
.kpi .v.money { font-family: var(--mono); }

/* The net band — the HEADLINE: real net-to-seller per offer (mono 18px). */
.net-band { background: var(--paper); border-top: 1px solid var(--line); padding: var(--sp-md) var(--sp-lg); }
.net-band .lab { font-size: var(--fs-label); font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-soft); margin: 0 0 var(--sp-sm); }
.net-row { display: grid; grid-template-columns: repeat(var(--cmp-cols, 1), 1fr); gap: var(--sp-md); }
.net-cell { display: flex; flex-direction: column; gap: var(--sp-xs); }
.net-cell .nm { font-size: var(--fs-label); font-weight: 600; color: var(--ink-soft); }
.net-cell .vl { font-family: var(--mono); font-size: var(--fs-heading); font-weight: 600; }
.net-cell .dl { font-size: var(--fs-label); font-weight: 600; color: var(--mute); }
.net-cell.top .vl { color: var(--sage-tx); }
.net-cell.top .dl { color: var(--sage-tx); }
.net-cell.low .vl { color: var(--clay-tx); }
.net-cell.low .dl { color: var(--clay-tx); }

/* Term-by-term table (offers as columns). */
.cmp-detail { padding: var(--sp-lg); }
.cmp-detail h3 { margin: 0 0 var(--sp-md); }
table.cmp-table { width: 100%; border-collapse: collapse; font-size: var(--fs-body); table-layout: fixed; }
table.cmp-table th { text-align: left; padding: var(--sp-sm); font-size: var(--fs-label); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-soft); border-bottom: 1.5px solid var(--ink); word-wrap: break-word; }
table.cmp-table td { padding: var(--sp-sm); border-bottom: 1px solid #ECE8DE; vertical-align: top; word-wrap: break-word; }
table.cmp-table td.f { font-weight: 600; color: var(--ink); }
table.cmp-table td.mono, table.cmp-table .mono { font-family: var(--mono); font-weight: 600; }
table.cmp-table th.win { color: var(--sage-tx); }
table.cmp-table td.win { background: var(--sage); color: var(--sage-tx); }
table.cmp-table td.win.mono { color: var(--sage-tx); }

/* Comparison empty state + footer. */
.cmp-empty { padding: var(--sp-lg); text-align: center; color: var(--ink-soft); }
.cmp-empty h3 { color: var(--ink); }
.cmp-empty p { font-size: var(--fs-body); margin: var(--sp-sm) 0 var(--sp-md); }
.cmp-disclaimer { padding: 0 var(--sp-lg); font-size: var(--fs-label); font-style: italic; color: var(--mute); line-height: 1.5; margin: var(--sp-md) 0 0; }
.cmp-back { padding: 0 var(--sp-lg) var(--sp-lg); margin: var(--sp-md) 0 0; }

@media (max-width: 760px) {
  .glance, .net-row { grid-template-columns: 1fr; }
  .card { border-right: none; border-bottom: 1px solid var(--line); }
}

/* ----------------------------------------------------------------------------
 * Print: ESTIMATE label + disclaimer; hide chrome/controls; white surface.
 * (NET-08 / D-14 — browser File->Print produces the estimate, no PDF lib.)
 * -------------------------------------------------------------------------- */
.estimate-label {
  display: none;
  font-size: var(--fs-label); font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  color: var(--mute); margin: 0 0 var(--sp-sm);
}
.ns-disclaimer {
  display: none;
  font-size: var(--fs-label); font-style: italic; color: var(--mute); line-height: 1.5;
  margin: var(--sp-md) 0 0;
}

@media print {
  body { background: var(--white); }
  /* Hide ALL chrome: the legacy .topbar AND the new SaaS shell (.app-sidebar/.app-topbar) so
   * the printable ESTIMATE net-sheet view survives clean (NET-08 / D-14 — required 05-04 edit). */
  .topbar, nav, .app-sidebar, .app-topbar, .ns-actions, td.actions, th.actions, .btn, button, #offer-form-slot { display: none !important; }
  /* Drop the sidebar offset so the sheet prints full-width. */
  .app-main { margin-left: 0 !important; min-height: 0 !important; }
  .ns-block, .cmp-block { box-shadow: none; margin: 0; }
  .estimate-label { display: block; }
  .ns-disclaimer { display: block; break-inside: avoid; }
  tr { break-inside: avoid; }
}

/* ----------------------------------------------------------------------------
 * Dashboard + Reports surface (05-05 / DASH-01/02/04/05/06).
 *
 * Composes the existing tokens + the KPI grid / status pills already declared above.
 * The KPI VALUES, pipeline best-net, report figures and spread dollar amounts are all
 * server-rendered strings — NOTHING here computes money. Charts (.chart/.spark) are drawn
 * by the draw-only dashboard.js; the spread bars are inline CSS sized server-side in Jinja.
 * -------------------------------------------------------------------------- */

/* Read-only load-failure / empty states (UI-SPEC copy). */
.report-error {
  background: var(--clay); border: 1px solid #E3B488; border-radius: 3px;
  padding: var(--sp-md) var(--sp-lg); margin: var(--sp-lg) 0;
  font-size: var(--fs-body); font-weight: 600; color: var(--clay-tx); max-width: 640px;
}
.dashboard-empty, .reports-empty {
  background: var(--white); border: 1px solid var(--line); box-shadow: 0 1px 0 var(--line);
  padding: var(--sp-2xl) var(--sp-lg); text-align: center; color: var(--ink-soft);
  margin: var(--sp-lg) 0;
}
.dashboard-empty h3, .reports-empty h3 { color: var(--ink); }
.dashboard-empty p, .reports-empty p { font-size: var(--fs-body); margin: var(--sp-sm) auto 0; max-width: 520px; }

/* KPI sparkline inside the card (draws via ApexCharts; degrades to nothing when no history). */
.kpi-card .spark { width: 100%; min-height: 36px; margin-top: var(--sp-xs); }

/* Pipeline list — a table.ns-table variant. */
.pipeline { margin: var(--sp-2xl) 0 var(--sp-xl); }
.pipeline h2 { margin: 0 0 var(--sp-md); }
table.pipeline-table { width: 100%; background: var(--white); box-shadow: 0 1px 0 var(--line); }
table.pipeline-table td { padding: var(--sp-sm); border-bottom: 1px solid #ECE8DE; vertical-align: middle; }
table.pipeline-table td.label a { font-weight: 600; }
table.pipeline-table td.amount { text-align: right; }
table.pipeline-table tr.is-top td.amount .money { color: var(--sage-tx); }
table.pipeline-table tr.is-top td.label { border-left: 3px solid var(--sage-line); }
.pipeline-blank { color: var(--mute); }

/* Date pill (pipeline next-date + dates panel) — 12px mono, neutral. */
.date-pill {
  display: inline-block; font-family: var(--mono); font-size: var(--fs-label); font-weight: 600;
  letter-spacing: .04em; border-radius: 2px; padding: 0 var(--sp-xs);
  color: var(--ink-soft); background: var(--paper); border: 1px solid var(--line); vertical-align: middle;
}

/* Reports: section blocks + the ApexCharts frame. */
.report-block { background: var(--white); border: 1px solid var(--line); box-shadow: 0 1px 0 var(--line); padding: var(--sp-lg); margin: 0 0 var(--sp-xl); }
.report-block h2 { margin: 0 0 var(--sp-md); }
.chart { width: 100%; min-height: 320px; }

/* Best-vs-list spread — inline CSS bars (sage over / clay under), NO JS (D-03). */
.spread-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-sm); }
.spread-row { display: grid; grid-template-columns: minmax(120px, 1.2fr) 3fr minmax(120px, auto); align-items: center; gap: var(--sp-md); }
.spread-label { font-size: var(--fs-body); font-weight: 600; color: var(--ink); }
.spread-bar-track { position: relative; height: 16px; background: var(--paper); border: 1px solid var(--line); border-radius: 2px; overflow: hidden; }
.spread-bar { position: absolute; top: 0; bottom: 0; left: 0; display: block; }
.spread-bar.over { background: var(--sage-line); }
.spread-bar.under { background: #E3B488; }
.spread-value { font-family: var(--mono); font-size: var(--fs-body); font-weight: 600; text-align: right; }
.spread-value.is-over { color: var(--sage-tx); }
.spread-value.is-under { color: var(--clay-tx); }
.spread-legend { font-size: var(--fs-label); font-weight: 600; color: var(--mute); margin: var(--sp-md) 0 0; }
.legend-swatch { display: inline-block; width: 12px; height: 12px; border-radius: 2px; vertical-align: middle; margin-right: var(--sp-xs); }
.legend-swatch.over { background: var(--sage-line); }
.legend-swatch.under { background: #E3B488; }

/* DASH-06 read-only dates panel on listing detail. */
.dates-panel { margin: var(--sp-xl) 0; }
.dates-panel h2 { margin: 0 0 var(--sp-md); }
.dates-offer { background: var(--white); border: 1px solid var(--line); box-shadow: 0 1px 0 var(--line); padding: var(--sp-md) var(--sp-lg); margin: 0 0 var(--sp-md); }
.dates-offer-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-sm); flex-wrap: wrap; margin: 0 0 var(--sp-sm); }
.dates-offer-buyer { font-weight: 600; color: var(--ink); }
.dates-anchor { font-family: var(--mono); font-size: var(--fs-label); font-weight: 600; letter-spacing: .04em; color: var(--mute); }
.dates-anchor-relative { color: var(--ink-soft); }
.dates-list { display: grid; grid-template-columns: max-content 1fr; gap: var(--sp-xs) var(--sp-lg); margin: 0; }
.dates-term { font-size: var(--fs-label); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--mute); margin: 0; }
.dates-val { margin: 0; font-size: var(--fs-body); }
.dates-relative { color: var(--ink-soft); }
.dates-empty { color: var(--ink-soft); padding: var(--sp-md) 0; }

/* Print: hide the presentation-only charts so the ESTIMATE/print views stay clean. */
@media print {
  .chart, .spark, .spread-legend { display: none !important; }
}
