    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    :root {
      --bg:         #162626;
      --bg-mid:     #1a2e2e;
      --bg-light:   #1e3838;
      --bg-card:    #1e3838;
      --border:     rgba(var(--gold-dim-rgb), 0.3);
      --gold:       #C9A464;
      --gold-light: #E6D0A5;
      --gold-dim:   #917040;
      --gold-rgb:   201, 164, 100;
      --bg-rgb:     22, 38, 38;
      --gold-light-rgb: 230, 208, 165;
      --gold-dim-rgb:   145, 112, 64;
      --bg-mid-rgb:     26, 46, 46;
      --bg-light-rgb:   30, 56, 56;
      --muted-rgb:      74, 112, 112;
      --gold-fill:  color-mix(in srgb, var(--gold) 7%, var(--bg-mid));  /* brand-derived (was the hardcoded legacy teal) */
      --white:      #ffffff;
      /* Tenant font contract (§2): --font is the DEFAULT only. vantage-brand.js
         applyFont() overwrites both from company_settings.font_family, so the
         document face follows the tenant — never a hardcoded family here. */
      --font:       'Lato', Arial, sans-serif;
      --font-body:  var(--font);
    }
    html { scroll-behavior: smooth; }
    body { font-family: var(--font); background: var(--bg); color: var(--gold-light); min-height: 100vh; }

    /* ── Sticky action bar ── */
    /* Bar chrome is CANONICAL: body.v-ui.v-face .v-preview-bar (vantage-facelift.css)
       owns position, height, padding, surface, blur and the hairline. The local copy
       was deleted — it duplicated the shell this page already declares, and its
       bespoke surface left the bar with no visible bottom edge once the hairline
       moved to the shared token. Only the page-owned inline padding stays. */
    /* Chrome from the canonical .v-preview-bar; the surface is forced OPAQUE
       here because the canon paints it at 94% over --vf-surface, which on this
       viewer (its own canvas + a fixed bar) reads as see-through. */
    /* Chrome from the canonical .v-preview-bar. The surface is forced OPAQUE and
       at matching specificity (body.v-ui.v-face .v-preview-bar is 3 body classes
       + 1, so a bare .action-bar loses): the canon paints 94% over --vf-surface,
       which over this viewer's own canvas reads as see-through. */
    .action-bar { padding-inline: 32px; }
    /* Same surface as .proposal-nav and the builder's .sidebar: var(--bg-mid).
       NOT --v-theme-chrome — that is color-mix(--bg-mid 88%, #ebebeb), i.e.
       deliberately LIGHTER, which rendered the bar as a pale band sitting on
       top of a dark page. Opaque + matching specificity so it beats the canon's
       94%-alpha .v-preview-bar fill. */
    body.v-ui.v-face .action-bar.v-preview-bar { background: var(--bg-mid); }
    @media (max-width: 1120px) {
      /* Nav is a drawer here, so the review band re-centres with the column. */
      body.has-proposal-nav .submit-mode-bar .v-banner { margin-left: auto !important; }
    }
    /* Narrow viewports: there is no width left for the copy to give up, so the
       action group takes its own row rather than squeezing Submit off the end. */
    @media (max-width: 760px) {
      .submit-mode-bar { padding: 10px 16px; }
      .submit-mode-bar .v-banner { flex-wrap: wrap; }
      .submit-mode-bar-btns { width: 100%; }
    }

    /* ── Scope ── */
    .scope-content { font-size: 14px; line-height: 1.8; color: var(--gold-light); }
    .scope-content ul, .scope-content ol { padding-left: 1.5em; margin: 8px 0; }
    .scope-content li { margin: 4px 0; }
    /* Quill saves each line as its own <p>; per-paragraph margin reads as
       double spacing. Blank lines in the editor arrive as empty <p><br></p>
       rows, so paragraph breaks the author typed still show. */
    .scope-content p { margin: 0; }
    .scope-content strong { color: var(--gold); }

    /* Option selector */
    .area-options { display: flex; gap: 8px; flex-wrap: wrap; }
    /* Option group — a bordered, labelled block so a required choice cannot be
       mistaken for decorative chrome. Token-only; the pending state borrows the
       page's own accent rather than introducing a colour. */
    .area-options-wrap {
      /* Compact: it is a two-line prompt, not a panel (Nate 2026-08-01). */
      border: 1px solid rgba(var(--gold-rgb), 0.28); border-radius: 8px;
      padding: 9px 12px; margin-bottom: 16px;
      background: rgba(var(--gold-rgb), 0.04);
    }
    .area-options-pending { border-color: var(--gold); background: var(--gold-fill, rgba(var(--gold-rgb), 0.09)); }
    .area-options-chosen  { border-color: rgba(var(--gold-rgb), 0.35); }
    .area-options-locked  { border-style: dashed; background: transparent; }
    .area-options-head {
      display: flex; align-items: center; gap: 7px; margin-bottom: 8px;
      font-size: 12px; color: var(--gold); letter-spacing: .02em;
    }
    .area-options-locked .area-options-head { color: var(--gold-dim-text, var(--gold-dim)); }
    .area-options-hint {
      margin-top: 9px; font-size: 11px; line-height: 1.55;
      color: var(--gold-dim-text, var(--gold-dim));
    }
    /* Locked chips are not controls — no pointer, no hover affordance. */
    .option-btn-static { cursor: default; opacity: 0.55; }
    .option-btn-static.selected { opacity: 1; }

    /* Choices callout below Payment Terms, shown only while a choice is
       outstanding (#choices-callout-section is hidden otherwise). Width and
       offset come from the section it sits in (.section.area-outer-section >
       .area-section-content, the space cards' own column), so it is exactly as
       wide as the cards above at every viewport. It used to sit in the body
       flow with its own max-width and nav offset, and with no section gutter
       it ran the full width of the column under 1120px (Nate, 2026-10-07). */
    .choices-callout {
      margin: 0 0 32px;
      border: 1px solid var(--gold); border-radius: var(--vf-r); padding: 16px 20px;
      background: var(--gold-fill, rgba(var(--gold-rgb), 0.09));
    }
    .choices-callout-title {
      display: flex; align-items: center; gap: 8px;
      font-size: 15px; color: var(--gold); margin-bottom: 6px;
    }
    .choices-callout-body { font-size: 13px; line-height: 1.65; color: var(--gold-light); }
    .choices-callout-list { margin: 10px 0 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
    .choices-callout-list button {
      font: inherit; font-size: 12px; cursor: pointer;
      border: 1px solid rgba(var(--gold-rgb), 0.45); border-radius: 999px;
      padding: 5px 12px; background: transparent; color: var(--gold);
    }
    .choices-callout-list button:hover { border-color: var(--gold); background: rgba(var(--gold-rgb), 0.12); }
    .option-btn {
      padding: 6px 16px; border: 1px solid var(--v-border);
      background: none; color: var(--gold-dim-text, var(--gold-dim)); font-family: var(--font); font-size: 12px;
      letter-spacing: 0.01em; cursor: pointer; transition: all 0.2s;
    }
    .option-btn:hover { border-color: var(--gold-light); color: var(--gold-light); }
    .option-btn.selected { border-color: var(--gold); background: var(--gold-fill); color: var(--gold); }
    /* Flash used by the option-selection gate when Accept is attempted with unchosen options */
    .option-attention { outline: 2px solid var(--gold); outline-offset: 4px; border-radius: 8px; animation: optionPulse 0.65s ease-in-out 3; }
    @keyframes optionPulse { 0%,100% { outline-color: var(--gold); } 50% { outline-color: transparent; } }

    /* Area description */
    .area-desc-header {
      display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
    }
    .area-description-label { }
    .area-desc-toggle {
      background: none; border: none; color: var(--gold-dim-text, var(--gold-dim)); cursor: pointer;
      font-size: 10px; padding: 0 2px; line-height: 1; transition: color 0.15s;
    }
    .area-desc-toggle:hover { color: var(--gold); }
    .area-description {
      font-size: 14px; line-height: 1.8; color: var(--gold-light); margin-bottom: 0;
      overflow: hidden; transition: max-height 0.25s ease;
    }
    /* Footer band — Space Description (left) shares a row with Space Total (right) */
    .area-footer-row {
      display: flex; justify-content: space-between; align-items: flex-start; gap: 28px;
      border-top: 1px solid rgba(var(--gold-dim-rgb),0.18); margin-top: 10px;
      padding: 16px 14px 4px; flex-wrap: wrap;
    }
    .area-desc-block {
      flex: 1 1 360px; min-width: 0;
      background: rgba(var(--gold-rgb),0.045);
      border: 1px solid rgba(var(--gold-dim-rgb),0.18);
      border-radius: 8px; padding: 12px 16px 14px;
    }
    .area-footer-row .area-total-row {
      border-top: none; margin-top: 0; margin-left: auto; padding: 0; flex: 0 0 auto;
    }
    /* An option's own discounts sit over its Space Total (option-discounts.md). */
    .area-footer-row .area-total-wrap { margin-left: auto; flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
    .area-footer-row .area-disc-line { padding: 0 0 2px; }

    .area-description img { max-width: 100%; border-radius: 6px; margin: 8px auto; display: block; }
    /* Quill alignment classes */
    .area-description .ql-align-center, .scope-content .ql-align-center { text-align: center; }
    .area-description .ql-align-right,  .scope-content .ql-align-right  { text-align: right; }
    .area-description .ql-align-justify,.scope-content .ql-align-justify { text-align: justify; }
    .area-description .ql-align-center img { margin: 8px auto; display: block; }

    /* Attachment row indentation */
    .attach-spacer { width: 56px; min-width: 56px; padding: 0 4px 0 32px !important; position: relative; }
    .attach-spacer::after { content:''; position:absolute; left:44px; top:0; bottom:50%; border-left:1px solid rgba(var(--gold-dim-rgb),0.35); border-bottom:1px solid rgba(var(--gold-dim-rgb),0.35); width:12px; }
    .attach-desc { padding-left: 8px !important; }
    .attach-desc-inner { display:flex; align-items:center; gap:10px; }
    /* The text beside the thumb may shrink below its longest line. A flex item
       will not by default, so on a phone a long brand ("Arlington Industries")
       ran out of the item column and under the qty (Nate, 2026-10-02) instead
       of taking the ellipsis .item-brand already carries there. */
    .attach-desc-inner > :last-child { flex: 1 1 auto; min-width: 0; }

    .item-thumb {
      width: 54px; height: 44px; object-fit: contain; border-radius: 7px;
      background: rgba(var(--bg-rgb),0.55); border: none; padding: 3px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.35);
      cursor: zoom-in; position: relative;
      transform-origin: left center;
      transition: transform 0.22s cubic-bezier(0.34,1.4,0.64,1), box-shadow 0.22s ease;
    }
    .item-thumb:hover {
      transform: scale(3);
      box-shadow: 0 12px 40px rgba(0,0,0,0.75);
      z-index: 100;
    }
    .item-thumb-placeholder {
      width: 54px; height: 44px; border-radius: 7px; background: rgba(var(--bg-rgb),0.45);
      border: none; display: flex; align-items: center; justify-content: center;
      color: var(--gold-dim-text, var(--gold-dim)); font-size: 16px;
      box-shadow: 0 1px 6px rgba(0,0,0,0.25);
      cursor: zoom-in; position: relative;
      transform-origin: left center;
      transition: transform 0.22s cubic-bezier(0.34,1.4,0.64,1), box-shadow 0.22s ease;
    }
    .item-thumb-placeholder:hover {
      transform: scale(3);
      box-shadow: 0 12px 40px rgba(0,0,0,0.75);
      z-index: 100;
    }
    /* A product line opens the item card (proposal.js openItemCard). */
    .items-table tr[data-item-card] { cursor: pointer; }
    .item-brand {opacity: 0.65;}
    .item-model { font-size: 14px; color: var(--gold-light); font-weight: 500; letter-spacing: 0.2px; }
    .item-desc { font-size: 11px; color: var(--gold); margin-top: 3px; opacity: 0.65; line-height: 1.5; white-space: pre-line; }
    .item-client-note { font-size: 12px; color: #4a9a9a; font-style: italic; margin-top: 5px; line-height: 1.5; }
    .item-child-toggle {
      display: inline-flex; align-items: center; gap: 5px; margin-top: 6px;
      background: none; border: none; cursor: pointer; padding: 0;
      font-size: 9px; letter-spacing: 0.01em;
      color: var(--gold-dim-text, var(--gold-dim)); opacity: 0.6; font-family: var(--font);
      transition: opacity 0.15s, color 0.15s;
    }
    .item-child-toggle:hover { opacity: 1; color: var(--gold); }
    .item-child-toggle .toggle-chevron { display: inline-block; transition: transform 0.2s ease; font-style: normal; }
    .item-child-toggle.collapsed .toggle-chevron { transform: rotate(-90deg); }
    .item-total-combined { font-size: 9px; letter-spacing: 0.01em; opacity: 0.45; margin-top: 3px; }
    .item-type-badge {
      display: inline-block; font-size: 8px; letter-spacing: 0.01em;
      padding: 1px 6px; border-radius: 3px; margin-left: 6px; vertical-align: middle;
    }
    .badge-selection { background: rgba(232,180,163,0.10); color: #e8b4a3; border: 1px solid rgba(232,180,163,0.25); }
    /* Customer Furnished Equipment. Token-only, unlike the three literal-colored
       badges above it (they predate the rule and are counted against this file's
       own budget): CFE already reads as the tenant accent everywhere else it
       appears in the product, so a rebrand carries it. */
    .badge-cfe { background: rgba(var(--gold-rgb),0.12); color: var(--gold); border: 1px solid rgba(var(--gold-rgb),0.35); }
    /* In the total cell, where a Customer Furnished line's $0 would be (Nate,
       2026-10-01). It may wrap to two lines in a phone's narrow total column
       rather than run past it; the row's height comes from its name anyway. */
    .item-total .item-type-badge { margin-left: 0; max-width: 100%; white-space: normal; text-align: center; line-height: 1.25; }
    /* Recurring (subscription) line. Token-only like CFE. The line is shown for
       the customer's awareness and is billed on its own cadence, so it needs to
       read as "not part of this total" everywhere its price appears. */
    .badge-recurring { background: rgba(var(--gold-rgb),0.12); color: var(--gold); border: 1px solid rgba(var(--gold-rgb),0.35); }
    /* Subscription line: the same purple the builder's .sub-recurring-badge uses. */
    .item-recurring { font-size: 11px; color: var(--recurring-purple, #b07fd4); margin-top: 3px; line-height: 1.5; }
    .item-total-period { font-size: 10px; color: var(--gold-dim-text, var(--gold-dim)); letter-spacing: 0.01em; }
    /* Subscription price cell: one cell across Price / Qty / Total. */
    .item-sub-price, .item-sub-total { text-align: right; vertical-align: middle; white-space: nowrap; }
    .item-sub-price-value { font-size: 13px; color: var(--recurring-purple, #b07fd4); letter-spacing: 0.2px; }
    .item-sub-price-value .item-total-period { color: var(--recurring-purple, #b07fd4); opacity: 0.8; }
    .item-sub-price-note { font-size: 9px; color: var(--recurring-purple, #b07fd4); letter-spacing: 0.01em; margin-top: 2px; }
    /* The subscription block shows in the Total cell only when the Price column is gone (compact). */
    .item-sub-price-compact { display: none; }
    .item-sub-price-value .item-total-period { margin-left: 2px; }
    /* Price and Qty read quieter than the Total by dimming their TEXT, never the cell:
       opacity on a <td> fades its background too, so inside a shaded block (a pre-wire
       plate's rows, tbody.v-group-body) the two columns came out a different shade from
       the rest of the row (Nate, 2026-10-14: "can we not make the price and qty different
       shading color?"). */
    .item-price { text-align: right; font-size: 13px; color: var(--gold); }
    .item-price > * { opacity: 0.75; }
    .item-price > .item-price-msrp { opacity: 0.45; }   /* its own 0.6 within the 0.75, as before */
    .item-price-msrp { font-size: 10px; color: var(--gold-dim-text, var(--gold-dim)); text-decoration: line-through; opacity: 0.6; }
    .item-price-sell { font-size: 13px; color: var(--gold); letter-spacing: 0.2px; }
    .item-total-savings { font-size: 10px; color: #4caf50; margin-top: 3px; font-weight: 500; white-space: nowrap; letter-spacing: 0.2px; }
    .item-qty { text-align: center; font-size: 13px; color: color-mix(in srgb, var(--gold) 50%, transparent); }
    .item-total { text-align: right; font-size: 15px; color: var(--gold-light); font-weight: 500; white-space: nowrap; letter-spacing: 0.2px; }

    /* Attachments */
    .attach-row td { background: transparent; padding: 5px 14px; }

    .area-total-label {opacity: 0.65;}
    .area-total-value { font-size: 22px; color: var(--gold-light); font-weight: 300; letter-spacing: 0.5px; }


    /* ── Admin pending-flags banner ── */
    /* Submit-mode banner. The band itself is the canonical .v-banner
       .v-banner-success primitive with trailing actions (vantage-ui.css); this
       rule owns only where it sits on the page. The former page-local green
       button family (.submit-mode-confirm/cancel/settings-btn) was replaced by
       canonical .v-btn-primary / .v-btn-secondary and deleted. */
    .submit-mode-bar {
      /* Sticks to --proposal-chrome-h (0 on shell pages, where the 56px band
         is already reserved by body.v-app-shell). */
      /* FLOATS over the document — it does not reserve a band (Nate 2026-08-01).
         This was position:sticky, which keeps the bar IN FLOW: the strip it
         occupied pushed the document down and showed as an empty box under the
         green banner. That box is why this keeps regressing — every previous
         attempt treated it as a paint problem (reserve less height; make the
         padding opaque) when the reservation itself was the bug. Nothing in flow
         means no strip to style, and no content pushed down.
         The offset clears the fixed .v-preview-bar above it: the same
         --v-doc-bar-h the cover's top padding uses, since a fixed element
         cannot inherit the shell's padding reservation. */
      position: fixed;
      top: calc(var(--proposal-chrome-h, 0px) + var(--v-doc-bar-h, 56px));
      left: 0; right: 0; z-index: 160;
      padding: 10px 32px;
      /* The bar now hovers over live document, so its transparent gutter must
         not swallow clicks meant for the content underneath. */
      pointer-events: none;
    }
    .submit-mode-bar > * { pointer-events: auto; }
    /* Width: the band tracks the DOCUMENT COLUMN, not the viewport (Nate
       2026-08-01). It was left:0/right:0 with only a --pnav-w margin, which made
       it span the whole window — far wider than the 900px proposal, and wide
       enough that its trailing Submit button ran past the right edge while the
       review-progress track was still present. The column is the same geometry
       .section-inner uses. These declarations are only the PRE-MEASURE DEFAULT:
       syncReviewBarToColumn() overwrites width and margin-left from the real
       column box on load, scroll, resize, and rail toggle. Do not re-add a
       hand-computed shell offset here — a fixed element cannot see the body
       padding the rail applies, and every attempt to re-derive it landed the
       band a rail-width off in one shell state or another. */
    .submit-mode-bar .v-banner {
      border-radius: var(--v-radius-lg, 10px);
      max-width: var(--section-max);
      margin: 0 auto;
      /* NOT flex-wrap here: with wrap on, the flex line breaks BEFORE the copy
         is allowed to shrink, so the action group drops to a second row even
         when it would have fitted. Left nowrap, the canon's min-width:0 on
         .v-banner-body makes the copy reflow and the group stays on one row.
         The narrow-viewport wrap is opted into further down. */
    }
    body.has-proposal-nav .submit-mode-bar .v-banner {
      /* Less this bar's own 32px gutter: --content-ml is measured from the
         content edge, and the banner starts inside the padding. */
      margin-left: calc(var(--content-ml) - 32px);
      margin-right: auto;
    }
    /* The canon tints .v-banner-success at 6% over TRANSPARENT, which is
       unreadable over a scrolling document. Same tint, opaque base. */
    body.v-ui .submit-mode-bar .v-banner-success {
      background: color-mix(in srgb, var(--v-ok) 9%, var(--bg-mid));
      backdrop-filter: blur(10px);
    }
    /* The control group is ONE ROW and never breaks (Nate 2026-08-01). It was
       flex-wrap:wrap, which let Submit fall to a line of its own the moment the
       group was squeezed. nowrap + shrink:0 on the buttons makes the copy the
       only thing that can yield, which is what the canon's min-width:0 on
       .v-banner-body is for. */
    .submit-mode-bar-btns {
      display: flex; align-items: center; gap: 10px; flex: 0 0 auto;
      margin-left: auto; flex-wrap: nowrap; justify-content: flex-end;
    }
    .submit-mode-bar-btns > button { flex: 0 0 auto; white-space: nowrap; }
    /* Share Preview's review: the canonical switch in the band's row (layout only). */
    .submit-mode-pricing { position: relative; display: flex; align-items: center; gap: 8px; white-space: nowrap; flex: 0 0 auto; }
    /* The amber variant of the band, opaque for the same reason as the green one. */
    body.v-ui .submit-mode-bar .v-banner-warning {
      background: color-mix(in srgb, var(--v-warn, #e5a54b) 14%, var(--bg-mid));
      backdrop-filter: blur(10px);
    }

    /* Client View Settings drawer: vantage-client-view-settings.js owns it and its layout. */

    /* Submit confirmation modal */
    /* Send-modal CSS moved to /vantage-send-routing.js (2026-08-02). */

    /* ── Submit-mode scroll gate ──────────────────────────────────────────────
       Review mode is only a real review if the reviewer actually reaches the
       end of the document, so the bar's confirm button stays inert until they
       do. The progress track sits in the bar itself so the disabled state
       reads as "not yet" rather than "broken". */
    .submit-mode-progress {
      flex: 0 0 80px; height: 3px; border-radius: 2px; align-self: center;
      background: rgba(var(--gold-rgb),0.2); overflow: hidden;
    }
    .submit-mode-progress-fill {
      display: block; height: 100%; width: 0;
      background: var(--v-ok); transition: width 0.12s linear;
    }

    /* End-of-document submit block — the same confirm action, parked where the
       reviewer lands after reading. Admin + submit mode only. The card itself is
       the page's canonical .area-block; only the inner copy is local. */
    .admin-submit-end { display: none; max-width: var(--section-max); margin: 0 auto; padding: 8px 40px 56px; }
    /* Centre inside the region RIGHT OF THE NAV. The previous
       margin-left: calc(var(--content-ml) - 40px) was hand-computed arithmetic
       borrowed from .section-inner (whose -40px cancels its own padding); here it
       started the block 40px INSIDE the nav gutter and left margin-right at 0, so
       the card sat left of centre at every width. Give the outer block the gutter
       and let the card centre itself with auto margins — no arithmetic to drift. */
    body.has-proposal-nav .admin-submit-end {
      margin-left: var(--pnav-w);
      margin-right: 0;
      max-width: none;
    }
    body.has-proposal-nav .admin-submit-end .area-block {
      max-width: var(--section-max);
      margin-left: auto;
      margin-right: auto;
    }
    .admin-submit-end.visible { display: block; }
    .admin-submit-end .area-block { display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; padding: 28px 24px; }
    .ase-title { font-size: 18px; font-weight: 300; color: var(--gold); }
    .ase-sub { font-size: 13px; line-height: 1.6; max-width: 440px; color: var(--gold-dim-text, var(--gold-dim)); }

    /* Pre-submit confirmation — canonical .modal-overlay / .modal.v-service-modal
       frame (vantage-ui.css + vantage-facelift.css). Only the three review blocks
       below are page-local, and they are content layout, not a component family. */
    .pf-block { border: 1px solid var(--v-border, var(--gold-dim)); border-radius: 8px; overflow: hidden; margin-bottom: 14px; }
    .pf-block:last-of-type { margin-bottom: 0; }
    .pf-block-head {
      display: flex; align-items: center; gap: 12px; padding: 10px 14px;
      background: rgba(var(--gold-rgb),0.06); border-bottom: 1px solid var(--v-border, var(--gold-dim));
    }
    .pf-block-head-title { flex: 1; text-align: left; font-size: 13px; color: var(--gold); }
    .pf-check { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--gold-dim-text, var(--gold-dim)); cursor: pointer; white-space: nowrap; }
    .pf-check input { accent-color: var(--gold); cursor: pointer; }
    .pf-block.confirmed .pf-block-head { background: rgba(var(--gold-rgb),0.13); }
    .pf-block.confirmed .pf-check { color: var(--gold-light); }
    .pf-body { padding: 12px 14px; font-size: 13px; color: var(--gold-light); text-align: left; }
    .pf-row { display: flex; justify-content: space-between; gap: 14px; padding: 6px 0; border-bottom: 1px solid rgba(var(--gold-dim-rgb),0.25); }
    .pf-row:last-child { border-bottom: none; }
    .pf-row-label { color: var(--gold-dim-text, var(--gold-dim)); }
    .pf-row-value { color: var(--gold-light); text-align: right; }
    .pf-sub { display: block; font-size: 11px; color: var(--gold-dim-text, var(--gold-dim)); }
    .pf-note { margin-top: 10px; font-size: 12px; line-height: 1.6; color: var(--gold-dim-text, var(--gold-dim)); }
    .pf-note strong { color: var(--gold-light); }
    .pf-flag { color: var(--v-danger); }
    /* Lines-to-price groups. Each group is a heading, its rows, then one line
       saying what the group means, so the sender is not left to infer why a
       line is listed. */
    .pf-price-group { margin-bottom: 14px; }
    .pf-price-group:last-child { margin-bottom: 0; }
    .pf-price-group-title {
      font-size: 12px; font-weight: 500; color: var(--gold-light);
      padding-bottom: 6px; margin-bottom: 2px;
      border-bottom: 1px solid rgba(var(--gold-dim-rgb),0.35);
    }
    .pf-price-group .pf-note { margin-top: 6px; }
    .pf-ok { color: var(--v-ok); }
    /* Sentence-case section label, same role/size as .pf-block-head-title. NOT an
       eyebrow — no uppercase, no letter-spacing (C3b). */
    .pf-section-label { font-size: 13px; color: var(--gold); margin: 14px 0 4px; }
    .pf-section-label:first-child { margin-top: 0; }
    /* Cloned Investment / Payment markup keeps its canonical styling; only the
       outer spacing is neutralized inside the modal. */
    .pf-body .fin-card { padding: 0; }
    .pf-body .payment-item { margin: 0 0 6px; }
    .pf-body .payment-item:last-child { margin-bottom: 0; }

    .admin-flags-banner {
      max-width: var(--section-max); margin: 0 auto 0; padding: 0 40px 20px;
    }
    .admin-flags-banner-inner {
      display: flex; align-items: center; gap: 12px; padding: 12px 18px;
      background: rgba(230,126,34,0.08); border: 1px solid rgba(230,126,34,0.4);
      border-radius: 8px; font-size: 13px; color: #e67e22;
    }
    .admin-flags-banner-inner strong { font-weight: 500; }

    /* ── Locked-proposal cover overlay ── */
    .cover-locked-msg {
      display: none; margin-top: 40px; text-align: center;
      padding: 28px 32px; max-width: 480px;
      background: rgba(var(--bg-rgb),0.7); border: 1px solid var(--v-border);
      border-radius: 12px; backdrop-filter: blur(4px);
    }
    .cover-locked-msg .lock-icon { font-size: 28px; margin-bottom: 12px; }
    .cover-locked-msg .lock-title { font-size: 18px; font-weight: 300; color: var(--gold); margin-bottom: 10px; }
    .cover-locked-msg .lock-body { font-size: 13px; color: var(--gold-dim-text, var(--gold-dim)); line-height: 1.7; }

    .fin-savings-line { display: flex; align-items: center; padding: 0 0 8px 16px; font-size: 12px; }
    .fin-savings-label { color: #4caf50; }
    .fin-savings-value { color: #4caf50; font-weight: 500; }
    .fin-savings-total { display: flex; justify-content: space-between; align-items: center; padding: 10px 0 0; font-size: 13px; font-weight: 500; }
    .fin-savings-total-label { color: #4caf50; }
    .fin-savings-total-value { color: #4caf50; }

    /* ── Payment Schedule ── */
    .payment-item {
      display: flex; align-items: flex-start; gap: 20px; padding: 20px 0;
      border-bottom: 1px solid rgba(var(--gold-dim-rgb),0.3);
    }
    /* The row padding spaces rows around the rule between them. The last row
       has no rule under it, so its bottom padding only stacked on the card's
       own: 44px under the number against 28px over it (Nate, 2026-10-07). */
    .payment-item:last-child { border-bottom: none; padding-bottom: 0; }
    .payment-num { width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--v-border); display: flex; align-items: center; justify-content: center; font-size: 13px; color: var(--gold); flex-shrink: 0; }
    .payment-details { flex: 1; }
    .payment-type { font-size: 13px; color: var(--gold-light); margin-bottom: 3px; }
    .payment-due { font-size: 11px; color: var(--gold-dim-text, var(--gold-dim)); }
    /* "Due on Receipt" wraps as one phrase, never "Due" over "on Receipt". */
    .payment-due-terms { white-space: nowrap; }
    .payment-amount { font-size: 18px; color: var(--gold); font-weight: 300; text-align: right; white-space: nowrap; }

    /* ── Action buttons ── */
    .btn-accept {
    }
    
    .btn-changes {
    }
    
    .btn-decline {
    }
    
    /* ── Accepted state: .accepted-banner is shared with the change order
       (vantage-document.css). ── */
    .contract-signature-record {
      display:none; max-width:1120px; margin:0 auto 64px; padding:0 40px;
    }
    body.has-proposal-nav .contract-signature-record {
      max-width:var(--section-max);
      margin-left:var(--content-ml);
      margin-right:auto;
      padding:0;
    }
    .contract-signature-record.visible { display:block; }
    .contract-signature-card {
      display:grid; grid-template-columns:minmax(0,1fr) auto; gap:28px; align-items:center;
      background:var(--bg-mid); border:1px solid var(--v-border); border-radius:12px; padding:26px 30px;
    }
    .contract-signature-label { letter-spacing:2.5px; }
    .contract-signature-name { font-size:22px; color:var(--gold-light); margin:6px 0; }
    .contract-signature-meta { font-size:12px; line-height:1.7; color:var(--gold-dim-text, var(--gold-dim)); }
    .contract-signature-mark {
      min-width:200px; min-height:84px; display:flex; align-items:center; justify-content:center;
      background:var(--bg-light); border:1px solid rgba(var(--gold-rgb),.2); border-radius:8px; padding:14px;
    }
    .contract-signature-mark img { max-width:220px; max-height:72px; object-fit:contain; filter:invert(1) grayscale(1) brightness(1.8); }
    .contract-signature-mark.typed { font-size:26px; font-style:italic; color:var(--gold-light); }
    @media(max-width:1120px) {
      body.has-proposal-nav .contract-signature-record {
        margin-left:auto !important; margin-right:auto !important; padding:0 40px;
      }
    }
    @media(max-width:640px) {
      .contract-signature-record { padding:0 18px; }
      .contract-signature-card { grid-template-columns:1fr; padding:22px; }
      .contract-signature-mark { width:100%; min-width:0; }
    }

    /* Toasts are CANONICAL: vantage-sidebar.js owns VToast/showFloatToast and
       vantage-facelift.css owns .v-toast-wrap/.v-toast. The local #toast box and
       its fixed bottom-right anchoring were deleted — page CSS may not position
       toasts (C12). toast() below now delegates to the canonical owner. */

    /* Modal frame, title, body, footer and button roles are ALL canonical
       (vantage-ui.css + vantage-buttons.css). The local .modal/.modal-overlay/
       .modal-title/.modal-body/.modal-actions/.btn-sm/.btn-gold/.btn-outline-sm/
       .btn-red copies were deleted here — the canon owns every one of them (§3, §4).
       The canon accepts .open on .modal-overlay, so closeModal() is unchanged. */

    /* ── Loading ── */
    .loading { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; gap: 16px; color: var(--gold-dim-text, var(--gold-dim)); }

    /* ── Forward / Share ── */
    .btn-forward {
      display: inline-flex; align-items: center; gap: 8px; margin-top: 20px;
    }
    
    .share-modal { max-width: 520px !important; }
    .share-field { margin-bottom: 18px; }
    .share-label { font-size: 11px; letter-spacing: 0.01em; color: var(--gold); margin-bottom: 8px; display: block; }
    .share-input {
      width: 100%; background: var(--bg-light); border: 1px solid var(--v-border);
      border-radius: 6px; padding: 10px 14px; color: var(--gold-light);
      font-family: var(--font); font-size: 13px;
    }
    .share-input:focus { outline: none; border-color: var(--gold); }
    .share-checkbox-row {
      display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px;
      background: var(--bg-light); border: 1px solid var(--v-border); border-radius: 6px; cursor: pointer;
    }
    .share-checkbox-row:has(input:checked) { border-color: var(--v-ok); background: rgba(46,204,113,0.05); }
    .share-checkbox-label { font-size: 13px; color: var(--gold-light); line-height: 1.5; cursor: pointer; }
    .share-checkbox-label small { font-size: 11px; color: var(--gold-dim-text, var(--gold-dim)); display: block; margin-top: 3px; }
    .share-expiry-row { display: flex; align-items: center; gap: 10px; }
    .share-expiry-toggle { font-size: 12px; color: #4a9fc4; background: none; border: none; cursor: pointer; padding: 0; text-decoration: underline; }

    /* ── Guest banner ──
       Neutral and theme-aware: reads light-on-dark in dark mode and dark-on-light
       in light mode, with no color of its own. It consumes the canonical facelift
       roles (--vf-text / --vf-text-muted / --vf-line-soft / --vf-panel), which
       resolve from --v-theme-* — re-emitted by vantage-brand.js inside
       html[data-theme="light"] — so the toggle drives it for free and a tenant
       rebrand cascades. The previous #4a9fc4 was a hardcoded cyan-family literal
       (C27b) that ignored the theme entirely. */
    .guest-banner {
      background: var(--vf-panel, rgba(var(--bg-light-rgb), 0.35));
      border: 1px solid var(--vf-line-soft, var(--gold-dim));
      border-radius: var(--vf-r-sm, 8px); padding: 14px 18px; margin-bottom: 28px;
      display: flex; align-items: flex-start; gap: 12px;
    }
    .guest-banner-icon { color: var(--vf-text-muted, var(--gold-dim)); flex-shrink: 0; line-height: 1.4; display: flex; }
    .guest-banner-text { font-size: 13px; color: var(--vf-text-muted, var(--gold-light)); line-height: 1.7; }
    .guest-banner-text strong { font-weight: 500; display: block; margin-bottom: 2px; color: var(--vf-text, var(--gold-light)); }

    /* ── Shares activity log ── */
    .shares-log { margin-top: 40px; padding-top: 28px; border-top: 1px solid var(--gold-dim); text-align: left; }
    .shares-log-title { font-size: 11px; letter-spacing: 0.01em; color: var(--gold); margin-bottom: 16px; }
    .share-log-row {
      display: flex; align-items: center; gap: 10px; padding: 12px 0;
      border-bottom: 1px solid rgba(var(--gold-dim-rgb),0.2); flex-wrap: wrap;
    }
    .share-log-row:last-child { border-bottom: none; }
    .share-log-email { color: var(--gold-light); font-size: 13px; flex: 1; min-width: 160px; }
    .share-log-date  { color: var(--gold-dim-text, var(--gold-dim)); font-size: 11px; white-space: nowrap; }
    .share-log-badges { display: flex; gap: 6px; flex-wrap: wrap; }
    .slbadge { font-size: 9px; letter-spacing: 0.01em; padding: 2px 7px; border-radius: 3px; white-space: nowrap; }
    .slbadge-customer { background: rgba(var(--gold-rgb),0.12); color: var(--gold); border: 1px solid rgba(var(--gold-rgb),0.35); }
    .slbadge-delegate { background: rgba(46,204,113,0.1); color: #2ecc71; border: 1px solid rgba(46,204,113,0.3); }
    .slbadge-viewonly { background: rgba(74,155,196,0.1); color: #4a9fc4; border: 1px solid rgba(74,155,196,0.3); }
    .slbadge-opened   { background: rgba(var(--gold-rgb),0.1); color: var(--gold); border: 1px solid var(--v-border); }
    .slbadge-unseen   { background: rgba(150,150,150,0.08); color: #888; border: 1px solid #555; }
    .slbadge-accepted { background: rgba(46,204,113,0.1); color: #2ecc71; border: 1px solid rgba(46,204,113,0.3); }
    .slbadge-declined { background: rgba(192,57,43,0.1); color: #e07070; border: 1px solid rgba(192,57,43,0.3); }
    .slbadge-feedback { background: rgba(230,126,34,0.1); color: #e67e22; border: 1px solid rgba(230,126,34,0.3); }
    .slbadge-expired  { background: rgba(127,140,141,0.08); color: #95a5a6; border: 1px solid rgba(127,140,141,0.3); }

    /* ── Item table mobile wrapper — lets the table scroll horizontally
       when descriptions / SKUs are wider than the viewport, and forces
       long words to break instead of pushing the table off the page. */
    /* .items-table-wrap scroll containment is canonical (vantage-document.css). */

    /* ── Section-nav button ──
       Placement and breakpoint are CANONICAL (#action-bar-compact,
       vantage-document.css) so co.html gets the identical control. The
       hamburger, the duplicate mobile status pill and the hand-rolled
       #mob-menu-dropdown that stood here are GONE — see the note in proposal.js
       where the sync pass used to live. */

    /* ── Item table columns ──
       Each <col> is named for what it holds (proposal.js), so a rule keeps
       meaning the same column whether or not the photo or price column is
       rendered. Widths live here, never inline, so the phone rules below can
       restate them without !important. */
    .items-table col.col-photo { width: 60px; }
    .items-table col.col-price { width: 130px; }
    .items-table col.col-qty   { width: 70px; }
    .items-table col.col-total { width: 110px; }

    /* ── Mobile item row: expandable detail ── */

    @media (max-width: 700px) {
      /* ── Action bar ──
         The cluster is NOT hidden here any more. It used to be
         `display:none !important`, which took View History off a phone entirely
         (the chip lives inside .action-bar-right) and left a hand-rolled
         hamburger to carry a hand-copied subset of the same controls.
         VantageDocBar collapses the actions into the canonical row menu at this
         same width, so the chip and the CTA stay on screen and everything else
         is one tap away with the same labels. */
      .action-bar { padding: 0 12px; }
      /* The title's own hide is canonical (.v-preview-bar__title, 700px). */
      .action-bar-logo { gap: 8px; }

      /* Cover / section / area-card / action-button narrow-viewport rules are
         canonical (vantage-document.css @media 700px). Only the proposal's own
         footer band needs a page rule here. */
      .area-footer-row { padding: 14px 2px 4px; gap: 14px; }
      .area-desc-block { padding: 10px 12px 12px; }
      /* An option's discount spans the footer: its name from the left edge,
         its figure at the right, on one line. Sized to the Space Total row it
         was a 174px column, so the name wrapped and its "(-$300.00)" dropped
         under it (Nate, 2026-10-07). The Investment card's phone rule that
         drops a qualifier to its own line is for rows sharing a narrow ledger;
         this row has the card's full width. The Space Total stays right. */
      .area-footer-row .area-total-wrap { flex: 1 1 100%; align-items: stretch; }
      .area-footer-row .area-disc-line .fin-line-qual { display: inline; font-size: inherit; }

      /* ── Compact item table ──
         The price cells are hidden below, so the price <col> goes too: a
         display:none column is not built at all, and the remaining cells line
         up with photo | item | qty | total. Its width was zeroed instead until
         2026-10-01, which left an empty fifth column, and Safari's fixed table
         layout reads a 0px column as auto: it split the free width between
         Item and that empty column, so a phone showed a squeezed Item column
         and a blank band down the right of every space (Nate's screenshot;
         measured in WebKit, Item 101px and 101px empty). */
      .items-table { min-width: 0; table-layout: fixed; width: 100%; }
      .items-table col.col-photo { width: 40px; }
      .items-table col.col-price { display: none; }
      .items-table col.col-qty   { width: 32px; }
      /* 84px holds "Saved $12,345.67" on one line at 9px (measured 76px). */
      .items-table col.col-total { width: 84px; }
      .items-table td:first-child { padding: 8px 3px 8px 4px; }
      /* Hide ONLY the unit-price column (header + cells) by class — robust
         whether or not the price column is present in this client view. */
      .item-price { display: none; }
      .item-sub-price-compact { display: block; }
      .items-table td { padding: 8px 4px; vertical-align: middle; }
      .items-table th { padding: 6px 4px; font-size: 9px; letter-spacing: 0.01em; }
      /* Photo: tighter */
      .item-thumb { width: 34px; height: 28px; }
      .item-thumb-placeholder { width: 34px; height: 28px; font-size: 12px; }
      /* Brand + SKU + names: compact, single-line with ellipsis */
      .item-brand {display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;}
      /* Model / name: wrap to a max of two lines (ellipsis only past line 2)
         and break long unbroken SKUs so they never overflow the column. */
      .item-model, .item-name {
        font-size: 12px; max-width: 100%; line-height: 1.3;
        white-space: normal; overflow-wrap: anywhere; word-break: break-word;
        display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
      }
      /* A material's description is hidden by default; shown when the row is
         expanded. A labor, fee or expense line has no description row: its
         description is its name (proposal.js quietLineHtml). */
      .item-desc, .item-client-note { display: none; }
      .item-row.expanded .item-desc,
      .item-row.expanded .item-client-note,
      .attach-row.expanded .item-desc,
      .attach-row.expanded .item-client-note { display: block; margin-top: 4px; font-size: 11px; line-height: 1.45; word-break: break-word; white-space: normal; }
      /* Qty: small + centered, clearly its own column */
      .item-qty { display: table-cell; text-align: center; font-size: 11px; color: color-mix(in srgb, var(--gold) 70%, transparent); padding: 8px 1px !important; }
      /* Total column: right-aligned, no-wrap, room reserved */
      .item-total { white-space: nowrap; text-align: right; font-size: 12px; padding: 8px 6px 8px 2px !important; }
      /* Saved $X is always one line (Nate, 2026-10-01): no smiley on a phone, and
         flush right as a flex row, so a figure wider than the column runs left
         into the qty column instead of wrapping under itself. */
      .item-total-savings { font-size: 9px; display: flex; justify-content: flex-end; white-space: nowrap; }
      .item-total-savings [data-vi-icon] { display: none; }
      /* Customer Furnished wraps to two lines here, and a wrapped inline-block
         takes the column's full width, padding it with empty space. min-content
         sizes it to its longest word instead (Nate, 2026-10-02). */
      .item-total .item-type-badge { width: min-content; }
      /* Attachment (child) rows: shrink the indent and the child thumbs */
      .attach-spacer { padding: 0 0 0 4px !important; }
      .attach-spacer::after { left: 14px; top: 0; bottom: 50%; width: 6px; }
      .attach-desc { padding-left: 4px !important; }
      .attach-desc-inner { gap: 6px; }
      .attach-row .item-thumb { width: 26px !important; height: 22px !important; }
      .attach-row .item-thumb-placeholder { width: 26px !important; height: 22px !important; font-size: 10px !important; }
      /* Expand indicator on item rows */
      .items-table tbody .item-row { cursor: pointer; }
      .items-table tbody .item-row td:nth-child(2)::after {
        content: '›'; float: right; opacity: 0.3; font-size: 16px; line-height: 1; transition: transform 0.2s; margin-left: 4px;
      }
      .items-table tbody .item-row.expanded td:nth-child(2)::after { transform: rotate(90deg); opacity: 0.6; }
    }

    /* ── About Us section — always dark, uses CSS vars so brand colors apply ── */
    .about-section {
      padding: 0 !important;
      background: linear-gradient(to bottom, var(--bg, #162626), var(--bg-mid, #1a2e2e)) !important;
      border-bottom: 1px solid var(--v-border);
    }
    .about-gold-bar { height: 7px; background: var(--gold, #C9A464); width: 100%; }
    .about-inner { padding: 44px 48px 0; max-width: var(--section-max); margin: 0 auto; }
    .about-title { text-align: center; font-size: 42px; font-weight: 300; color: var(--gold, #C9A464); letter-spacing: 6px; margin: 0 0 22px 0; }
    .about-hr { border: none; border-top: 1.5px solid var(--gold-dim, #917040); margin: 0 0 22px 0; }
    .about-stats-row { display: flex; gap: 12px; margin: 0 0 22px 0; }
    .about-stat-box {
      flex: 1; border: 1px solid rgba(var(--gold-rgb,201,164,100),0.25); border-radius: 12px;
      background: linear-gradient(180deg, rgba(var(--gold-rgb,201,164,100),0.06), rgba(var(--gold-rgb,201,164,100),0.02)), var(--bg-mid, #1a2e2e);
      padding: 20px 18px 16px; text-align: center;
    }
    .about-stat-num { font-size: 32px; font-weight: 300; color: var(--gold, #C9A464); line-height: 1.1; margin-bottom: 8px; }
    .about-stat-label { font-size: 12px; color: var(--gold-light, #E6D0A5); line-height: 1.5; }
    @media (max-width: 600px) {
      .about-inner { padding: 36px 20px 0; }
      .about-title { font-size: 28px; letter-spacing: 4px; }
      .about-stats-row { flex-direction: column; gap: 10px; }
      .about-stat-box { flex: none; width: 100%; }
      .about-stat-num { font-size: 26px; }
    }
    .about-body-text { font-size: 15px; font-weight: 300; color: var(--gold-light, #E6D0A5); line-height: 1.8; margin: 0 0 14px 0; }
    .about-brands-title { text-align: center; font-size: 20px; font-weight: 300; color: var(--gold, #C9A464); letter-spacing: 4px; margin: 0 0 14px 0; }
    .about-brands-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; padding-bottom: 8px; }
    .about-brand-tag {
      border: 1px solid rgba(var(--gold-rgb,201,164,100),0.25); border-radius: 20px; padding: 6px 18px;
      font-size: 13px; color: var(--gold-light, #E6D0A5);
      background: rgba(var(--gold-rgb,201,164,100),0.05);
    }
    .about-bottom-bar { height: 7px; background: var(--gold, #C9A464); width: 100%; margin-top: 36px; }

    /* ── Print / PDF export ── */
    @media print {
      .action-bar, .cover-scroll-hint,
      .btn-changes, .btn-decline,
      /* The local #toast was retired for the canonical toast (C12); hide the
         canon's wrap instead or toasts would print. */
      #vToastWrap, .v-toast-wrap,
      .modal-overlay, .proposal-nav,
      #snapshot-banner, .admin-flags-banner,
      /* Submit-mode review chrome is admin-only and must never print. */
      .submit-mode-bar, .admin-submit-end,
      /* Portal/admin chrome must never appear in a printed/exported PDF —
         this also covers the logged-in admin's window.print() export:
         #vsb / #vsb-toggle / #vsb-appbar = the shared shell (vantage-sidebar.js),
         which this page now mounts for BOTH staff and customers,
         #vantage-alert-capsule-stack = the alert capsule stack
         (vantage-alert-capsule.js; the session guard renders into it).

         #vpn-sidebar / #vpn-topbar / #vcl-sidebar were listed here too — the
         retired vantage-portal-nav rail and the legacy client mobile nav. This
         page loads neither any more, so hiding them was hiding nothing. */
      #vsb, #vsb-toggle, #vsb-appbar,
      #vantage-alert-capsule-stack { display: none !important; }
      /* The staff rail offsets the body via padding-left:var(--sb-w), injected with
         !important by vantage-sidebar.js. Zero the width vars in print so the body
         collapses to full width in BOTH expanded and collapsed (body.sb-off) states —
         cleaner and more robust than fighting selector specificity. */
      :root { --sb-w: 0px !important; --sb-cw: 0px !important; }
      /* Nav is hidden in print — drop the sidebar offsets so the cover, company
         summary, and content sections center on the page instead of being pushed
         right into the (now absent) nav gutter. */
      body.has-proposal-nav .section-inner { margin-left: auto !important; margin-right: auto !important; }
      body.has-proposal-nav .area-section-content { margin-left: auto !important; margin-right: auto !important; }
      body.has-proposal-nav .cover { padding-left: 40px !important; padding-right: 40px !important; }
      body.has-proposal-nav .about-inner { margin-left: auto !important; margin-right: auto !important; }
      body.has-proposal-nav .proposal-actions-inner { margin-left: auto !important; margin-right: auto !important; }
      body.has-proposal-nav .contract-signature-record { margin-left:auto !important; margin-right:auto !important; }
      .section { padding: 20px 40px; }
      .section-inner { background: white !important; border: 1px solid #ddd !important; border-radius: 8px !important; padding: 32px 40px !important; }
      .area-block { background: white !important; border: 1px solid #ddd !important; border-radius: 6px !important; padding: 20px 24px !important; }

      * { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; }
      html, body { background: white !important; margin: 0; padding: 0; }

      /* Cover stays dark — forced to exactly one page. `vh` is unreliable in
         print (Safari maps it to the screen viewport, not the sheet, which made
         the cover span two pages), so we use a fixed physical height that fits
         within one Letter page's printable area. Overflow is clipped and spacing
         trimmed so the meta block can't spill to page 2. */
      .cover {
        height: auto !important; min-height: 9in !important; max-height: 9.4in !important;
        page-break-after: always; page-break-inside: avoid; overflow: hidden !important;
        padding: 44px 40px !important;
        color: var(--gold-light) !important;
        background: linear-gradient(180deg, var(--v-theme-canvas, var(--bg)) 0%, var(--bg) 60%, var(--bg-mid) 100%) !important;
      }
      .cover-brand { margin-bottom: 26px !important; }
      .cover-brand-logo { margin-bottom: 12px !important; }
      .cover-divider { margin: 16px auto !important; }
      .cover-meta { margin-top: 26px !important; }

      /* Company Summary — forced to exactly one page; spacing/fonts trimmed so
         the TRUSTED BRANDS row can't push onto a second page. */
      .about-section {
        page-break-after: always; page-break-inside: avoid;
        background: linear-gradient(to bottom, var(--bg), var(--bg-mid)) !important;
      }
      .about-inner { padding: 26px 48px 0 !important; }
      .about-title { font-size: 30px !important; margin-bottom: 14px !important; }
      .about-hr { margin: 0 0 14px 0 !important; }
      .about-stats-row { margin: 0 0 14px 0 !important; gap: 10px !important; }
      .about-stat-box { padding: 12px 12px 10px !important; }
      .about-stat-num { font-size: 24px !important; margin-bottom: 5px !important; }
      .about-stat-label { font-size: 10.5px !important; line-height: 1.4 !important; }
      .about-body-text { font-size: 12px !important; line-height: 1.55 !important; margin: 0 0 9px 0 !important; }
      .about-brands-title { font-size: 16px !important; margin: 0 0 10px 0 !important; }
      .about-brand-tag { padding: 4px 13px !important; font-size: 11px !important; }
      .about-bottom-bar { margin-top: 20px !important; }

      /* Design / Spaces section starts on a fresh page after Scope of Work. */
      #dynamic-sections > section:first-child {
        page-break-before: always; break-before: page;
      }

      /* Content sections: white paper */
      .section {
        background: white !important;
        page-break-inside: avoid;
        border-bottom: 1px solid #ddd !important;
        padding: 48px 40px !important;
      }
      /* Keep a floor's title card glued to its first space block so it can't be
         orphaned at the bottom of a page — push both to the next page. */
      .areas-header-section {
        page-break-after: avoid;
        break-after: avoid;
      }
      .areas-header-section + .area-outer-section {
        page-break-before: avoid;
        break-before: avoid;
      }
      .section-title { color: #7a5a2c !important; }
      .scope-content { color: #1a1208 !important; }
      .area-floor-label {opacity: 0.8 !important;}
      .area-name { color: #1a1208 !important; }
      .area-header-row { border-bottom-color: rgba(var(--gold-rgb),0.4) !important; }
      .area-total-row { background: transparent !important; border-top-color: rgba(var(--gold-rgb),0.4) !important; }
      .area-total-value { color: #7a5a2c !important; }
      .items-table th { color: #9a7a52 !important; border-bottom-color: rgba(var(--gold-rgb),0.4) !important; }
      .items-table td { border-bottom-color: #eee !important; }
      .item-model { color: #1a1208 !important; }
      .item-brand, .item-desc { }
      .item-total { color: #7a5a2c !important; }
      .item-qty { color: #6a5038 !important; }
      .item-price-sell { color: #1a1208 !important; }
      .item-thumb { background: #f5f0e8 !important; border-color: rgba(var(--gold-rgb),0.3) !important; }
      .fin-card { background: white !important; border-color: rgba(var(--gold-rgb),0.4) !important; }
      .fin-line { border-bottom-color: #eee !important; }
      .fin-line-label { color: #6a5038 !important; }
      .fin-line-value { color: #1a1208 !important; }
      .fin-line.total .fin-line-label,
      .fin-line.total .fin-line-value { color: #7a5a2c !important; }
      .item-total-period, .item-sub-price-note, .fin-recurring-note { color: #6a5038 !important; }
      .item-sub-price-value { color: #1a1208 !important; }
      .item-recurring { color: #7d3c98 !important; }
      .payment-item { border-bottom-color: #eee !important; }
      .payment-type { color: #1a1208 !important; }
      .payment-due { color: #9a7a52 !important; }
      .payment-amount { color: #7a5a2c !important; }
      .payment-num { border-color: rgba(var(--gold-rgb),0.4) !important; color: #7a5a2c !important; }
      .proposal-actions { background: white !important; border-top-color: rgba(var(--gold-rgb),0.4) !important; }
      .proposal-actions-title { color: #7a5a2c !important; }
      .proposal-actions-sub { color: #6a5038 !important; }
      .btn-accept { }
      .accepted-banner { display: block !important; background: rgba(46,204,113,0.08) !important; border-color: rgba(46,204,113,0.3) !important; }
    }

    /* ── Designs Section ── */

    /* Building group */
    .fp-building-section { margin-bottom: 32px; }
    .fp-building-header {
      display: flex; align-items: center; gap: 10px;
      padding: 10px 0 10px 2px; cursor: pointer; user-select: none;
      border-bottom: 1px solid rgba(var(--gold-dim-rgb),0.18); margin-bottom: 16px;
    }
    .fp-building-header:hover .fp-building-name { color: var(--gold); }
    .fp-building-name {
      font-size: 13px; letter-spacing: 0.01em;
      color: var(--gold-dim-text, var(--gold-dim)); font-weight: 500; flex: 1; transition: color 0.15s;
    }
    .fp-building-chevron {
      font-size: 11px; color: var(--gold-dim-text, var(--gold-dim)); transition: transform 0.2s;
    }
    .fp-building-section.collapsed .fp-building-chevron { transform: rotate(-90deg); }
    .fp-building-section.collapsed .fp-building-body { display: none; }

    /* Individual floor plan card */
    .fp-design-card {
      background: var(--bg-mid);
      border: 1px solid rgba(var(--gold-dim-rgb),0.2);
      border-radius: 10px;
      overflow: hidden;
      margin-bottom: 20px;
    }
    .fp-design-card-header {
      display: flex; align-items: center; gap: 10px;
      padding: 12px 16px; border-bottom: 1px solid rgba(var(--gold-dim-rgb),0.15);
      background: rgba(var(--bg-rgb),0.6); cursor: pointer; user-select: none;
    }
    .fp-card-collapse-btn {cursor: pointer;
      flex-shrink: 0;}
    .fp-design-card.collapsed .fp-card-collapse-btn {transform: rotate(-90deg);}
    .fp-design-card.collapsed .fp-design-layout { display: none; }
    .fp-design-card-name {
      font-size: 14px; font-weight: 400; color: var(--gold); letter-spacing: 0.5px; flex: 1;
    }
    .fp-design-card-level {
      font-size: 10px; letter-spacing: 0.01em;
      color: var(--gold-dim-text, var(--gold-dim)); background: rgba(var(--gold-dim-rgb),0.1);
      padding: 3px 8px; border-radius: 12px;
    }

    /* Layout: the plan beside its panel, or the panel under the plan on a narrow card.
       The card is what the layout answers to, not the window: the card is the window less
       the page's margins, and a 180px panel beside a plan under ~540px wide left a strip
       of plan over an empty block (Nate, 2026-10-15). */
    .fp-design-card { container: fp-card / inline-size; }
    .fp-design-layout { display: flex; }
    /* The plan's box is the plan's shape (--fp-aspect, set by buildFpCard), and grows to the
       panel's height when the panel is the taller: the plan fits inside it (fpSizeCanvas
       fill), so a wide plan never leaves an empty block under it.
       The pointing hand, to point at things on the plan; the closed hand while it is dragged
       (Nate, 2026-10-14). Two fingers on a trackpad move it too (fpAttachZoomPan). */
    .fp-design-canvas-wrap {
      flex: 1; min-width: 0; position: relative; aspect-ratio: var(--fp-aspect, 16 / 10);
      background: var(--bg); overflow: hidden; cursor: pointer;
    }
    .fp-design-canvas-wrap.is-dragging { cursor: grabbing; }
    .fp-design-canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
    /* Zoom buttons in fp card header */
    .fp-zoom-btns {display: flex; gap: 2px; margin-left: auto; flex-shrink: 0;}
    .fp-zoom-btn {cursor: pointer; display: flex; align-items: center;
      justify-content: center; line-height: 1;}
    .fp-zoom-btn:hover { }

    /* ── The panel beside the plan on a wide card ── */
    /* As narrow as the widest control row allows: Icon Size with its SM / MD / LG
       inline (Nate 2026-10-01). The builder's cards use the same width. */
    .fp-design-panel {
      width: 180px; flex-shrink: 0; align-self: flex-start;   /* its own height, so it can stick */
      background: transparent;   /* one color with the card — no floating block */
      border-left: 1px solid rgba(var(--gold-dim-rgb),0.15);
      display: flex; flex-direction: column;
      overflow-y: auto;
      position: sticky; top: var(--v-doc-bar-h, 56px);   /* stays visible when scrolling past a tall floor plan */
      max-height: calc(100vh - var(--v-doc-bar-h, 56px));
    }
    .fp-panel-section {
      padding: 10px;
      border-bottom: 1px solid rgba(var(--gold-dim-rgb),0.1);
    }
    .fp-panel-section:last-child { border-bottom: none; flex: 1; }
    /* A section holds one group of the customer's controls (vantage-fp-viewer.js
       fpViewControls): canonical .v-choice-row / .v-switch-row / .v-seg rows. */

    /* A device's hover preview is THE device preview (design-device-preview.js): the
       canon's hover card, styled in vantage-ui.css. Nothing here. */

    /* The Legend's and the controls' buttons on the plan (vantage-fp-viewer.js fpPanelBar,
       placed by vantage-ui.css, hidden there) and the Legend's own section: only where the plan
       has the card or the screen to itself (below). Beside a wide card's panel the Legend is
       drawn over the plan, as the designer draws it. */
    .fp-legend-section { display: none; }

    /* Where the plan has no room beside it (.is-compact, vantage-fp-viewer.js fpSyncCompact: a
       card under 720px wide; on the whole screen, one under 720px wide or 560px tall, a phone
       either way up). The plan has its whole box and the viewer draws no Legend over it
       (--fp-legend-place: panel). Two buttons over its bottom left open the Legend or the
       controls, one at a time, in a panel of their own under the plan (Nate, 2026-10-16: "two
       buttons that are for legend and controls at the bottom and they expand in a panel of
       their own when clicked on"). */
    .fp-design-card.is-compact .fp-design-layout { flex-direction: column; }
    .fp-design-card.is-compact .fp-design-canvas-wrap { flex: none; --fp-legend-place: panel; }
    .fp-design-card.is-compact .fp-view-bar { display: block; }
    .fp-design-card.is-compact .fp-design-panel {
      display: none; width: 100%; align-self: stretch; position: static; max-height: none; overflow: visible;
      border-left: none; border-top: 1px solid rgba(var(--gold-dim-rgb),0.15);
    }
    .fp-design-card.is-compact[data-fp-open] .fp-design-panel { display: flex; }
    /* No Legend button where the floor has no Legend (none drawn, or the designer's is off) */
    .fp-design-card.is-compact:has([data-fp-legend-rows="0"]) [data-fp-panel-btn="legend"] { display: none; }
    .fp-design-card.is-compact[data-fp-open="legend"] .fp-panel-section:not(.fp-legend-section) { display: none; }
    /* The Legend's rows (vantage-fp-viewer.js fills them, vantage-ui.css styles a row): as many
       across as fit */
    .fp-design-card.is-compact[data-fp-open="legend"] .fp-legend-section {
      display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px 12px;
      border-bottom: none;
    }
    /* The controls in two columns where two fit on a card: the coverage in the first and what
       is drawn in the second, a rule between them in place of the coverage's own line */
    @container fp-card (min-width: 460px) {
      .fp-design-card.is-compact:not(.v-fullscreen)[data-fp-open="controls"] .fp-design-panel {
        display: block; columns: 2; column-gap: 0; column-rule: 1px solid rgba(var(--gold-dim-rgb),0.15);
      }
      .fp-design-card.is-compact:not(.v-fullscreen) .fp-panel-section { break-inside: avoid; }
      .fp-design-card.is-compact:not(.v-fullscreen) .fp-panel-section:nth-child(2) { border-bottom: none; }
    }
    @media print {
      .fp-design-card { break-inside: avoid; }
    }

    /* ── A card on the whole screen (proposal.js setFpFullScreen) ──
       The canon's .v-fullscreen puts it there; this lays the card out inside: its header on
       top, the plan filling the rest. The plan's box is the screen's, not the plan's shape.
       The card is the screen here, so what the screen is shaped like is a media query. */
    .fp-design-card.v-fullscreen { display: flex; flex-direction: column; }
    .fp-design-card.v-fullscreen .fp-design-card-header { cursor: default; flex-shrink: 0; }
    body.v-ui .fp-design-card.v-fullscreen .fp-card-collapse-btn { display: none; }
    .fp-design-card.v-fullscreen .fp-design-layout { flex: 1; min-height: 0; }
    .fp-design-card.v-fullscreen .fp-design-canvas-wrap { min-height: 0; aspect-ratio: auto; }
    .fp-design-card.v-fullscreen .fp-design-panel { position: static; max-height: none; align-self: stretch; }
    /* The plan fills the screen; an open panel takes at most the bottom 45% and scrolls */
    .fp-design-card.v-fullscreen.is-compact .fp-design-canvas-wrap { flex: 1; }
    .fp-design-card.v-fullscreen.is-compact .fp-design-panel { flex-shrink: 0; max-height: 45%; overflow-y: auto; }
    /* A landscape screen (a phone on its side): a slimmer header, and an open panel beside the
       plan, so the plan keeps the screen's height */
    @media (orientation: landscape) {
      .fp-design-card.v-fullscreen.is-compact .fp-design-card-header { padding-top: 6px; padding-bottom: 6px; }
      .fp-design-card.v-fullscreen.is-compact .fp-design-layout { flex-direction: row; }
      .fp-design-card.v-fullscreen.is-compact .fp-design-panel {
        width: 280px; max-height: none; border-top: none; border-left: 1px solid rgba(var(--gold-dim-rgb),0.15);
      }
      /* The Legend's rows are short: its panel is as wide as they are, one under another */
      .fp-design-card.v-fullscreen.is-compact[data-fp-open="legend"] .fp-design-panel { width: auto; }
      .fp-design-card.v-fullscreen.is-compact[data-fp-open="legend"] .fp-legend-section { grid-template-columns: auto; padding-right: 16px; }
    }

    /* ── Rack Layout Section ── */
    .rack-proposal-wrap {
      display: flex;
      flex-direction: column;
      gap: 40px;
    }
    /* Each rack, its title over it, centred on the card at the drawing's own width */
    .rack-layout-block {
      display: flex;
      flex-direction: column;
      gap: 16px;
      align-self: center;
      width: fit-content;
      max-width: 100%;
    }
    .rack-layout-title {
      font-family: var(--font-body);
      font-size: 15px;
      font-weight: 400;
      color: var(--gold);
      letter-spacing: 0.5px;
    }
    /* The drawing's own width, with no backing of its own: the box was wider than the
       drawing and its black backing showed as a band down the right side (Nate,
       2026-10-15). The drawing carries its frame. */
    .rack-svg-wrap {
      border-radius: 10px;
      overflow: hidden;
      box-shadow: 0 6px 32px rgba(0,0,0,0.5);
      width: fit-content;
      max-width: 100%;
    }
    .rack-svg-wrap svg {
      display: block;
      max-width: 100%;
      height: auto;
    }
    /* A rack's gear opens its card on hover or tap (rackGearCard); a tap focuses it, and the
       ring that left round it is for the keyboard only */
    .rack-svg-wrap [data-v-hover-html]:focus:not(:focus-visible) { outline: none; }
    /* Global confirm/prompt dialogs and toasts: ALL CANONICAL, nothing local.
       DELETED HERE, and why each mattered:
       - .v-btn / .v-btn-ghost / .v-btn-primary / .v-btn-danger — this page
         REDEFINED the canonical roles (C6e). Because this <style> follows the
         canon links, the local copies won, so every .v-btn-primary on the page
         rendered as an 11px uppercase letterspaced pill instead of the canonical
         button. .v-btn-ghost is not a real role at all (C32) — it rendered
         unstyled. Use .v-btn-secondary / -primary / -danger from the canon.
       - .v-overlay / .v-modal* — a hand-rolled overlay + frame (C8e); replaced by
         the canonical .modal-overlay > .modal.v-service-modal anatomy.
       - .v-toast* / @keyframes vToastIn — vantage-facelift.css owns .v-toast-wrap
         and .v-toast for body.v-ui.v-face, and vantage-sidebar.js creates
         #vToastWrap and owns VToast. Page CSS may not position toasts (C12). */


    /* ── Comments (Share Preview and the submitted proposal) ───────────────────
       Page layout only: the buttons, banner, drawer, thread rows and table are the
       canonical components (vantage-comment-threads.js renders the thread). */
    /* A line's comment chip (Nate 2026-10-01): pinned to the right edge of the
       item cell, centered on the row, so it never adds to the row's height and
       never touches the brand, model or description. The cell keeps the room it
       needs on its contents (cell padding is the canon's). A line with comments
       always shows its count; the rest show Comment while the row is hovered
       (always, faintly, where there is no hover). */
    .items-table td.cmt-host { position: relative; }
    .items-table td.cmt-host > :not(.cmt-btn) { margin-right: 112px; }
    .items-table td.cmt-host > .cmt-btn {
      position: absolute; right: 16px; top: 50%; transform: translateY(-50%);
    }
    .items-table td.cmt-host > .cmt-btn:not(.has-comments) { opacity: 0; transition: opacity 0.12s ease; }
    .items-table tr:hover td.cmt-host > .cmt-btn,
    .items-table td.cmt-host > .cmt-btn:focus-visible { opacity: 1; }
    @media (hover: none) {
      .items-table td.cmt-host > .cmt-btn:not(.has-comments) { opacity: 0.6; }
    }
    @media (max-width: 760px) {
      .items-table td.cmt-host > :not(.cmt-btn) { margin-right: 44px; }
      .items-table td.cmt-host > .cmt-btn { right: 8px; }
      .items-table td.cmt-host > .cmt-btn:not(.has-comments) .cmt-btn-label { display: none; }
    }
    .area-header-row .cmt-btn { flex-shrink: 0; }
    .fp-design-card-header .cmt-fp-btn { margin-left: auto; flex-shrink: 0; }
    .cmt-placing, .cmt-placing canvas { cursor: crosshair !important; }

    /* A payment schedule that does not fit the chosen options (renderPayments,
       payment-schedule.js resolutionIssues): said in the list, never clamped. */
    .payment-item.payment-issue .payment-num,
    .payment-item.payment-issue .payment-type { color: var(--v-danger, #c0392b); }
    .payment-item.payment-issue .payment-num { border-color: var(--v-danger, #c0392b); }
