/* ==========================================================================
   Tally - quotes.css (Phase 3: the Quotes list and the quote builder)
   Loaded after app.css and uses its tokens (--color-*, --space-*, --tap).
   Mobile-first like app.css; the @media (min-width: 900px) block at the end
   turns the builder's two tabs into two columns.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Extra tokens: status colours (draft grey, sent blue, accepted green,
      declined red) and the totals bar height the builder reserves space for
   -------------------------------------------------------------------------- */
:root {
  --status-draft: #4b5563;
  --status-draft-bg: #e5e7eb;
  --status-sent: #1e40af;
  --status-sent-bg: #dbeafe;
  --status-accepted: #166534;
  --status-accepted-bg: #dcfce7;
  --status-declined: #991b1b;
  --status-declined-bg: #fee2e2;
  --totals-height: 72px;
}
@media (prefers-color-scheme: dark) {
  :root {
    --status-draft: #d1d5db;
    --status-draft-bg: #374151;
    --status-sent: #bfdbfe;
    --status-sent-bg: #1e3a8a;
    --status-accepted: #bbf7d0;
    --status-accepted-bg: #14532d;
    --status-declined: #fecaca;
    --status-declined-bg: #7f1d1d;
  }
}

/* --------------------------------------------------------------------------
   2. Shared bits: search box, chips, segmented toggle, status badges
   -------------------------------------------------------------------------- */
.search-row { margin-bottom: var(--space-2); }
.search-input {
  width: 100%;
  min-height: var(--tap);
  font-size: 16px;                 /* no iPhone zoom on focus */
  padding: 0 var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  -webkit-appearance: none;
  appearance: none;
}
.search-input:focus { border-color: var(--color-primary); }

/* Status chips: a wrapping row of pills; the pressed one is filled. */
.chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.chip {
  min-height: 36px;
  padding: 0 var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.chip[aria-pressed="true"] {
  background: var(--color-primary);
  color: var(--color-primary-text);
  border-color: var(--color-primary);
}

/* Everyone / Mine: two joined buttons. */
.segmented { display: inline-flex; border: 1px solid var(--color-border); border-radius: 999px; overflow: hidden; }
.segment {
  min-height: 36px;
  padding: 0 var(--space-3);
  border: 0;
  background: var(--color-surface);
  color: var(--color-text);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.segment + .segment { border-left: 1px solid var(--color-border); }
.segment[aria-pressed="true"] { background: var(--color-primary); color: var(--color-primary-text); }

.status-badge { border-color: transparent; }
.status-draft { color: var(--status-draft); background: var(--status-draft-bg); }
.status-sent { color: var(--status-sent); background: var(--status-sent-bg); }
.status-accepted { color: var(--status-accepted); background: var(--status-accepted-bg); }
.status-declined { color: var(--status-declined); background: var(--status-declined-bg); }

/* "/mo" and "/yr" on monthly and yearly items (catalog list and Add items) and "custom" on quote lines. */
.badge-monthly { color: var(--color-primary); border-color: var(--color-primary); background: var(--color-surface); }
.badge-custom { color: var(--color-warn); background: var(--color-warn-bg); border-color: transparent; }

/* --------------------------------------------------------------------------
   3. Quotes list
   -------------------------------------------------------------------------- */
.quote-filters { display: flex; flex-direction: column; gap: var(--space-2); margin-bottom: var(--space-3); }
.filter-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.filter-row .toggle { min-height: 36px; font-size: 13px; padding: 0 var(--space-2); }
.filter-select {
  min-height: 36px;
  max-width: 100%;
  font-size: 14px;
  padding: 0 var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  background: var(--color-surface);
}

.quote-row { align-items: flex-start; }
.quote-number { font-variant-numeric: tabular-nums; color: var(--color-primary); }
.quote-row-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-1);
  margin-left: auto;
  flex-shrink: 0;
}
.quote-total { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --------------------------------------------------------------------------
   4. Builder frame: header, tabs, panes
   -------------------------------------------------------------------------- */
.builder { padding-bottom: calc(var(--totals-height) + var(--space-3)); }   /* room for the fixed totals bar */

.builder-header { margin-bottom: var(--space-2); }
/* Number, status, save indicator, "..." on ONE row, whatever the indicator
   says ("Offline, will retry" is the longest): the indicator is the part that
   gives way (it shrinks and ellipsises), never the menu button. */
.builder-title-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-1);
}
.builder-number { font-size: 22px; margin-right: var(--space-1); flex-shrink: 0; }
.builder-title-row .status-select { flex-shrink: 0; }
.builder-title-row .save-indicator { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.builder-title-row .menu-wrap { flex-shrink: 0; }
/* Under 400px there is no room to say anything next to the number: the
   indicator moves to its own line beneath, and "..." stays top right. */
@media (max-width: 399px) {
  .builder-title-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; row-gap: 2px; }
  .builder-title-row .status-select { justify-self: start; }
  .builder-title-row .save-indicator { grid-row: 2; grid-column: 1 / -1; }
  .builder-title-row .menu-wrap { grid-row: 1; grid-column: 3; justify-self: end; }
}

.status-select {
  min-height: 36px;
  padding: 0 var(--space-4) 0 var(--space-3);
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 14px) 50%, calc(100% - 9px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.save-indicator { font-size: 13px; color: var(--color-muted); white-space: nowrap; }
.indicator-saving::before, .indicator-offline::before, .indicator-conflict::before, .indicator-error::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-radius: 50%;
  vertical-align: middle;
  background: currentColor;
}
.indicator-saving { color: var(--color-muted); }
.indicator-offline { color: var(--color-warn); }
.indicator-conflict, .indicator-error { color: var(--color-danger); }

/* The customer summary under the number: a full-width text button. */
.customer-line {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-text);
  font-weight: 600;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}
.customer-line-empty { color: var(--color-primary); font-weight: 600; }

/* "..." menu: anchored under its button. */
.menu-wrap { position: relative; margin-left: auto; }
.menu-button { font-size: 22px; line-height: 1; }
.menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 15;
  min-width: 180px;
  padding: var(--space-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
}
.menu-item {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: 0 var(--space-3);
  border: 0;
  border-radius: 6px;
  background: none;
  color: var(--color-text);
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.menu-item:hover, .menu-item:focus-visible { background: var(--color-bg); }
.menu-item-danger { color: var(--color-danger); }

.banner-conflict { border-color: var(--color-danger); background: var(--color-danger-bg); color: var(--color-danger); }

.builder-tabs { margin-bottom: var(--space-3); }
.builder-tabs .tab { flex: 1 1 0; }

/* Phone: one pane at a time, chosen by data-tab on .builder. */
.pane-title { display: none; }
.builder[data-tab="add"] .pane-quote { display: none; }
.builder[data-tab="quote"] .pane-add { display: none; }

/* --------------------------------------------------------------------------
   5. Add items tab (the category dropdown itself is .category-select in app.css)
   -------------------------------------------------------------------------- */
.add-results .category-row { margin-bottom: var(--space-2); }
.item-row { align-items: center; }
.item-price {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-1);
  margin-left: auto;
  flex-shrink: 1;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
/* No nowrap: volume pricing (D63) makes the text longer ("$50.00 each,
   $29.00 at 5+"), so on a narrow phone it wraps instead of overflowing. */

.custom-line { margin-bottom: var(--space-2); }   /* sits under the title, above search; same gap as search-row */
.custom-line-toggle { border-style: dashed; color: var(--color-primary); }   /* "+ Custom line" and "+ Add discount" */
.custom-line-form {
  margin-top: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}

/* Option chooser: the confirm dialog's look with radio groups inside. */
.chooser { max-width: 420px; }
.chooser-title { font-size: 18px; margin-bottom: var(--space-1); }
.chooser-groups { margin: var(--space-3) 0; max-height: 60vh; overflow-y: auto; }
.chooser-group { margin-bottom: var(--space-2); }
.chooser-group legend { font-size: 14px; font-weight: 600; color: var(--color-muted); margin-bottom: var(--space-1); }
.chooser-choice {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap);
}
.chooser-choice input { width: 24px; height: 24px; margin: 0; flex-shrink: 0; accent-color: var(--color-primary); }
.chooser-choice label { display: flex; flex: 1; justify-content: space-between; gap: var(--space-2); cursor: pointer; }

/* --------------------------------------------------------------------------
   6. Quote tab: customer card, grouped lines and discounts, stepper, inline edits
   -------------------------------------------------------------------------- */
.customer-card { padding: 0; margin-bottom: var(--space-3); overflow: hidden; }
.customer-toggle {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-height: 56px;
  padding: var(--space-2) var(--space-3);
  border: 0;
  background: none;
  color: var(--color-text);
  text-align: left;
  cursor: pointer;
}
.customer-toggle-title { font-weight: 700; flex-shrink: 0; }
.customer-summary { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.customer-chevron::after { content: "\203A"; display: inline-block; font-size: 24px; line-height: 1; color: var(--color-muted); transform: rotate(90deg); }
.customer-card-open .customer-chevron::after { transform: rotate(-90deg); }
.customer-body { padding: 0 var(--space-3) var(--space-2); border-top: 1px solid var(--color-border); padding-top: var(--space-3); }
.required-mark { color: var(--color-danger); }

.line-group { margin-bottom: var(--space-3); }
.line-group-title {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  font-size: 16px;
  margin-bottom: var(--space-1);
}
.line-group-total { font-size: 14px; font-weight: 600; color: var(--color-muted); font-variant-numeric: tabular-nums; }

/* A quote line: name row, then controls row, then the three small action buttons. */
.qline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--color-border);
}
.qline:last-child { border-bottom: 0; }
.qline-head { flex: 1 1 100%; min-width: 0; }
.qline-name { font-weight: 600; overflow-wrap: anywhere; }
.qline-sub { font-size: 13px; color: var(--color-muted); overflow-wrap: anywhere; }
.qline-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  flex: 1 1 auto;
  min-width: 0;
}
.qline-total {
  margin-left: auto;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.qline-actions { flex: 0 0 auto; margin-left: auto; }

/* Terms (D68, D70): the term control is the row's last line (after the
   action buttons): the checkbox ("Spread over" / "For"), the length as a
   tap-to-edit value, and the Months / Years and Per period / Split choices
   as segmented controls; on a narrow phone the parts wrap. A one-time line
   spread into a period gets a primary-coloured edge and its "$30.53/mo × 36
   (total $1,099.00)" note under the name; a "for 12 months" line just the note. */
.term-control {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  flex: 1 1 100%;
  order: 20;
}
.term-toggle { justify-content: flex-start; padding-left: var(--space-2); }
.term-toggle input[type="checkbox"] { width: 24px; height: 24px; min-height: 0; margin: 0; flex-shrink: 0; accent-color: var(--color-primary); }
.term-length { min-width: 56px; font-weight: 700; }
.term-word { font-size: 14px; color: var(--color-muted); white-space: nowrap; }
.term-segmented .segment { min-height: var(--tap); }
.inline-input-short { width: 72px; }
.qline-spread { box-shadow: inset 3px 0 0 var(--color-primary); }
.qline-term-note { color: var(--color-primary); font-weight: 600; font-variant-numeric: tabular-nums; }

/* The custom line box's term row (D68): "Spread over [N] [months]" or
   "For [N] months", the input short, the words beside it. */
.custom-term .term-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.custom-term .custom-term-length { width: 5em; flex: 0 0 auto; }   /* two classes: outranks app.css's ".field input" */
.custom-term .custom-term-unit { width: auto; flex: 0 0 auto; }

/* Volume pricing (D63): the price button with the small muted "5+ price" note
   under it, kept together so the note stays with the price when the controls
   row wraps. The inline price editor's hint goes after this wrapper. */
.qline-price-wrap { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; }
.qline-tier-note { font-size: 12px; line-height: 1.2; color: var(--color-muted); white-space: nowrap; }

/* Unit price: looks like a value, behaves like a button (tap to override). */
.qline-price {
  min-height: var(--tap);
  padding: 0 var(--space-2);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius);
  background: none;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  cursor: pointer;
}
.qline-unit { font-size: 12px; color: var(--color-muted); }

/* Stepper: minus, value, plus, each a 44px tap target. Since D45 it sits on
   fixed lines too (whole numbers), with the same classes as on per-unit lines. */
.stepper { display: inline-flex; align-items: stretch; border: 1px solid var(--color-border); border-radius: var(--radius); overflow: hidden; }
.stepper-btn { border: 0; border-radius: 0; min-width: var(--tap); font-size: 20px; }
.stepper-btn:disabled { opacity: 0.35; }
.stepper-value {
  min-width: 48px;
  min-height: var(--tap);
  padding: 0 var(--space-1);
  border: 0;
  border-left: 1px solid var(--color-border);
  border-right: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  cursor: text;
}

/* The text input that replaces a value while it is being typed. */
.inline-input {
  width: 96px;
  min-height: var(--tap);
  padding: 0 var(--space-2);
  font-size: 16px;
  border: 1px solid var(--color-primary);
  border-radius: var(--radius);
  background: var(--color-surface);
  font-variant-numeric: tabular-nums;
}
/* The live hint under the price editor ("Options add $100.00; line total will
   be $1,798.00"): the last item of the controls row, on a row of its own. */
.inline-hint { flex: 1 1 100%; order: 10; margin: 0; font-size: 13px; }

/* Discounts (D38): a line group like One-time and Monthly, each discount a
   .qline. The name and the "Monthly · $10.00 each" line under it are buttons
   that read like text: tap the name to rename it in place, tap the small line
   for the chooser (two segmented controls take its place). The row total is
   the computed amount, negative. */
.qline-text-btn {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  overflow-wrap: anywhere;
  vertical-align: top;
  cursor: pointer;
  text-decoration: underline dashed;
  text-decoration-color: var(--color-border);
  text-underline-offset: 4px;
}
.qline-name-btn { min-height: var(--tap); }
/* The small line is the codebase's secondary 36px size (chips, segments), so
   a discount row stays close to a line row's height. */
.qline-sub-btn { min-height: 36px; }
.qline-chooser { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-1); }
.qline-chooser .segment { min-height: var(--tap); }
/* A discount's message ("Enter a name ..."): the row's last line, like a field error. */
.qline-error { flex: 1 1 100%; order: 30; margin: 0; font-size: 14px; color: var(--color-danger); }
/* A name needs more room than a number; the inline input keeps its 16px and 44px. */
.inline-input-text { width: 100%; max-width: 320px; font-variant-numeric: normal; }
.discount-add { margin-top: var(--space-2); }

/* The tax select. */
.quote-extras { margin-bottom: var(--space-3); }
.quote-extras select {
  min-height: var(--tap);
  font-size: 16px;
  padding: 0 var(--space-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
}
.quote-extras .field { margin-bottom: 0; }
.quote-extras select { width: 100%; }

.notes-card { margin-bottom: var(--space-3); }
.notes-card .field:last-child { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   7. Totals bar: fixed above the tab bar on a phone
   -------------------------------------------------------------------------- */
.totals-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: var(--nav-height);
  z-index: 9;                       /* under the nav (10) and the toast (20) */
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);
}
.totals-main {
  display: flex;
  justify-content: space-around;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: var(--totals-height);
  padding: var(--space-2) var(--space-3);
  border: 0;
  background: none;
  color: var(--color-text);
  cursor: pointer;
}
.totals-bucket { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.totals-label { font-size: 12px; font-weight: 600; color: var(--color-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.totals-value { font-size: 24px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.totals-detail {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2) var(--space-4);
  padding: 0 var(--space-3) var(--space-3);
  max-height: 40vh;
  overflow-y: auto;
  border-top: 1px solid var(--color-border);
  font-size: 14px;
}
.totals-dl { display: grid; grid-template-columns: 1fr auto; gap: 2px var(--space-3); padding-top: var(--space-2); }
.totals-dl dt { color: var(--color-muted); }
.totals-dl dd { text-align: right; font-variant-numeric: tabular-nums; }
.totals-dl-title { font-weight: 700; color: var(--color-text); }
.totals-dl dt:last-of-type, .totals-dl dd:last-of-type { font-weight: 700; color: var(--color-text); }

/* The toast sits above the totals bar while the builder is open. */
body.has-totals-bar .toast { bottom: calc(var(--nav-height) + var(--totals-height) + var(--space-3)); }

/* A short pulse after an add or a merge from the Add items tab (quote_builder.js
   flashTotals): the bar is what both tabs share, so it is where the change shows. */
.totals-bar.totals-bar-flash { animation: totals-flash 600ms ease-out; }
@keyframes totals-flash {
  0% { background: var(--color-surface); }
  25% { background: var(--color-ok-bg); }
  100% { background: var(--color-surface); }
}
@media (prefers-reduced-motion: reduce) {
  .totals-bar.totals-bar-flash { animation: none; outline: 2px solid var(--color-primary); outline-offset: -2px; }
}

/* --------------------------------------------------------------------------
   8. Desktop (900px and up): Add items left, Quote right, totals bottom right
   -------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .quote-filters { flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between; }

  .builder {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--space-4);
    padding-bottom: 0;
    align-items: start;
  }
  .builder-header, .banner-conflict { grid-column: 1 / -1; }
  .builder-tabs { display: none; }
  .builder-body { display: contents; }          /* the two panes become grid items */
  .pane-title { display: block; font-size: 18px; margin-bottom: var(--space-2); }
  .builder[data-tab="add"] .pane-quote, .builder[data-tab="quote"] .pane-add { display: block; }
  .pane-add { grid-column: 1; }
  .pane-quote { grid-column: 2; }

  .totals-bar {
    position: sticky;
    grid-column: 2;
    bottom: var(--space-3);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  }
  .totals-detail { grid-template-columns: 1fr 1fr; }
  body.has-totals-bar .toast { bottom: var(--space-4); }
}
