/* QuotingHub app shell + phone layout.
 *
 * Loaded on every app page AFTER Bootstrap (see src/app_shell.php). Desktop keeps the
 * layouts the pages already had; everything below 768px is laid out for one hand and a
 * thumb: an app bar instead of a page header, 44px touch targets, quotes as cards, and
 * the quote builder's price summary as a bottom bar that opens into a sheet.
 *
 * Brand (2026-10-23): the Bay-Lynx Design System (claude.ai artifact "Bay-Lynx Design
 * System", from the 2017 Brand Standards). Its foundations, taken as they are:
 *  - Bay-Lynx Yellow #FFD600 (Pantone 116 C) and Black (Black 6) carry the brand; yellow is
 *    for action and attention (primary button, active item, bars, single hero numbers),
 *    never a big fill behind text-heavy content; text on yellow is black. Hover #FFE34D,
 *    pressed #E6B800, focus ring yellow at 35%.
 *  - The neutrals are its cool near-black ink ramp (#161a20 ink-750 is our dark).
 *  - Type: Brandon Grotesque for all UI and copy; Outage for display (the product name,
 *    headlines), LOWERCASE ONLY, never under 12pt (.qh-display).
 *  - Radii 3 / 5 / 8 / 12, 8 the default card and button.
 *  - Logos: the supplied artwork only (pictures/BL-Logo_Primary-RGB.png on white or
 *    yellow, BL-Logo_Primary-White.png on dark); never redrawn.
 * QuotingHub keeps light surfaces (the system's dark "cockpit" is LYNX360's product look).
 * Bootstrap's warning colour is mapped onto the brand yellow below, so .btn-warning and
 * .bg-warning are brand yellow everywhere; pages use these tokens instead of hex.
 */
@font-face { font-family: 'Brandon Grotesque'; src: url('../fonts/HVD Fonts - BrandonGrotesque-Light.otf') format('opentype'); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: 'Brandon Grotesque'; src: url('../fonts/HVD Fonts - BrandonGrotesque-Regular.otf') format('opentype'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Brandon Grotesque'; src: url('../fonts/HVD Fonts - BrandonGrotesque-RegularItalic.otf') format('opentype'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Brandon Grotesque'; src: url('../fonts/HVD Fonts - BrandonGrotesque-Medium.otf') format('opentype'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Brandon Grotesque'; src: url('../fonts/HVD Fonts - BrandonGrotesque-Bold.otf') format('opentype'); font-weight: 600 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Brandon Grotesque'; src: url('../fonts/HVD Fonts - BrandonGrotesque-BoldItalic.otf') format('opentype'); font-weight: 600 700; font-style: italic; font-display: swap; }
@font-face { font-family: 'Brandon Grotesque'; src: url('../fonts/HVD Fonts - BrandonGrotesque-Black.otf') format('opentype'); font-weight: 800 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'Outage'; src: url('../fonts/Outage-Cut.ttf') format('truetype'); font-weight: 400 900; font-style: normal; font-display: swap; }

:root {
    --qh-dark: #161a20;               /* ink-750 */
    --qh-dark-hover: #262c34;         /* ink-600 */
    --qh-dark-border: #333a44;        /* ink-500 */
    --qh-muted: #9aa3af;              /* ink-200: secondary text on the dark */
    --qh-black: #000;                 /* Black 6: text on yellow */
    --qh-yellow: #ffd600;             /* Bay-Lynx Yellow, Pantone 116 C */
    --qh-yellow-hover: #ffe34d;
    --qh-yellow-press: #e6b800;
    --qh-yellow-soft: #fff8d6;        /* the yellow at 16% on white: a picked or pending row */
    --qh-yellow-ring: rgba(255, 214, 0, .35);
    --qh-on-yellow-muted: #4a4000;    /* second-rank text on a yellow bar (7:1) */
    --qh-bg: #f4f7f6;
    --qh-surface: #fff;
    --qh-border: #dee2e6;
    --qh-text: #212529;
    --qh-text-muted: #6c757d;         /* 4.7:1 on white; #777 and #888 fall short of 4.5:1 */
    --qh-radius: 8px;                 /* the system's default card / button radius */
    --qh-font-body: 'Brandon Grotesque', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --qh-font-display: 'Outage', 'Brandon Grotesque', system-ui, sans-serif;
    --qh-safe-top: env(safe-area-inset-top, 0px);
    --qh-safe-bottom: env(safe-area-inset-bottom, 0px);

    /* Bootstrap, onto the brand: the UI face, the warning colour, the radii. */
    --bs-font-sans-serif: var(--qh-font-body);
    --bs-body-font-family: var(--qh-font-body);
    --bs-warning: #ffd600;
    --bs-warning-rgb: 255, 214, 0;
    --bs-border-radius-sm: 5px;
    --bs-border-radius: 8px;
    --bs-border-radius-lg: 12px;
}
.btn-warning {
    --bs-btn-color: #000; --bs-btn-bg: var(--qh-yellow); --bs-btn-border-color: var(--qh-yellow);
    --bs-btn-hover-color: #000; --bs-btn-hover-bg: var(--qh-yellow-hover); --bs-btn-hover-border-color: var(--qh-yellow-hover);
    --bs-btn-active-color: #000; --bs-btn-active-bg: var(--qh-yellow-press); --bs-btn-active-border-color: var(--qh-yellow-press);
    --bs-btn-disabled-color: #000; --bs-btn-disabled-bg: var(--qh-yellow); --bs-btn-disabled-border-color: var(--qh-yellow);
    --bs-btn-focus-shadow-rgb: 255, 214, 0;
}
.btn-outline-warning {
    --bs-btn-color: #6b5a00; --bs-btn-border-color: var(--qh-yellow);
    --bs-btn-hover-color: #000; --bs-btn-hover-bg: var(--qh-yellow); --bs-btn-hover-border-color: var(--qh-yellow);
    --bs-btn-active-color: #000; --bs-btn-active-bg: var(--qh-yellow-press); --bs-btn-active-border-color: var(--qh-yellow-press);
}
.text-bg-warning, .badge.bg-warning { color: #000 !important; }
/* Display: Outage, the brand's headline face. Lowercase only (the brand rule), never under 12pt. */
.qh-display { font-family: var(--qh-font-display); font-weight: 700; text-transform: lowercase; letter-spacing: .01em; line-height: 1.05; }

/* No pinch or double-tap zoom on the app pages: they are laid out for the phone already,
   and a zoomed-in dashboard is how a fixed bar ends up off screen. Android honours the
   viewport meta (app_shell.php); iOS ignores that but honours touch-action. The quote
   document (generate_pdf.php) does not load this file and stays zoomable on purpose.
   overscroll-behavior stops the rubber-band at the top and bottom of the page: in the
   installed app, dragging down past the top pulled the whole page (app bar included)
   away from the top edge and showed the grey behind it. */
html, body { touch-action: pan-x pan-y; overscroll-behavior-y: none; }

/* ---------- App bar (phone only) ---------- */
.qh-appbar {
    position: sticky;
    top: 0;
    z-index: 1040;
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--qh-dark);
    color: #fff;
    padding: calc(8px + var(--qh-safe-top)) 10px 8px 10px;
    min-height: 56px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .28);
}
.qh-appbar .qh-logo { width: 30px; height: 30px; border-radius: 7px; flex: 0 0 auto; margin-left: 4px; }
.qh-appbar .qh-brand { flex: 1 1 auto; min-width: 0; line-height: 1.15; }
.qh-appbar .qh-title { font-weight: 700; font-size: 1.02rem; letter-spacing: .2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qh-appbar .qh-sub { font-size: .74rem; color: var(--qh-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qh-iconbtn {
    flex: 0 0 auto;
    width: 40px; height: 40px;
    border-radius: 50%;
    border: 0;
    background: rgba(255, 255, 255, .08);
    color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    text-decoration: none;
    font-weight: 700;
    font-size: .9rem;
    letter-spacing: .5px;
}
.qh-iconbtn:active { background: rgba(255, 255, 255, .18); }
.qh-iconbtn:hover, .qh-iconbtn:focus { color: #fff; }
.qh-avatar { background: var(--qh-yellow); color: var(--qh-black); }

/* Visibility helpers. Mobile is < 768px (Bootstrap's md breakpoint). */
@media (min-width: 768px) { .qh-mobile-only { display: none !important; } }
@media (max-width: 767.98px) { .qh-desktop-only { display: none !important; } }

/* ---------- Shared components (every width) ---------- */
body.qh-page { background: var(--qh-bg); }

/* The sign-in screens (login, change password, two-step): the dark page, the reversed
   Bay-Lynx logo (the brand's artwork for dark grounds) over the white card. */
body.qh-gate { background: var(--qh-dark); display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; padding: 24px 0; }
.qh-gate-logo { display: block; width: 240px; max-width: 70vw; height: auto; margin: 0 auto 22px; }
.qh-muted { color: var(--qh-text-muted); }

/* The page header on the desk: the title, one line under it, the actions on the right. */
.qh-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.qh-head h4 { margin: 0; font-weight: 700; }
.qh-head .sub { color: var(--qh-text-muted); font-size: .9rem; }
.qh-head .actions { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* A white panel under a yellow bar. .caps for the small upper-case bar; .meta is the quiet
   text beside the title, .tools the controls pushed to the right. */
.qh-panel { background: var(--qh-surface); border: 1px solid var(--qh-border); border-radius: var(--qh-radius); }
.qh-panel-head { display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap; background: var(--qh-yellow); color: var(--qh-black);
                 font-weight: 700; padding: 7px 12px; border-radius: calc(var(--qh-radius) - 1px) calc(var(--qh-radius) - 1px) 0 0; }
.qh-panel-head.caps { text-transform: uppercase; letter-spacing: .12em; font-size: .78rem; }
.qh-panel-head .meta { font-weight: 400; text-transform: none; letter-spacing: 0; font-size: .8rem; color: var(--qh-on-yellow-muted); }
.qh-panel-head .tools { margin-left: auto; display: flex; align-items: center; gap: 8px; }
.qh-panel-body { padding: 12px 14px; }

/* Status badges, on Bootstrap's .badge. */
.qh-badge-rev { background: var(--qh-dark); color: #fff; }
.qh-badge-draft { background: #adb5bd; color: var(--qh-dark); }
.qh-badge-changes { background: var(--qh-yellow); color: var(--qh-black); }

/* A square button holding one 14px glyph (+, X, pencil), on a Bootstrap .btn for its colours.
   A dark one carries the yellow glyph. */
.qh-icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; padding: 0; flex: 0 0 auto; vertical-align: middle; }
.btn-dark.qh-icon-btn { --bs-btn-color: var(--qh-yellow); --bs-btn-hover-color: var(--qh-yellow); --bs-btn-active-color: var(--qh-yellow);
                        --bs-btn-bg: var(--qh-dark); --bs-btn-border-color: var(--qh-dark);
                        --bs-btn-hover-bg: var(--qh-dark-hover); --bs-btn-hover-border-color: var(--qh-dark-hover); }

/* A search box with its magnifier, for a panel bar or a toolbar. */
.qh-search { position: relative; display: flex; align-items: center; margin: 0; font-weight: 400; text-transform: none; letter-spacing: 0; }
.qh-search svg { position: absolute; left: 9px; color: var(--qh-text-muted); pointer-events: none; }
.qh-search input { width: 230px; max-width: 100%; height: 32px; padding: 0 8px 0 29px; font-size: .86rem; border: 1px solid var(--qh-dark);
                   border-radius: var(--qh-radius); background: var(--qh-surface); color: var(--qh-text); }
.qh-search input:focus { outline: 2px solid var(--qh-dark); outline-offset: 1px; }

/* A column heading that sorts: <th aria-sort><button class="qh-sort">. The arrow follows aria-sort. */
th .qh-sort { all: unset; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; font-weight: 700; white-space: nowrap; }
th .qh-sort:hover { color: #000; text-decoration: underline; }
th .qh-sort:focus-visible { outline: 2px solid var(--qh-dark); outline-offset: 2px; border-radius: 3px; }
th .qh-sort::after { content: "\2195"; font-size: .75rem; opacity: .3; }
th[aria-sort="ascending"] .qh-sort::after { content: "\25B2"; font-size: .6rem; opacity: 1; }
th[aria-sort="descending"] .qh-sort::after { content: "\25BC"; font-size: .6rem; opacity: 1; }

/* ---------- Phone: shared ---------- */
@media (max-width: 767.98px) {
    body.qh-page { background: var(--qh-bg); }
    html { background: var(--qh-bg); }

    /* One element wider than the screen is enough for iOS to let the whole page be pinched
       out: Safari sets the minimum zoom from the widest thing in the document, not from the
       viewport, so the app ends up narrower than the screen with a bare strip down one side
       while the fixed bottom bar still spans the lot. Clip anything that pokes past the
       root so the document is never wider than the screen and the page cannot be zoomed
       out below 1. `clip`, not `hidden`: hidden would turn <body> into a scroll container
       and the sticky app bar would stop sticking. */
    @supports (overflow: clip) {
        html, body.qh-page { overflow-x: clip; }
    }
    body.qh-page > .container,
    body.qh-page > .container-fluid { padding: 12px 12px calc(20px + var(--qh-safe-bottom)); max-width: none; }

    /* Fingers, not cursors. 16px text also stops iOS zooming the page when a field is focused. */
    body.qh-page .form-control,
    body.qh-page .form-select { min-height: 44px; font-size: 1rem; }
    body.qh-page .form-control-sm,
    body.qh-page .form-select-sm { min-height: 42px; font-size: 1rem; padding-top: .35rem; padding-bottom: .35rem; }
    body.qh-page .form-select-lg { font-size: 1.05rem; }
    body.qh-page .btn { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
    body.qh-page .btn-sm { min-height: 40px; font-size: .92rem; }
    body.qh-page .btn-link { min-height: 0; display: inline; }
    body.qh-page .qh-icon-btn { width: 44px; height: 44px; min-height: 44px; }
    body.qh-page .qh-search input { height: 44px; font-size: 1rem; }
    body.qh-page .dropdown-item { padding: .7rem 1rem; font-size: 1rem; }
    body.qh-page .form-check-input { width: 1.25em; height: 1.25em; }
    body.qh-page .card { border-radius: 12px; }
    body.qh-page .modal-dialog { margin: 8px; }
    body.qh-page .modal-footer .btn { flex: 1 1 auto; }
    body.qh-page .offcanvas { --bs-offcanvas-width: min(92vw, 380px); }
}

/* ---------- Dashboard ---------- */
@media (max-width: 767.98px) {
    .page-dashboard .dash-header { display: none !important; }  /* beats Bootstrap's .d-flex !important */
    .page-dashboard .account-col { display: none; }

    /* Product line + Create: the two things a rep came for. */
    .page-dashboard #productLineForm { flex-wrap: wrap; margin-bottom: 10px !important; }
    .page-dashboard #productLineForm label { flex: 1 1 100%; }
    .page-dashboard #productLineForm select { max-width: none !important; flex: 1 1 auto; }
    .page-dashboard #productLineForm .badge { display: none; }
    .page-dashboard .cta-create { width: 100%; padding: 15px 20px; font-size: 1.08rem; border-radius: 12px; }

    /* Catalog management stays on the desk. */
    .page-dashboard .tile-desk { display: none; }
    .page-dashboard .nav-tile { flex-direction: row; align-items: center; gap: 10px; padding: 12px 14px; }
    .page-dashboard .nav-tile .label::after { content: " \203A"; color: #adb5bd; }
    .page-dashboard .nav-tile .desc { display: none; }

    /* Filters: search always, the rest behind one button. */
    .page-dashboard .filters-more:not(.open) { display: none; }
    .page-dashboard .filters-search { order: -1; }
    .page-dashboard .quotes-hint { display: none; }

    /* The quotes table becomes a list of cards. One DOM, two layouts. */
    .page-dashboard .table-responsive { overflow: visible; }
    .page-dashboard .table-tight,
    .page-dashboard .table-tight tbody { display: block; width: 100%; }
    .page-dashboard .table-tight thead { display: none; }
    .page-dashboard .table-tight tr.quote-row {
        display: grid;
        grid-template-columns: auto 1fr auto;
        grid-template-areas:
            "qno    status  total"
            "cust   cust    cust"
            "model  line    date"
            "rep    rep     actions";
        column-gap: 8px;
        row-gap: 2px;
        align-items: center;
        padding: 12px 14px;
        border-bottom: 1px solid #edf0f2;
        background: #fff;
    }
    .page-dashboard .table-tight tr.quote-row:active { background: #f8f9fa; }
    .page-dashboard .table-tight td { display: block; padding: 0; border: 0; background: transparent; box-shadow: none; }
    .page-dashboard .c-qno    { grid-area: qno; font-size: 1.02rem; }
    .page-dashboard .c-status { grid-area: status; }
    .page-dashboard .c-status .badge { font-size: .68rem; }
    .page-dashboard .c-total  { grid-area: total; text-align: right; font-size: 1.02rem; white-space: nowrap; }
    .page-dashboard .c-cust   { grid-area: cust; margin-top: 4px; font-weight: 600; }
    .page-dashboard .c-cust .small { font-weight: 400; }
    .page-dashboard .c-model  { grid-area: model; }
    .page-dashboard .c-line   { grid-area: line; }
    .page-dashboard .c-date   { grid-area: date; text-align: right; }
    .page-dashboard .c-rep    { grid-area: rep; color: #6c757d; }
    .page-dashboard .c-actions { grid-area: actions; text-align: right; margin-top: 2px; }
    .page-dashboard.role-sales .c-rep { visibility: hidden; }
    .page-dashboard .c-actions .dropdown-toggle::after { display: none; }
    .page-dashboard .c-actions .btn { min-height: 36px; padding: 4px 14px; border-radius: 999px; }
}

/* ---------- Quote builder ---------- */
/* The floating summary panel is hidden below 1200px by the page's own CSS. Below that
   width the total lives in a fixed bottom bar and the breakdown opens as a sheet. */
.qh-bottombar, .qh-sheet-backdrop { display: none; }
@media (max-width: 1199.98px) {
    .page-quote { padding-bottom: calc(84px + var(--qh-safe-bottom)); }
    .page-quote .submit-desktop { display: none !important; }

    .qh-bottombar {
        position: fixed; left: 0; right: 0; bottom: 0; z-index: 1050;
        display: flex; align-items: center; gap: 12px;
        background: #fff;
        border-top: 1px solid #dee2e6;
        padding: 10px 14px calc(10px + var(--qh-safe-bottom));
        box-shadow: 0 -6px 20px rgba(0, 0, 0, .08);
    }
    .qh-bottombar .bb-total { flex: 1 1 auto; min-width: 0; text-align: left; background: none; border: 0; padding: 0; }
    .qh-bottombar .bb-label { font-size: .68rem; text-transform: uppercase; letter-spacing: .6px; color: #6c757d; display: flex; align-items: center; gap: 6px; }
    .qh-bottombar .bb-label .bb-meta { text-transform: none; letter-spacing: 0; color: #adb5bd; }
    .qh-bottombar .bb-amount { font-weight: 800; font-size: 1.3rem; color: #0d6efd; line-height: 1.1; white-space: nowrap; }
    .qh-bottombar .bb-amount::after { content: " \25B4"; font-size: .8rem; color: #6c757d; }
    .qh-bottombar .btn { flex: 0 0 auto; min-height: 46px; padding-left: 18px; padding-right: 18px; font-weight: 700; }

    .page-quote #live_summary {
        display: block !important;
        position: fixed; left: 0; right: 0; top: auto; bottom: 0;
        width: auto; max-height: 78vh; overflow: auto;
        border-radius: 16px 16px 0 0;
        transform: translateY(100%);
        transition: transform .25s ease;
        z-index: 1070;
        box-shadow: 0 -10px 34px rgba(0, 0, 0, .25);
        padding-bottom: var(--qh-safe-bottom);
    }
    .page-quote #live_summary.sheet-open { transform: translateY(0); }
    .page-quote #live_summary .ls-header { border-radius: 16px 16px 0 0; cursor: default; padding: 12px 14px; }
    .page-quote #live_summary .ls-header .ls-title { font-size: .85rem; }
    .page-quote #live_summary .ls-body { padding: 12px 16px 16px; font-size: .95rem; }
    .page-quote #live_summary .ls-grand .ls-grand-amount { font-size: 1.35rem; }
    .page-quote #live_summary #ls_toggle { display: none; }
    .page-quote #live_summary .ls-close { display: inline-flex; }
    .page-quote #live_summary.collapsed .ls-body { display: block; }

    .qh-sheet-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, .4); z-index: 1065; }
    .qh-sheet-backdrop.show { display: block; }
}
.page-quote #live_summary .ls-close {
    display: none;
    background: none; border: 0; color: #fff; font-size: 1.3rem; line-height: 1; padding: 0 4px;
}

@media (max-width: 767.98px) {
    .page-quote .quote-back { display: none; }
    .page-quote .container { padding-top: 12px !important; padding-bottom: 12px !important; }
    .page-quote form.card { padding: 16px 14px !important; margin-bottom: 0 !important; }
    .page-quote .quote-head { flex-direction: column; align-items: stretch !important; gap: 6px; }
    .page-quote .quote-head h2 { font-size: 1.3rem; }
    .page-quote .quote-no { text-align: left !important; }
    .page-quote .quote-no .h3 { font-size: 1.3rem; }
    .page-quote .quote-no .d-flex { justify-content: flex-start !important; }
    .page-quote .section-label { margin-bottom: 10px; font-size: .9rem; }

    /* The rep's own block is prefilled from their account: fold it until it is needed. */
    .page-quote .rep-col { text-align: left !important; margin-top: 8px; }
    .page-quote .rep-col .text-end { text-align: left !important; }
    .page-quote .rep-details:not(.open) { display: none; }
    .page-quote .rep-toggle {
        display: flex; align-items: center; justify-content: space-between; gap: 10px;
        width: 100%; text-align: left;
        background: #fff; border: 1px solid #dee2e6; border-radius: .375rem;
        padding: 10px 12px; margin-bottom: .5rem; color: #212529;
    }
    .page-quote .rep-toggle .rt-name { font-weight: 600; }
    .page-quote .rep-toggle .rt-sub { font-size: .8rem; color: #6c757d; }
    .page-quote .rep-toggle .rt-caret { color: #6c757d; transition: transform .15s; }
    .page-quote .rep-toggle[aria-expanded="true"] .rt-caret { transform: rotate(180deg); }

    /* Options: the whole card is the tap target. */
    .page-quote .option-card { min-height: 52px; padding: 10px 10px !important; }
    .page-quote .option-checkbox { width: 1.4em; height: 1.4em; flex: 0 0 auto; }
    .page-quote .option-price-label { margin-right: 0 !important; white-space: nowrap; margin-left: 10px; }
    /* Standard rows: the name on its own line, then the spec tag, the credit and Deduct under it. */
    .page-quote .std-row { padding: 10px 12px; flex-wrap: wrap; row-gap: 6px; }
    .page-quote .std-row .std-dot { flex: 0 0 10px; text-align: center; }
    .page-quote .std-row .std-name { flex: 1 1 calc(100% - 18px); }
    .page-quote .std-row .std-trim { margin-left: 18px; }
    .page-quote .std-row .std-deduct { min-height: 44px; }
    .page-quote .group-row { flex-wrap: wrap; row-gap: 6px; }
    .page-quote .group-row--addon .group-name { flex: 1 1 100%; min-width: 0; padding-left: 0; }
    .page-quote .group-row .group-select { flex: 1 1 auto; min-width: 0; }
    .page-quote .group-row--addon .group-price { margin-right: 0; }
    /* Counters (fenders, toolboxes, admix): a thumb-sized − and + on every one of them. */
    .page-quote .qty-btn,
    .page-quote .count-btn,
    .page-quote .custom-opt-remove { min-width: 44px; min-height: 44px; font-size: 1.1rem; }

    /* Chassis rows: a labelled card per unit. */
    .page-quote .chassis-row { padding: 12px !important; }
    .page-quote .chassis-row .col-md-1 { text-align: left !important; margin-bottom: 4px; }
    .page-quote .chassis-row .col-md-1 .badge::before { content: "Unit "; }
    .page-quote .chassis-row .form-control-sm { min-height: 42px; }
    .page-quote .chassis-row .input-group-sm > .input-group-text { font-size: 1rem; }

    .page-quote textarea.form-control { min-height: 60px; }
}

/* ---------- Users ---------- */
@media (max-width: 767.98px) {
    .page-users .users-header { display: none !important; }
    .page-users .users-toolbar { display: flex; gap: 10px; margin-bottom: 12px; }
    .page-users .users-toolbar .btn { flex: 1 1 auto; }
    .page-users .table-responsive { overflow: visible; }
    .page-users #usersTable,
    .page-users #usersTable tbody { display: block; width: 100%; }
    .page-users #usersTable thead { display: none; }
    .page-users #usersTable tr {
        display: grid;
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "name    role"
            "email   email"
            "phone   region"
            "pw      pw"
            "actions actions";
        column-gap: 10px; row-gap: 4px;
        align-items: center;
        padding: 12px 14px;
        border-bottom: 1px solid #edf0f2;
    }
    .page-users #usersTable td { display: block; padding: 0; border: 0; box-shadow: none; }
    .page-users .u-name   { grid-area: name; font-size: 1.02rem; }
    .page-users .u-email  { grid-area: email; color: #495057; word-break: break-all; }
    .page-users .u-phone  { grid-area: phone; color: #6c757d; font-size: .9rem; }
    .page-users .u-region { grid-area: region; color: #6c757d; font-size: .9rem; text-align: right; }
    .page-users .u-role   { grid-area: role; }
    .page-users .u-role .role-select { width: auto !important; min-width: 130px; }
    .page-users .u-pw     { grid-area: pw; margin-top: 2px; }
    .page-users .u-actions { grid-area: actions; text-align: left !important; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
    .page-users .u-actions .btn { margin: 0 !important; flex: 1 1 auto; }
}
