/* ===========================================================================
   THE CUSTOMER-FACING QUOTE FLOW  —  /quote/{token}, /accept, /decline
   ===========================================================================

   WHY THIS IS A GLOBAL STYLESHEET AND NOT COMPONENT-SCOPED CSS
   ------------------------------------------------------------
   These three pages share one visual language: .oc-pq is the page grid,
   .oc-pq-card is the panel, .oc-pq-header/.oc-pq-title the masthead,
   .oc-pq-actions the button row. Until now that vocabulary lived in
   Pages/Public/QuoteView.razor.css, which Blazor CSS isolation rewrites to
   `.oc-pq-card[b-<QuoteView's scope>]`. QuoteAccept and QuoteDecline write the
   same class names on their own markup, which carries a DIFFERENT scope
   attribute (QuoteDecline had no .razor.css at all, so no scope attribute at
   any point) — so on the accept and decline pages every one of those rules
   silently missed and the markup rendered as unstyled blocks: no card, no
   masthead, and buttons at their raw intrinsic height.

   That is the same defect class this file's phone rules exist to fix, on the
   same three routes, so the shared chrome moves here — the pattern the Portal
   already uses for a page family (oc-quoting-guided.css,
   oc-quoting-walkthrough.css, oc-knowledgebase.css). Nothing outside these
   three pages uses an `oc-pq-` class, and every selector below is rooted in
   one, so this file cannot reach anything else.

   PHONE IS THE PRIMARY DEVICE HERE. A customer opens /quote/{token} from a
   link in an email, overwhelmingly on a phone, and presses Accept there. The
   @media block at the bottom is therefore not a courtesy — it is the main
   rendering path. Colors are `--oc-*` tokens only, so light and dark both
   follow the theme.
   =========================================================================== */

.oc-pq {
    display: grid;
    gap: var(--oc-space-5);
}

/* ── Masthead ─────────────────────────────────────────────────────────── */

.oc-pq-header {
    background: var(--oc-surface);
    border: 1px solid var(--oc-gray-200);
    border-radius: var(--oc-radius-lg);
    padding: var(--oc-space-6) var(--oc-space-5);
    box-shadow: var(--oc-shadow-xs);
}

.oc-pq-eyebrow {
    color: var(--oc-gray-500);
    font-size: var(--oc-fs-xs);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin: 0 0 var(--oc-space-2);
}

.oc-pq-title {
    font-size: var(--oc-fs-h1);
    line-height: var(--oc-lh-tight);
    margin: 0 0 var(--oc-space-2);
    color: var(--oc-gray-900);
}

.oc-pq-subtitle {
    margin: 0;
    color: var(--oc-gray-600);
    font-size: var(--oc-fs-body);
}

.oc-pq-expires {
    color: var(--oc-gray-500);
}

/* ── Cards ────────────────────────────────────────────────────────────── */

.oc-pq-card {
    background: var(--oc-surface);
    border: 1px solid var(--oc-gray-200);
    border-radius: var(--oc-radius-lg);
    padding: var(--oc-space-5);
    box-shadow: var(--oc-shadow-xs);
}

.oc-pq-card-head h2 {
    margin: 0 0 var(--oc-space-4);
    font-size: var(--oc-fs-h2);
    color: var(--oc-gray-900);
}

.oc-pq-lines {
    display: grid;
    gap: var(--oc-space-5);
}

.oc-pq-line-category {
    margin: 0 0 var(--oc-space-3);
    font-size: var(--oc-fs-h3);
    color: var(--oc-gray-700);
}

/* ── Line table (desktop shape — unchanged) ───────────────────────────── */

/* The wrapper is the escape valve for the in-between widths (a tablet, a
   landscape phone) where the table is still a table: wide content scrolls
   inside its own box instead of pushing the document sideways. */
.oc-pq-table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.oc-pq-line-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--oc-fs-sm);
}

.oc-pq-line-table th,
.oc-pq-line-table td {
    text-align: left;
    padding: var(--oc-space-3) var(--oc-space-2);
    border-bottom: 1px solid var(--oc-gray-100);
    vertical-align: top;
}

.oc-pq-line-table th {
    background: var(--oc-gray-50);
    color: var(--oc-gray-600);
    font-weight: 600;
}

.oc-pq-col-num {
    text-align: right;
    white-space: nowrap;
}

.oc-pq-line-name {
    font-weight: 600;
    color: var(--oc-gray-900);
}

.oc-pq-line-desc {
    color: var(--oc-gray-500);
    font-size: var(--oc-fs-xs);
    margin-top: 2px;
}

.oc-pq-line-cadence {
    color: var(--oc-gray-500);
    font-size: var(--oc-fs-xs);
    margin-top: 2px;
}

/* ── Totals ───────────────────────────────────────────────────────────── */

.oc-pq-totals-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--oc-space-3) var(--oc-space-6);
    margin: 0;
}

.oc-pq-totals-grid dt {
    color: var(--oc-gray-600);
    min-width: 0;
}

.oc-pq-totals-grid dd {
    margin: 0;
    text-align: right;
    font-weight: 600;
    color: var(--oc-gray-900);
}

/* ── Action row ───────────────────────────────────────────────────────── */

.oc-pq-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--oc-space-3);
    align-items: center;
}

/* The "View PDF" control is an <a> (it opens a document in a new tab), so it
   cannot be an OcButton — and OcButton's own .oc-btn rules are component-scoped,
   so they never reached this anchor. It gets the button shape here, the same way
   oc-architecture-map.css shapes its raw .oc-btn anchors. */
.oc-pq-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.6rem 1rem;
    border: 1px solid transparent;
    border-radius: var(--oc-radius-md);
    font-family: var(--oc-font-sans);
    font-size: var(--oc-fs-body);
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    transition: background-color var(--oc-dur-fast) var(--oc-ease),
                border-color var(--oc-dur-fast) var(--oc-ease),
                color var(--oc-dur-fast) var(--oc-ease);
}

.oc-pq-btn:focus-visible {
    outline: none;
    box-shadow: var(--oc-shadow-focus);
}

.oc-pq-btn-ico {
    font-size: 0.95em;
}

.oc-pq-btn-secondary {
    background: var(--oc-surface);
    color: var(--oc-gray-900);
    border-color: var(--oc-gray-300);
    box-shadow: var(--oc-shadow-xs);
}

.oc-pq-btn-secondary:hover {
    background: var(--oc-gray-50);
    border-color: var(--oc-gray-500);
    color: var(--oc-gray-900);
}

.oc-pq-pdf-pending {
    color: var(--oc-gray-500);
    font-style: italic;
    font-size: var(--oc-fs-sm);
}

.oc-pq-empty {
    color: var(--oc-gray-500);
    font-style: italic;
}

/* ── Terminal states (expired / declined / accepted confirmations) ─────── */

.oc-pq-status {
    text-align: center;
    padding: var(--oc-space-8) var(--oc-space-5);
}

.oc-pq-status-heading {
    margin: 0 0 var(--oc-space-3);
    color: var(--oc-gray-900);
    font-size: var(--oc-fs-h1);
}

.oc-pq-status-meta {
    color: var(--oc-gray-500);
    margin: 0;
}

.oc-pq-status-error .oc-pq-status-heading {
    color: var(--oc-danger);
}

.oc-pq-loading {
    text-align: center;
    padding: var(--oc-space-7);
    color: var(--oc-gray-500);
}

/* ── Quote-document additions (unified quote documents, Phase 4) ───────── */

.oc-pq-state-banner {
    margin-top: var(--oc-space-4);
    padding: var(--oc-space-3) var(--oc-space-4);
    border-radius: var(--oc-radius-md);
    font-size: var(--oc-fs-sm);
    font-weight: 600;
}

.oc-pq-state-expired {
    background: var(--oc-warning-bg);
    color: var(--oc-warning-text);
}

.oc-pq-state-declined {
    background: var(--oc-danger-bg);
    color: var(--oc-danger-text);
}

.oc-pq-group-subtitle {
    margin: calc(-1 * var(--oc-space-3)) 0 var(--oc-space-3);
    color: var(--oc-gray-500);
    font-size: var(--oc-fs-sm);
}

.oc-pq-amount-muted {
    color: var(--oc-text-muted);
}

.oc-pq-counterparty {
    color: var(--oc-text-muted);
    font-size: var(--oc-fs-xs);
    font-style: italic;
    margin-top: 2px;
}

.oc-pq-group-total-label {
    text-align: right;
    color: var(--oc-gray-600);
    font-weight: 600;
}

.oc-pq-group-total {
    font-weight: 700;
    color: var(--oc-gray-900);
}

.oc-pq-totals-grid dt.oc-pq-total-due,
.oc-pq-totals-grid dd.oc-pq-total-due {
    font-weight: 700;
    color: var(--oc-gray-900);
    font-size: var(--oc-fs-body);
}

.oc-pq-permo {
    color: var(--oc-text-muted);
    font-weight: 400;
    font-size: var(--oc-fs-xs);
    margin-left: 2px;
}

.oc-pq-notes {
    margin: var(--oc-space-4) 0 0;
    color: var(--oc-gray-600);
    font-size: var(--oc-fs-sm);
    white-space: pre-line;
}

/* ── Ship to ────────────────────────────────────────────────────────────
   The delivery address, rendered only when the quote carries one. Set as an
   address block rather than prose: tight leading so the lines read as one
   unit, and the name at body weight so it does not compete with the card
   heading directly above it. */

.oc-pq-shipto-name {
    margin: 0;
    font-weight: 600;
    color: var(--oc-gray-900);
}

.oc-pq-shipto-line {
    margin: 0;
    color: var(--oc-gray-700);
    line-height: 1.45;
}

.oc-pq-shipto-note {
    margin: var(--oc-space-4) 0 0;
    color: var(--oc-text-muted);
    font-size: var(--oc-fs-sm);
}

/* ── Quiet monthly section + the big Total Monthly bar ─────────────────── */

.oc-pq-monthly .oc-pq-card-head h2 {
    color: var(--oc-gray-600);
    font-size: var(--oc-fs-h3);
}

/* Names-only list (document RecurringDisplayMode = TotalOnly). */
.oc-pq-monthly-names {
    list-style: none;
    margin: 0;
    padding: 0;
}

.oc-pq-monthly-names li {
    display: flex;
    gap: var(--oc-space-2);
    align-items: baseline;
    flex-wrap: wrap;
    padding: var(--oc-space-2) var(--oc-space-2);
    border-bottom: 1px solid var(--oc-gray-100);
}

.oc-pq-monthly-names .oc-pq-line-name {
    font-weight: 500;
    color: var(--oc-gray-700);
}

/* Muted itemized table (document Itemized): quieter than the one-time table. */
.oc-pq-table-muted th {
    background: transparent;
    color: var(--oc-gray-500);
}

.oc-pq-table-muted td,
.oc-pq-table-muted .oc-pq-line-name {
    color: var(--oc-text-muted);
    font-weight: 400;
}

/* ── ROW INK BY LINE KIND (CEO 2026-08-22) ──────────────────────────────────
   "licence/SaaS lines render in a GREEN font and one-time fees in BLUE, so the
   three kinds are distinguishable at a glance." The class comes from
   LineKindCss and lands on the row (a <tr> in the itemized table, an <li> in the
   names-only list). No class for LineKind.Default, so an unclassified document
   is byte-identical to what it was.

   ⚠️ SPECIFICITY, MEASURED — this is why the rules are shaped like this. The
   muted-monthly rule two blocks up is a TWO-CLASS selector:
       .oc-pq-table-muted td            (0,2,1)
       .oc-pq-table-muted .oc-pq-line-name  (0,2,0)
   and MONTHLY rows are exactly where the licences are, so a single-class kind
   rule would lose on the very rows this feature exists for and look like it did
   nothing. These beat both:
       .oc-pq-line-table tr.oc-kind-* td:not(.oc-pq-amount-muted)   (0,3,2)
       .oc-pq-line-table tr.oc-kind-* .oc-pq-line-name              (0,3,1)
   This is a plain stylesheet, not scoped CSS, so nothing invisible is helping —
   the class count has to do the work on its own. (`.oc-pq-amount-muted` inside
   :not() counts toward specificity; that is deliberate, not accidental.)

   WHY THE AMOUNT COLUMN IS EXCLUDED. .oc-pq-amount-muted means "your partner
   pays this, it is not in your total" on a document a customer signs. It sits at
   (0,1,0) and any kind rule that touched that cell would erase the signal. So an
   amount the customer does not owe stays muted whatever kind its line is; every
   other cell of the row takes the ink. The row's own secondary text
   (.oc-pq-line-desc, .oc-pq-counterparty) keeps its own colour for the same
   reason — it is set on the element, so it outranks the inherited ink.

   Tokens only (--oc-emerald-600 #15803d -> #4ade80, --oc-info #2563eb ->
   #6ea8ff): this page has a dark mode too, and a raw hex would not flip. */
.oc-pq-line-table tr.oc-kind-software td:not(.oc-pq-amount-muted),
.oc-pq-line-table tr.oc-kind-software .oc-pq-line-name,
.oc-pq-monthly-names li.oc-kind-software .oc-pq-line-name {
    color: var(--oc-emerald-600);
}

.oc-pq-line-table tr.oc-kind-fee td:not(.oc-pq-amount-muted),
.oc-pq-line-table tr.oc-kind-fee .oc-pq-line-name,
.oc-pq-monthly-names li.oc-kind-fee .oc-pq-line-name {
    color: var(--oc-info);
}

/* The big Total Monthly bar. Informational (never money due today) → info hue. */
.oc-pq-monthly-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--oc-space-2);
    margin-top: var(--oc-space-4);
    padding: var(--oc-space-3) var(--oc-space-4);
    border: 1px solid var(--oc-info);
    border-left-width: 5px;
    border-radius: var(--oc-radius-md);
    background: var(--oc-info-bg);
}

.oc-pq-monthly-bar-label {
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-size: var(--oc-fs-xs);
    font-weight: 700;
    color: var(--oc-info-text);
}

.oc-pq-monthly-bar-value {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--oc-info-text);
}

/* Totals card: the monthly line reads as the second headline figure. */
.oc-pq-totals-grid dt.oc-pq-total-monthly,
.oc-pq-totals-grid dd.oc-pq-total-monthly {
    font-weight: 700;
    color: var(--oc-info-text);
}

/* ── Line Grouping (2026-08-22): sub-groups inside a section card ───────────
   A section card can now hold Depth-1 sub-groups (stations), each with its own
   rows and its own subtotal, with the SECTION's subtotal re-emitted after
   them. The sub-block indents with a quiet left rule so the hierarchy reads
   without stealing weight from the money column. */

.oc-pq-subgroup {
    margin-top: var(--oc-space-4);
    padding-left: var(--oc-space-4);
    border-left: 2px solid var(--oc-gray-100);
}

.oc-pq-subgroup-title {
    margin: 0 0 var(--oc-space-2);
    font-size: var(--oc-fs-body);
    font-weight: 600;
    color: var(--oc-gray-700);
}

/* Monthly sub-group headers stay quieter than one-time ones, matching the
   muted treatment their section already carries. */
.oc-pq-monthly .oc-pq-subgroup-title {
    color: var(--oc-gray-600);
    font-weight: 500;
}

.oc-pq-subgroup-subtitle {
    margin: calc(-1 * var(--oc-space-1)) 0 var(--oc-space-2);
    color: var(--oc-gray-500);
    font-size: var(--oc-fs-xs);
}

/* Compact subtotal line under a MONTHLY sub-group (its muted table renders no
   tfoot). Muted, tabular digits, label left / money right. */
.oc-pq-subgroup-subtotal {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--oc-space-3);
    margin-top: var(--oc-space-1);
    padding: var(--oc-space-2) var(--oc-space-2) 0;
    border-top: 1px solid var(--oc-gray-200);
    font-size: var(--oc-fs-sm);
}

.oc-pq-subgroup-subtotal-label {
    color: var(--oc-gray-600);
    font-weight: 600;
    min-width: 0;
}

.oc-pq-subgroup-subtotal-value {
    font-weight: 700;
    color: var(--oc-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* The whole-section subtotal, re-emitted AFTER the sub-groups it sums. Reuses
   the tfoot's label/value classes so the two spellings cannot drift. */
.oc-pq-section-subtotal {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--oc-space-3);
    margin-top: var(--oc-space-3);
    padding: var(--oc-space-3) var(--oc-space-2) 0;
    border-top: 1px solid var(--oc-gray-200);
}

.oc-pq-section-subtotal .oc-pq-group-total {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ── Licences ride with their hardware (CEO 2026-08-22): the BLOCK subtotal ──
   A station block closes with TWO figures that are NEVER summed — its one-time
   money and its monthly money, in the same order and the same two inks the PDF
   prints them in (BrandedInvoiceRenderer.ComposeDualSubtotal). No new subtotal
   object: the row IS .oc-pq-section-subtotal, and both figures wear the tfoot's
   own .oc-pq-group-total, so a change to the page's subtotal look reaches all
   three places at once.

   The pair is wrapped so `justify-content: space-between` still splits LABEL
   from MONEY rather than spreading three children across the row, and the wrap
   is allowed so a long station name plus two figures degrades on a phone (the
   primary device here) instead of overflowing — each figure keeps its own
   nowrap from the rule above. */

.oc-pq-block-subtotal-values {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: baseline;
    gap: var(--oc-space-1) var(--oc-space-3);
}

/* Decorative only — aria-hidden in the markup, so a screen reader hears two
   separate figures rather than one run-on amount. */
.oc-pq-block-subtotal-sep {
    color: var(--oc-text-muted);
    font-weight: 400;
}

/* The monthly half takes the informational hue the TOTAL MONTHLY bar and the
   Totals row already use, so "ongoing, not due today" reads the same way
   wherever it appears on this page. */
.oc-pq-block-monthly {
    color: var(--oc-info-text);
}

/* ── The per-section payer split (CEO 2026-08-23) ─────────────────────
   A section a partner is paying into closes with TWO labelled rows — "Merchant
   Paid" over "Partner Paid" — instead of one figure preceded by a "Less items
   your partner is paying for" deduction row.

   The PARTNER row is quiet: it wears the same muted ink the partner-paid LINE
   rows above it already use (.oc-pq-amount-muted / .oc-pq-counterparty), so the
   eye lands on the merchant's money — the only figure they owe. It is also the
   only row here that is not a border-topped seam: the merchant row above it
   already drew that seam, and a second one would read as two separate sections
   rather than one section closing with a split.

   Applied to a <tr> in the ungrouped tfoot and to a <div> in the block layout,
   which is why the ink is set on the element itself and inherited rather than
   on a child selector. */

.oc-pq-partner-subtotal,
.oc-pq-partner-subtotal .oc-pq-group-total,
.oc-pq-partner-subtotal .oc-pq-group-total-label {
    color: var(--oc-text-muted);
}

.oc-pq-partner-subtotal.oc-pq-section-subtotal {
    margin-top: 0;
    padding-top: var(--oc-space-1);
    border-top: 0;
}

/* The monthly section states its split between its rows and its TOTAL MONTHLY
   bar. Neither figure carries "/mo": nothing inside that section does — the
   section title states the cadence once — and the bar below carries it for the
   whole section. The bar supplies the bottom seam, so this pair needs none. */
.oc-pq-monthly-payer {
    border-top: 0;
    margin-top: 0;
    padding-top: var(--oc-space-1);
}

/* The MERCHANT row of that pair draws the seam. Selected by NOT being the partner
   row rather than by :first-of-type, which would have keyed on being the first
   <div> among the card children - true only in the names-only (TotalOnly) branch,
   where the rows above render as a <ul>. In the itemized branch the table wrapper
   is a div and takes that match instead, so the seam would silently vanish on half
   the documents and appear on the other half. */
.oc-pq-monthly-payer:not(.oc-pq-partner-subtotal) {
    margin-top: var(--oc-space-3);
    padding-top: var(--oc-space-3);
    border-top: 1px solid var(--oc-gray-200);
}

/* A grouped document has no monthly SECTION to hang the bar under, so the bar
   renders once after the whole block stack as a direct child of the .oc-pq page
   grid. The grid's own gap already spaces it; the in-card margin would double
   that up. */
.oc-pq-monthly-bar-standalone {
    margin-top: 0;
}

/* ── Accept / decline forms ───────────────────────────────────────────── */

.oc-pq-field {
    display: grid;
    gap: var(--oc-space-2);
    margin-bottom: var(--oc-space-4);
}

.oc-pq-field label {
    font-weight: 600;
    color: var(--oc-gray-700);
    font-size: var(--oc-fs-sm);
}

.oc-pq-input {
    width: 100%;
    padding: var(--oc-space-3) var(--oc-space-3);
    border: 1px solid var(--oc-gray-300);
    border-radius: var(--oc-radius-md);
    font-size: var(--oc-fs-body);
    font-family: var(--oc-font-sans);
    background: var(--oc-surface);
    color: var(--oc-gray-900);
    transition: border-color .15s ease, box-shadow .15s ease;
}

.oc-pq-input:focus {
    outline: none;
    border-color: var(--oc-orange);
    box-shadow: var(--oc-shadow-focus);
}

.oc-pq-signature {
    font-family: "Brush Script MT", "Segoe Script", cursive;
    font-size: 1.25rem;
}

.oc-pq-hint {
    color: var(--oc-gray-500);
    font-size: var(--oc-fs-xs);
}

.oc-pq-error {
    background: var(--oc-danger-100);
    color: var(--oc-danger);
    padding: var(--oc-space-3) var(--oc-space-4);
    border-radius: var(--oc-radius-md);
    margin-bottom: var(--oc-space-4);
    font-size: var(--oc-fs-sm);
}

.oc-pq-success {
    text-align: center;
}

/* Gated payment-method notice on the accept form. */
.oc-pq-payment-note {
    display: flex;
    gap: var(--oc-space-3);
    align-items: flex-start;
    margin: var(--oc-space-4) 0 var(--oc-space-1);
    padding: 14px 16px;
    border: 1px solid var(--oc-orange-100);
    background: var(--oc-orange-50);
    border-radius: var(--oc-radius-md);
}

.oc-pq-payment-note i {
    color: var(--oc-orange);
    font-size: 1.25rem;
    line-height: 1.4;
    flex: 0 0 auto;
}

.oc-pq-payment-note > div {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.oc-pq-payment-note strong {
    color: var(--oc-text);
    font-size: 0.95rem;
}

.oc-pq-payment-note span {
    color: var(--oc-gray-600);
    font-size: 0.85rem;
    line-height: 1.4;
}

/* ===========================================================================
   PHONE (<= 640px) — the primary rendering path for this flow.
   ===========================================================================
   Four things have to hold at 390px:
     1. the line table reads as a card stack, not a squeezed four-column grid;
     2. both totals — one-time and monthly — survive with their subtitles;
     3. Accept / View PDF / Decline are full-width, >= 44px tall, unclipped;
     4. nothing pushes the document sideways.
   =========================================================================== */

@media (max-width: 640px) {

    .oc-pq-card,
    .oc-pq-header {
        padding: var(--oc-space-4);
    }

    /* ── 1. The line table becomes a card stack ────────────────────────────
       Every row renders as:

           Product name
           product description
           2 x $365.00                              $730.00

       The elements are re-laid-out with `display`, which drops their implicit
       table roles from the accessibility tree — so QuoteView.razor states the
       roles explicitly (role="rowgroup"/"row"/"columnheader"/"cell"). The
       header row is kept in the tree and moved off-screen rather than
       display:none'd, so a screen reader still announces the column names.  */
    .oc-pq-line-table,
    .oc-pq-line-table thead,
    .oc-pq-line-table tbody,
    .oc-pq-line-table tfoot,
    .oc-pq-line-table tr,
    .oc-pq-line-table th,
    .oc-pq-line-table td {
        display: block;
    }

    .oc-pq-line-table thead {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
        border: 0;
    }

    .oc-pq-line-table tbody tr {
        display: grid;
        grid-template-columns: auto auto minmax(0, 1fr) auto;
        align-items: baseline;
        column-gap: var(--oc-space-2);
        row-gap: var(--oc-space-1);
        padding: var(--oc-space-3) 0;
        border-bottom: 1px solid var(--oc-gray-100);
    }

    .oc-pq-line-table tbody td {
        padding: 0;
        border-bottom: 0;
    }

    /* A component sub-row can carry no quantity and no unit price. An empty
       grid item would still claim its column and open a gap before the
       amount, so collapse it. */
    .oc-pq-line-table tbody td:empty {
        display: none;
    }

    .oc-pq-cell-item {
        grid-column: 1 / -1;
    }

    .oc-pq-cell-qty {
        grid-column: 1;
        text-align: left;
    }

    .oc-pq-cell-unit {
        grid-column: 2;
        text-align: left;
    }

    /* "2 x $365.00" — the multiplication sign is drawn only when BOTH sides
       are present, so a component row showing a bare price never leads with a
       dangling operator. */
    .oc-pq-cell-qty:not(:empty) + .oc-pq-cell-unit:not(:empty)::before {
        content: "\00d7\00a0";
        color: var(--oc-text-muted);
    }

    .oc-pq-cell-qty,
    .oc-pq-cell-unit {
        color: var(--oc-text-muted);
    }

    .oc-pq-cell-amount {
        grid-column: 4;
        justify-self: end;
        text-align: right;
        font-weight: 600;
    }

    /* Money reads down the right edge only if the digits share a width. */
    .oc-pq-col-num,
    .oc-pq-group-total,
    .oc-pq-monthly-bar-value,
    .oc-pq-totals-grid dd {
        font-variant-numeric: tabular-nums;
    }

    .oc-pq-cell-item .oc-pq-line-name {
        font-size: var(--oc-fs-body);
        line-height: var(--oc-lh-snug);
    }

    /* Sub-group blocks: shallower indent at phone width so the card-stack rows
       keep their room; the subtotal lines already stack label/money on one
       flex row and need no re-layout. */
    .oc-pq-subgroup {
        padding-left: var(--oc-space-3);
    }

    /* The group subtotal row: label left, money right, on one line. */
    .oc-pq-line-table tfoot tr {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: var(--oc-space-3);
        padding-top: var(--oc-space-3);
        border-bottom: 0;
        border-top: 1px solid var(--oc-gray-200);
    }

    .oc-pq-line-table tfoot td {
        padding: 0;
        border-bottom: 0;
    }

    .oc-pq-group-total-label {
        text-align: left;
    }

    /* ── 2. Totals stay legible and unambiguous ──────────────────────────
       The one-time / monthly split IS the document, so at phone width each
       pair becomes its own block: the label (which wraps freely) above the
       figure (which never wraps), with the two headline figures scaled up.
       The column gap is 0 and the LABEL carries it as padding instead, so the
       rules under the headline pairs run unbroken across the pair — a rule with
       a gap in its middle reads as two unrelated numbers rather than one line of
       the document.  */
    .oc-pq-totals-grid {
        grid-template-columns: minmax(0, 1fr) auto;
        column-gap: 0;
        row-gap: var(--oc-space-2);
    }

    .oc-pq-totals-grid dt {
        padding-right: var(--oc-space-3);
    }

    .oc-pq-totals-grid dd {
        white-space: nowrap;
    }

    .oc-pq-totals-grid dt.oc-pq-total-due,
    .oc-pq-totals-grid dd.oc-pq-total-due,
    .oc-pq-totals-grid dt.oc-pq-total-monthly,
    .oc-pq-totals-grid dd.oc-pq-total-monthly {
        font-size: var(--oc-fs-h3);
        line-height: var(--oc-lh-snug);
        padding-top: var(--oc-space-2);
        border-top: 1px solid var(--oc-gray-200);
    }

    .oc-pq-monthly-bar-value {
        font-size: var(--oc-fs-h2);
    }

    /* ── 3. One full-width, comfortably tappable control per line ───────── */
    .oc-pq-actions {
        flex-direction: column;
        align-items: stretch;
        gap: var(--oc-space-3);
    }

    /* .oc-btn is OcButton's own component-scoped class; min-height and width
       are properties it never sets, so this adds to its look rather than
       racing it on specificity. 44px is the iOS/WCAG touch-target floor —
       OcButton's md size is 36px, which Accept must not be. */
    .oc-pq-actions .oc-btn,
    .oc-pq-actions .oc-pq-btn {
        width: 100%;
        min-height: 44px;
    }

    /* Accept is the decision this page exists for: taller and larger-typed than
       the two controls under it. It is already first in the DOM. */
    .oc-pq-actions .oc-pq-accept {
        min-height: 52px;
        font-size: var(--oc-fs-h3);
    }
}
