/* =====================================================================
   build.css — Build & Price pages (index, line/floorplans, configurator)

   Deliberately NOT in style.css: nothing here is shared with the
   homepage/listings/detail pages. Bump the ?v= in the three build-*.html
   files when you edit this.

   Layout language is lifted from detail.html's VDP on purpose (two-column
   grid, sticky right card, sticky section-nav capsule, fixed mobile CTA
   bar) so the configurator feels like the same product.

   Sticky offsets follow the HANDOFF rule: .header-container is 73px tall
   at EVERY breakpoint. Desktop sticky = 94px (matches the VDP), <=1024px
   = 87px (73 + 14).
   ===================================================================== */

/* ---------- shared page furniture ---------- */

/* Page ground. Matches listings.html / detail.html, which each set
   `body { background-color: var(--bg-light); }` in their inline <style>.
   The three Build & Price pages used to inherit style.css's white body,
   which made every card sit white-on-white; they now use the same grey
   ground so the whole prototype reads as one product (user decision
   2026-09-03). Mechanism deliberately identical: body background, not a
   page wrapper. It lives here because build.css is loaded by exactly the
   three B&P pages and by nothing else. */
body {
    background-color: var(--bg-light);
}

.bp-hero {
    background-color: var(--primary-dark);
    background-image: linear-gradient(135deg, rgba(15, 41, 66, 0.97) 0%, rgba(10, 17, 24, 0.98) 100%);
    /* padding (NOT margin) so the navy paints behind the fixed header */
    padding: calc(73px + 44px) 24px 44px;
    text-align: center;
    color: var(--text-light);
}

.bp-hero h1 {
    font-family: var(--font-headings);
    font-size: 2.4rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.12;
    text-wrap: balance;          /* "Build & Price Your Coachmen RV" on a phone: no "RV" alone on the last line */
}

.bp-hero .bp-hero-sub {
    color: var(--text-light-muted);
    font-size: 1.05rem;
    margin-top: 10px;
}

.bp-hero .bp-hero-note {
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.82rem;
    margin-top: 14px;
}

.bp-wrap {
    max-width: 1200px;
    margin: 0 auto;
    padding: 32px 24px 80px;
}

.bp-visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* =====================================================================
   1. Index page — filter bar + line cards
   ===================================================================== */
.bp-filter-section {
    background-color: var(--bg-white);
    border-bottom: 1px solid var(--border-color);
    position: sticky;
    top: 73px; /* must equal the real header height at every breakpoint */
    z-index: 30;
    box-shadow: var(--shadow-sm);
    padding: 14px 24px;
}

.bp-filter-container {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.bp-filter-row {
    display: flex;
    align-items: center;
    gap: 12px;
}

.bp-search-wrapper {
    position: relative;
    flex: 1;
    width: 0;
    min-width: 0;
}

.bp-search-wrapper .bp-search-icon {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: none;
    display: flex;
}

.bp-search-wrapper input {
    width: 100%;
    padding: 11px 40px 11px 42px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    font-family: var(--font-body);
    font-size: max(16px, 1rem);   /* 16px minimum: iOS zooms the page on focus below it (section 8.6) */
    color: var(--text-dark);
    outline: none;
    transition: var(--transition-fast);
}

/* "Search model lines" (the phone hint, build-index.js) at 16px is a few
   pixels wider than the field of a 320px screen: the hint, not the typed
   text, keeps the smaller size there (as the unit page's lead form does) */
@media (max-width: 360px) {
    .bp-search-wrapper input::placeholder { font-size: 0.9rem; }
}

.bp-search-wrapper input:focus {
    border-color: var(--primary-light);
    box-shadow: 0 0 0 3px rgba(0, 164, 228, 0.15);
}

.bp-clear-search {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    font-size: 1.2rem;
    line-height: 1;
    display: none;
    cursor: pointer;
}
.bp-clear-search:hover { color: var(--text-dark); }

.bp-sort {
    flex-shrink: 0;
    padding: 11px 14px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    font-family: var(--font-body);
    font-size: 0.9rem;
    color: var(--text-dark);
    background-color: var(--bg-white);
    outline: none;
    cursor: pointer;
}
.bp-sort:focus { border-color: var(--primary-light); }

/* Type pills reuse style.css's .filter-pill / .filter-pills language */
.bp-type-pills {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 2px;
}
.bp-type-pills::-webkit-scrollbar { display: none; }

.bp-result-count {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px 24px 0;
    font-size: 0.9rem;
    color: var(--text-muted);
}

.bp-line-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 24px;
}

.bp-line-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background-color: var(--bg-white);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: var(--transition-medium);
}

.bp-line-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-card-hover);
    border-color: rgba(0, 164, 228, 0.35);
}

.bp-line-card-img {
    aspect-ratio: 4 / 3;
    background-color: #eaeaea;
    overflow: hidden;
}

.bp-line-card-img img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: var(--transition-medium);
}

.bp-line-card:hover .bp-line-card-img img { transform: scale(1.05); }

.bp-line-card-body {
    padding: 18px;
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: 6px;
}

.bp-line-card-name {
    font-family: var(--font-headings);
    font-size: 1.15rem;
    font-weight: 800;
    color: var(--primary-dark);
    line-height: 1.2;
}

.bp-line-card-by {
    font-size: 0.8rem;
    color: var(--text-muted);
}

.bp-type-tag {
    align-self: flex-start;
    background-color: rgba(0, 164, 228, 0.1);
    color: var(--primary-link);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    padding: 4px 10px;
    border-radius: 20px;
    margin-top: 2px;
}

.bp-line-card .btn {
    margin-top: 14px;
    width: 100%;
    /* .btn's default padding + uppercase gives a wide min-content box;
       trim it so a 260px card can never force page-wide overflow. */
    padding: 10px 12px;
    font-size: 0.8rem;
}

/* Whole card clickable (stretched-link pattern, same as the inventory card's
   .stretched-link in style.css §6B). The ::after fills the card's positioned
   box, so a click anywhere on .bp-line-card / .bp-fp-card activates this link —
   and because it's the anchor's own pseudo-element it carries .btn's
   cursor: pointer and triggers the card's :hover lift. Used by BOTH card types.
   Any secondary link inside a card must get position: relative + z-index: 2 to
   stay independently clickable (same rule as .get-approved-link). */
.bp-card-link::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
}

/* The stretched anchor must NEVER get a transform: a transformed element
   becomes the containing block for its absolute descendants, which collapses
   the ::after overlay from the card down to the button — and since hovering
   the card IS hovering this anchor, .btn-primary:hover's translateY(-2px)
   killed whole-card clicks in real browsers the moment the mouse moved in
   (synthetic .click() tests don't hover, so the pane never caught it).
   The card's own :hover lift provides the motion affordance instead. */
.bp-card-link:hover {
    transform: none;
}

/* Keyboard affordance — the card is the target, so ring the card, not just the
   button (the UA default ring on a stretched link points at the wrong box). */
.bp-card-link:focus-visible {
    outline: none;
}

.bp-card-link:focus-visible::after {
    outline: 3px solid var(--primary-light);
    outline-offset: -3px;
    border-radius: var(--radius-md);
}

.bp-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 60px 20px;
    color: var(--text-muted);
}

.bp-empty h2 {
    font-family: var(--font-headings);
    color: var(--primary-dark);
    font-size: 1.4rem;
    margin-bottom: 8px;
}

/* =====================================================================
   2. Line page — hero + floorplan cards
   ===================================================================== */
.bp-line-hero {
    display: grid;
    grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
    gap: 32px;
    align-items: center;
    margin-bottom: 40px;
}

.bp-line-hero-img {
    border-radius: var(--radius-md);
    overflow: hidden;
    border: 1px solid var(--border-color);
    aspect-ratio: 4 / 3;
    background-color: #eaeaea;
}

.bp-line-hero-img img { width: 100%; height: 100%; object-fit: cover; }

.bp-line-hero h1 {
    font-family: var(--font-headings);
    font-size: 2.1rem;
    font-weight: 800;
    color: var(--primary-dark);
    letter-spacing: -0.02em;
    line-height: 1.15;
}

.bp-line-hero .bp-line-meta {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin: 6px 0 14px;
}

.bp-section-heading {
    font-family: var(--font-headings);
    font-size: 1.4rem;
    font-weight: 800;
    color: var(--primary-dark);
    margin-bottom: 4px;
}

.bp-section-sub {
    color: var(--text-muted);
    font-size: 0.9rem;
    margin-bottom: 22px;
}

.bp-fp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 24px;
}

.bp-fp-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background-color: var(--bg-white);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    transition: var(--transition-medium);
}

.bp-fp-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-card-hover);
    border-color: rgba(0, 164, 228, 0.35);
}

.bp-fp-img {
    aspect-ratio: 4 / 3;
    background-color: #fff;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
}

.bp-fp-img img { max-width: 100%; max-height: 100%; object-fit: contain; }

.bp-fp-body { padding: 16px 18px 18px; display: flex; flex-direction: column; flex: 1; }

.bp-fp-code {
    font-family: var(--font-headings);
    font-size: 1.2rem;
    font-weight: 800;
    color: var(--primary-dark);
    margin-bottom: 10px;
}

.bp-fp-specs {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
    margin-bottom: 14px;
}

.bp-fp-specs th {
    text-align: left;
    font-weight: 500;
    color: var(--text-muted);
    padding: 5px 0;
    border-bottom: 1px dashed var(--border-color);
}

.bp-fp-specs td {
    text-align: right;
    font-weight: 600;
    color: var(--text-dark);
    padding: 5px 0;
    border-bottom: 1px dashed var(--border-color);
    white-space: nowrap;
}

.bp-fp-card .btn {
    margin-top: auto;
    width: 100%;
    padding: 10px 12px;
    font-size: 0.8rem;
}

/* =====================================================================
   3. Configurator (build.html) — VDP-style two column
   ===================================================================== */
.bp-build-layout {
    max-width: 1200px;
    margin: 0 auto;
    padding: 16px 24px 80px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 380px;
    gap: 32px;
    align-items: start;
}

.bp-build-main { min-width: 0; }

.bp-intro {
    background-color: var(--bg-white);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    padding: 24px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 24px;
    align-items: center;
}

.bp-intro-figure {
    position: relative;
    background-color: #fff;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    aspect-ratio: 4 / 3;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    cursor: zoom-in;
}

.bp-intro-figure img { max-width: 100%; max-height: 100%; object-fit: contain; }

.bp-enlarge-tag {
    position: absolute;
    right: 8px;
    bottom: 8px;
    background-color: rgba(15, 41, 66, 0.85);
    color: #fff;
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.4px;
    padding: 5px 9px;
    border-radius: 20px;
    display: flex;
    align-items: center;
    gap: 5px;
}

.bp-intro h1 {
    font-family: var(--font-headings);
    font-size: 1.9rem;
    font-weight: 800;
    color: var(--primary-dark);
    line-height: 1.15;
    letter-spacing: -0.02em;
}

.bp-intro .bp-intro-sub {
    font-size: 0.9rem;
    color: var(--text-muted);
    margin: 6px 0 12px;
}

.bp-intro p { color: var(--text-muted); font-size: 0.92rem; line-height: 1.65; }

/* --- sticky section nav (copied language from detail.html's VDP nav) --- */
.bp-section-nav {
    position: sticky;
    top: 94px;
    z-index: 30;
    background-color: var(--bg-white);
    border: 1px solid var(--border-color);
    border-radius: 40px;
    box-shadow: var(--shadow-sm);
    margin: 24px 0;
    padding: 6px;
    display: flex;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: none;
}
.bp-section-nav::-webkit-scrollbar { display: none; }

/* 7 pills (6 categories + Specs) have to fit a ~740px left column at 1266px,
   so these are slimmer than the VDP's 5-pill row. They still scroll (and
   auto-centre) at narrow widths. */
.bp-nav-pill {
    flex: 1;
    white-space: nowrap;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    padding: 9px 10px;
    border-radius: 30px;
    text-align: center;
    transition: var(--transition-fast);
}

.bp-nav-pill:hover { color: var(--primary-dark); background-color: var(--bg-light); }
.bp-nav-pill.active { background-color: rgba(0, 164, 228, 0.1); color: var(--primary-link); }

.bp-section {
    background-color: var(--bg-white);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    padding: 28px;
    margin-bottom: 24px;
    scroll-margin-top: 164px;
}

.bp-section-title {
    font-family: var(--font-headings);
    font-size: 1.4rem;
    font-weight: 800;
    color: var(--primary-dark);
    letter-spacing: -0.3px;
}

.bp-section-note {
    font-size: 0.88rem;
    color: var(--text-muted);
    margin: 4px 0 18px;
}

/* --- option rows --- */
.bp-cat + .bp-cat { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--border-color); }

.bp-cat-legend {
    font-family: var(--font-headings);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--primary-dark);
    margin-bottom: 2px;
}

.bp-cat-note {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-bottom: 12px;
}

.bp-opts { display: flex; flex-direction: column; gap: 8px; }

.bp-opt {
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background-color: var(--bg-white);
    transition: var(--transition-fast);
}

.bp-opt:hover { border-color: rgba(0, 164, 228, 0.5); }

/* The row is label + extras. The LABEL is the whole clickable area (generous
   tap target); the swatch/details buttons live OUTSIDE it, because a <button>
   inside a <label for> would toggle the input every time it's pressed. */
.bp-opt-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

.bp-opt-label {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
    min-width: 0;
    padding: 13px 14px;
    min-height: 52px;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
}

.bp-opt-extras {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    padding-right: 12px;
}

.bp-opt input[type="checkbox"],
.bp-opt input[type="radio"] {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    accent-color: var(--primary-light);
    cursor: pointer;
    margin: 0;
}

.bp-opt-text { flex: 1; min-width: 0; }

.bp-opt-title {
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--text-dark);
    line-height: 1.35;
}

.bp-opt-price {
    font-family: var(--font-headings);
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--primary-dark);
    white-space: nowrap;
    flex-shrink: 0;
}

.bp-opt-price.included { color: var(--text-muted); font-weight: 600; font-size: 0.8rem; }

.bp-opt.selected {
    border-color: var(--primary-light);
    background-color: rgba(0, 164, 228, 0.05);
    box-shadow: 0 0 0 1px rgba(0, 164, 228, 0.25) inset;
}

.bp-opt.selected .bp-opt-title { color: var(--primary-dark); }

/* Locked factory standards: a positive "Included" state, not disabled grey */
.bp-opt.locked {
    border-color: rgba(15, 138, 126, 0.35);
    background-color: rgba(15, 138, 126, 0.06);
}

.bp-opt.locked .bp-opt-label { cursor: default; }

.bp-lock-check {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    border-radius: 50%;
    background-color: #0f8a7e;
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
}

.bp-included-tag {
    background-color: rgba(15, 138, 126, 0.14);
    color: #0b6b61;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 4px 9px;
    border-radius: 20px;
    white-space: nowrap;
    flex-shrink: 0;
}

/* swatches */
.bp-swatch {
    width: 28px;
    height: 28px;
    border-radius: 7px;
    border: 1px solid rgba(0, 0, 0, 0.18);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
    flex-shrink: 0;
    cursor: zoom-in;
    padding: 0;
}

/* description disclosure (no alert(), no tooltip) */
.bp-opt-more {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--primary-link);
    padding: 8px 4px;
    white-space: nowrap;
}

.bp-opt-more:hover { text-decoration: underline; }
.bp-opt-more svg { transition: var(--transition-fast); }
.bp-opt-more[aria-expanded="true"] svg { transform: rotate(180deg); }

.bp-opt-desc {
    font-size: 0.83rem;
    color: var(--text-muted);
    line-height: 1.6;
    padding: 0 14px 13px 46px;
}

.bp-opt-desc[hidden] { display: none; }

/* Non-blocking dependency notice (the legacy site used a blocking alert()) */
.bp-dep-notice {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin: 6px 0 0;
    padding: 10px 12px;
    background-color: rgba(255, 193, 7, 0.14);
    border: 1px solid rgba(255, 193, 7, 0.5);
    border-radius: var(--radius-sm);
    font-size: 0.8rem;
    line-height: 1.5;
    color: #7a5500;
    animation: bp-notice-in 0.25s ease-out;
}

.bp-dep-notice .bp-undo {
    margin-left: auto;
    flex-shrink: 0;
    font-weight: 700;
    color: #7a5500;
    text-decoration: underline;
    font-size: 0.78rem;
    padding: 2px 4px;
}

@keyframes bp-notice-in {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: none; }
}

/* --- specifications --- */
.bp-spec-toggle {
    display: inline-flex;
    gap: 4px;
    background-color: var(--bg-light);
    border: 1px solid var(--border-color);
    border-radius: 30px;
    padding: 4px;
    margin-bottom: 16px;
}

.bp-spec-toggle button {
    font-family: var(--font-body);
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-muted);
    padding: 7px 16px;
    border-radius: 30px;
    transition: var(--transition-fast);
}

.bp-spec-toggle button.active {
    background-color: var(--bg-white);
    color: var(--primary-dark);
    box-shadow: var(--shadow-sm);
}

.bp-spec-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }

.bp-spec-table th {
    text-align: left;
    font-weight: 500;
    color: var(--text-muted);
    padding: 10px 0;
    border-bottom: 1px solid var(--border-color);
}

.bp-spec-table td {
    text-align: right;
    font-weight: 600;
    color: var(--text-dark);
    padding: 10px 0;
    border-bottom: 1px solid var(--border-color);
}

.bp-spec-table td.metric { color: var(--text-muted); font-weight: 500; }

/* =====================================================================
   4. "Your Build" card (sticky right column) — VDP purchase-card styling
   ===================================================================== */
/* Owner, 2026-10-08: the card takes its natural height and never scrolls
   inside itself (the pinned head / scrolling middle / pinned button of the
   first build are gone). It is sticky 94px under the header when it fits
   the window; when it is taller, build.js moves the stop (--bp-card-top)
   so the card travels with the page until its bottom edge is in view, and
   back until its top is: every part is reached by scrolling the page.
   Without the script it sticks at 94px, as the unit page's card does. */
.bp-build-col { position: sticky; top: var(--bp-card-top, 94px); }

.bp-build-card {
    background-color: var(--bg-white);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    padding: 20px 22px 18px;
}

.bp-card-brandline {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--primary-link);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: 6px;
}

.bp-card-title {
    font-family: var(--font-headings);
    font-size: 1.5rem;
    font-weight: 800;
    color: var(--primary-dark);
    line-height: 1.2;
    letter-spacing: -0.3px;
    overflow-wrap: anywhere;
}

/* Title, then the price: no type / length / weight line and no rule
   between them (owner, 2026-10-08). */
.bp-price-block { margin-top: 10px; }

.bp-price-label {
    display: block;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.bp-retail {
    font-family: var(--font-headings);
    font-size: 2rem;
    font-weight: 800;
    color: var(--text-muted);
    text-decoration: line-through;
    line-height: 1.1;
    display: block;
}

/* Staff (template: in_group): ONLY the sale price, in the unit page's
   price style (.vdp-price). No retail, no discount, no pitch. */
.bp-sale {
    display: block;
    font-family: var(--font-headings);
    font-size: 2.1rem;
    font-weight: 800;
    color: var(--primary-link);
    line-height: 1.1;
}
.bp-sale.is-stale, .bp-mobile-bar .bar-price.is-stale { opacity: 0.5; }

/* --- selections summary: a row INSIDE the lead box (owner, 2026-10-08),
   not a card of its own. One line where both parts fit ("No options
   selected yet" + the link do, at the card's desktop width, with 3px to
   spare: the 6px gap and the 0.75rem link are what make them), two where
   they do not; nothing is cut.
   The full list lives in the drawer. --- */
.bp-recap-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0 6px;
    width: 100%;
    margin: 0 0 10px;
    padding: 0;
    text-align: left;
    background: none;
    border: 0;
    -webkit-user-select: none;
    user-select: none;
    touch-action: manipulation;
}

.bp-recap-line {
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--primary-dark);
    line-height: 1.5;
}

.bp-recap-cta {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.5;
    color: var(--primary-link);
    white-space: nowrap;
}
.bp-recap-cta svg { position: relative; top: 2px; }
.bp-recap-summary:hover .bp-recap-cta, .bp-recap-summary:focus-visible .bp-recap-cta { text-decoration: underline; }

/* =====================================================================
   4b. Selections drawer
   Deliberately the SAME class names and transitions as the listings
   Filter & Sort drawer (whose CSS lives in listings.css since 2026-09-03,
   when it was extracted from listings.html's inline <style>). The two are
   still separate copies with small per-page deltas (listings' .drawer-body
   is a 28px-gap flex column, its .drawer-header padding is 24px and its
   #btn-apply-drawer takes flex:1.4) — that's why they weren't merged into
   style.css. If these two ever move into style.css, merge them and keep the
   per-page deltas as page-level overrides; they are meant to be one component.
   ===================================================================== */
.drawer-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(15, 41, 66, 0.4);
    backdrop-filter: blur(4px);
    z-index: 100;
    display: none;
    opacity: 0;
    transition: opacity var(--transition-medium);
}

.drawer-overlay.show { display: block; opacity: 1; }

.filters-drawer {
    position: fixed;
    top: 0;
    right: -420px;
    width: 100%;
    max-width: 420px;
    height: 100%;
    background-color: var(--bg-white);
    z-index: 110;
    box-shadow: var(--shadow-lg);
    display: flex;
    flex-direction: column;
    transition: right var(--transition-medium) cubic-bezier(0.16, 1, 0.3, 1);
}

.filters-drawer.show { right: 0; }

.drawer-header {
    padding: 22px 24px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.drawer-header h2 {
    font-family: var(--font-headings);
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--primary-dark);
}

.btn-close-drawer {
    font-size: 1.8rem;
    color: var(--text-muted);
    line-height: 1;
    /* 44px tap target */
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: var(--transition-fast);
}

.btn-close-drawer:hover { color: var(--text-dark); }

.drawer-body {
    padding: 24px;
    overflow-y: auto;
    flex-grow: 1;
}

.drawer-footer {
    padding: 20px 24px calc(20px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--border-color);
    display: flex;
    gap: 12px;
}

.drawer-footer .btn {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    white-space: nowrap;
    padding: 14px 12px;
    font-weight: 600;
    border-radius: var(--radius-sm);
}

.apply-count-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 20px;
    padding: 0 7px;
    border-radius: 999px;
    background-color: rgba(15, 41, 66, 0.16);
    color: var(--primary-dark);
    font-size: 0.75rem;
    font-weight: 800;
    line-height: 1;
}

/* --- grouped selection list --- */
.bp-sel-group + .bp-sel-group { margin-top: 22px; }

.bp-sel-group-label {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: var(--text-muted);
    margin-bottom: 8px;
}

.bp-sel-rows { display: flex; flex-direction: column; gap: 8px; }

/* Same interaction language as the listings drawer's .filter-tag (blue tint,
   blue × that darkens on hover) — adapted from a wrapping pill row to a
   grouped list, so long option titles stay readable. */
.bp-sel-row {
    display: flex;
    align-items: center;
    gap: 10px;
    background-color: rgba(0, 164, 228, 0.08);
    border: 1px solid rgba(0, 164, 228, 0.15);
    border-radius: 20px;
    padding: 9px 8px 9px 14px;
    transition: var(--transition-fast);
}

.bp-sel-row:hover { background-color: rgba(0, 164, 228, 0.15); }

.bp-sel-swatch {
    width: 16px;
    height: 16px;
    border-radius: 4px;
    border: 1px solid rgba(0, 0, 0, 0.2);
    flex-shrink: 0;
}

.bp-sel-title {
    flex: 1;
    min-width: 0;
    font-size: 0.84rem;
    font-weight: 600;
    color: var(--primary-link);
    line-height: 1.35;
}

.bp-sel-price {
    font-family: var(--font-headings);
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--primary-dark);
    white-space: nowrap;
    flex-shrink: 0;
}

.bp-sel-remove {
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--primary-link);
    font-size: 1.2rem;
    line-height: 1;
    transition: var(--transition-fast);
}

.bp-sel-remove:hover { color: var(--primary-dark); background-color: rgba(0, 164, 228, 0.18); }

/* Locked factory standards: listed, never removable */
.bp-sel-row.locked {
    background-color: rgba(15, 138, 126, 0.07);
    border-color: rgba(15, 138, 126, 0.28);
    padding-right: 14px;
}
.bp-sel-row.locked:hover { background-color: rgba(15, 138, 126, 0.07); }
.bp-sel-row.locked .bp-sel-title { color: #0b6b61; }

.bp-sel-included {
    background-color: rgba(15, 138, 126, 0.16);
    color: #0b6b61;
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 3px 8px;
    border-radius: 20px;
    white-space: nowrap;
    flex-shrink: 0;
}

.bp-sel-empty {
    font-size: 0.9rem;
    color: var(--text-muted);
    font-style: italic;
    padding: 8px 0 20px;
}

/* --- lead form: the unit page's lead form (css/src/detail.css
   .vdp-lead-form), value for value: dashed tinted box that OPENS with the
   "our price is lower" sentence (owner, 2026-10-08: one box, no separate
   note above it), 16px padding, 41px fields 10px apart, 0.68rem consent,
   full-width button, centred success line. Different on purpose: the
   selections row between the sentence and the fields (8px under the
   sentence, where the unit page has 12px before its first field). --- */
.bp-lead {
    border: 1px dashed rgba(0, 164, 228, 0.4);
    background-color: rgba(0, 164, 228, 0.04);
    border-radius: var(--radius-sm);
    padding: 16px;
    margin-top: 12px;
}

.bp-lead-blurb {
    font-size: 0.82rem;
    color: var(--text-dark);
    line-height: 1.5;
    margin-bottom: 8px;
}

.bp-lead-blurb strong { color: var(--primary-dark); }

.bp-field { margin-bottom: 10px; }

.bp-lead input[type="text"],
.bp-lead input[type="email"],
.bp-lead input[type="tel"] {
    width: 100%;
    height: 41px;
    padding: 0 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background-color: #fff;
    font-family: var(--font-body);
    font-size: max(16px, 1rem);   /* 16px minimum: section 8.6 */
    outline: none;
    transition: var(--transition-fast);
}

.bp-lead input:focus {
    border-color: var(--primary-light);
    box-shadow: 0 0 0 3px rgba(0, 164, 228, 0.15);
}

/* "Full Name (first & last) *" at 16px is wider than the field of a 320px
   screen: the hint keeps its old size there, as on the unit page */
@media (max-width: 360px) {
    .bp-lead input::placeholder { font-size: 0.9rem; }
}

.bp-error {
    display: none;
    color: #c62828;
    font-size: 0.72rem;
    line-height: 1.35;
    margin-top: 4px;
}
.bp-field.has-error .bp-error { display: block; }
.bp-field.has-error input { border-color: #e53935; }
.bp-field.has-error input:focus { border-color: #e53935; box-shadow: 0 0 0 3px rgba(229, 57, 53, 0.15); }

/* The consent checkbox can't show a red text-field border, so flag the
   checkbox itself and the copy beside it. */
.bp-field-consent { margin-bottom: 12px; }
.bp-field-consent.has-error .bp-consent { color: #c62828; }
.bp-field-consent.has-error input[type="checkbox"] { outline: 2px solid #e53935; outline-offset: 2px; }

.bp-consent {
    display: flex;
    gap: 8px;
    align-items: flex-start;
    font-size: 0.68rem;
    color: var(--text-muted);
    line-height: 1.5;
    margin-bottom: 0;
    cursor: pointer;
}

.bp-consent input[type="checkbox"] {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    margin-top: 2px;
    accent-color: var(--primary-light);
}

@media (max-width: 480px) {
    .bp-consent { gap: 10px; padding: 2px 0; }
    .bp-consent input[type="checkbox"] { width: 18px; height: 18px; }
}

.bp-consent a { color: var(--primary-link); text-decoration: underline; }

.bp-lead .btn { width: 100%; }
.bp-lead .btn:disabled { opacity: 0.7; cursor: progress; transform: none; box-shadow: none; }

/* Honeypot — visually hidden but still a real, focusable-by-bots input.
   Excluded from validation (see build.js). */
.bp-hp {
    position: absolute !important;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    padding: 0; margin: -1px;
}

/* the unit page's .lead-success and .lead-server-error (ee.css) */
.bp-lead-success {
    display: none;
    text-align: center;
    padding: 10px 0 0;
    color: var(--accent-teal-text);
    font-weight: 600;
    font-size: 0.9rem;
    line-height: 1.45;
}

.bp-lead-success.show { display: block; }

.bp-lead .bp-lead-server-error {
    background: #fdecea;
    border: 1px solid #f5c6c2;
    color: #a32b20;
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    margin: 12px 0 0;
    font-size: 0.85rem;
    font-weight: 400;
    line-height: 1.45;
}

.bp-card-assurance {
    display: flex;
    justify-content: center;
    gap: 18px;
    margin-top: 14px;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.bp-card-assurance span { display: flex; align-items: center; gap: 5px; }

/* =====================================================================
   5. Mobile CTA bar + enlarge lightbox
   ===================================================================== */
.bp-mobile-bar {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: var(--bg-white);
    border-top: 1px solid var(--border-color);
    box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1);
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    z-index: 60;
    align-items: center;
    gap: 14px;
}

.bp-mobile-bar .bar-block { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }

.bp-mobile-bar .bar-label {
    font-size: 0.63rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.bp-mobile-bar .bar-price {
    font-family: var(--font-headings);
    font-size: 1.2rem;
    font-weight: 800;
    color: var(--text-muted);
    text-decoration: line-through;
}

.bp-mobile-bar .bar-sub { font-size: 0.66rem; color: var(--text-muted); }

.bp-mobile-bar .btn {
    flex: 1;
    min-width: 0;
    text-align: center;
    padding: 13px 10px;
    font-size: 0.85rem;
    font-weight: 700;
    border-radius: var(--radius-sm);
}

/* Simple enlarge view for floorplans + swatches */
.bp-lightbox {
    display: none;
    position: fixed;
    inset: 0;
    background-color: #080d13;
    z-index: 500;
    padding: 24px;
    align-items: center;
    justify-content: center;
}

.bp-lightbox.open { display: flex; }

.bp-lightbox img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    background-color: #fff;
    border-radius: var(--radius-sm);
    padding: 12px;
}

.bp-lb-swatch {
    width: min(60vw, 260px);
    height: min(60vw, 260px);
    border-radius: var(--radius-md);
    border: 2px solid rgba(255, 255, 255, 0.35);
}

.bp-lb-caption {
    position: absolute;
    left: 0; right: 0; bottom: 28px;
    text-align: center;
    color: #fff;
    font-size: 0.9rem;
    font-weight: 600;
}

.bp-lb-close {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background-color: rgba(255, 255, 255, 0.14);
    color: #fff;
    font-size: 1.6rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* =====================================================================
   6. Responsive
   ===================================================================== */
@media (max-width: 1024px) {
    /* Plan doc 36.6 (B3): the card is NOT moved first any more. Order =
       rail, intro, options, specifications, then price card + lead form;
       the fixed price bar (below) carries the price until then. */
    .bp-build-layout { grid-template-columns: minmax(0, 1fr); padding-top: 8px; padding-bottom: 120px; }
    .bp-build-col { position: static; width: 100%; max-width: 620px; margin: 0 auto; }
    .bp-mobile-bar { display: flex; }
    /* 73px header + 14px gap — the header does NOT shrink on mobile. */
    .bp-section-nav { top: 87px; }
    .bp-line-hero { grid-template-columns: 1fr; gap: 20px; }
}

@media (max-width: 768px) {
    .bp-hero { padding: calc(73px + 28px) 16px 30px; }
    .bp-hero h1 { font-size: 1.65rem; }
    .bp-hero .bp-hero-sub { font-size: 0.92rem; }
    .bp-wrap { padding: 22px 16px 100px; }
    .bp-result-count { padding: 16px 16px 0; }
    .bp-filter-section { padding: 12px 16px; }
    .bp-build-layout { padding: 8px 16px 120px; gap: 20px; }
    .bp-section { padding: 20px 16px; scroll-margin-top: 156px; }
    .bp-intro { grid-template-columns: 1fr; padding: 18px; gap: 18px; }
    .bp-intro h1 { font-size: 1.5rem; }
    .bp-line-grid, .bp-fp-grid { grid-template-columns: 1fr; gap: 18px; }
    .bp-opt-desc { padding-left: 46px; }
    .bp-card-title { font-size: 1.35rem; }
    .bp-sale { font-size: 1.9rem; }
    .bp-retail { font-size: 1.75rem; }
    .bp-filter-row { flex-wrap: wrap; }
    .bp-sort { flex: 1; }
    /* Full-width drawer on mobile, same as the listings drawer */
    .filters-drawer { max-width: 100%; right: -100%; }
    .drawer-body { padding: 20px 16px; }
    .drawer-header { padding: 18px 16px; }
    .drawer-footer { padding: 16px calc(16px) calc(16px + env(safe-area-inset-bottom)); }
}

@media (prefers-reduced-motion: reduce) {
    .bp-line-card, .bp-fp-card, .bp-line-card-img img { transition: none; }
    .bp-line-card:hover, .bp-fp-card:hover { transform: none; }
    .bp-dep-notice { animation: none; }
}

/* =====================================================================
   7. Unified Build & Price: index and line page (plan doc 36, package C)

   THIS FILE = redesign/build.css, verbatim (sections 1-6 above, the
   builder's rules included: package D edits those; plan doc 37 took the
   dead p.bp-line-desc rule out of section 2), plus this block.
   `rvn.sh sync` prefers css/src/ (pick_src), so redesign/build.css, the
   prototype and the approved mockups stay as they are.

   Ported from the approved mockup redesign/explore/build-and-price/
   bpx.css (concept "final"), with the bpx- class names, minus the
   body.bpx-c-* qualifiers, the concept A / B / C blocks and the mockup
   chip. Everything here is scoped to markup that exists only on
   site/.bp-index-v2 (main.bpx-index) and site/.bp-models-v2
   (main.bpx-line-wrap), or to bpx-* classes: no rule above is changed for
   the builder (site/.bp-options-v2) or the 404 body, except that the rail
   (.bpx-rail-wrap, .bpx-rail, .bpx-step*) and the back link (.bpx-back)
   are written to be reused there as they are.

   The floating search card, the Sort menu button, the count / tag row,
   the suggestions listbox and the pills' base look are in the app2 bundle
   (css/src/ee.css plan doc 27, style.css .filter-pill), which is linked
   BEFORE this file: only the differences are restated here.
   ===================================================================== */

body.bp-page {
    --bpx-stock: #0d7d72;                /* = --accent-teal-fill */
    --bpx-tint: #eaf6fd;
    --bpx-tint-border: #bde3f6;
}

/* display:flex / grid on a card would otherwise beat the UA's [hidden] */
.bpx-index [hidden],
.bpx-line-wrap [hidden] { display: none !important; }

/* ---------------------------------------------------------------------
   7.1 Step rail (index: under the hero; line page and builder: under the
       header). ol.bpx-rail > li.bpx-step.is-done|is-current|is-todo >
       a|span.bpx-step-inner > .bpx-step-n + .bpx-step-label + .bpx-step-value
   --------------------------------------------------------------------- */
.bpx-rail-wrap { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.bpx-rail-wrap--hero { margin-top: -30px; position: relative; z-index: 2; }
.bpx-rail-wrap--page { padding-top: calc(73px + 16px); }
.bpx-rail {
    list-style: none; margin: 0; padding: 10px 8px; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    background: var(--bg-white); border: 1px solid var(--border-color); border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
}
.bpx-step { position: relative; min-width: 0; }
.bpx-step + .bpx-step::before {
    content: ""; position: absolute; left: 0; top: 50%; width: 1px; height: 60%; transform: translateY(-50%);
    background: var(--border-color);
}
.bpx-step-inner {
    display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 10px;
    min-height: 48px; padding: 6px 14px; border-radius: 10px; color: var(--text-muted);
}
a.bpx-step-inner:hover { background: var(--bpx-tint); }
.bpx-step-n {
    grid-row: 1 / span 2; width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    font-family: var(--font-headings); font-weight: 800; font-size: 0.85rem;
    border: 1.5px solid #c5cfdb; color: var(--text-muted); background: var(--bg-white);
}
.bpx-step-label { font-family: var(--font-headings); font-weight: 700; font-size: 0.9rem; line-height: 1.2; color: var(--text-muted); }
/* PM (plan doc 36.4): a value WRAPS, it is never cut with an ellipsis (the
   mockup's was). At 1440 every name fits on one line; "XLR Boost Travel
   Trailer" takes two in a 110px column at 800px, three in 71px at 320px. */
.bpx-step-value {
    font-size: 0.78rem; line-height: 1.3; color: var(--text-muted);
    overflow-wrap: anywhere;
}
.bpx-step.is-done .bpx-step-n {
    border-color: var(--bpx-stock); background: var(--bpx-stock) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") no-repeat center / 13px 13px;
    font-size: 0;
}
.bpx-step.is-done .bpx-step-label { color: var(--primary-dark); }
.bpx-step.is-done .bpx-step-value { color: var(--primary-link); font-weight: 600; }
.bpx-step.is-current .bpx-step-n { border-color: var(--primary-dark); background: var(--primary-dark); color: #fff; }
.bpx-step.is-current .bpx-step-label { color: var(--primary-dark); }
.bpx-step.is-current .bpx-step-value { color: var(--text-dark); }
@media (max-width: 768px) {
    .bpx-rail-wrap { padding-left: 16px; padding-right: 16px; }
    .bpx-rail-wrap--hero { margin-top: -22px; }
    .bpx-rail { padding: 6px 2px; border-radius: 12px; align-items: start; }
    .bpx-step-inner { grid-template-columns: minmax(0, 1fr); justify-items: center; align-content: start; text-align: center; row-gap: 3px; padding: 6px 4px; }
    .bpx-step-n { grid-row: auto; width: 24px; height: 24px; font-size: 0.76rem; }
    .bpx-step.is-done .bpx-step-n { background-size: 11px 11px; }
    .bpx-step-label { font-size: 0.72rem; }
    .bpx-step-value { font-size: 0.68rem; max-width: 100%; }
    .bpx-step + .bpx-step::before { display: none; }
}

/* the hero makes room for the rail that overlaps its lower edge */
.bpx-index .bp-hero { padding-bottom: 64px; }
@media (max-width: 768px) { .bpx-index .bp-hero { padding-bottom: 48px; } }

/* ---------------------------------------------------------------------
   7.2 Index: RV-type cards
   --------------------------------------------------------------------- */
.bpx-chooser { margin-bottom: 36px; }
.bpx-chooser-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 16px; margin-bottom: 14px; }
.bpx-chooser-head h2 { font-family: var(--font-headings); font-size: 1.5rem; font-weight: 800; color: var(--primary-dark); letter-spacing: -0.01em; }
.bpx-chooser-head p { color: var(--text-muted); font-size: 0.9rem; }

.bpx-type-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.bpx-type-card {
    position: relative; display: flex; flex-direction: column; overflow: hidden;
    background: var(--bg-white); border: 1px solid var(--border-color); border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm); color: var(--text-dark); transition: var(--transition-medium);
}
.bpx-type-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-card-hover); border-color: rgba(0, 164, 228, 0.35); }
.bpx-type-card img { width: 100%; height: auto; aspect-ratio: 5 / 2; object-fit: contain; background: #fff; border-bottom: 1px solid var(--border-color); padding: 6px 0; }
.bpx-type-card-body { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 14px 16px 16px; }
.bpx-type-card b { display: block; font-family: var(--font-headings); font-size: 1.1rem; font-weight: 800; color: var(--primary-dark); line-height: 1.2; }
.bpx-type-card small { display: block; margin-top: 2px; font-size: 0.8rem; color: var(--text-muted); }
.bpx-type-card svg { flex-shrink: 0; color: var(--primary-link); }
.bpx-type-skip { font-size: 0.9rem; color: var(--text-muted); }
.bpx-type-skip a { color: var(--primary-link); font-weight: 600; text-decoration: underline; }
@media (max-width: 600px) {
    .bpx-chooser { margin-bottom: 28px; }
    .bpx-chooser-head h2, .bpx-results-head h2 { font-size: 1.25rem; }
    .bpx-type-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    .bpx-type-card img { aspect-ratio: 4 / 3; padding: 0; }
    .bpx-type-card-body { padding: 10px 12px 12px; }
    .bpx-type-card b { font-size: 0.92rem; }
    .bpx-type-card small { font-size: 0.72rem; }
    .bpx-type-card svg { display: none; }
}

/* Manufacturer landing (/build-and-price/{mfr}, no RV type): the type cards
   shrink to one compact row so that manufacturer's lines start on the first
   screen. */
.bpx-type-grid.is-compact { grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: 12px; }
.bpx-type-grid.is-compact .bpx-type-card svg { display: none; }
.bpx-type-grid.is-compact .bpx-type-card { flex-direction: row; align-items: stretch; border-radius: 12px; }
.bpx-type-grid.is-compact .bpx-type-card:hover { transform: none; }
.bpx-type-grid.is-compact .bpx-type-card img { flex: 0 0 72px; width: 72px; height: auto; aspect-ratio: 4 / 3; padding: 0; border-bottom: 0; border-right: 1px solid var(--border-color); }
.bpx-type-grid.is-compact .bpx-type-card-body { flex: 1; min-width: 0; padding: 8px 12px; }
.bpx-type-grid.is-compact .bpx-type-card b { font-size: 0.92rem; }
.bpx-type-grid.is-compact .bpx-type-card small { font-size: 0.76rem; }
.bpx-chooser.is-aside { margin-bottom: 22px; }
.bpx-chooser.is-aside .bpx-chooser-head { margin-bottom: 8px; }
.bpx-chooser.is-aside .bpx-chooser-head h2 { font-size: 1.05rem; letter-spacing: 0; }
.bpx-chooser.is-aside + .bpx-results-head { margin-bottom: 10px; }
/* PM (plan doc 36.1): on phones the manufacturer landing has no compact type
   row: the RV-type control in the search card does that job. */
@media (max-width: 600px) {
    .bpx-chooser.is-aside { display: none; }
}

/* ---------------------------------------------------------------------
   7.3 Index: results heading, search card, line cards, empty state
   --------------------------------------------------------------------- */
.bpx-results-head { margin: 0 0 16px; }
.bpx-results-head h2 {
    font-family: var(--font-headings); font-size: 1.5rem; font-weight: 800; color: var(--primary-dark);
    letter-spacing: -0.01em; line-height: 1.2;
}
.bpx-results-head h2:focus { outline: none; }
.bpx-results-head p { margin-top: 4px; color: var(--text-muted); font-size: 0.92rem; }
.bpx-results-head .bpx-scope-note a { color: var(--primary-link); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.bpx-results-anchor { scroll-margin-top: 96px; }

/* Search card layout: one grid, re-placed per breakpoint, so the SAME
   controls serve desktop and phone (no duplicated markup except the RV
   type control: pills on wide screens, a select below 900px). */
.bpx-search-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas:
        "search mfr sort"
        "pills pills pills"
        "meta meta meta";
    gap: 10px;
    align-items: stretch;
}
.bpx-g-search { grid-area: search; }
.bpx-g-mfr { grid-area: mfr; }
.bpx-search-grid .bpx-g-type { grid-area: type; display: none; }
.bpx-g-sort { grid-area: sort; }
.bpx-search-grid .bpx-g-pills { grid-area: pills; flex-wrap: wrap; overflow: visible; padding-bottom: 0; }
.bpx-g-meta { grid-area: meta; }

.bp-filter-section--floating .bpx-g-search { width: auto; }
.bp-filter-section--floating .bpx-g-search input { min-height: 44px; }
.bpx-search-grid .bp-sort-menu { min-width: 220px; }
.bpx-search-grid .search-card-meta { margin-top: 0; min-height: 24px; }
.bpx-search-grid .search-card-tags { min-width: 0; max-width: 100%; }
/* a 60-character term with no space must wrap inside its tag, not widen the page */
.bpx-search-grid .search-card-tag { gap: 2px; padding: 0 2px 0 10px; min-height: 24px; max-width: 100%; overflow-wrap: anywhere; }
.bpx-search-grid .search-card-tag button,
.bpx-search-grid .search-card-tag a {
    display: inline-flex; align-items: center; justify-content: center;
    background: none; border: 0; min-width: 24px; min-height: 24px; padding: 0 4px; font-size: 1rem; line-height: 1;
    color: var(--text-muted); cursor: pointer; border-radius: 999px; text-decoration: none;
}
.bpx-search-grid .search-card-tag button:hover,
.bpx-search-grid .search-card-tag a:hover { color: var(--text-dark); }
.bpx-clear-all {
    background: none; border: 0; padding: 2px 4px; font: inherit; font-size: 0.78rem; font-weight: 600;
    color: var(--primary-link); text-decoration: underline; cursor: pointer;
}

.bpx-select-wrap { position: relative; display: block; min-width: 0; }
.bpx-select {
    -webkit-appearance: none; appearance: none;
    width: 100%; min-width: 0; height: 100%; min-height: 44px;
    padding: 0 36px 0 14px;
    border: 1px solid var(--border-color); border-radius: var(--radius-sm);
    background: var(--bg-white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235c5e62' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat right 12px center / 14px 14px;
    font-family: var(--font-body); font-size: max(16px, 1rem); font-weight: 600; color: var(--text-dark);   /* 16px minimum: section 8.6 */
    text-overflow: ellipsis; white-space: nowrap; overflow: hidden; cursor: pointer;
}
.bpx-select:hover { border-color: var(--primary-light); }
.bpx-select.is-set { border-color: var(--primary-link); background-color: var(--bpx-tint); color: var(--primary-dark); }
.bpx-g-mfr .bpx-select { min-width: 210px; }

.bp-type-pills .filter-pill { cursor: pointer; min-height: 36px; font-family: var(--font-body); }
/* a choice that would lead to an empty list is switched off rather than offered */
.bp-type-pills .filter-pill:disabled { opacity: 0.45; border-style: dashed; cursor: not-allowed; }
.bp-type-pills .filter-pill:disabled:hover { border-color: var(--border-color); color: var(--text-muted); }

@media (max-width: 899px) {
    .bpx-search-grid {
        grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto;
        grid-template-areas:
            "search search sort"
            "mfr type type"
            "meta meta meta";
        gap: 8px;
    }
    .bpx-search-grid .bpx-g-type { display: block; }
    .bpx-search-grid .bpx-g-pills { display: none; }
    .bpx-g-mfr .bpx-select { min-width: 0; }
    .bpx-select { padding-left: 10px; padding-right: 26px; background-position: right 8px center; background-size: 12px 12px; }
}
/* a manufacturer with a single line: no type filter and no sort to offer */
.bpx-single .bpx-search-grid .bpx-g-type, .bpx-single .bpx-search-grid .bpx-g-pills, .bpx-single .bpx-search-grid .bpx-g-sort { display: none; }
.bpx-single .bpx-search-grid { grid-template-areas: "search search mfr" "meta meta meta"; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; }
@media (max-width: 899px) {
    .bpx-single .bpx-search-grid { grid-template-areas: "search search search" "mfr mfr mfr" "meta meta meta"; }
}

/* 601-768px: section 6 drops both grids to ONE column at 768, which makes a
   736px-wide card. Two or three columns read better on a tablet; phones are
   handled below. */
@media (min-width: 601px) and (max-width: 768px) {
    .bpx-index .bp-line-grid { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); }
    .bpx-line-wrap .bp-fp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Line cards: additions on top of section 1's .bp-line-card */
.bpx-index .bp-line-card-img { background-color: #fff; }
.bpx-index .bp-line-card-img img { object-fit: contain; }
.bpx-qual { font-weight: 600; color: var(--primary-link); }
.bpx-stock-line {
    display: flex; align-items: center; gap: 6px; margin-top: 4px;
    font-size: 0.8rem; font-weight: 600; color: var(--bpx-stock);
}
.bpx-stock-line::before {
    content: ""; flex-shrink: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--bpx-stock);
}
.bpx-stock-line.is-zero { color: var(--text-muted); font-weight: 500; }
.bpx-stock-line.is-zero::before { background: none; border: 1.5px solid #b8bcc4; }

/* Empty state: a card, with ways out */
.bpx-empty {
    background: var(--bg-white); border: 1px dashed #c5cfdb; border-radius: var(--radius-md);
    padding: 36px 24px; text-align: center;
}
.bpx-empty h2, .bpx-empty h3 {
    font-family: var(--font-headings); font-size: 1.3rem; font-weight: 800; color: var(--primary-dark); margin-bottom: 8px;
    overflow-wrap: anywhere;
}
.bpx-empty p { color: var(--text-muted); font-size: 0.95rem; max-width: 56ch; margin: 0 auto; }
.bpx-empty-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 20px; }
.bpx-empty-actions .btn { padding: 10px 18px; font-size: 0.8rem; text-transform: none; letter-spacing: 0; min-height: 44px; max-width: 100%; white-space: normal; overflow-wrap: anywhere; }

/* Phones: compact row cards (owner, plan doc 36.1) */
@media (max-width: 600px) {
    .bpx-index .bp-line-grid { gap: 10px; }
    .bpx-index .bp-line-card { flex-direction: row; align-items: stretch; border-radius: 12px; }
    .bpx-index .bp-line-card:hover { transform: none; }
    .bpx-index .bp-line-card-img { flex: 0 0 34%; max-width: 132px; aspect-ratio: auto; min-height: 92px; }
    .bpx-index .bp-line-card-body {
        display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 8px; row-gap: 2px;
        align-content: center; padding: 10px 10px 10px 12px;
    }
    .bpx-index .bp-line-card-body > * { grid-column: 1; min-width: 0; }
    .bpx-index .bp-line-card-name { font-size: 1rem; }
    .bpx-index .bp-line-card-by { font-size: 0.76rem; }
    .bpx-index .bp-type-tag {
        background: none; padding: 0; margin: 0; border-radius: 0; text-transform: none; letter-spacing: 0;
        font-size: 0.76rem; font-weight: 600;
    }
    .bpx-index .bpx-stock-line { font-size: 0.74rem; margin-top: 2px; }
    .bpx-index .bp-line-card .btn {
        grid-column: 2; grid-row: 1 / span 5; align-self: center; margin: 0; width: 36px; height: 36px; padding: 0;
        border-radius: 50%; font-size: 0; letter-spacing: 0; box-shadow: none;
    }
    .bpx-index .bp-line-card .btn::before {
        content: ""; width: 9px; height: 9px; margin-left: -3px;
        border-top: 2.5px solid var(--primary-dark); border-right: 2.5px solid var(--primary-dark); transform: rotate(45deg);
    }
    .bpx-index .bp-card-link:focus-visible::after { border-radius: 12px; }
}

/* ---------------------------------------------------------------------
   7.4 Line page (and the back link, reused by the builder)
   --------------------------------------------------------------------- */
.bpx-back {
    display: inline-flex; align-items: center; gap: 6px; min-height: 32px; margin-bottom: 14px;
    font-size: 0.88rem; font-weight: 600; color: var(--primary-link);
}
.bpx-back:hover { text-decoration: underline; }
.bpx-back svg { flex-shrink: 0; }

.bp-wrap.bpx-line-wrap { padding-top: 8px; }
.bpx-line-wrap .bp-line-hero { margin-bottom: 32px; align-items: start; }
.bpx-line-wrap .bp-line-hero-img { background-color: #fff; }
.bpx-line-wrap .bp-line-hero-img img { object-fit: contain; }
.bpx-line-wrap .bp-line-hero h1 { overflow-wrap: anywhere; }
.bpx-line-wrap .bp-line-desc { overflow-wrap: anywhere; }       /* one long word must not widen the page */
.bpx-line-wrap .bp-line-desc p { color: var(--text-muted); line-height: 1.7; }
.bpx-line-wrap .bp-line-desc > * + * { margin-top: 10px; }
/* The descriptions are paragraphs today; the plugin's allow-list also lets
   lists, headings, quotes and links through (Rvcatalog::safe_html()), so
   these get the page's typography. A quote is indented: no bar on its left. */
.bpx-line-wrap .bp-line-desc :is(li, blockquote) { color: var(--text-muted); line-height: 1.7; }
.bpx-line-wrap .bp-line-desc :is(ul, ol) { padding-left: 1.4em; }
.bpx-line-wrap .bp-line-desc ul { list-style: disc; }
.bpx-line-wrap .bp-line-desc ol { list-style: decimal; }
.bpx-line-wrap .bp-line-desc :is(h2, h3, h4, h5, h6) {
    font-family: var(--font-headings); font-size: 1.05rem; font-weight: 700; line-height: 1.3; color: var(--primary-dark);
}
.bpx-line-wrap .bp-line-desc blockquote { padding: 0 1.4em; font-style: italic; }
.bpx-line-wrap .bp-line-desc a { color: var(--primary-link); text-decoration: underline; }

/* Stock (plan doc 37; owner, 2026-10-09): a quiet way to inventory, not a
   second call to action. It is the last item of the "by ..." line
   (span.bpx-meta-stock#bpx-stock): a link when there are units to show,
   plain words when there are none; then the manufacturer's listing is one
   plain line after the floorplans (.bpx-stock-after). No card, no box and
   no coloured bar on a left edge (owner rule, 2026-10-08).
   The item wraps as one piece ("&middot;&nbsp;12 in inventory"): its dot is
   never left behind at the end of a line. Up to 600px it has a line of
   its own and no dot (span.bpx-meta-dot; the phone block below).
   The link is the old card's "View them": bold, no underline until hover.
   On a touch screen its ::after makes the hit area 44px or more tall and
   adds no height; with a mouse the words are the target. (Not the padding
   and negative margin of the small links at the end of this file: at 13px
   the focus ring, drawn round the padding, would cut through the lines
   above and below.) */
.bpx-line-wrap .bpx-meta-stock { white-space: nowrap; }
.bpx-line-wrap .bpx-stock-link {
    position: relative; display: inline-block;
    font-weight: 700; color: var(--primary-link); text-decoration: none;
}
@media (pointer: coarse) {
    .bpx-line-wrap .bpx-stock-link::after { content: ""; position: absolute; inset: -13px 0; }
}
.bpx-line-wrap .bpx-stock-link:hover { text-decoration: underline; }
.bpx-line-wrap .bpx-stock-after { margin: 24px 0 0; font-size: 0.95rem; line-height: 1.6; color: var(--text-muted); }
/* keyboard: the site's ring in --primary-link, as on the menu rows (the
   global --primary-light ring is under 3:1 on the page background) */
.bpx-line-wrap .bpx-stock-link:focus-visible,
.bpx-line-wrap .bpx-desc-toggle:focus-visible,
.bpx-line-wrap .bpx-photo-toggle:focus-visible { outline-color: var(--primary-link); }

/* The description shows its first lines at every width: five from 1025px
   (they and the button stay inside the photo's height, so the floorplans
   start at the same place for every line), three up to 1024px, two up to
   600px. The rest is one click away and never leaves the HTML (the clamp
   is overflow, not display:none). -webkit-line-clamp counts lines across
   paragraphs, lists and headings, so a two-paragraph description needs
   nothing special. js/src/build-line.js adds the "Read more" button after
   the description, and only while the clamp hides something.
   The text column is a one-column grid so that the button can share the
   description's cell: it sits at the end of the last visible line, on a
   fade to the page background; open, it takes the row under the text.
   44px to tap either way. */
.bpx-line-wrap .bpx-hero-text { display: grid; grid-template-columns: minmax(0, 1fr); }
.bpx-line-wrap .bpx-hero-text > * { grid-column: 1; }
.bpx-line-wrap .bp-line-hero { scroll-margin-top: 85px; }       /* "Show less" brings it back under the 73px header */
.bpx-line-wrap .bp-line-desc { grid-row: 3; }
.bpx-line-wrap .bp-line-desc:not(.is-open) {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 5; line-clamp: 5; overflow: hidden;
}
.bpx-line-wrap .bpx-desc-toggle {
    display: inline-flex; align-items: flex-end; gap: 4px;
    grid-row: 3; align-self: end; justify-self: end; z-index: 1;
    min-height: 44px; margin: 0; padding: 0 0 4px 34px; border: 0; cursor: pointer;
    background: linear-gradient(to right, rgba(248, 249, 250, 0), var(--bg-light) 26px) bottom / 100% 26px no-repeat;
    font-family: var(--font-body); font-size: 0.88rem; font-weight: 600; line-height: 1.2; color: var(--primary-link);
}
.bpx-line-wrap .bpx-desc-toggle[aria-expanded="true"] {
    grid-row: 4; justify-self: start; align-items: center; margin: -9px 0; padding: 0 4px 0 0; background: none;
}
.bpx-line-wrap .bpx-desc-toggle:hover .bpx-desc-toggle-label { text-decoration: underline; }
.bpx-line-wrap .bpx-desc-toggle svg { flex-shrink: 0; transition: transform 0.2s; }
.bpx-line-wrap .bpx-desc-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
/* forced colours drop the fade (a gradient), so the button takes the row
   under the text, where it also is when open */
@media (forced-colors: active) {
    .bpx-line-wrap .bpx-desc-toggle { grid-row: 4; justify-self: start; align-items: center; margin: -9px 0; padding: 0 4px 0 0; background: none; }
}

/* Up to 1024px (plan doc 37): the floorplans start on the first screen.
   The back link is not shown (rail step 2, "Model line", is the same link
   and gets the same href from build-line.js; the element and its id stay
   in the HTML). The hero stays two columns with a medium photo (section 6
   makes it one column with a photo up to 976px wide); three lines of
   description. The rail is not touched.
   The three layouts are this block, the next one and the rules above, by
   max-width only: no width, whole or fractional (browser zoom), falls
   between them. */
@media (max-width: 1024px) {
    .bpx-line-wrap .bpx-back { display: none; }
    .bp-wrap.bpx-line-wrap { padding-top: 14px; }
    .bpx-line-wrap .bp-line-hero { grid-template-columns: clamp(220px, 32vw, 320px) minmax(0, 1fr); gap: 0 24px; margin-bottom: 24px; }
    .bpx-line-wrap .bp-line-hero .bp-line-meta { margin-bottom: 10px; }
    .bpx-line-wrap .bp-line-desc:not(.is-open) { -webkit-line-clamp: 3; line-clamp: 3; }
}

/* Up to 600px (plan doc 37.13, 37.14; owner, 2026-10-09): the title; the
   "by ..." line directly under it, without the RV type (span.bpx-meta-type:
   the type is the value of rail step 1 right above, and without it the
   line stays on ONE line on every phone, which is what keeps the
   floorplans on the first screen for the lines with long type names); the
   stock item on a line of its own, without its dot; the photo in a
   full-width band; two lines of description; the floorplans. The text wrapper steps aside (display:
   contents) so its children sit on the hero's one-column grid, and every
   piece is placed by row: the photo is still first in the HTML. The
   sub-text under "Choose your floorplan" is not shown.

   The band. Every line photo is a 4:3 cut-out on white, and the vehicle
   with its shadow fills up to 86% of the picture's height, not always
   centred: a `cover` crop to a band would cut roofs and wheels. So the
   whole photo is shown (contain) and enlarged by 12%, which trims 5.4% of
   the picture at the top and at the bottom: white that every line photo
   has (82 lines, 2026-10-09). The photo is fitted to the band's HEIGHT, so that trim is the
   same whatever the band's shape; a wider shape only makes the photo
   smaller. Do not raise the 1.12: a photo with less white round it would
   be the first to lose its roof.

   Enlarging. js/src/build-line.js adds one small button (no button without
   the script) and makes the whole band tap it: .is-open is the full 4:3
   photo at its natural scale, which pushes the page down; again, and it is
   the band. In the HTML the button comes AFTER the "by ..." paragraph, so
   that it is focused and read after the stock item, as it is seen; the
   text wrapper steps aside on phones, so the button is an item of the
   hero's grid and shares the photo's cell: its bottom right corner, 8px
   inside the band's border. It lies over the band, so adding it moves
   nothing. That corner is outside the photo while the band is closed (the
   photo takes the middle 60% of the band's width). Above 600px the button
   is display:none (and hidden), so it is no item of the text column's
   grid there. */
.bpx-line-wrap .bpx-photo-toggle { display: none; }
@media (max-width: 600px) {
    .bp-wrap.bpx-line-wrap { padding-top: 10px; }
    .bpx-line-wrap .bp-line-hero { grid-template-columns: minmax(0, 1fr); gap: 0; margin-bottom: 10px; }
    .bpx-line-wrap .bpx-hero-text { display: contents; }
    .bpx-line-wrap .bp-line-hero h1 { grid-row: 1; margin-bottom: 4px; font-size: 1.85rem; }
    .bpx-line-wrap .bp-line-hero .bp-line-meta { grid-row: 2; margin: 0 0 8px; line-height: 1.55; }
    .bpx-line-wrap .bpx-meta-stock { display: block; }
    .bpx-line-wrap .bpx-meta-type,
    .bpx-line-wrap .bpx-meta-dot { display: none; }
    .bpx-line-wrap .bp-line-hero-img { grid-column: 1; grid-row: 3; aspect-ratio: 5 / 2; scroll-margin-top: 85px; }
    .bpx-line-wrap .bp-line-hero-img img { transform: scale(1.12); }
    .bpx-line-wrap .bp-line-hero-img.is-open { aspect-ratio: 4 / 3; }
    .bpx-line-wrap .bp-line-hero-img.is-open img { transform: none; }
    .bpx-line-wrap .bp-line-hero-img.has-toggle { cursor: pointer; }
    /* quiet: white, the cards' border, a dark icon. Not a call to action. */
    .bpx-line-wrap .bpx-photo-toggle {
        display: inline-flex; align-items: center; justify-content: center;
        position: relative; z-index: 1; grid-row: 3; align-self: end; justify-self: end;
        width: 32px; height: 32px; margin: 0 9px 9px 0; padding: 0;
        border: 1px solid var(--border-color); border-radius: 50%; background: rgba(255, 255, 255, 0.92);
        color: var(--primary-dark); cursor: pointer;
    }
    .bpx-line-wrap .bpx-photo-toggle .bpx-photo-less,
    .bpx-line-wrap .bpx-photo-toggle[aria-expanded="true"] .bpx-photo-more { display: none; }
    .bpx-line-wrap .bpx-photo-toggle[aria-expanded="true"] .bpx-photo-less { display: block; }
    .bpx-line-wrap .bp-line-desc { grid-row: 4; margin-top: 8px; }
    .bpx-line-wrap .bp-line-desc:not(.is-open) { -webkit-line-clamp: 2; line-clamp: 2; }
    .bpx-line-wrap .bpx-desc-toggle { grid-row: 4; }
    .bpx-line-wrap .bpx-desc-toggle[aria-expanded="true"] { grid-row: 5; }
    .bpx-line-wrap .bp-section-heading { margin-bottom: 10px; }
    .bpx-line-wrap .bp-section-sub { display: none; }
}
/* The smallest phones (360 x 640: about 530px of page on the first screen):
   a slightly wider band, 12% less tall, and a smaller title (one that
   wraps costs less), so that "Choose your floorplan" is whole on that
   screen for every line. The photo is fitted to the band's height, so the
   12% rule above holds unchanged. 374px is the header's seam too (ee.css). */
@media (max-width: 374px) {
    .bpx-line-wrap .bp-line-hero h1 { font-size: 1.7rem; }
    .bpx-line-wrap .bp-line-hero-img { aspect-ratio: 14 / 5; }
}
@media (max-width: 600px) and (pointer: coarse) {
    /* the whole band is the target; this is for a finger that aims at the
       button: 30px inside its border + 7 + 7 = 44 */
    .bpx-line-wrap .bpx-photo-toggle::after { content: ""; position: absolute; inset: -7px; }
    /* the stock link's 44px must stop short of the band 8px under it */
    .bpx-line-wrap .bp-line-meta .bpx-stock-link::after { inset: -16px 0 -7px; }
}
@media (max-width: 600px) and (forced-colors: active) {
    .bpx-line-wrap .bpx-desc-toggle { grid-row: 5; }
}

/* Never a clamp without a way out of it. After every rule that sets a line
   count, the text is shown in full and there is no button:
   - without JavaScript (no button can be added);
   - on paper;
   - when the page script did not arrive or the button could not be made:
     site/.footer-v2 (onerror on the script tag) or build-line.js (catch)
     then puts .page-js-failed on <html>. */
@media (scripting: none) {
    .bpx-line-wrap .bp-line-desc:not(.is-open) { display: block; overflow: visible; -webkit-line-clamp: none; line-clamp: none; }
}
@media print {
    .bpx-line-wrap .bp-line-desc:not(.is-open) { display: block; overflow: visible; -webkit-line-clamp: none; line-clamp: none; }
    .bpx-line-wrap .bpx-desc-toggle,
    .bpx-line-wrap .bpx-photo-toggle { display: none; }
}
.page-js-failed .bpx-line-wrap .bp-line-desc:not(.is-open) { display: block; overflow: visible; -webkit-line-clamp: none; line-clamp: none; }
.page-js-failed .bpx-line-wrap .bpx-desc-toggle { display: none; }

/* a floorplan without a drawing */
.bpx-fp-sample .bp-fp-img { background: repeating-linear-gradient(135deg, #fbfcfd 0 12px, #f3f6f9 12px 24px); }

/* the ways on: other lines of the type, another type, a manufacturer */
.bpx-more { margin-top: 56px; padding-top: 32px; border-top: 1px solid var(--border-color); }
.bpx-more + .bpx-more { margin-top: 32px; }
.bpx-more-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 16px; margin-bottom: 14px; }
.bpx-more-head h2 { font-family: var(--font-headings); font-size: 1.25rem; font-weight: 800; color: var(--primary-dark); }
.bpx-more-head a { font-size: 0.88rem; font-weight: 600; color: var(--primary-link); }
.bpx-more-head a:hover { text-decoration: underline; }

.bpx-strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 14px; }
.bpx-mini {
    position: relative; display: flex; flex-direction: column; background: var(--bg-white);
    border: 1px solid var(--border-color); border-radius: 12px; box-shadow: var(--shadow-sm); overflow: hidden;
    transition: var(--transition-fast);
}
.bpx-mini:hover { border-color: rgba(0, 164, 228, 0.45); box-shadow: var(--shadow-md); }
.bpx-mini img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: contain; background: #fff; border-bottom: 1px solid var(--border-color); }
.bpx-mini-body { padding: 10px 12px 12px; }
.bpx-mini-name { display: block; font-family: var(--font-headings); font-weight: 800; font-size: 0.95rem; color: var(--primary-dark); line-height: 1.2; }
.bpx-mini-by { display: block; font-size: 0.76rem; color: var(--text-muted); margin-top: 2px; }
.bpx-mini a::after { content: ""; position: absolute; inset: 0; }
.bpx-mini a:focus-visible { outline: none; }
.bpx-mini a:focus-visible::after { outline: 3px solid var(--primary-light); outline-offset: -3px; border-radius: 12px; }
@media (max-width: 600px) {
    .bpx-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
}

.bpx-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.bpx-chip {
    display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 6px 14px;
    background: var(--bg-white); border: 1px solid var(--border-color); border-radius: 999px;
    font-family: var(--font-headings); font-weight: 700; font-size: 0.9rem; color: var(--primary-dark);
    transition: var(--transition-fast);
}
.bpx-chip:hover { border-color: var(--primary-light); color: var(--primary-link); }
.bpx-chip small { font-family: var(--font-body); font-weight: 600; font-size: 0.74rem; color: var(--text-muted); }
.bpx-chip[aria-current="true"] { background: var(--primary-dark); border-color: var(--primary-dark); color: #fff; }
.bpx-chip[aria-current="true"] small { color: rgba(255, 255, 255, 0.7); }

@media (prefers-reduced-motion: reduce) {
    .bpx-type-card, .bpx-mini, .bpx-chip, .bpx-line-wrap .bpx-desc-toggle svg { transition: none; }
    .bpx-type-card:hover { transform: none; }
}

/* =====================================================================
   8. Builder (site/.bp-options-v2, plan doc 36.6, package D)

   What the builder adds to sections 3-6 above (which package D edited in
   place: the card and its lead form (section 4, reworked 2026-10-08 on
   the owner's review), the <=1024px order, the price bar's breakpoint,
   the breadcrumb rules that left with the breadcrumb).
   The rail (7.1) and the back link (7.4) are package C's, used as they
   are. Everything here is scoped to body.bp-builder or to classes only
   the builder prints.
   ===================================================================== */

/* ---- 8.1 the back link under the rail ---- */
.bpx-builder-context { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.bpx-builder-context .bpx-back { margin-bottom: 0; }
@media (max-width: 768px) { .bpx-builder-context { padding: 0 16px; } }

/* ---- 8.2 in the card: the note under the price when rvmachine cannot be
        reached, and the rule notices ---- */
.bp-quote-note { margin-top: 8px; font-size: 0.78rem; line-height: 1.45; color: #7a5500; }
#bp-card-notices .bp-dep-notice { margin: 10px 0 0; }

/* Laptop heights (window 847px tall or less, from 1,025px wide). Goal
   (owner, 2026-10-08): the whole card inside the window at first load,
   1366x768 included. The threshold is measured, not round: the normal card
   (Riverstone 39RKFB: 625px from 207px) ends at 832px, so it needs a window
   of 832px, and 848px to keep the 16px under it that initCardStick keeps
   everywhere else. Below that this compact arrangement applies (it first
   stopped at 800px, and windows 801-831px tall got the normal card, cut
   off: plan doc 36.13). A window under 748px (1280x720) still ends 28px
   short: the design is not shrunk further, the card travels with the page.
   The card's own rhythm is left alone; the room comes from around it:
     - the rail sits 10px under the header (16px elsewhere) and the layout
       starts 8px under the back link (16px);
     - the card starts level with the back link, in the empty right half of
       that row (-32px), instead of under it;
     - the two assurance words are not shown, and the card's padding is
       16 / 18px (20 / 18px elsewhere).
   Riverstone 39RKFB: 587px from 161px = bottom edge at 748px. A taller card
   (a rule notice, the failure note, a two-line title, a selection that
   wraps the summary) travels with the page instead: build.js initCardStick. */
@media (min-width: 1025px) and (max-height: 847px) {
    .bp-builder .bpx-rail-wrap--page { padding-top: calc(73px + 10px); }
    .bp-builder .bp-build-layout { padding-top: 8px; }
    .bp-build-col { margin-top: -32px; }
    .bp-card-assurance { display: none; }
    .bp-build-card { padding-top: 16px; padding-bottom: 18px; }
}

/* ---- 8.3 a factory standard that a rule has removed ---- */
.bp-opt.locked.is-removed { border-color: var(--border-color); background-color: var(--bg-light); }
.bp-opt.locked.is-removed .bp-opt-title { text-decoration: line-through; color: var(--text-muted); }
.bp-opt.locked.is-removed .bp-lock-check { background-color: #a9b3bf; }
.bp-opt.locked.is-removed .bp-included-tag { background-color: rgba(122, 85, 0, 0.12); color: #7a5500; }

/* ---- 8.4 fixed price bar: up to 1,024px, away while the form is on screen.
        Staff: the sale price, not struck through, in the unit page's bar style ---- */
.bp-mobile-bar .bar-price--sale { color: var(--primary-link); text-decoration: none; }
.bp-mobile-bar .bar-sub:empty { display: none; }
.bp-mobile-bar { transition: transform 0.2s ease, visibility 0.2s; }
.bp-mobile-bar.is-away { transform: translateY(110%); visibility: hidden; }
@media (max-width: 1024px) {
    /* Room under the footer (plan doc 38): at the end of the page the
       footer's bottom edge is the window's, so the bar covered the last
       lines of the disclaimer. The footer that follows the bar gets the
       bar's height (72.8px) plus its safe-area term as extra bottom
       padding, in its own colour; its own 32px stay above the bar as the
       gap. Not when build.js has taken the bar out ("Build not found":
       fail() sets an inline display: none), and it does not follow
       .is-away: nothing at the end of the page moves. The index and line
       pages have no bar, so no room. */
    .bp-mobile-bar:not([style*="display: none"]) ~ .site-footer { padding-bottom: calc(73px + env(safe-area-inset-bottom, 0px)); }
}
@media (min-width: 601px) and (max-width: 1024px) {
    .bp-mobile-bar { padding-left: 24px; padding-right: 24px; }
    .bp-mobile-bar .btn { flex: 0 1 360px; margin-left: auto; }
}

/* ---- 8.5 phones (B10): the option title gets a line of its own; the
        price, the "Included" tag, the photo and "Details" share the next.
        The label still covers the whole row as the tap target. ---- */
@media (max-width: 480px) {
    .bp-opt-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 0; }
    .bp-opt-label {
        grid-column: 1 / -1; grid-row: 1 / span 2;
        display: grid; grid-template-columns: 20px minmax(0, 1fr); align-items: start; gap: 6px 12px;
        padding: 13px 14px 12px;
    }
    .bp-opt-label > input, .bp-opt-label > .bp-lock-check { grid-column: 1; grid-row: 1; margin-top: 1px; }
    .bp-opt-text { grid-column: 2; grid-row: 1; }
    .bp-opt-price, .bp-included-tag { grid-column: 2; grid-row: 2; justify-self: start; }
    .bp-opt-price, .bp-opt-price.included { line-height: 22px; }
    .bp-opt-extras { grid-column: 2; grid-row: 2; position: relative; z-index: 1; padding: 0 10px 6px 0; }
    .bp-opt-desc { padding-left: 46px; }
    .bp-dep-notice { flex-wrap: wrap; }
}

/* ---- 8.6 Form controls are never smaller than 16px (owner, 2026-10-08:
        the default for this project). Below 16px iOS Safari zooms the page
        when a field takes focus. This is the floor for every input, select
        and textarea on the three Build & Price pages (body.bp-page), the
        option boxes and hidden fields included; the rules that size a
        visible control (.bp-search-wrapper input, .bpx-select, the lead
        form's fields) say the same. Nothing in the app2 bundle is
        overridden: none of its rules sized a control on these pages. ---- */
body.bp-page input,
body.bp-page select,
body.bp-page textarea { font-size: max(16px, 1rem); }

@media (prefers-reduced-motion: reduce) {
    .bp-mobile-bar { transition: none; }
}

/* ---- 8.7 After the independent QA (plan doc 36.13) ---- */

/* The retail total while rvmachine's answer for a changed build is on its
   way (or cannot be had): the last confirmed figure, dimmed. The public
   page holds no option prices to move it by. Opacity only: nothing moves. */
.bp-retail, .bp-mobile-bar .bar-price { transition: opacity 0.2s ease; }
.bp-retail.is-pending, .bp-mobile-bar .bar-price.is-pending { opacity: 0.5; }

/* Option rows without an amount (the public page). Desktop: title, then the
   photo and "Details" at the right, as before minus the price. Phones (8.5):
   the second line used to hold the price next to the photo / "Details"; a
   row that has those keeps that line, so they never sit on the title. */
@media (max-width: 480px) {
    .bp-opt--plain.bp-opt--extras .bp-opt-label::after { content: ""; grid-column: 2; grid-row: 2; height: 22px; }
}

/* Up to 1,024px the fixed price bar (about 70px) covers the bottom of the
   window: a control that takes keyboard focus is scrolled clear of it. The
   option boxes sit at the top of a row that is the real target: 52px tall,
   and on phones up to about 105px (a title of three lines over the photo /
   "Details" line), hence the larger figure there. */
@media (max-width: 1024px) {
    body.bp-builder main a, body.bp-builder main button, body.bp-builder main input,
    body.bp-builder main select, body.bp-builder main textarea, body.bp-builder main [tabindex] { scroll-margin-bottom: 104px; }
}
@media (max-width: 480px) {
    body.bp-builder main .bp-opt input { scroll-margin-bottom: 172px; }
}

/* Line page: the two kinds of small text link get a hit area at least 24px
   tall. Padding and an equal negative margin: nothing moves. */
.bpx-more-head a { display: inline-block; padding: 4px 0; margin: -4px 0; }
.bpx-mini-name { padding: 4px 0; margin: -4px 0; }

/* The 404 / 503 page (site/.bp-notfound-v2): its message is the H1, and the
   hero line above it is a paragraph that looks like the other pages' H1. */
.bp-hero .bp-hero-title {
    font-family: var(--font-headings);
    font-size: 2.4rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.12;
}
.bp-empty h1 {
    font-family: var(--font-headings);
    color: var(--primary-dark);
    font-size: 1.4rem;
    margin-bottom: 8px;
}
@media (max-width: 768px) {
    .bp-hero .bp-hero-title { font-size: 1.65rem; }
}

@media (prefers-reduced-motion: reduce) {
    .bp-retail, .bp-mobile-bar .bar-price { transition: none; }
}

/* =====================================================================
   9. Index hero: the scroll-linked build video (plan doc 39)

   site/.bp-index-v2 prints section.bp-hero.bp-hero--video on the unified
   index only; js/src/build-hero.js drives it. Approved mockup:
   redesign/explore/bp-hero-video/c-compact-navy-2.html ("option C compact,
   navy with black pool").

   EVERY rule here is scoped to .bp-hero--video (or to a .bph- part inside
   it). The plain .bp-hero of the manufacturer landings, the not-found page
   and the other Build & Price pages is not touched, and this section must
   stay AFTER the .bp-hero and .bpx-index .bp-hero rules above: it wins by
   order at equal specificity.

   Layout: copy left / footage right in a two-column grid; stacked (copy,
   then a 5:3 footage box as wide as the screen) up to 700px. The ground
   is .bp-hero's own navy. The footage is an opaque 5:3 rectangle on pure
   black, so behind it sits a static pool of that same black, larger than
   the rectangle and fading to nothing into the navy: no blend mode and no
   mask on the video.

   Height, and why it never shifts:
     - split: clamp(370px, min(54svh + 40px, 28vw + 170px), 480px). svh is
       the SMALL viewport (browser bars showing): the size at load, and it
       does not change when a phone or tablet toolbar collapses. dvh is
       deliberately NOT used. The vh line before it is for browsers
       without svh.
     - stacked: no viewport-height term at all: the copy plus a 5:3 box as
       wide as the screen, known at first layout.
     - padding: 24px under the 73px fixed header and 54px at the bottom
       (30px of rail overlap + 24px clear); stacked 26px and 40px.
     - the poster carries width and height, the video is absolutely
       positioned over it, and build-hero.js only ever sets transform and
       opacity.
   ===================================================================== */
.bp-hero.bp-hero--video {
    position: relative;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: center;
    column-gap: 28px;
    height: clamp(370px, min(54vh + 40px, 28vw + 170px), 480px);
    height: clamp(370px, min(54svh + 40px, 28vw + 170px), 480px);
    padding: calc(73px + 24px) max(24px, calc(50% - 576px)) 54px;
    overflow: hidden;
    overflow: clip;
    isolation: isolate;
    color: #fff;
    text-align: left;
    /* The footage and the copy are moved with transforms while scrolling.
       Chrome restores a reloaded page relative to an "anchor" element; if it
       picks one of these the page comes back 73px out. Keep the hero out. */
    overflow-anchor: none;
}

/* ---- 9.1 footage ---- */
.bp-hero--video .bph-stage {
    position: relative;
    z-index: 0;
    grid-column: 2;
    grid-row: 1;
    align-self: stretch;
    min-width: 0;
    container-type: size;          /* the footage box is sized from the stage (cqh / cqw) */
    pointer-events: none;
}
.bp-hero--video .bph-media {
    position: absolute;
    left: 50%;
    top: 50%;
    height: 100%;                  /* browsers without container units */
    height: min(100cqh, 60cqw);    /* a 5:3 box, as large as the stage allows */
    aspect-ratio: 5 / 3;
    translate: -50% -50%;          /* layout offset; build-hero.js owns `transform` */
    will-change: transform;
}
.bp-hero--video .bph-media picture { display: contents; }
.bp-hero--video .bph-poster,
.bp-hero--video .bph-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
    border: 0;
    max-width: none;
}
.bp-hero--video .bph-poster { z-index: 1; opacity: 1; transition: opacity 0.35s ease; }
.bp-hero--video .bph-frame { z-index: 2; opacity: 0; background: #000; }

/* The black pool: solid past the corners of the footage box, then fading
   to nothing, so the opaque rectangle has no edge to show against the navy. */
.bp-hero--video .bph-media::before {
    content: "";
    position: absolute;
    inset: -60%;
    z-index: 0;
    background: radial-gradient(closest-side, #000 0, #000 66%, rgba(0, 0, 0, 0.55) 80%, rgba(0, 0, 0, 0) 100%);
}
/* The feather, painted OVER the footage. Parts fly in from outside the
   frame and would be cut off along a straight line. The crop leaves 6-7%
   of clear space round the finished RV, so the feather is 6% wide: fly-in
   parts fade at the edge, the finished RV does not. */
.bp-hero--video .bph-media::after {
    content: "";
    position: absolute;
    inset: -1px;
    z-index: 3;
    background:
        linear-gradient(to right, #000 0, rgba(0, 0, 0, 0) 6%, rgba(0, 0, 0, 0) 94%, #000 100%),
        linear-gradient(to bottom, #000 0, rgba(0, 0, 0, 0) 6%, rgba(0, 0, 0, 0) 94%, #000 100%);
}

/* poster / video states: classes on <html>, set by the inline script before
   the hero (bph-js) and by build-hero.js (bph-live, bph-static).
   No class at all (no JavaScript): the poster, the finished RV, in full. */
.bph-js .bp-hero--video .bph-poster { opacity: 0.3; }
/* build-hero.js or build-index.js did not arrive (.footer-v2's onerror):
   nothing may be left waiting for a video that will never start */
.page-js-failed .bp-hero--video .bph-poster { opacity: 1; }
.bph-live .bp-hero--video .bph-poster { opacity: 0; }
.bph-live .bp-hero--video .bph-frame { opacity: 1; }
.bph-static .bp-hero--video .bph-poster { opacity: 1; }
.bph-static .bp-hero--video .bph-frame { display: none; }

/* ---- 9.2 copy ---- */
.bp-hero--video .bph-text {
    position: relative;
    z-index: 2;
    grid-column: 1;
    grid-row: 1;
    will-change: transform, opacity;
}
.bp-hero--video .bph-text-inner { position: relative; max-width: 470px; }
.bp-hero.bp-hero--video h1 {
    font-size: clamp(1.75rem, 0.9rem + 2vw, 2.5rem);
    color: #fff;
    margin: 0;
    text-wrap: balance;
}
.bp-hero.bp-hero--video .bp-hero-sub { color: rgba(255, 255, 255, 0.92); font-size: 1.05rem; margin-top: 8px; }
.bp-hero.bp-hero--video .bp-hero-note { color: rgba(255, 255, 255, 0.8); margin-top: 10px; text-wrap: balance; }

/* load-in: CSS only, starts at first paint, needs no script and no video bytes */
@keyframes bph-rise {
    from { opacity: 0; transform: translate3d(0, 18px, 0); }
    to   { opacity: 1; transform: none; }
}
.bp-hero--video .bph-text-inner > * { animation: bph-rise 0.7s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
.bp-hero--video .bph-text-inner > :nth-child(2) { animation-delay: 0.12s; }
.bp-hero--video .bph-text-inner > :nth-child(3) { animation-delay: 0.24s; }

/* ---- 9.3 stacked ---- */
@media (max-width: 700px) {
    .bp-hero.bp-hero--video {
        display: flex;             /* the stage is first in the HTML; show the copy first */
        flex-direction: column;
        height: auto;
        padding: calc(73px + 26px) 0 40px;   /* 40 = 22px of rail overlap + 18px clear */
        text-align: center;
    }
    .bp-hero--video .bph-text { order: 1; padding: 0 16px; }
    .bp-hero--video .bph-text-inner { margin: 0 auto; }
    .bp-hero.bp-hero--video .bp-hero-sub { font-size: 0.95rem; margin-top: 4px; }
    .bp-hero.bp-hero--video .bp-hero-note { margin-top: 6px; }
    .bp-hero--video .bph-stage {
        order: 2;
        flex: none;
        align-self: center;
        width: min(100%, 520px);
        aspect-ratio: 5 / 3;
        margin: 0 auto;            /* flush: the footage starts where the copy ends. Tucking the copy
                                      into the box failed AA when a white panel flies in. */
    }
    .bp-hero--video .bph-media { height: 100%; }
}

/* ---- 9.4 no motion: the finished RV and still copy ---- */
@media (prefers-reduced-motion: reduce) {
    .bp-hero--video .bph-text-inner > * { animation: none; }
    .bp-hero--video .bph-poster { opacity: 1 !important; transition: none; }
    .bp-hero--video .bph-frame { display: none; }
}
.bph-static .bp-hero--video .bph-text-inner > * { animation: none; }
.bph-static .bp-hero--video .bph-text,
.bph-static .bp-hero--video .bph-media { transform: none !important; opacity: 1 !important; }
