/* Estimate Builder and the interactive customer estimate (plans/interactive-estimate-gbb.md). Shared classes only, and
   colors / corners / fonts come ONLY from the house tokens (--blue --grass --ink --line --paper --muted --card --red
   --orange), so Default, LMN (assets/styles/lmn.css) and later Styles restyle all of this from their own override file.
   Built on the house .stats/.stat .card .badge .phone-sheet .form-grid label.check button.quiet .btn. */

/* est-bar: the live money strip (a .stats row). One line, sticky, scrolls sideways on phones instead of wrapping. */
.stats.est-bar { display: flex; flex-wrap: nowrap; grid-template-columns: none; gap: 8px; position: sticky; top: var(--top-h, 0px); /* under the pinned page-top bar */ z-index: 6; overflow-x: auto; scrollbar-width: none; margin: 0 0 8px; padding: 6px 0; background: var(--paper); }
.est-bar::-webkit-scrollbar { display: none; }
.est-bar .stat { flex: 1 1 0; min-width: 118px; padding: 8px 12px; }
.est-bar .stat b { font-size: 1.1rem; white-space: nowrap; font-variant-numeric: tabular-nums; }
.est-bar .stat span { white-space: nowrap; font-size: .76rem; }
.est-bar .stat em { overflow: hidden; text-overflow: ellipsis; }
.est-bar .stat.good b { color: color-mix(in srgb, var(--grass) 60%, var(--ink)); }
.est-bar .stat.warn b { color: var(--orange); }
.est-bar .stat.bad b { color: var(--red); }

/* gauge + meter: the one reusable, understated pattern (window.ttGauge / window.ttMeter in assets/js/estimate-builder.js).
   Tone classes only: .good at/above target, .warn within 5 points, .bad below that or below breakeven. */
.stat.has-gauge { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 8px; }
.stat.has-gauge > span, .stat.has-gauge > b, .stat.has-gauge > em { grid-column: 1; }
.stat.has-gauge > .gauge { grid-column: 2; grid-row: 1 / span 3; }
.stat em { display: block; font-style: normal; font-size: .72rem; color: var(--muted); white-space: nowrap; }
.gauge { display: block; width: 46px; height: 28px; flex: none; }
.gauge path { fill: none; stroke-width: 6; stroke-linecap: round; }
.gauge .track { stroke: var(--line); }
.gauge .val { stroke: var(--grass); transition: stroke-dasharray .2s; }
.gauge .tick { stroke: var(--ink); stroke-width: 1.5; stroke-linecap: butt; }
.gauge.warn .val { stroke: var(--orange); }
.gauge.bad .val { stroke: var(--red); }
.meter { position: relative; display: inline-block; width: 64px; height: 6px; border-radius: 99px; background: var(--paper); box-shadow: inset 0 0 0 1px var(--line); vertical-align: middle; }
.meter i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 99px; background: var(--grass); transition: width .2s; }
.meter b { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--ink); border-radius: 1px; }
.meter.warn i { background: var(--orange); }
.meter.bad i { background: var(--red); }
.meter + .pct { display: inline-block; min-width: 46px; text-align: right; font-variant-numeric: tabular-nums; margin-left: 6px; font-size: .85rem; }

/* est-tools: the one toolbar. Same order everywhere, one row, scrolls sideways on phones. */
.est-tools { display: flex; gap: 8px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; align-items: center; margin: 0 0 10px; }
.est-tools::-webkit-scrollbar { display: none; }
.est-tools > * { flex: none; white-space: nowrap; }
.est-tools > [data-save-label] { margin-left: auto; font-size: .8rem; }
.est-tools .ai-open { margin: 0; }
.est-tools label.check { margin: 0; }

/* est-lines: the line table (a .phone-sheet). */
.card.est-sheet { padding: 0; overflow-x: auto; }
table.est-lines { width: 100%; border-collapse: collapse; margin: 0; }
table.est-lines th { font-size: .74rem; text-align: left; font-weight: 650; padding: var(--t-pad, 8px); border-bottom: 1px solid var(--t-line, var(--line)); white-space: nowrap; }
table.est-lines td { padding: var(--t-pad, 6px 8px); border-bottom: 1px solid var(--t-line, var(--line)); vertical-align: middle; white-space: nowrap; }
table.est-lines td.num, table.est-lines th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.est-lines td.name { white-space: normal; min-width: 180px; width: 100%; }
table.est-lines td.name > input { width: 100%; height: 32px; margin: 0; font-weight: 600; }
table.est-lines td.name .muted { display: block; font-size: .76rem; margin-top: 2px; }
table.est-lines input.cell { width: 74px; height: 32px; margin: 0; padding: 0 6px; text-align: right; font-variant-numeric: tabular-nums; }
table.est-lines input.cell[readonly] { background: transparent; border-color: transparent; }
table.est-lines td.open { width: 1%; }
table.est-lines .est-toggle { width: 30px; height: 30px; min-height: 30px; padding: 0; }
table.est-lines tr.est-group td { background: var(--paper); font-size: .85rem; padding: var(--t-pad, 7px 8px); white-space: nowrap; }
table.est-lines tr.est-group label.check { display: inline-flex; margin: 0 0 0 8px; font-size: .8rem; }
table.est-lines tr.est-off td:not(:first-child) { color: var(--muted); }
table.est-lines tr.est-off td.name > input { color: var(--muted); }
table.est-lines tr.est-open td { background: color-mix(in srgb, var(--blue) 5%, var(--card)); }
table.est-lines tr.est-detail td { text-align: left; padding: 0 12px 12px; background: color-mix(in srgb, var(--blue) 5%, var(--card)); white-space: normal; }
table.est-lines tr.est-detail .est-tools { margin: 8px 0; }
table.est-lines tr.est-detail .form-grid { margin-top: 6px; }
.est-notes { margin: 4px 0 8px; font-size: .85rem; }
.est-notes summary { cursor: pointer; white-space: nowrap; }
.est-notes label { text-align: left; }

/* est-cost: "where the cost comes from" under a line (a div grid, not a nested table, so phones never restack it). */
.est-cost { display: grid; font-size: .85rem; padding-top: 6px; }
.est-cost > div { display: grid; grid-template-columns: 200px minmax(0, 1fr) 110px; gap: 10px; align-items: center; padding: 4px 0; border-bottom: 1px solid var(--line); }
.est-cost > div[hidden] { display: none; }
.est-cost > div[data-equip-rows], .est-cost > div[data-mat-rows] { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; padding: 0; border: 0; }
.est-cost > div:last-child { border-bottom: 0; font-weight: 650; }
.est-cost .est-cost-head { font-size: .72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); font-weight: 650; }
.est-cost .est-cost-row { display: grid; grid-template-columns: 200px minmax(0, 1fr) 110px; gap: 10px; align-items: center; padding: 4px 0 4px 14px; border-bottom: 1px solid var(--line); }
.est-cost .est-cost-row select, .est-cost .est-cost-row input { height: 30px; margin: 0; min-height: 30px; }
.est-cost .est-cost-row select, .est-cost .est-cost-row input[data-f=name] { width: 100%; }
.est-cost .est-cost-row input.cell { width: 64px; padding: 0 6px; text-align: right; }
.est-cost .est-cost-row button { width: 28px; height: 28px; min-height: 28px; padding: 0; }
.est-cost > div > span, .est-cost .est-cost-row > span { text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.est-cost .num { text-align: right !important; font-variant-numeric: tabular-nums; }

/* seg: a small segmented control (Included / On / Off). */
.seg { display: inline-flex; flex-wrap: nowrap; border: 1px solid var(--line); border-radius: 999px; background: var(--card); padding: 2px; gap: 2px; }
.seg label { position: relative; margin: 0; cursor: pointer; display: block; font-weight: 400; }
.seg input { position: absolute; left: 0; top: 0; width: 1px; height: 1px; min-height: 0; margin: 0; padding: 0; opacity: 0; pointer-events: none; }
.seg span { display: block; padding: 4px 10px; border-radius: 999px; font-size: .76rem; font-weight: 650; color: var(--muted); white-space: nowrap; }
.seg input:checked + span { background: var(--blue); color: #fff; }
.seg input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 1px; }
.seg input:disabled + span { cursor: default; }

/* est-switch: the customer's on/off toggle for an optional Service. */
.est-switch { position: relative; display: inline-block; width: 46px; height: 26px; flex: none; vertical-align: middle; }
.est-switch input { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; margin: 0; cursor: pointer; z-index: 1; }
.est-switch i { position: absolute; inset: 0; border-radius: 99px; background: var(--line); transition: background .15s; }
.est-switch i::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.25); transition: transform .15s; }
.est-switch input:checked + i { background: var(--grass); }
.est-switch input:checked + i::after { transform: translateX(20px); }
.est-switch input:focus-visible + i { outline: 2px solid var(--blue); outline-offset: 2px; }

/* est-item: one Service row on the customer estimate (name, price, switch or Included). */
.est-items { display: grid; }
.est-item { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 14px; align-items: center; padding: 12px 0; border-bottom: 1px solid var(--line); }
.est-item:last-child { border-bottom: 0; }
.est-item b { display: block; }
.est-item .muted { font-size: .82rem; }
.est-item .price { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; font-weight: 650; }
.est-item .price small { display: block; font-weight: 500; color: var(--muted); font-size: .76rem; }
.est-item:has(input[type=checkbox]:not(:checked)) b, .est-item:has(input[type=checkbox]:not(:checked)) .price { color: var(--muted); }
.est-item .badge { white-space: nowrap; }

/* est-total: the customer's running total, sticky at the bottom. */
.est-total { position: sticky; bottom: 0; z-index: 6; display: flex; align-items: center; gap: 16px; flex-wrap: nowrap; padding: 10px 16px; margin: 0 0 16px; background: var(--card); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 -6px 20px rgba(17,17,17,.08); }
.est-total .stat { border: 0; padding: 0; min-width: 0; background: none; box-shadow: none; }
.est-total .stat b { font-size: 1.25rem; white-space: nowrap; font-variant-numeric: tabular-nums; }
.est-total .stat span { white-space: nowrap; font-size: .76rem; }

/* est-help: the "I don't understand, explain simpler" line every widget gets. */
.est-help { font-size: .8rem; margin: 0 0 10px; }
.est-help summary { cursor: pointer; color: var(--blue); font-weight: 600; white-space: nowrap; }
.est-help p { margin: 6px 0 0; max-width: 72ch; }

@media (max-width: 800px) {
  .stats.est-bar { top: var(--est-top, calc(env(safe-area-inset-top, 0px) + 52px)); margin: 0 -16px 8px; padding: 6px 16px; }
  .stats.est-bar .stat { flex: 0 0 auto; min-width: 128px; }
  .card.est-sheet { background: none; border: 0; box-shadow: none; overflow: visible; }
  /* Each Service is one compact card: Customer switch and name on top, the typed boxes side by side, then the meter. */
  table.est-lines.phone-sheet tr:first-child:not(:has(> td)) { display: none; }
  table.est-lines.phone-sheet tr.est-group { display: block; border: 0; background: none; margin: 10px 0 4px; }
  table.est-lines.phone-sheet tr.est-group td { display: block; background: none; padding: 0; border: 0; white-space: normal; }
  table.est-lines.phone-sheet tr.est-group td::before { content: none; }
  table.est-lines.phone-sheet tr[data-i] { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px 8px; padding: 10px 12px; margin: 0 0 8px; }
  table.est-lines.phone-sheet tr[data-i] td { display: block; padding: 0; border: 0; white-space: nowrap; min-width: 0; background: none; }
  table.est-lines.phone-sheet tr[data-i] td::before { display: block; margin: 0 0 2px; font-size: .7rem; }
  table.est-lines.phone-sheet tr[data-i] td.name { grid-column: 1 / -1; order: -1; width: auto; }
  table.est-lines.phone-sheet tr[data-i] td.name::before { content: none; }
  table.est-lines.phone-sheet tr[data-i] td[data-label="Customer"] { grid-column: 1 / -1; order: -2; }
  table.est-lines.phone-sheet tr[data-i] td[data-label="Customer"]::before { content: none; }
  table.est-lines.phone-sheet tr[data-i] td[data-label="Customer"] .seg { display: flex; }
  table.est-lines.phone-sheet tr[data-i] td[data-label="Customer"] .seg label { flex: 1 1 0; text-align: center; }
  table.est-lines.phone-sheet tr[data-i] td.num { text-align: left; }
  table.est-lines.phone-sheet tr[data-i] input.cell { width: 100%; text-align: left; height: 36px; }
  table.est-lines.phone-sheet tr[data-i] td[data-label="Cost"] { grid-column: 1; align-self: center; }
  table.est-lines.phone-sheet tr[data-i] td[data-label="Margin"] { grid-column: 2 / 4; align-self: center; }
  table.est-lines.phone-sheet tr[data-i] td.open { grid-column: 4; justify-self: end; align-self: end; width: auto; }
  table.est-lines.phone-sheet tr[data-i] td.open::before { content: none; }
  table.est-lines.phone-sheet tr[data-i] .meter { width: calc(100% - 52px); }
  table.est-lines.phone-sheet tr.est-detail { display: block; margin: -8px 0 8px; padding: 0; }
  table.est-lines.phone-sheet tr.est-detail[hidden] { display: none; }
  table.est-lines.phone-sheet tr.est-detail td { display: block; padding: 0 12px 10px; }
  table.est-lines.phone-sheet tr.est-detail td::before { content: none; }
  table.est-lines.phone-sheet tr.est-open td { background: none; }
  .est-cost > div, .est-cost .est-cost-row { grid-template-columns: minmax(0, 1fr) auto; }
  .est-cost > div > .muted, .est-cost .est-cost-head { display: none; }
  .est-cost .est-cost-row { grid-template-columns: minmax(0, 1fr) auto; padding-left: 0; }
  .est-cost .est-cost-row > span.muted { display: block; grid-column: 1 / -1; grid-row: 2; }
  .est-item { grid-template-columns: minmax(0, 1fr) auto; }
  .est-item .price { grid-column: 1; grid-row: 2; text-align: left; }
  .est-item .price small { display: inline; margin-left: 6px; }
  .est-item > :last-child { grid-column: 2; grid-row: 1 / span 2; }
  .est-total { gap: 12px; padding: 10px 12px; bottom: env(safe-area-inset-bottom, 0px); }
  body:has(.phone-dock) .est-total { bottom: calc(env(safe-area-inset-bottom, 0px) + 68px); }
  .est-total .stat b { font-size: 1.05rem; }
}

/* Phone header on one estimate: the old two-row header (Oct 17) is gone (Spot Clean, Oct 21 2026). The Top Bar is one line on
   every page; extra tiles fold into ··· past the 25% line (assets/js/topbar-fold.js). */

/* Document builder (estimates.php?view=documents): blocks on the left, the real estimate on the right. */
.est-doc-ed { display: grid; grid-template-columns: minmax(360px, 440px) minmax(0, 1fr); gap: 16px; align-items: start; }
.est-doc-side { min-width: 0; }
.est-doc-prev { min-width: 0; position: sticky; top: 64px; max-height: calc(100vh - 80px); overflow: auto; }
.est-doc-prev > .est-tools select { max-width: 260px; height: 32px; min-height: 32px; margin: 0; }
.est-doc-paper { background: var(--paper); border: 1px solid var(--line); border-radius: 12px; padding: 12px; }
.est-doc-paper .est-total { position: static; }
.est-doc-tabs { display: none; }
.est-doc-fields { margin: 4px 0 10px; font-size: .8rem; }
.est-doc-fields .est-suggest { display: flex; gap: 6px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding: 4px 0; }
.est-doc-fields .est-suggest::-webkit-scrollbar { display: none; }
.est-doc-fields .est-suggest > * { flex: none; white-space: nowrap; }
.est-bad { color: var(--red); font-size: .8rem; }
.est-blocks { list-style: none; margin: 0 0 10px; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; }
.est-doc-side, .est-doc-prev, .est-block { min-width: 0; }
.est-doc-bar { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; min-width: 0; }
.est-doc-bar > select { flex: 1 1 auto; min-width: 0; }
.est-doc-bar > .seg, .est-doc-bar > button, .est-doc-bar > .btn, .est-doc-bar > b { flex: none; }
.est-doc-bar > [data-save-label], .est-doc-bar > .est-doc-note { flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.est-block { border: 1px solid var(--line); border-radius: 10px; background: var(--card); }
.est-block.is-drag { opacity: .5; }
.est-block-head { display: flex; align-items: center; gap: 8px; padding: 6px 8px; flex-wrap: nowrap; }
.est-block-head .grip { color: var(--muted); cursor: grab; flex: none; letter-spacing: -2px; }
.est-block-head .est-block-name { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.est-block-head .est-block-name b, .est-block-head .est-block-name span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.est-block-head .est-block-name span { font-size: .74rem; }
.est-block-head button { flex: none; width: 30px; height: 30px; min-height: 30px; padding: 0; }
.est-block:has([data-on]:not(:checked)) .est-block-name b { color: var(--muted); text-decoration: line-through; }
.est-block-body { padding: 0 8px 8px; }
.est-sigline { display: inline-block; min-width: 180px; border-bottom: 1px solid var(--ink); color: var(--muted); font-size: .8rem; }
@media (max-width: 1000px) {
  .est-doc-ed { grid-template-columns: minmax(0, 1fr); }
  .est-doc-tabs { display: inline-flex; }
  .est-doc-bar > [data-save-label], .est-doc-bar > .est-doc-note { display: none; }
  .est-doc-ed[data-tab="edit"] .est-doc-prev, .est-doc-ed[data-tab="preview"] .est-doc-side { display: none; }
  .est-doc-prev { position: static; max-height: none; }
}

/* Phase 3 speed tools: the Add box, suggestion chips, Copy from…, Bulk Edit (house tokens only). */
.est-add { position: relative; margin: 0 0 8px; }
.est-add > input[type=search] { width: 100%; height: 40px; margin: 0; font-size: .95rem; }
.est-add-list { position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 4px); display: flex; flex-direction: column; background: var(--card); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 8px 24px rgba(0, 0, 0, .12); overflow: hidden; max-height: 60dvh; overflow-y: auto; }
.est-add-head { font-size: .74rem; padding: 6px 12px 2px; }
button.est-add-item { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; width: 100%; min-height: 40px; height: auto; margin: 0; padding: 8px 12px; border: 0; border-radius: 0; background: transparent; color: inherit; box-shadow: none; font: inherit; text-align: left; cursor: pointer; }
button.est-add-item span { flex: 1 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
button.est-add-item em { flex: 0 1 auto; min-width: 0; max-width: 45%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-style: normal; font-size: .76rem; color: var(--muted); }
button.est-add-item.on, button.est-add-item:hover { background: color-mix(in srgb, var(--blue) 8%, var(--card)); }
.est-suggest { display: flex; gap: 6px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin: 0 0 8px; padding: 1px 0; }
.est-suggest::-webkit-scrollbar { display: none; }
.est-suggest > * { flex: none; white-space: nowrap; }
.est-tools > select[data-est-copy] { width: auto; min-width: 150px; max-width: 240px; height: auto; min-height: 32px; align-self: stretch; margin: 0; padding: 0 28px 0 10px; font-size: 12.5px; } /* stretch: always the height of the buttons beside it (32px desktop, taller on phones) */
.est-tools > select + button, .est-tools > select + .btn, .est-tools > select + label { margin-top: 0; } /* house 'select + button' spacing is for forms, not toolbars */
.est-bulk { position: sticky; top: var(--top-h, 0px); z-index: 6; padding: 6px 8px; border: 1px solid var(--line); border-radius: 10px; background: var(--paper); }
.est-bulk .est-bulk-in { display: inline-flex; align-items: center; gap: 4px; margin: 0; font-size: .85rem; }
.est-bulk input.cell { width: 58px; height: 30px; min-height: 30px; margin: 0; padding: 0 6px; text-align: right; }
.est-bulk button { height: var(--btn-h-sm); min-height: var(--btn-h-sm); }
.est-bulk .seg button { margin: 0; }
table.est-lines .check-col { width: 34px; padding-right: 0; }
table.est-lines tr.est-picked td { background: color-mix(in srgb, var(--blue) 6%, var(--card)); }
table.est-lines tr.est-new td.name > input { border-color: var(--green, var(--blue)); }
@media (max-width: 800px) {
  table.est-lines.phone-sheet tr[data-i] { position: relative; }
  table.est-lines.phone-sheet tr[data-i] td.check-col { position: absolute; top: 10px; right: 12px; width: auto; padding: 0; }
  table.est-lines.phone-sheet tr[data-i] td.check-col::before { content: none; }
  table.est-lines.phone-sheet tr[data-i]:has(td.check-col) td[data-label="Customer"] { padding-right: 34px; }
  .est-add > input[type=search] { height: 44px; font-size: 16px; }
}

/* Document extras: survey photos, notes, design drawings, 360° viewer, "Read all" for long footers (house tokens). */
.est-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; margin: 6px 0; }
.est-gallery figure { margin: 0; min-width: 0; }
.est-gallery img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 8px; border: 1px solid var(--line); background: var(--paper); }
.est-gallery figcaption { font-size: .8rem; color: var(--muted); margin-top: 4px; overflow-wrap: anywhere; }
.est-x-item { margin: 0 0 14px; }
.est-x-item h3 { font-size: .95rem; margin: 0 0 6px; }
.est-x-notes p { margin: 0 0 8px; }
.est-video { display: block; width: 100%; aspect-ratio: 16 / 9; max-height: min(60vh, 520px); border-radius: 10px; background: #000; } /* never fills the screen (Oct 17, 2026) */
.est-play { position: relative; display: flex; align-items: center; justify-content: center; width: 100%; aspect-ratio: 16 / 9; max-height: min(60vh, 520px); border-radius: 10px; overflow: hidden; background: #111; text-decoration: none; }
.est-play img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.est-play span { position: relative; padding: 8px 16px; border-radius: 999px; background: rgba(0, 0, 0, .7); color: #fff; font-weight: 700; white-space: nowrap; }
.est-pano { position: relative; width: 100%; aspect-ratio: 16 / 9; max-height: min(60vh, 520px); border-radius: 10px; overflow: hidden; background: var(--paper) center / cover no-repeat; touch-action: pan-y; cursor: grab; } /* pan-y: an up/down swipe scrolls the page; sideways turns the view. Never taller than 60% of the screen or 520px. */
.est-pano-zoom { position: absolute; right: 8px; top: 8px; display: flex; flex-direction: column; gap: 4px; }
.est-pano-zoom button { width: 32px; height: 32px; min-height: 32px; padding: 0; border: 0; border-radius: 8px; background: rgba(0, 0, 0, .55); color: #fff; font-size: 18px; font-weight: 700; line-height: 1; cursor: pointer; }
.est-pano-zoom button:hover { background: rgba(0, 0, 0, .7); }
.est-pano.est-pano-flat .est-pano-zoom { display: none; }
.est-pano canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.est-pano-hint { position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%); padding: 3px 10px; border-radius: 999px; font-size: .78rem; color: #fff; background: rgba(0, 0, 0, .55); white-space: nowrap; pointer-events: none; transition: opacity .3s; }
.est-pano.est-pano-used .est-pano-hint { opacity: 0; }
.est-pano.est-pano-flat { touch-action: auto; cursor: auto; background-size: auto 100%; background-repeat: repeat-x; overflow-x: auto; }
.est-pano.est-pano-flat canvas { display: none; }
/* Full screen (opened in the shared file viewer, assets/viewer.js type "pano"): fills the screen in portrait or landscape; every drag looks around. */
.est-pano.est-pano-full { width: 100%; height: 100%; max-height: none; aspect-ratio: auto; border-radius: 0; background: none; touch-action: none; }
.est-pano.est-pano-full.est-pano-gyro .est-pano-hint { opacity: 0; transition-delay: 2.5s; }
.est-gallery img, .est-pano { image-orientation: from-image; }
.est-long { max-height: 22em; overflow: hidden; position: relative; }
.est-long::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 4em; background: linear-gradient(transparent, var(--card)); }
.est-more { display: inline-flex; margin-top: 8px; }
.est-more span + span, .est-more-t:checked ~ .est-more span:first-child { display: none; }
.est-more-t:checked ~ .est-more span + span { display: inline; }
.est-more-t:checked + .est-long { max-height: none; }
.est-more-t:checked + .est-long::after { content: none; }
@media print { .est-long { max-height: none; } .est-long::after, .est-more { display: none; } }
/* Staff: Photos & Drawings page. */
.est-x-pick, .est-x-files { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; margin: 10px 0; }
.est-x-pick { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); } /* two across on phones */
h2 .badge { white-space: nowrap; vertical-align: middle; }
.est-x-pick figure, .est-x-files figure { position: relative; margin: 0; min-width: 0; border: 1px solid var(--line); border-radius: 10px; padding: 6px; background: var(--card); }
.est-x-pick img, .est-x-files img, .est-x-noimg { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 6px; background: var(--paper); }
.est-x-noimg { display: flex; align-items: center; justify-content: center; font-weight: 700; color: var(--muted); }
.est-x-pick label.check { position: absolute; top: 10px; left: 10px; margin: 0; padding: 2px 4px; border-radius: 6px; background: var(--card); }
.est-x-pick[data-pick="all"] label.check { display: none; }
.est-x-pick input:not([type]), .est-x-files input:not([type]), .est-x-files select { width: 100%; margin: 6px 0 0; height: 32px; min-height: 32px; }
.est-x-files figcaption { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; min-width: 0; }
.est-x-name { font-size: .8rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.est-x-files figcaption .badge { align-self: flex-start; }
.est-x-notes-pick { display: flex; flex-direction: column; gap: 4px; margin: 6px 0; }
.est-x-notes-pick label.check { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; }
.est-x-up { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin: 8px 0; }
.est-x-up > * { flex: none; white-space: nowrap; }
.est-x-up label { margin: 0; display: inline-flex; align-items: center; gap: 6px; }
.est-x-up select { width: auto; height: 34px; min-height: 34px; margin: 0; }
.est-x-up [data-x-upmsg] { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.est-x-link input[type=url] { flex: 1 1 auto; min-width: 0; width: auto; margin: 0; }
.est-x-link input:not([type]) { flex: 0 1 200px; min-width: 0; width: auto; margin: 0; }
.est-x-link { flex-wrap: nowrap; }
h2 .badge { vertical-align: middle; margin-left: 6px; }

/* Phones: the save note gives its room to the Save button (the button still shows Saving… / Saved). */
@media (max-width: 600px) { .est-tools > [data-save-label] { display: none; } }

/* Good · Better · Best (includes/estimate_gbb.php): the customer's tier cards and the builder's tier strip and ticks.
   House tokens only. 2 or 3 cards side by side; one per row on phones. */
.est-tiers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0 0 12px; }
.est-tiers.est-tiers-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.est-tiers.est-tiers-1 { grid-template-columns: minmax(0, 1fr); }
.est-tier { position: relative; display: block; min-width: 0; margin: 0; padding: 16px; color: var(--ink); font-weight: 400; font-size: 1rem; background: var(--card); border: 2px solid var(--line); border-radius: 12px; }
label.est-tier { cursor: pointer; }
.est-tier > input[type="radio"] { position: absolute; left: 0; top: 0; width: 1px; height: 1px; min-height: 0; margin: 0; opacity: 0; }
.est-tier:has(> input:checked) { border-color: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 18%, transparent); }
.est-tier:has(> input:focus-visible) { outline: 2px solid var(--blue); outline-offset: 2px; }
.est-tier h3 { margin: 0 0 2px; display: flex; flex-wrap: wrap; gap: 6px 8px; align-items: center; }
.est-tier .est-tier-blurb { display: block; font-size: .86rem; }
.est-tier .big { margin-top: 8px; font-size: 1.6rem; font-weight: 750; white-space: nowrap; font-variant-numeric: tabular-nums; }
.est-tier .big small { font-size: .8rem; font-weight: 500; color: var(--muted); }
.est-tier ul { list-style: none; padding: 0; margin: 10px 0 0; display: grid; gap: 4px; font-size: .86rem; overflow-wrap: anywhere; }
.est-tier li::before { content: "✓"; color: var(--grass); font-weight: 800; margin-right: 6px; }
.est-tier li.no { color: var(--muted); }
.est-tier li.no::before { content: "–"; color: var(--muted); }
.est-tier .pick { margin-top: 12px; display: block; text-align: center; padding: 7px; border-radius: 999px; border: 1px solid var(--line); font-weight: 650; }
.est-tier:has(> input:checked) .pick { background: var(--blue); border-color: var(--blue); color: #fff; }
.est-gbb h2 { margin-bottom: 10px; }
/* builder */
.est-tier-edit .est-tier-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-bottom: 10px; }
.est-tier.est-tier-ed { cursor: default; padding: 12px; display: grid; gap: 6px; }
.est-tier.est-tier-ed.rec { border-color: var(--blue); }
.est-tier-ed .est-tier-name { font-weight: 700; font-size: 1rem; width: 100%; }
.est-tier-ed .est-tier-blurb { width: 100%; font-size: .86rem; }
.est-tier-money { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-variant-numeric: tabular-nums; }
.est-tier-money b { font-size: 1.3rem; }
.est-ticks { display: inline-flex; gap: 4px; margin-right: 6px; vertical-align: middle; }
.est-ticks label { display: inline-flex; margin: 0; cursor: pointer; }
.est-ticks input { position: absolute; opacity: 0; width: 1px; height: 1px; min-height: 0; }
.est-ticks span { display: inline-block; padding: 3px 8px; border: 1px solid var(--line); border-radius: 999px; font-size: .74rem; font-weight: 650; color: var(--muted); background: var(--card); white-space: nowrap; max-width: 7em; overflow: hidden; text-overflow: ellipsis; }
.est-ticks input:checked + span { background: var(--blue); border-color: var(--blue); color: #fff; }
.est-ticks input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 1px; }
table.est-lines tr.in-tier .seg { display: none; }
.est-gbb-seg button { white-space: nowrap; }
@media (max-width: 800px) {
  .est-tiers, .est-tiers.est-tiers-2 { grid-template-columns: minmax(0, 1fr); }
  table.est-lines.phone-sheet tr[data-tiers] td[data-label="Customer"] { white-space: normal; }
  .est-ticks { flex-wrap: wrap; margin: 0 0 4px; }
}
.seg button { min-height: 0; margin: 0; padding: 4px 10px; border: 0; border-radius: 999px; background: transparent; color: var(--muted); font-size: .76rem; font-weight: 650; box-shadow: none; }
.seg button.on { background: var(--blue); color: #fff; }

/* Phones: nothing slides sideways (Travis's rule, Oct 17, 2026). The money strip becomes a compact grid, Price · Cost ·
   Breakeven · Gross profit on the first line and Net profit · Margin · Man-hours on the second, still sticky; the small
   notes under each number step out (the "explain simpler" line says them). The toolbar and suggestion chips are data-fit
   rows (assets/js/fit-row.js): what doesn't fit goes into More, Save stays. Desktop is unchanged. */
@media (max-width: 1100px) { /* also a narrow desktop (1024): seven cards no longer fit one line there either */
  .stats.est-bar { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 6px; overflow: visible; }
  .stats.est-bar .stat { grid-column: span 3; min-width: 0; }
  .stats.est-bar .stat:nth-child(n+5) { grid-column: span 4; }
}
@media (max-width: 600px) {
  .stats.est-bar .stat { padding: 6px 8px; border-radius: 10px; }
  .stats.est-bar .stat span { font-size: .68rem; overflow: hidden; text-overflow: ellipsis; }
  .stats.est-bar .stat b { font-size: .95rem; overflow: hidden; text-overflow: ellipsis; }
  .stats.est-bar .stat em { display: none; }
  .stats.est-bar .stat.has-gauge { column-gap: 4px; }
  .stats.est-bar .stat .gauge { width: 30px; height: 18px; }
  .stats.est-bar .stat:nth-child(-n+4) .gauge { display: none; } /* the 4-up first line has no room for Gross profit's dial */
  .est-suggest > .qa-ex { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .est-tools[data-fit] > select[data-est-copy] { min-width: 0; max-width: 150px; }
}
@media (max-width: 380px) {
  .stats.est-bar { gap: 4px; }
  .stats.est-bar .stat { padding: 5px 6px; }
  .stats.est-bar .stat .gauge { display: none; }
}
/* A layout switch or Copy from… that moved into the toolbar's More menu: full width, readable. */
.est-tools .fit-more .status-menu > .seg.fit-moved { display: flex; height: auto; padding: 4px; }
.est-tools .fit-more .status-menu > .seg.fit-moved > button { flex: 1 1 0; }
.est-tools .fit-more .status-menu > select.fit-moved { width: 100%; max-width: none; height: 40px; margin: 0; }

/* Desktop: the line table fits its card at every width, no sideways scroll, nothing wraps (Travis's rule, Oct 17, 2026).
   Step 1 (up to 1400px): a row's tier ticks sit over its Included · On · Off switch in the Customer column instead of
   beside it. Step 2 (up to 1200px): tighter cells, narrower number boxes, short headers (Hrs, $ / visit), Margin shows
   just its %. Step 3 (801-1023px): Cost and Margin step out, smaller boxes (both are in the line's ▸ and the money strip). The Service
   name takes what is left and ends in … (full name in the box). */
table.est-lines th .th-short { display: none; }
@media (min-width: 801px) {
  .card.est-sheet { overflow-x: clip; }
  table.est-lines td.name { min-width: 0; max-width: 0; }
  table.est-lines td.name > input, table.est-lines td.name > b { display: block; min-width: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }
  table.est-lines td.name .muted { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}
@media (min-width: 801px) and (max-width: 1400px) {
  table.est-lines td[data-label="Customer"]:has(.est-ticks) .est-ticks { display: flex; width: max-content; margin: 0 0 4px; }
}
@media (min-width: 801px) and (max-width: 1200px) {
  table.est-lines th, table.est-lines td { padding-left: 5px; padding-right: 5px; }
  table.est-lines input.cell { width: 64px; padding: 0 5px; }
  table.est-lines th .th-full { display: none; }
  table.est-lines th .th-short { display: inline; }
  table.est-lines td[data-label="Margin"] .meter { display: none; }
  table.est-lines td[data-label="Margin"] .pct { min-width: 0; margin-left: 0; }
  .est-ticks { gap: 3px; }
  .est-ticks span { padding: 3px 6px; max-width: 64px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
  table.est-lines td[data-label="Customer"] .seg label > span { padding-left: 7px; padding-right: 7px; }
}
@media (min-width: 801px) and (max-width: 1023px) {
  table.est-lines tr > :nth-last-child(2), table.est-lines tr > :nth-last-child(3) { display: none; }
  table.est-lines input.cell { width: 58px; }
  table.est-lines td[data-label="Customer"] .seg label > span { padding-left: 5px; padding-right: 5px; font-size: .75rem; }
  .est-ticks span { max-width: 50px; }
}
@media (max-width: 800px) { .est-x-item h3 { padding-right: 60px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } /* Tracker 37 (Travis Oct 21 2026): the floating Assistant button never covers a video or 360 card title at 390 */
/* Tracker 941, 942: no clipped names or statuses in Estimates tables when there is room */
@media (min-width: 601px) { main table.phone-sheet td, main table.phone-sheet td > a { max-width: none !important; white-space: nowrap !important; } main table.phone-sheet td .badge { white-space: nowrap !important; } }
