/* ============================================================
   BA2 MediaMarket – BookAddiction Storefront & Admin Styles
   ============================================================ */

/* ─── ROOT VARIABLES ─── */
:root {
    /* #989 (ledger 645) — the ONE storefront font stack; every rule uses this. */
    --sf-font: 'Segoe UI', system-ui, Roboto, 'Helvetica Neue', Arial, sans-serif;
    --ba-primary: #2c3e50;
    --ba-primary-rgb: 44, 62, 80;
    --ba-primary-light: #34495e;
    --ba-primary-dark: #1a252f;
    --ba-accent: #c0392b;
    --ba-accent-rgb: 192, 57, 43;
    --ba-accent-light: #e74c3c;
    --ba-accent-hover: #a93226;
    --ba-cream: #f5f0eb;
    --ba-cream-dark: #e8dfd6;
    --ba-green: #27ae60;
    --ba-green-light: #2ecc71;
    --ba-orange: #f39c12;
    --ba-orange-light: #f1c40f;
    --ba-blue-info: #2980b9;
    --ba-body-bg: var(--ba-cream);
    --ba-card-bg: #ffffff;
    --ba-text: #333333;
    --ba-text-muted: #6c757d;
    --ba-border: #dee2e6;
    --ba-shadow: 0 2px 8px rgba(0,0,0,0.08);
    --ba-shadow-hover: 0 6px 20px rgba(0,0,0,0.12);
    --ba-radius: 0.5rem;
    --ba-transition: all 0.2s ease-in-out;

    /* ════════════════════════════════════════════════════════════════
       Ledger 767 — canonical admin list-page typography tokens.
       ONE source of truth for every admin list-type page (uniform tables
       AND the Order Block). Change a value here and every list page moves
       together — no more per-column ad-hoc font drift. Deliberate
       exceptions (e.g. bold running totals) get their OWN token below so
       they stay intentional and documented, never accidental.
       ════════════════════════════════════════════════════════════════ */
    --list-row-font-size: 0.8rem;      /* base body-cell text size          */
    --list-row-font-weight: 400;       /* base body-cell weight             */
    --list-header-font-size: 0.8rem;   /* column-header text size           */
    --list-header-font-weight: 600;    /* column-header weight              */
    --list-total-font-size: 0.8rem;    /* running-total cell size (matches) */
    --list-total-font-weight: 700;     /* DELIBERATE exception: totals bold */
    --list-helper-text-size: 0.72rem;  /* sub-labels / muted helper text    */
    --list-pill-font-size: 0.72rem;    /* status pills / count pills        */
}

/* ─── GLOBAL ─── */
html {
    scroll-behavior: smooth;
}

body {
    font-family: var(--sf-font); /* #989 unified */
    background-color: var(--ba-body-bg);
    color: var(--ba-text);
    line-height: 1.6;
}

a {
    color: var(--ba-primary);
    transition: var(--ba-transition);
}

a:hover {
    color: var(--ba-accent);
}

/* ── Hyperlink consistency (Orlando, 19 Jun 2026) ──────────────────────
   Every admin content link now matches the All Products SKU link: brand
   navy, no underline, accent-red on hover. Anchors that are really
   buttons / badges / nav / pagination / list-group keep their own styling.
   Dark mode keeps the readable link colour (never the navy-on-dark). */
main.container-fluid a:not(.btn):not(.badge):not(.nav-link):not(.dropdown-item):not(.page-link):not(.list-group-item):not(.navbar-brand):not([role="button"]) {
    color: var(--ba-primary);
    text-decoration: none;
}
main.container-fluid a:not(.btn):not(.badge):not(.nav-link):not(.dropdown-item):not(.page-link):not(.list-group-item):not(.navbar-brand):not([role="button"]):hover {
    color: var(--ba-accent);
    text-decoration: none;
}
[data-bs-theme="dark"] main.container-fluid a:not(.btn):not(.badge):not(.nav-link):not(.dropdown-item):not(.page-link):not(.list-group-item):not(.navbar-brand):not([role="button"]) {
    color: var(--bs-link-color);
}
[data-bs-theme="dark"] main.container-fluid a:not(.btn):not(.badge):not(.nav-link):not(.dropdown-item):not(.page-link):not(.list-group-item):not(.navbar-brand):not([role="button"]):hover {
    color: var(--bs-link-hover-color);
}

/* ── Zero-stock rows: greyed but fully clickable (CATFIX §122). The grey
   was specified but never actually had a CSS rule — added here. Dark mode
   keeps them legible: a dimmed light-grey rather than washed-out, overriding
   the DARKTEXT1 white-text rule for these rows only (Orlando, 19 Jun 2026). */
.ba2-row-oos td { color: var(--ba-text-muted); }
.ba2-row-oos .ba2-thumb { opacity: .5; }
.ba2-row-oos:hover td { color: var(--ba-text); }
.ba2-row-oos:hover .ba2-thumb { opacity: 1; }
[data-bs-theme="dark"] .ba2-row-oos td { color: #9aa5b1 !important; }
[data-bs-theme="dark"] .ba2-row-oos:hover td { color: #ffffff !important; }

h1, h2, h3, h4, h5, h6 {
    color: var(--ba-primary);
}

/* ─── ADMIN NAV ─── */
.navbar-admin {
    position: sticky;
    top: 0;
    z-index: var(--ba2-z-navbar);
    background: #ffffff;
    box-shadow: 0 1px 4px rgba(0,0,0,0.1);
    padding: 0.5rem 1rem;
}

.navbar-admin .navbar-brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 700;
    color: var(--ba-primary);
    text-decoration: none;
}

.navbar-admin .navbar-brand img {
    width: 40px;
    height: 40px;
    object-fit: contain;
}

.navbar-admin .nav-link {
    color: var(--ba-primary);
    font-weight: 500;
    padding: 0.5rem 0.75rem;
    position: relative;
    transition: var(--ba-transition);
}

.navbar-admin .nav-link:hover,
.navbar-admin .nav-link.active {
    color: var(--ba-accent);
}

.navbar-admin .nav-link::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    width: 0;
    height: 2px;
    background: var(--ba-accent);
    transition: var(--ba-transition);
    transform: translateX(-50%);
}

.navbar-admin .nav-link:hover::after,
.navbar-admin .nav-link.active::after {
    width: 80%;
}

/* Dropdown menus */
.navbar-admin .dropdown-menu {
    border: none;
    box-shadow: var(--ba-shadow-hover);
    border-radius: var(--ba-radius);
    padding: 0.5rem 0;
}

.navbar-admin .dropdown-item {
    padding: 0.5rem 1rem;
    transition: var(--ba-transition);
}

.navbar-admin .dropdown-item:hover {
    background-color: var(--ba-cream);
    color: var(--ba-accent);
}

/* Desktop dropdown on hover */
@media (min-width: 992px) {
    .navbar-admin .dropdown:hover .dropdown-menu {
        display: block;
        margin-top: 0;
    }
}

/* CatID badge */
.catid-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background-color: var(--ba-green);
    color: #fff;
    font-weight: 700;
    font-size: 0.75rem;
    text-transform: uppercase;
}

/* ─── ADMIN PRODUCT FORM ─── */
.product-form .form-group.required .form-label::after {
    content: ' *';
    color: var(--ba-accent);
    font-weight: 700;
}

.product-form .form-control.field-required {
    border: 2px solid var(--ba-primary);
    border-width: 2px;
}

.product-form .form-control.field-required:focus {
    border-color: var(--ba-accent);
    box-shadow: 0 0 0 0.2rem rgba(var(--ba-accent-rgb), 0.25);
}

/* 30 Jul 2026 — the two rules above never matched (form uses #productForm, not
   .product-form; labels use .ba2-flabel, not .form-label). These are the only
   three fields BA2 actually rejects a save for (ProductsController.Create:
   ConditionId, ProductTypeId, Title) — mark them so a cataloguer can see it. */
#productForm .ba2-required-marker::after {
    content: ' *';
    color: #dc3545;
    font-weight: 700;
}

#productForm .ba2-field-required {
    border-width: 2px !important;
}

/* Light-mode error background — dark-mode equivalent already defined at
   [data-bs-theme="dark"] #productForm .ba2-field-error (75% red, line ~1399).
   No light-mode base rule existed for this class before 30 Jul 2026. */
#productForm .ba2-field-error {
    background-color: var(--ba2-error-bg-light, rgba(220, 53, 69, .10)) !important;
}

.product-form .two-column {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

@media (max-width: 768px) {
    .product-form .two-column {
        grid-template-columns: 1fr;
    }
}

/* Sticky field toggle */
.sticky-field-toggle {
    position: absolute;
    top: 0;
    right: 0;
}

.sticky-field-toggle input[type="checkbox"] {
    accent-color: var(--ba-accent);
    width: 16px;
    height: 16px;
    cursor: pointer;
}

.sticky-field-toggle input[type="checkbox"]:checked + label,
.sticky-field-toggle .sticky-active {
    color: var(--ba-accent);
    font-weight: 600;
}

/* DJ section conditional styling */
.dj-section {
    transition: opacity 0.3s ease, max-height 0.3s ease;
}

.dj-section.hidden {
    opacity: 0.4;
    pointer-events: none;
}

/* ─── SOLD OVERLAY ─── */
.sold-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    pointer-events: none;
    z-index: var(--ba2-z-base);
}

.sold-overlay::after {
    content: 'SOLD';
    position: absolute;
    top: 20px;
    left: -35px;
    width: 140px;
    padding: 4px 0;
    background: var(--ba-accent);
    color: #ffffff;
    font-weight: 800;
    font-size: 0.85rem;
    text-align: center;
    text-transform: uppercase;
    letter-spacing: 2px;
    transform: rotate(-45deg);
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}

/* ─── BARGAIN CORNER BADGE ─── */
.bargain-corner-badge {
    background: linear-gradient(135deg, var(--ba-orange), var(--ba-orange-light));
    color: #fff;
    font-weight: 700;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 0.25em 0.5em;
    border-radius: 0.25rem;
}

/* ─── PRODUCT CARDS ─── */
.product-card {
    border-radius: var(--ba-radius);
    transition: var(--ba-transition);
    overflow: hidden;
    background: var(--ba-card-bg);
}

.product-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--ba-shadow-hover);
}

.product-image-container {
    position: relative;
    overflow: hidden;
}

.product-thumb {
    width: 100%;
    aspect-ratio: 3 / 4;
    object-fit: cover;
    transition: transform 0.3s ease;
}

.product-card:hover .product-thumb {
    transform: scale(1.03);
}

.product-thumb-placeholder {
    width: 100%;
    aspect-ratio: 3 / 4;
    background: var(--ba-cream);
}

/* Condition badge top-right */
.condition-badge {
    position: absolute;
    top: 8px;
    right: 8px;
    z-index: var(--ba2-z-base);
    font-size: 0.65rem;
    font-weight: 600;
    background: rgba(255,255,255,0.92);
    color: var(--ba-primary);
    border: 1px solid var(--ba-border);
    padding: 0.2em 0.5em;
    border-radius: 0.25rem;
}

/* ─── STOREFRONT ─── */
.hero-section {
    background: linear-gradient(135deg, var(--ba-primary) 0%, var(--ba-primary-light) 100%);
    color: #ffffff;
    padding: 4rem 0;
    position: relative;
    overflow: hidden;
}

.hero-section::before {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    width: 40%;
    height: 100%;
    background: url('/images/hero-books.jpg') center/cover no-repeat;
    opacity: 0.15;
    mask-image: linear-gradient(to left, rgba(0,0,0,1), rgba(0,0,0,0));
    -webkit-mask-image: linear-gradient(to left, rgba(0,0,0,1), rgba(0,0,0,0));
}

.hero-section h1 {
    color: #ffffff;
    font-size: 2.75rem;
    font-weight: 800;
}

.hero-section .lead {
    font-size: 1.25rem;
    opacity: 0.9;
}

/* Category grid cards */
.category-card {
    text-align: center;
    padding: 1.5rem;
    border-radius: var(--ba-radius);
    background: var(--ba-card-bg);
    transition: var(--ba-transition);
    text-decoration: none;
    color: var(--ba-text);
    display: block;
}

.category-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--ba-shadow-hover);
    color: var(--ba-accent);
}

.category-card i {
    font-size: 2rem;
    color: var(--ba-primary);
    transition: var(--ba-transition);
}

.category-card:hover i {
    color: var(--ba-accent);
}

/* ─── PRICING DISPLAY ─── */
.price-original {
    text-decoration: line-through;
    color: var(--ba-text-muted);
    font-size: 0.85em;
}

.price-current {
    font-weight: 800;
    font-size: 1.4rem;
    color: var(--ba-accent);
}

.price-current.large {
    font-size: 2rem;
}

.price-savings {
    font-size: 0.8rem;
    color: var(--ba-green);
    font-weight: 600;
}

/* ─── CART TABLE ─── */
.cart-table th {
    font-weight: 600;
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border-bottom-width: 2px;
}

.cart-table td {
    vertical-align: middle;
    padding: 1rem 0.75rem;
}

.cart-table tr:hover {
    background-color: var(--ba-cream);
}

/* ─── CHECKOUT STEPS ─── */
.checkout-steps {
    display: flex;
    align-items: center;
    gap: 0;
}

.checkout-step {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
}

.checkout-step .step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--ba-border);
    color: var(--ba-text-muted);
    font-weight: 700;
    font-size: 0.9rem;
    transition: var(--ba-transition);
}

.checkout-step.active .step-number {
    background: var(--ba-primary);
    color: #fff;
}

.checkout-step.completed .step-number {
    background: var(--ba-green);
    color: #fff;
}

.checkout-step .step-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--ba-text-muted);
}

.checkout-step.active .step-label {
    color: var(--ba-primary);
}

.checkout-step-line {
    flex: 1;
    height: 2px;
    background: var(--ba-border);
    margin: 0 0.5rem;
    margin-bottom: 1.2rem;
}

/* ─── FILTER SIDEBAR ─── */
.filter-sidebar .card-header {
    background: var(--ba-primary);
    color: #fff;
    font-weight: 600;
}

.filter-sidebar .form-label {
    font-weight: 600;
    font-size: 0.85rem;
    margin-bottom: 0.25rem;
}

/* ─── TOAST NOTIFICATIONS ─── */
.toast-container {
    position: fixed;
    top: 80px;
    right: 20px;
    z-index: var(--ba2-z-toast);
}

.toast.toast-success {
    border-left: 4px solid var(--ba-green);
}

.toast.toast-error {
    border-left: 4px solid var(--ba-accent);
}

/* ─── RESPONSIVE ─── */
@media (max-width: 991.98px) {
    .hero-section h1 {
        font-size: 2rem;
    }

    .filter-sidebar {
        margin-bottom: 1rem;
    }
}

@media (max-width: 767.98px) {
    .hero-section {
        padding: 2rem 0;
    }

    .hero-section h1 {
        font-size: 1.75rem;
    }

    .product-form .two-column {
        grid-template-columns: 1fr;
    }

    .checkout-step .step-label {
        display: none;
    }

    /* Mobile filter toggle */
    .filter-sidebar {
        position: fixed;
        top: 0;
        left: -300px;
        width: 280px;
        height: 100vh;
        z-index: var(--ba2-z-modal);
        background: #fff;
        box-shadow: var(--ba-shadow-hover);
        transition: left 0.3s ease;
        overflow-y: auto;
        padding: 1rem;
    }

    .filter-sidebar.show {
        left: 0;
    }

    .filter-overlay {
        display: none;
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0,0,0,0.4);
        z-index: var(--ba2-z-backdrop);
    }

    .filter-overlay.show {
        display: block;
    }
}

/* ─── FOOTER ─── */
.footer {
    background: var(--ba-primary);
    color: rgba(255,255,255,0.8);
    padding: 2rem 0;
    margin-top: 3rem;
}

.footer a {
    color: rgba(255,255,255,0.8);
    text-decoration: none;
    transition: var(--ba-transition);
}

.footer a:hover {
    color: #ffffff;
}

.footer .footer-links {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    gap: 1.5rem;
    flex-wrap: wrap;
}

.footer .footer-links li a {
    font-size: 0.9rem;
}

/* ─── PRINT STYLES ─── */
@media print {
    .navbar-admin,
    .footer,
    .filter-sidebar,
    .btn,
    .toast-container,
    .checkout-steps {
        display: none !important;
    }

    body {
        background: #fff !important;
        color: #000 !important;
        font-size: 12pt;
    }

    .card {
        border: 1px solid #ccc !important;
        box-shadow: none !important;
    }

    .price-current {
        color: #000 !important;
        font-size: 14pt;
    }

    .price-original {
        color: #666 !important;
    }

    a {
        color: #000 !important;
        text-decoration: none !important;
    }

    a[href]::after {
        content: ' (' attr(href) ')';
        font-size: 0.8em;
        color: #666;
    }

    /* Invoice / Shipping labels */
    .invoice-header {
        border-bottom: 2px solid #000;
        padding-bottom: 1rem;
        margin-bottom: 1rem;
    }

    .shipping-label {
        border: 3px solid #000;
        padding: 1rem;
        page-break-inside: avoid;
    }

    .shipping-label .address {
        font-size: 14pt;
        font-weight: 700;
        line-height: 1.8;
    }

    table {
        border-collapse: collapse;
    }

    table th, table td {
        border: 1px solid #ccc;
        padding: 0.5rem;
    }

    .page-break {
        page-break-after: always;
    }
}

/* ─── MISCELLANEOUS ─── */

/* Chivvy warning banners */
.chivvy-warning {
    background: #fff3cd;
    border-left: 4px solid var(--ba-orange);
    padding: 0.75rem 1rem;
    border-radius: 0 var(--ba-radius) var(--ba-radius) 0;
    margin-bottom: 0.5rem;
    font-size: 0.9rem;
}

/* Template info banner */
.template-banner {
    background: #fff8e1;
    border-left: 4px solid var(--ba-orange-light);
    padding: 0.75rem 1rem;
    border-radius: 0 var(--ba-radius) var(--ba-radius) 0;
    margin-bottom: 1rem;
}

/* Sold item greyed price */
.price-sold {
    color: var(--ba-text-muted);
    opacity: 0.6;
}

/* Cart badge on nav */
.cart-badge {
    position: absolute;
    top: -4px;
    right: -8px;
    background: var(--ba-accent);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
    min-width: 18px;
    height: 18px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 4px;
}

/* Loading spinner */
.spinner-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(255,255,255,0.7);
    z-index: var(--ba2-z-overlay);
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Image gallery */
.gallery-main {
    width: 100%;
    aspect-ratio: 3/4;
    object-fit: contain;
    background: #f8f8f8;
    border-radius: var(--ba-radius);
}

.gallery-thumbstrip {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
    overflow-x: auto;
}

.gallery-thumb {
    width: 60px;
    height: 80px;
    object-fit: cover;
    border: 2px solid transparent;
    border-radius: 0.25rem;
    cursor: pointer;
    transition: var(--ba-transition);
}

.gallery-thumb:hover,
.gallery-thumb.active {
    border-color: var(--ba-primary);
}

/* Pagination custom */
.pagination .page-link {
    color: var(--ba-primary);
    border: 1px solid var(--ba-border);
}

.pagination .page-item.active .page-link {
    background-color: var(--ba-primary);
    border-color: var(--ba-primary);
    color: #fff;
}

.pagination .page-link:hover {
    background-color: var(--ba-cream);
    color: var(--ba-accent);
}

/* ══════ Voice Dictation ══════ */
/* ── Voice Dictation ─────────────────────────────────────── */
.voice-field-filled {
    animation: voice-fill-flash 0.6s ease;
    background-color: #d4edda !important;
    transition: background-color 2s ease;
}
@keyframes voice-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.3; }
}
@keyframes voice-fill-flash {
    0% { background-color: #28a745; color: #fff; }
    100% { background-color: #d4edda; color: inherit; }
}
#voiceIndicator {
    align-items: center;
    gap: 6px;
    font-weight: 600;
    font-size: 0.85rem;
}
#voiceIndicator .pulse-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: #fff;
    animation: voice-pulse 1.2s infinite;
}
#voiceFullPanel {
    margin-top: 0.5rem;
}
#voiceRawText {
    font-size: 0.9rem;
}
#voiceLivePreview {
    min-height: 1.2em;
}

/* ═══════════════════════════════════════════════════════
   Product Image Banners — diagonal overlay, top-right corner
   SOLD (red) | BARGAIN CORNER (yellow) | SALE (purple)
   Priority: SOLD > SALE > BARGAIN CORNER (only one shown)
   Text + colour admin-editable via Settings → Banners
   ═══════════════════════════════════════════════════════ */

.product-image-wrapper {
    position: relative;
    overflow: hidden;
}

.product-banner {
    position: absolute;
    top: 18px;
    right: -35px;
    width: 150px;
    text-align: center;
    padding: 4px 0;
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: #fff;
    transform: rotate(45deg);
    z-index: var(--ba2-z-base);
    box-shadow: 0 2px 4px rgba(0,0,0,.25);
}

.product-banner.banner-sold {
    background: var(--sf-sold, #dc3545);
}

.product-banner.banner-bargain-corner {
    background: var(--sf-bc, #ffc107);
    color: var(--sf-bc-text, #212529); /* Dark text on yellow */
}

.product-banner.banner-bc {
    background: linear-gradient(135deg, #f39c12, #f1c40f);
    color: #212529;
}

.product-banner.banner-sale {
    background: #27ae60;
}

/* ── Storefront tile title — 3-line clamp with ellipsis (§195 tile spec, ledger row
   650) — ADDED 8 Aug 2026, DEFECT FIX (evidence sweep B13). The "lines 1-3 = title,
   clipped to 3 lines, ellipsis on overflow, fixed-height box so every tile in a row
   aligns" convention was documented in the tile's own source comment and the bible,
   but no CSS ever implemented it: long titles ran to 4-7 lines with no clamp, no
   max-height and no overflow:hidden, so grid rows did not line up. This clips
   .sf-title (the tile's <h6 class="card-title sf-title">) to exactly 3 lines.
   -webkit-line-clamp is honoured by every current major browser (Chromium, Firefox
   68+, Safari); max-height is kept as a fallback for anything that ignores it. The
   full-title-on-hover behaviour is unchanged — it comes from the title="" attribute
   already on the element, not from anything here. 1.2rem line-height = 19.2px,
   matching the tile's live measured line-height; 3 lines = 3.6rem = 57.6px, so
   min-height/max-height give every tile in a row the SAME title-box height whether
   the title is one word or seven. */
.sf-title {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.2rem;
    max-height: 3.6rem;
    min-height: 3.6rem;
    word-break: break-word;
}

/* ── Diagonal corner ribbons (storefront tiles) — RESTORED 8 Aug 2026 ──
   REGRESSION FIX: these rules were dropped during the 7 Aug 2026 storefront
   header rework (site.css rebuild that day silently lost them - nothing to
   do with the header work itself, just an accidental omission). Restored
   verbatim from the last known-good copy per Orlando's 3 Aug 2026 ruling
   (bible §3.11 / §3.19 / §195.4): Sold = red, LEFT corner. Bargain Corner =
   yellow with BLACK text, RIGHT corner. Both may show at once on the same
   tile, one per corner, neither covering the other or the cover image.
   Colours come from the SAME --sf-sold / --sf-bc / --sf-bc-text variables
   used by .product-banner on the product detail page (defined above), so
   the tile ribbon and the product-page ribbon can never disagree. */
.sf-ribbon { position: absolute; top: 22px; width: 160px; text-align: center; font-family: var(--sf-font); font-size: 13px; font-weight: 700; letter-spacing: .5px; padding: 6px 0; box-shadow: 0 2px 6px rgba(0,0,0,.3); z-index: var(--ba2-z-base); }
.sf-ribbon-sold { left: -38px; transform: rotate(-45deg); background: var(--sf-sold); color: #fff; }
.sf-ribbon-bc { right: -38px; transform: rotate(45deg); background: var(--sf-bc); color: var(--sf-bc-text, #212529); }

/* Sold item overlay — dims the image slightly */
.product-image-wrapper.is-sold img {
    opacity: 0.75;
    filter: grayscale(25%);
}

/* ─── BOX PRODUCT TILE — shared component (Boxes/Index preview + Boxes/Location) ───
   DEFECT FIX (evidence sweep B18, 8 Aug 2026 / REQ-ORL-BoxTileLayout). This ONE set
   of rules is now used by BOTH the small inline preview on the Boxes tree list
   (Areas/Admin/Views/Boxes/Index.cshtml) and the full working screen staff use every
   day for a box (Areas/Admin/Views/Boxes/Location.cshtml), via the shared renderer
   wwwroot/js/box-tile-render.js (Ba2BoxTile.render) — so the two screens cannot
   drift into two different tile designs again.
   Previously Index.cshtml's preview used its OWN class family (.box-tile/.tile-*)
   with a hardcoded `background: #fff`, which — combined with the dark theme's white
   text — made every tile invisible in dark mode (white-on-white). This background
   uses var(--bs-body-bg), which is theme-aware, so dark mode text is visible again.
   Top line = SKU (left) / Volumes (centre, tap-to-edit on the full/Location tile) /
   Price (right). Title clamps to 2 lines with ellipsis, full title on hover via the
   title="" attribute. The photo is the enlarged SKU_1 thumbnail (1:1, contained). */
.bx-tile { position: relative; border: 1px solid var(--bs-border-color); border-radius: .5rem; overflow: hidden; background: var(--bs-body-bg); }
.bx-tile.bx-tile-compact { width: 200px; }
.bx-tile.t-hv { background: rgba(217, 119, 6, .12); }             /* amber — high value */
.bx-tile.t-multi { background: rgba(111, 66, 193, .14); }         /* violet — multi-copy */
.bx-tile.t-hv.t-multi { background: linear-gradient(135deg, rgba(217, 119, 6, .12) 50%, rgba(111, 66, 193, .14) 50%); }
.bx-tile.t-sold { opacity: .85; }
.bx-tile.t-sold img.bx-photo { filter: grayscale(.6); opacity: .75; }
.bx-tile.t-present { outline: 3px solid #198754; outline-offset: -3px; }
.bx-tile.t-miss { outline: 3px solid #d97706; outline-offset: -3px; }
.bx-img { position: relative; width: 100%; aspect-ratio: 1 / 1; background: var(--bs-tertiary-bg); }
.bx-img img.bx-photo { width: 100%; height: 100%; object-fit: contain; }
.bx-zoom { position: absolute; right: .4rem; bottom: .4rem; z-index: var(--ba2-z-base); width: 2.6rem; height: 2.6rem;
           border-radius: 50%; border: 1px solid var(--bs-border-color);
           background: var(--bs-body-bg); opacity: .92; }
.bx-check { position: absolute; left: .4rem; top: .4rem; z-index: var(--ba2-z-base); }
.bx-check .form-check-input { width: 2.2rem; height: 2.2rem; }
.bx-body { padding: .5rem .6rem .6rem; }
.bx-topline { display: flex; align-items: center; justify-content: space-between; gap: .35rem; font-size: .8rem; }
.bx-topline .bx-vols { text-align: center; }
.bx-topline .bx-price { text-align: right; }
/* LINES = title, clipped to exactly 2 lines, ellipsis on overflow, full title on hover
   (title="" attribute set by the renderer). Fixed min-height so short titles still
   line up with long ones in the same row. */
.bx-title { display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
            overflow: hidden; line-height: 1.25; min-height: calc(1.25em * 1); margin-top: .15rem; }
.bx-badges { margin-top: .35rem; }
.bx-vols { border: 0; }
.bx-vols-input { width: 4.5rem; }
.bx-pill-multi { background: #6f42c1; color: #fff; }
.bx-pill-hv { background: #d97706; color: #fff; }   /* site amber */
.bx-pill-miss { background: #d97706; color: #fff; }
.bx-price-hv { color: var(--bs-danger); font-weight: 700; }

/* Strikethrough for sale price */
.price-original {
    text-decoration: line-through;
    color: #999;
    font-size: 0.85em;
    margin-right: 0.3em;
}

.price-sale {
    color: #800080;
    font-weight: 700;
}

/* B22.1 — All Products sold pill: tappable, with a subtle hover/active state */
.ba2-sold-pill {
    cursor: pointer;
    transition: background-color .15s ease;
}

.ba2-sold-pill:hover,
.ba2-sold-pill:focus-visible {
    background-color: rgba(108, 117, 125, .45) !important;
}

.ba2-sold-pill:active {
    background-color: rgba(108, 117, 125, .6) !important;
}


/* ════════════════════════════════════════════════════════════════════
   B24.4 — Global pill style (Orlando, 13 Jun 2026)
   "A nice box with rounded corners." All pills/badges render as
   rounded-corner BOXES — never fully circular. Use .ba2-pill for new
   pills; existing Bootstrap `.badge.rounded-pill` instances are coerced
   to the same rounded-box radius site-wide so they inherit the look.
   ════════════════════════════════════════════════════════════════════ */
.ba2-pill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: .375rem;
    padding: .15rem .4rem;
    font-size: .72rem;
    font-weight: 600;
    line-height: 1;
    white-space: nowrap;
    vertical-align: middle;
    text-decoration: none;
}
.ba2-pill-red    { background: #dc3545; color: #fff; }
.ba2-pill-green  { background: #198754; color: #fff; }
.ba2-pill-amber  { background: #d97706; color: #fff; }
.ba2-pill-grey   { background: #6c757d; color: #fff; }
.ba2-pill-blue   { background: #0d6efd; color: #fff; }
.ba2-pill-info   { background: #0dcaf0; color: #000; }
/* Fixed-size single-letter variant (e.g. Orders status pill, formerly a circle) */
.ba2-pill-letter { min-width: 1.4rem; height: 1.4rem; padding: .1rem .25rem; }
/* Coerce Bootstrap's fully-circular pill badges into rounded boxes site-wide */
.badge.rounded-pill { border-radius: .375rem !important; }

/* ── B24.4 — reusable dismissible Legend/Key bar (above list column headers) ── */
.ba2-legend {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .35rem .9rem;
    font-size: .8rem;
    border: 1px solid #e3e3e3;
    border-radius: .375rem;
    background: #f8f9fa;
    padding: .4rem .6rem;
}
.ba2-legend .ba2-legend-item { display: inline-flex; align-items: center; gap: .3rem; }
.ba2-legend .ba2-legend-dismiss { margin-left: auto; }


/* ====================================================================
   B41a - Full-surface dark mode (15 Jun 2026, Orlando)
   Mops up the remaining custom admin surfaces that hardcoded light hex
   (cream / white / light-grey) and therefore ignored data-bs-theme="dark",
   leaving "light islands" on an otherwise dark page. Each surface is driven
   off a Bootstrap 5.3 theme variable where one fits; fixed dark tones are
   applied ONLY inside this [data-bs-theme="dark"] guard - never a stray
   light hex. The purple navbar deliberately stays purple (handled in
   _AdminLayout's dark block). The dismissible legend/key bar (.ba2-legend)
   and flash toasts (.toast-*) are owned by separate chunks and untouched.
   ==================================================================== */
[data-bs-theme="dark"] .chivvy-warning,
[data-bs-theme="dark"] .template-banner {
    background: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}
[data-bs-theme="dark"] .spinner-overlay {
    background: rgba(0, 0, 0, .6);
}
[data-bs-theme="dark"] .gallery-main,
[data-bs-theme="dark"] .product-thumb-placeholder {
    background: var(--bs-tertiary-bg);
}
[data-bs-theme="dark"] .pagination .page-link {
    border-color: var(--bs-border-color);
}
[data-bs-theme="dark"] .pagination .page-link:hover {
    background-color: var(--bs-tertiary-bg);
    color: var(--bs-link-hover-color);
}
[data-bs-theme="dark"] .condition-badge {
    background: rgba(0, 0, 0, .78);
    color: var(--bs-body-color);
    border-color: var(--bs-border-color);
}
[data-bs-theme="dark"] .voice-field-filled {
    background-color: #14331c !important;
    color: var(--bs-body-color) !important;
}
[data-bs-theme="dark"] .category-card,
[data-bs-theme="dark"] .product-card {
    background: var(--bs-secondary-bg);
    color: var(--bs-body-color);
}
[data-bs-theme="dark"] .filter-sidebar {
    background: var(--bs-secondary-bg);
}

/* B41a - Marketplace Config colour-coded panels (formerly inline light hex).
   Light tints preserved for light mode; flip to a dark surface in dark mode so
   the default body-colour text stays readable (no light island, no contrast loss). */
.ba2-tint-warm  { background: #f8f4f0; }
.ba2-tint-cool  { background: #f0f0fa; }
.ba2-tint-peach { background: #fff8f0; }
[data-bs-theme="dark"] .ba2-tint-warm,
[data-bs-theme="dark"] .ba2-tint-cool,
[data-bs-theme="dark"] .ba2-tint-peach {
    background: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}

/* B41a - dashboard widget drag-grip: dark-mode legible hover/active tones */
[data-bs-theme="dark"] .widget-grip:hover {
    color: #cccccc;
    background-color: rgba(255, 255, 255, .06);
}
[data-bs-theme="dark"] .widget-grip:active {
    color: #ffffff;
    background-color: rgba(255, 255, 255, .1);
}

/* ====================================================================
   B41 - New Product -> Search dark-mode fix (15 Jun 2026, Orlando)
   The Comparable Search results screen carried hardcoded light hex on its
   result cards, thumbnails, filter pills and the comparable toast/alt-items,
   leaving "light islands" under data-bs-theme="dark" (same class of bug as
   B41a). Light-mode appearance is unchanged; dark mode flips each surface to
   the matching Bootstrap 5.3 theme variable so body-colour text stays legible.
   ==================================================================== */
[data-bs-theme="dark"] .result-card {
    background: var(--bs-secondary-bg);
    border-color: var(--bs-border-color);
    color: var(--bs-body-color);
}
[data-bs-theme="dark"] .result-thumb,
[data-bs-theme="dark"] .result-thumb-placeholder {
    background: var(--bs-tertiary-bg);
}
[data-bs-theme="dark"] .abe-filter-btn {
    background: var(--bs-secondary-bg);
}
[data-bs-theme="dark"] .abe-filter-btn:hover {
    background: var(--bs-tertiary-bg);
}
[data-bs-theme="dark"] .comp-toast {
    background: var(--bs-secondary-bg);
    border-color: var(--bs-border-color);
    color: var(--bs-body-color);
}
[data-bs-theme="dark"] .comp-toast .comp-toast-header {
    background: var(--bs-tertiary-bg);
    border-bottom-color: var(--bs-border-color);
    color: var(--bs-body-color);
}
[data-bs-theme="dark"] .comp-alt-item {
    border-color: var(--bs-border-color);
}
[data-bs-theme="dark"] .comp-alt-item.selected {
    border-color: #198754;
    background: #14331c;
}

/* ====================================================================
   STICKY1 (19 Jun 2026, Orlando) - Bulletproof sticky list headers
   ba2-sticky-headers.js sets an inline background on each stuck <th>, but
   Bootstrap 5.3 paints striped/hover rows with an INSET box-shadow that is
   drawn ABOVE the cell background — so scrolling product rows bled through
   the stuck header (and the stuck filter/toolbar bars). Fix in the CSS layer:
   lay an opaque surface down with a solid inset box-shadow that defeats the
   striping accent (inset shadow paints above background, below text, so the
   header text stays crisp). Theme variables => dark-mode safe.
   ==================================================================== */
table[data-sticky-header] thead th {
    background-color: var(--bs-tertiary-bg) !important;
    box-shadow: inset 0 0 0 9999px var(--bs-tertiary-bg) !important;
    background-clip: padding-box;
}
[data-sticky-stack] {
    background-color: var(--bs-body-bg);
}
[data-sticky-stack].card {
    background-color: var(--bs-card-bg);
}

/* ====================================================================
   DARKTEXT1 (19 Jun 2026, Orlando) - "ALL TEXT WHITE in dark mode,
   other than hyperlinks." Several custom admin surfaces forced dark/grey
   text (headings pinned to --ba-primary purple; .text-muted/.text-secondary
   greys; .text-dark/.text-black; .text-primary purple) which vanished on the
   dark page shell. Force them all white under the dark theme. Hyperlinks keep
   their link colour. Semantic status colours (success/danger/warning/info)
   and badge/button text are intentionally preserved so meaning + the amber
   (#d97706) brand rule survive.
   ==================================================================== */
[data-bs-theme="dark"] body,
[data-bs-theme="dark"] h1,
[data-bs-theme="dark"] h2,
[data-bs-theme="dark"] h3,
[data-bs-theme="dark"] h4,
[data-bs-theme="dark"] h5,
[data-bs-theme="dark"] h6,
[data-bs-theme="dark"] p,
[data-bs-theme="dark"] label,
[data-bs-theme="dark"] th,
[data-bs-theme="dark"] td,
[data-bs-theme="dark"] li,
[data-bs-theme="dark"] dt,
[data-bs-theme="dark"] dd,
[data-bs-theme="dark"] small,
[data-bs-theme="dark"] .form-text,
[data-bs-theme="dark"] .card-title,
[data-bs-theme="dark"] .card-text,
[data-bs-theme="dark"] .text-body,
[data-bs-theme="dark"] .text-body-secondary,
[data-bs-theme="dark"] .text-muted,
[data-bs-theme="dark"] .text-secondary,
[data-bs-theme="dark"] .text-dark,
[data-bs-theme="dark"] .text-black,
[data-bs-theme="dark"] .text-primary {
    color: #ffffff !important;
}

/* A1 (29 Jul 2026, Orlando) - field labels must be legible in dark mode but NEVER
   pure white. .form-label was pulled out of the blanket #ffffff group above and
   given the established light-grey label tone (#e0e0e0, same as the dark table-header
   tone from #857). Shared theme CSS, so every admin page's field labels flip at once.
   The left-label variant (.ba2-flabel #aab4be) already had its own non-white tone;
   labels stay vertically centred on their input row (left-label rules untouched). */
[data-bs-theme="dark"] .form-label { color: #e0e0e0 !important; }
/* Hyperlinks keep their colour (explicitly excluded from the white rule). */
[data-bs-theme="dark"] a,
[data-bs-theme="dark"] a:visited {
    color: var(--bs-link-color);
}

/* --- BA-FOOTER CONTRAST FIX (#846) --- */
/* Bootstrap's --bs-light-text-emphasis (#495057) is unreadable on bg-dark (~1.6:1). */
/* Re-point the token inside the footer to a light grey (~7:1 on #212529). */
.ba-footer {
    --bs-light-text-emphasis: #adb5bd;
}

/* ====================================================================
   B41b / #857 (10 Jul 2026) — Dark-mode sweep, testing round 1
   (T-18, T-19, T-21, T-22, T-23). One disease, one cure: Bootstrap's
   fixed-tone classes (.table-light, .table-warning, .bg-light…) and
   default placeholder colour never flip with data-bs-theme, so dark
   pages kept light islands, transparent stuck headers, invisible amber
   highlights and unreadable placeholder labels. All fixes live inside
   the [data-bs-theme="dark"] guard — light mode is untouched.
   ==================================================================== */

/* ba2-newprod2-0812 chunk 3, 12 Aug 2026 — honest progress bar for the New Product /
   New Prod 2 "machine fills keywords and categories" AI call, same look as the voice
   strip's own AI-sort progress bar (a moving bar + a running seconds count). Generic,
   not scoped to the voice panel, so any AI wait on the product form can reuse it. */
.ba2-ai-prog-wrap { height: .4rem; border-radius: 999px; background: rgba(13,110,253,.15); overflow: hidden; margin-bottom: .25rem; }
.ba2-ai-prog-bar { display: block; height: 100%; width: 0; background: #0d6efd; transition: width 1s linear; }
[data-bs-theme="dark"] .ba2-ai-prog-wrap { background: rgba(255,255,255,.15); }

/* T-23 — placeholder-as-label convention: Bootstrap's default placeholder
   grey vanishes on the #000 dark input surface, making data-entry forms
   unusable. Readable but clearly-not-a-value grey, full opacity. */
/* ba2-newprod2-0812 chunk 3, 12 Aug 2026 (Orlando: placeholder text should be "slightly
   grey", #4a4f57 in dark mode) — was #9a9aa2, noticeably brighter than a placeholder
   should read against the dark form surface. */
[data-bs-theme="dark"] .form-control::placeholder,
[data-bs-theme="dark"] .form-control::-webkit-input-placeholder {
    color: #4a4f57 !important;
    opacity: 1;
}
[data-bs-theme="dark"] .form-control:focus::placeholder { color: #4a4f57 !important; }

/* T-19 — sticky/thead surfaces: .table-light is a FIXED light tone that the
   .table variable override in the dark layout block hollows out, leaving
   stuck headers transparent so rows scrolled through them. Solid opaque dark
   header surface on every table head cell (inset shadow defeats striping
   accents exactly as STICKY1 does in light mode). */
[data-bs-theme="dark"] .table > thead > tr > th,
[data-bs-theme="dark"] thead.table-light > tr > th {
    background-color: #161616 !important;
    box-shadow: inset 0 0 0 9999px #161616 !important;
    color: #e0e0e0 !important;
    border-color: #2a2a2a;
}

/* T-21 (+ siblings) — contextual row tints: the dark layout block's
   `.table { --bs-table-bg:#111 }` outranks Bootstrap's variant classes by
   source order, so amber multi-order rows (and any success/danger/info rows)
   rendered as plain dark. Re-arm every variant with a dark-legible tint. */
[data-bs-theme="dark"] .table .table-warning,
[data-bs-theme="dark"] .table .table-warning > * {
    --bs-table-bg: #3a2e00; --bs-table-color: #ffd97a;
    --bs-table-bg-state: #4a3c08; --bs-table-bg-type: #3f3302;
    background-color: #3a2e00; color: #ffd97a;
}
[data-bs-theme="dark"] .table .table-danger,
[data-bs-theme="dark"] .table .table-danger > * {
    --bs-table-bg: #3a0e0e; --bs-table-color: #f0a0a0;
    background-color: #3a0e0e; color: #f0a0a0;
}
[data-bs-theme="dark"] .table .table-success,
[data-bs-theme="dark"] .table .table-success > * {
    --bs-table-bg: #0e2e14; --bs-table-color: #9fdcae;
    background-color: #0e2e14; color: #9fdcae;
}
[data-bs-theme="dark"] .table .table-info,
[data-bs-theme="dark"] .table .table-info > * {
    --bs-table-bg: #0c2733; --bs-table-color: #9cd3e8;
    background-color: #0c2733; color: #9cd3e8;
}

/* T-18 — dismissible legend strip: hardcoded #f8f9fa/light border (was
   deliberately left out of B41a as "owned by the legend chunk"). Dark
   surface, readable text; coloured legend swatches inside are inline and
   survive untouched. */
[data-bs-theme="dark"] .ba2-legend {
    background: #161616;
    border-color: #2a2a2a;
    color: #d0d0d0;
}
[data-bs-theme="dark"] .ba2-legend .text-muted { color: #a0a0a0 !important; }

/* T-22 — global search dropdown group headers: .bg-light re-toned to #111 by
   B41a while .text-muted dropped to #888 — ghost text on near-black. Lift the
   header text (and keep row primary text properly bright). */
[data-bs-theme="dark"] #searchDropdown .bg-light small,
[data-bs-theme="dark"] #searchDropdown .bg-light .text-muted {
    color: #b8b8c0 !important;
}
[data-bs-theme="dark"] #searchDropdown .dropdown-item { color: #e0e0e0; }
[data-bs-theme="dark"] #searchDropdown .dropdown-item .text-muted { color: #9a9aa2 !important; }

/* #858 companion to T-19 — list-page sort links use .text-dark, which stays
   near-black (utility !important) on the dark header surface. Lift them. */
[data-bs-theme="dark"] .table > thead a.text-dark,
[data-bs-theme="dark"] thead.table-light a.text-dark {
    color: #e0e0e0 !important;
}

/* ══ EB6 (18 Jul 2026) — approved 11 Jul data-entry form conventions ══
   Pink sticky squares between label and field, and dark-mode field-state
   tokens (RULED: focused = 75% grey step, possible-error = 75% red step).
   Tune the tokens, not the rules. ba2-sticky-pink */
:root {
  --ba2-sticky-pink: #f8c8dc;
  --ba2-sticky-pink-checked: #e83e8c;
  --ba2-focus-bg-dark: #4a4a52;   /* focused field, dark mode */
  --ba2-error-bg-dark: #5c2f35;   /* possible-error field, dark mode */
  --ba2-error-bg-light: rgba(220,53,69,.10); /* 10% red tint, light mode */
}
/* #973 item 4 (RULED 28–29 Jul) — theme-aware sticky squares, tabindex=-1 on all.
   LIGHT: grey = OFF, pink = ON.  DARK: grey tones only (darker = OFF, lighter = ON)
   — no pink in dark mode. */
.sticky-toggle, .sticky-toggle-all {
  appearance: none; -webkit-appearance: none;
  width: .85rem; height: .85rem; min-width: .85rem;
  border: 1px solid #adb5bd;
  background: #ced4da;
  border-radius: 2px; cursor: pointer; margin-top: 0;
  background-repeat: no-repeat; background-position: center; background-size: 70% 70%;
}
/* ba2-newprod2-0812 chunk 3, 12 Aug 2026 (Orlando: "a ticked one currently does not read as
   ticked") — appearance:none strips the browser's own tick/dash entirely, so a checked or
   part-ticked box previously differed from an unticked one ONLY by a colour change that is easy
   to miss at this size. A checked box now also carries a plain white tick mark, and a part-ticked
   master carries a plain white dash, so the ON state is obvious at a glance, not just a colour. */
.sticky-toggle:checked, .sticky-toggle-all:checked {
  background-color: var(--ba2-sticky-pink-checked);
  border-color: var(--ba2-sticky-pink-checked);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M3 8.5l3.5 3.5 6.5-8'/%3E%3C/svg%3E");
}
.sticky-toggle-all:indeterminate {
  background-color: var(--ba2-sticky-pink-checked);
  border-color: var(--ba2-sticky-pink-checked);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-width='2.5' d='M3 8h10'/%3E%3C/svg%3E");
}
.sticky-toggle-all {
  width: 1rem; height: 1rem; min-width: 1rem; /* "slightly larger" master control */
}
[data-bs-theme="dark"] .sticky-toggle, [data-bs-theme="dark"] .sticky-toggle-all { background-color: #343a40; border-color: #495057; }
[data-bs-theme="dark"] .sticky-toggle:checked, [data-bs-theme="dark"] .sticky-toggle-all:checked {
  background-color: #868e96; border-color: #adb5bd;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23212529' stroke-linecap='round' stroke-linejoin='round' stroke-width='2.5' d='M3 8.5l3.5 3.5 6.5-8'/%3E%3C/svg%3E");
}
[data-bs-theme="dark"] .sticky-toggle-all:indeterminate {
  background-color: #868e96; border-color: #adb5bd;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23212529' stroke-linecap='round' stroke-width='2.5' d='M3 8h10'/%3E%3C/svg%3E");
}
/* EB6 completion (#946, 19 Jul 2026) — LEFT-LABEL rules moved here from the
   _ProductForm.cshtml inline <style> so the bundled CSS carries the approved
   11 Jul convention: label LEFT of its field, no colon, compressed rhythm. */
.ba2-flabel { font-size: .78rem; color: #555; margin: 0 .3rem 0 0; white-space: nowrap;
              min-width: 5.5rem; text-align: right; flex-shrink: 0; line-height: 1.1; }
.ba2-flabel + .sticky-toggle { margin-right: .3rem !important; }
/* narrow (1-2 col) fields get a compact label */
.ba2-flabel-sm { min-width: auto; }
[data-bs-theme="dark"] .ba2-flabel { color: #aab4be; }

/* ── #973 item 1 (RULED 28 Jul): grouping cards — dark-grey-bordered fieldset
      widgets on the product form (Binding + Condition; DJ + Condition + Protection). */
.ba2-group-card {
  border: 1px solid #6c757d; border-radius: .375rem;
  padding: .25rem .35rem; margin: 0; min-width: 0;
}
[data-bs-theme="dark"] .ba2-group-card { border-color: #565e64; }
/* #973 item 1b — greyed (DJ = No/blank) members of the DJ group: dimmed and
   mouse-inert; tabindex handled in JS so keyboard skips them too. */
.ba2-greyed { opacity: .45; pointer-events: none; }
/* #973 items 5+9 — derived/read-only field tint via Bootstrap theme tokens
   (theme-aware in light AND dark — replaces the bg-light dark-mode leak). */
.ba2-derived-field {
  background-color: var(--bs-secondary-bg) !important;
  color: var(--bs-secondary-color) !important;
}
.ba2-field-suspect { background-color: var(--ba2-error-bg-light) !important; }
[data-bs-theme="dark"] .form-control:focus,
[data-bs-theme="dark"] .form-select:focus { background-color: var(--ba2-focus-bg-dark); }
[data-bs-theme="dark"] .ba2-field-suspect { background-color: var(--ba2-error-bg-dark) !important; }

/* ══ Active-trail menu highlight (RULED 17 Jul) — whisper of grey in light mode,
   a step lighter than the panel in dark mode. Applies to the dropdown entry
   leading to the current page; top-level uses existing .active-section. */
.dropdown-item.active-trail { background: rgba(0,0,0,.05); }
[data-bs-theme="dark"] .dropdown-item.active-trail { background: rgba(255,255,255,.09); }
/* Queue item 16 (19 Jul 2026) — top-level item on the active trail gets the same
   subtle shade (light + dark), rounded to sit nicely in the navbar. */
.navbar-nav .nav-link.active-trail { background: rgba(0,0,0,.07); border-radius: .375rem; }
[data-bs-theme="dark"] .navbar-nav .nav-link.active-trail { background: rgba(255,255,255,.09); }

/* ── REQ-AP-FilterHighlight (18 Jul 2026) — shared list-page component ──
   Active filters get a bright background so live filters really stick out;
   the "Filters active (N)" pill offers one-click Clear all. Amber = #d97706
   per the site-wide convention. Light + dark theme safe. */
.ba2-filter-active {
    background-color: #fde68a !important; /* bright amber-200 */
    border-color: #d97706 !important;
    box-shadow: 0 0 0 1px #d97706 inset;
}
[data-bs-theme="dark"] .ba2-filter-active {
    background-color: #6b4e07 !important;
    color: #fff !important;
}
.ba2-filters-pill {
    background-color: #d97706;
    color: #fff;
    font-weight: 500;
}
.ba2-filters-pill .ba2-filters-clear {
    color: #fff;
    text-decoration: underline;
}


/* #143 (19 Jul 2026) - Calendar busy-day colouring: any month-grid or mini-month day with
   entries gets a distinct soft tint. Shared theme CSS, dark-mode aware; the today ring
   (amber inset) still reads over the tint. */
.ba2-month-cell.ba2-day-busy { background-color: rgba(13,110,253,.08); }
[data-bs-theme='dark'] .ba2-month-cell.ba2-day-busy { background-color: rgba(110,168,254,.16); }
.ba2-mini-day-busy { background-color: rgba(13,110,253,.12); border-radius: 4px; }
[data-bs-theme='dark'] .ba2-mini-day-busy { background-color: rgba(110,168,254,.22); }

/* ═══════════════════════════════════════════════════════════════════
   #939 BUG-EDIT-DarkMode (19 Jul 2026) — shared dark-mode field-state tokens.
   Ruling: in dark mode the FOCUSED field gets a 75% grey background and a
   possible-ERROR field a 75% red background. Tokens live here once (shared
   theme CSS); the product form (#productForm) applies them now, other pages
   opt in by reusing the same form classes. Light mode is untouched.
   ═══════════════════════════════════════════════════════════════════ */
:root {
    --ba2-field-focus-bg: rgba(108, 117, 125, .75); /* 75% grey */
    --ba2-field-error-bg: rgba(220, 53, 69, .75);   /* 75% red  */
}
[data-bs-theme="dark"] #productForm .form-control:focus,
[data-bs-theme="dark"] #productForm .form-select:focus,
[data-bs-theme="dark"] #productForm textarea.form-control:focus {
    background-color: var(--ba2-field-focus-bg);
    color: #fff;
}
[data-bs-theme="dark"] #productForm .form-control.is-invalid,
[data-bs-theme="dark"] #productForm .form-select.is-invalid,
[data-bs-theme="dark"] #productForm .input-validation-error,
[data-bs-theme="dark"] #productForm .ba2-field-error {
    background-color: var(--ba2-field-error-bg);
    color: #fff;
}

/* ═══════════════════════════════════════════════════════════════════
   #941 Dashboard mobile (RULED 22 Jul 2026) — mobile-first treatment of
   the admin dashboard on phones AND tablets (< lg / 992px; #964 raised
   the tablet/desktop boundary from md so ~820px tablets get the tablet
   layout). Desktop (≥ lg) layout is UNCHANGED.
   1. #dashTopRow becomes a swipeable horizontal carousel with scroll-snap;
      .dash-pips pips beneath it (wired in ba2-dash-mobile.js with
      click + pointerdown + touchstart so touch always works).
   2. .dash-na-strip = Needs Attention as a LEFT-TO-RIGHT scrolling chip
      strip placed under the 6 top widgets (phones/tablets, d-lg-none).
   ═══════════════════════════════════════════════════════════════════ */
.dash-pips { display: flex; justify-content: center; gap: .55rem; padding: .3rem 0; }
.dash-pip {
    width: .65rem; height: .65rem; border-radius: 50%;
    border: 0; padding: 0; background: #cbd5e1;
    touch-action: manipulation;
}
.dash-pip.active { background: #4a1942; }
[data-bs-theme="dark"] .dash-pip { background: #495057; }
[data-bs-theme="dark"] .dash-pip.active { background: #b98ab0; }

.dash-na-strip {
    display: flex; flex-wrap: nowrap; gap: .5rem;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    padding-bottom: .25rem;
}
.dash-na-chip { flex: 0 0 auto; white-space: nowrap; }

@media (max-width: 991.98px) {
    #dashTopRow {
        flex-wrap: nowrap;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    #dashTopRow::-webkit-scrollbar { display: none; }
    #dashTopRow > [class*="col"] {
        flex: 0 0 88%;
        max-width: 88%;
        scroll-snap-align: center;
    }
}

/* ── REQ-UI-AcronymTooltips (18 Jul 2026) — abbreviation lexicon mouseover (ba2-abbr.js) ── */
abbr.ba2-abbr {
    text-decoration: underline dotted;
    text-underline-offset: 2px;
    text-decoration-color: rgba(108, 117, 125, 0.85); /* muted grey dots — subtle, not shouty */
    cursor: help;
}

[data-bs-theme="dark"] abbr.ba2-abbr,
body.dark-mode abbr.ba2-abbr {
    text-decoration-color: rgba(173, 181, 189, 0.85);
}

/* ═══════════════════════════════════════════════════════
   §195 PUBLIC STOREFRONT — approved 'Bookshop Door' look
   (Orlando, 18 Jul 2026: dark green + parchment + gold,
   Georgia serif) + site-wide tile conventions.
   Palette exposed as CSS vars so per-tenant themes can
   override — nothing below is tenant-specific.
   ═══════════════════════════════════════════════════════ */
:root {
    --sf-green: #1e3a2f;
    --sf-green-2: #2a4d3e;
    --sf-parchment: #f6f1e7;
    --sf-parchment-2: #efe7d7;
    --sf-gold: #b8963e;
    --sf-ink: #2b2620;
    --sf-muted: #7a715f;
    --sf-bc: #ffc107;
    --sf-bc-text: #212529;
    --sf-sold: #dc3545;
}

/* ══════════════════════════════════════════════════════════════════
   Storefront brand band + hero + the ONE search control (6 Aug 2026).
   Orlando: the logo is the business name; nothing boxed behind it; the
   search bar itself must open into the detailed search; and no dead space.
   ══════════════════════════════════════════════════════════════════ */
:root {
    --sf-plum: #46177f;
    --sf-gold-bright: #f0cf6b;
}

/* ── Brand band: transparent logo on the site's own parchment, so there is
     no visible rectangle, no wave and no colour clash ── */
.ba-brandband { background: var(--sf-parchment); border-bottom: 1px solid #e7dfcd; }
.ba-brandrow { display: flex; align-items: center; justify-content: space-between; gap: 28px; padding: 14px 0 10px; }
.sf-brand-mark { display: inline-block; line-height: 0; flex: 0 0 auto; }
.sf-brand-mark img { height: 136px; width: auto; max-width: 100%; display: block; }
.ba-brandaside { flex: 1 1 auto; min-width: 0; text-align: right; }
.sf-phone-order { font-family: var(--sf-font); color: var(--sf-ink); line-height: 1.4; }
.sf-phone-order .sf-phone-lead { display: block; font-size: .95rem; font-weight: 600; color: var(--sf-plum); letter-spacing: .2px; }
.sf-phone-order .sf-phone-call { display: block; font-size: .95rem; }
.sf-phone-order .sf-phone-num { font-size: 1.35rem; font-weight: 700; color: var(--sf-plum); white-space: nowrap; letter-spacing: .5px; }
.sf-phone-order .sf-phone-note { display: block; font-size: .78rem; color: var(--sf-muted); }
.ba-navband { background: #fff; padding-top: .35rem; padding-bottom: .35rem; }

/* ── Hero: gold headline flanked by hairlines (echoes the logo flourish),
     white stock line, search front and centre ── */
.sf-hero {
    background: radial-gradient(115% 135% at 50% -15%, #305c48 0%, var(--sf-green) 52%, #16281f 100%);
    color: var(--sf-parchment);
    text-align: center;
    padding: 42px 20px 52px;
    font-family: var(--sf-font);
}
.sf-hero .sf-inner { max-width: 1040px; margin: 0 auto; }
.sf-hero h1 { display: flex; align-items: center; justify-content: center; gap: 18px; font-size: 30px; font-weight: normal; letter-spacing: 1.4px; color: var(--sf-gold); margin: 0 0 2px; }
.sf-hero h1::before, .sf-hero h1::after { content: ""; height: 1px; width: 84px; flex: 0 0 auto; background: linear-gradient(90deg, rgba(184,150,62,0) 0%, var(--sf-gold) 100%); }
.sf-hero h1::after { background: linear-gradient(90deg, var(--sf-gold) 0%, rgba(184,150,62,0) 100%); }
.sf-hero .sf-count { color: #fff; font-size: 42px; display: block; margin: 6px 0 2px; font-variant-numeric: tabular-nums; }
.sf-hero .sf-sub { font-size: 15px; color: rgba(246,241,231,.82); margin-bottom: 24px; }

/* ── The ONE search control. Closed: a single bar. Open: the same bar
     unfolds downward — same card, same width, nothing floating. ── */
.sf-searchwrap { max-width: 940px; margin: 0 auto; }
.sf-composer { background: #fff; border-radius: 14px; box-shadow: 0 14px 40px rgba(0,0,0,.30); overflow: hidden; text-align: left; transition: box-shadow .3s ease; }
.sf-composer.is-open { box-shadow: 0 22px 62px rgba(0,0,0,.42); }
.sf-searchbox { display: flex; align-items: stretch; background: #fff; }
.sf-searchbox .sf-searchicon { display: flex; align-items: center; padding-left: 20px; color: #a89c85; font-size: 18px; }
.sf-searchbox input[type="text"] { flex: 1 1 auto; min-width: 0; border: 0; background: transparent; font-size: 18px; padding: 18px 16px; font-family: inherit; color: var(--sf-ink); outline: none; }
.sf-searchbox input[type="text"]::placeholder { color: #8b8375; opacity: 1; }
.sf-refine { display: flex; align-items: center; gap: 8px; border: 0; border-left: 1px solid #ece5d8; background: #fbf8f2; color: var(--sf-ink); padding: 0 20px; font: inherit; cursor: pointer; white-space: nowrap; transition: background .2s ease, color .2s ease; }
.sf-refine .bi-chevron-down { font-size: .78em; transition: transform .3s ease; }
.sf-composer.is-open .sf-refine { background: var(--sf-ink); color: #fff; }
.sf-composer.is-open .sf-refine .bi-chevron-down { transform: rotate(180deg); }
.sf-primary-search { border: 0; background: var(--sf-gold); color: #fff; font-size: 17px; padding: 0 30px; cursor: pointer; font-family: inherit; white-space: nowrap; }
.sf-primary-search:hover { filter: brightness(1.08); }
.sf-morph { max-height: 0; opacity: 0; overflow: hidden; background: #fbf8f2; border-top: 0 solid var(--sf-gold); transition: max-height .4s cubic-bezier(.22,.71,.26,1), opacity .3s ease; }
.sf-composer.is-open .sf-morph { max-height: 640px; opacity: 1; border-top-width: 3px; }
.sf-morphinner { padding: 20px 22px 22px; }
.sf-morphhead { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.sf-morphhead span:first-child { font-size: .78rem; letter-spacing: 1.6px; text-transform: uppercase; color: var(--sf-ink); font-weight: 600; }
.sf-morphhead .sf-morphhint { font-size: .78rem; color: var(--sf-muted); }
.sf-morph label { display: block; font-size: .7rem; letter-spacing: .7px; text-transform: uppercase; color: var(--sf-muted); margin-bottom: 3px; }
.sf-morph .form-control, .sf-morph .form-select { border: 1px solid #e2d9c6; background: #fff; min-height: 42px; border-radius: 8px; font-size: .95rem; color: var(--sf-ink); }
.sf-morph .form-control:focus, .sf-morph .form-select:focus { border-color: var(--sf-gold); box-shadow: 0 0 0 .18rem rgba(184,150,62,.18); }
.sf-morphfoot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 16px; margin-top: 18px; }
.sf-morph-reset { background: transparent; border: 0; color: var(--sf-muted); font-size: .85rem; text-decoration: underline; padding: 6px 2px; cursor: pointer; }
.sf-morph-full { color: var(--sf-ink); font-size: .85rem; }
.sf-morph-submit { background: var(--sf-gold); border: 0; color: #fff; border-radius: 8px; padding: 11px 28px; font-size: 1rem; cursor: pointer; }
.sf-morph-submit:hover { filter: brightness(1.08); }
.sf-morph-submit .bi { margin-right: 6px; }

/* Products-page search row (unchanged behaviour, kept here with the rest) */
.sf-searchrow .sf-searchbox { flex: 1; }
.sf-clearfilters { align-self: center; color: var(--sf-ink); border: 1px solid #cfc4a8; border-radius: 18px; padding: 6px 14px; font-size: 13px; text-decoration: none; white-space: nowrap; }
.sf-clearfilters:hover { color: var(--sf-ink); border-color: var(--sf-gold); }

@media (max-width: 1199.98px) {
    .sf-brand-mark img { height: 116px; }
}
@media (max-width: 991.98px) {
    .ba-brandrow { padding: 10px 0 8px; gap: 16px; }
    .sf-brand-mark img { height: 94px; }
    .sf-phone-order .sf-phone-lead, .sf-phone-order .sf-phone-call { font-size: .84rem; }
    .sf-phone-order .sf-phone-num { font-size: 1.12rem; }
    .sf-searchrow { display: block; }
    .sf-clearfilters { display: inline-block; margin-top: 9px; }
}
@media (max-width: 767.98px) {
    .ba-brandrow { flex-direction: column; gap: 4px; padding: 10px 0 8px; }
    .ba-brandaside { text-align: center; }
    .sf-brand-mark img { height: 76px; }
    .sf-phone-order .sf-phone-lead, .sf-phone-order .sf-phone-call { display: inline; font-size: .82rem; }
    .sf-hero { padding: 28px 14px 34px; }
    .sf-hero h1 { font-size: 21px; gap: 10px; letter-spacing: .8px; }
    .sf-hero h1::before, .sf-hero h1::after { width: 26px; }
    .sf-hero .sf-count { font-size: 29px; }
    .sf-hero .sf-sub { font-size: 14px; margin-bottom: 18px; }
}
@media (max-width: 575.98px) {
    .sf-searchbox { flex-wrap: wrap; }
    .sf-searchbox .sf-searchicon { padding-left: 16px; }
    .sf-searchbox input[type="text"] { flex: 1 1 auto; padding: 15px 12px; font-size: 16px; }
    .sf-refine, .sf-primary-search { flex: 1 1 50%; min-height: 50px; justify-content: center; border-top: 1px solid #ece5d8; }
    .sf-refine { border-left: 0; }
    .sf-primary-search { text-align: center; }
    .sf-morphinner { padding: 16px; }
    .sf-composer.is-open .sf-morph { max-height: 1200px; }
    .sf-morphfoot { justify-content: center; gap: 12px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   STOREFRONT HEADER REWORK — 7 Aug 2026 (Orlando approved 16:01)
   One dark banner, pinned to the top of the window; the menu sits ON it;
   the menu-bar search box drops open into the full detailed search.
   Light mode only (§40.0). Nothing below is specific to one shop.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The pinned stack: holiday notice first (standing rule — it must never end up
   below the menu), then the banner. position:sticky keeps the space it occupies
   in the page, so no page content can ever be hidden underneath it. */
.ba-topstack { position: sticky; top: 0; z-index: var(--ba2-z-navbar); }

/* The banner colour is a single setting a shop look can change in one line
   (--sf-banner). Default is the deep purple Orlando approved on 7 Aug 2026. */
:root {
    --sf-banner: #0B001D; /* corrected 7 Aug 2026 evening - Orlando: must match logo background exactly, RGB 11,0,29 */
}
.ba-header--pinned {
    background: var(--sf-banner);
    box-shadow: 0 6px 18px rgba(0,0,0,.28);
}
/* ONE BAND, ONE COLOUR.
   The old header was two strips, and every shop-look file in wwwroot/themes still
   carries a rule that paints the menu strip in its own colour. Inside the single
   pinned banner that separate strip must not exist, so it is switched off here.
   This is deliberately forced, and deliberately limited to the pinned banner —
   nothing else on the site is affected, and a shop look still sets the banner
   colour, in one line, with --sf-banner above. */
.ba-header--pinned .ba-navband.navbar { background: transparent !important; }

/* Layout correction, 7 Aug 2026 evening (Orlando): the menu must sit BESIDE the logo
   on one row, not in its own band underneath, and the dead space that used to sit
   above the phone wording must go. The logo is the tallest thing in the banner, so
   everything else — the phone line and, immediately below it, the menu + search/
   currency/basket/account cluster — is stacked into one compact column that lives in
   that same row, beside the logo, starting flush at the top (no more bottom-anchoring,
   which is what was leaving a gap above the phone line before). */
.ba-header--pinned .ba-headrow {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 20px; padding: 6px 0 6px;
}
.ba-header--pinned .sf-brand-mark { display: inline-block; line-height: 0; flex: 0 0 auto; }
.ba-header--pinned .sf-brand-mark img { height: 84px; width: auto; max-width: 100%; display: block; }

.ba-header--pinned .ba-headmain {
    flex: 1 1 auto; min-width: 0;
    display: flex; flex-direction: column; align-items: stretch;
    gap: 3px;
}
.ba-header--pinned .ba-headaside { text-align: right; }

/* Phone-order wording, top right, readable on the dark band. */
.ba-header--pinned .sf-phone-order { color: #fff; line-height: 1.2; }
.ba-header--pinned .sf-phone-order .sf-phone-lead { display: inline; font-size: .84rem; font-weight: 400; color: #fff; letter-spacing: .2px; }
.ba-header--pinned .sf-phone-order .sf-phone-call { display: inline; font-size: .84rem; color: #fff; margin-left: .4em; }
.ba-header--pinned .sf-phone-order .sf-phone-num { font-size: 1rem; font-weight: 700; color: #fff; white-space: nowrap; letter-spacing: .5px; }
.ba-header--pinned .sf-phone-order .sf-phone-note { display: block; font-size: .68rem; color: rgba(255,255,255,.72); }

/* The menu row now sits ON the dark band, immediately beside the logo — no white
   strip, no border, and no extra top/bottom padding of its own (the ba-headmain
   gap above already gives it a little breathing room from the phone line). */
.ba-header--pinned .ba-navband {
    background: transparent; border: 0; box-shadow: none;
    padding: 0;
}
.ba-header--pinned .ba-navband .navbar-nav .nav-link,
.ba-header--pinned .ba-navband .nav-link,
.ba-header--pinned .ba-navband > .navbar-collapse a:not(.dropdown-item) {
    color: rgba(255,255,255,.92);
}
.ba-header--pinned .ba-navband .navbar-nav .nav-link:hover,
.ba-header--pinned .ba-navband .navbar-nav .nav-link:focus,
.ba-header--pinned .ba-navband .nav-link:hover,
.ba-header--pinned .ba-navband .nav-link:focus,
.ba-header--pinned .ba-navband .nav-link.show { color: var(--sf-gold-bright); }
.ba-header--pinned .ba-navband .navbar-nav .nav-link { padding-left: .85rem; padding-right: .85rem; letter-spacing: .2px; }

/* Buttons on the dark band: outlined in light, filling gold on hover. */
.ba-header--pinned .ba-navband .btn-outline-primary,
.ba-header--pinned .ba-navband .btn-outline-secondary,
.ba-header--pinned .ba-navband .btn-outline-light {
    color: #fff; border-color: rgba(255,255,255,.45); background: transparent;
}
.ba-header--pinned .ba-navband .btn-outline-primary:hover,
.ba-header--pinned .ba-navband .btn-outline-secondary:hover,
.ba-header--pinned .ba-navband .btn-outline-light:hover {
    color: #24103f; border-color: var(--sf-gold-bright); background: var(--sf-gold-bright);
}
/* Drop-down lists stay light — the shop is light mode only. */
.ba-header--pinned .ba-navband .dropdown-menu { background: #fff; }
.ba-header--pinned .ba-navband .dropdown-item { color: var(--sf-ink); }
.ba-header--pinned .ba-navband .navbar-toggler { border-color: rgba(255,255,255,.4); }
.ba-header--pinned .ba-navband .navbar-toggler-icon { filter: invert(1) grayscale(1) brightness(2.2); }
.ba-header--pinned .ba-navband .navbar-toggler:focus { box-shadow: 0 0 0 .2rem rgba(240,207,107,.35); }

/* ── The menu-bar copy of the ONE search control ─────────────────────────── */
.ba-navsearch { flex: 0 1 380px; min-width: 0; }
.sf-composer--navbar {
    position: relative; overflow: visible; box-shadow: none;
    background: transparent; border-radius: 8px; width: 100%;
}
.sf-composer--navbar .sf-searchbox {
    background: #fff; border-radius: 8px; overflow: hidden;
    border: 1px solid rgba(255,255,255,.35);
}
.sf-composer--navbar .sf-searchicon { padding-left: 11px; font-size: 14px; }
.sf-composer--navbar input[type="text"] { font-size: .9rem; padding: 7px 10px; }
.sf-composer--navbar .sf-refine { padding: 0 11px; font-size: .82rem; }
.sf-composer--navbar .sf-refine span { display: none; }
.sf-composer--navbar .sf-primary-search { font-size: .85rem; padding: 0 15px; }
/* The detailed fields drop DOWN from the box, sitting over the page. */
.sf-composer--navbar .sf-morph {
    position: absolute; top: calc(100% + 8px); right: 0;
    width: 720px; max-width: min(92vw, 720px);
    background: #fbf8f2; border-radius: 12px;
    box-shadow: 0 22px 62px rgba(0,0,0,.45);
    border-top: 0 solid var(--sf-gold); z-index: var(--ba2-z-navbar-menu);
}
.sf-composer--navbar.is-open .sf-morph { max-height: min(72vh, 640px); overflow-y: auto; }

/* ── The Advanced Search page copy: same control, simply always open ─────── */
.sf-composer--page { box-shadow: 0 8px 26px rgba(0,0,0,.10); }
.sf-composer--page .sf-searchbox { border-bottom: 1px solid #ece5d8; }
.sf-composer--page .sf-morph { max-height: none; opacity: 1; border-top-width: 3px; overflow: visible; }

@media (max-width: 1199.98px) {
    .ba-header--pinned .sf-brand-mark img { height: 76px; }
    .ba-navsearch { flex: 0 1 300px; }
}
@media (max-width: 991.98px) {
    .ba-header--pinned .ba-headrow { padding: 6px 0 6px; gap: 12px; }
    .ba-header--pinned .sf-brand-mark img { height: 64px; }
    .ba-header--pinned .sf-phone-order .sf-phone-lead,
    .ba-header--pinned .sf-phone-order .sf-phone-call { font-size: .78rem; }
    .ba-header--pinned .sf-phone-order .sf-phone-num { font-size: .92rem; }
    /* Narrow screens: the opened menu scrolls inside the pinned banner instead of
       running off the bottom of the screen. */
    .ba-header--pinned .navbar-collapse.show,
    .ba-header--pinned .navbar-collapse.collapsing { max-height: 66vh; overflow-y: auto; }
    .ba-navsearch { flex: 1 1 auto; margin: .5rem 0; }
    .sf-composer--navbar .sf-morph { position: static; width: auto; max-width: none; box-shadow: none; }
}
@media (max-width: 767.98px) {
    /* Mobile: logo + phone stay on the top line, menu collapses to just its toggle
       button underneath — still one tight banner, still pinned. */
    .ba-header--pinned .ba-headrow { align-items: center; gap: 10px; padding: 6px 0 6px; }
    .ba-header--pinned .sf-brand-mark img { height: 52px; }
    .ba-header--pinned .ba-headmain { gap: 4px; }
    .ba-header--pinned .ba-headaside { text-align: right; }
    .ba-header--pinned .sf-phone-order .sf-phone-lead,
    .ba-header--pinned .sf-phone-order .sf-phone-call { display: inline; font-size: .72rem; }
    .ba-header--pinned .sf-phone-order .sf-phone-num { font-size: .84rem; }
    .ba-header--pinned .sf-phone-order .sf-phone-note { display: none; }
}

/* ─── Storefront tile price (§195 tile spec) — ADDED 9 Aug 2026 (BA2 build queue,
   item 1, Orlando approved 9 Aug 2026 18:17). Line 5 of the shared tile
   (_StorefrontTile.cshtml) was already marked in its own source comment as
   "right-justified and slightly larger than the author line", and the price
   line already carries a text-end (right-justify) wrapper, but no CSS ever
   gave the price text its own size, so it rendered at the SAME size as the
   author line. This makes it visibly larger and bolder than lines 1-4, and
   (paired with the mt-auto on .sf-price-line in the shared partial) pins the
   price to the BOTTOM of the tile card so every tile in a row lines its price
   up at the same height regardless of how many lines the title/author area
   used. Site-wide via the one shared tile partial: search results, category
   pages, home page, related items and Bargain Corner all use this same rule. */
.sf-price {
    font-size: 1.25rem;
    font-weight: 700;
}

/* ══════════════════════════════════════════════════════════════════════════
   Stock Audit tiles + shared photo magnifier (12 Aug 2026 spec, CHUNK 2)
   Tile grid replaces the old table on Audit.cshtml. The magnifier/photo-swap
   control (.ba2-magnifier-*) is a SHARED control (partial + this CSS + one JS
   file) meant to be reused unchanged on Pick List and Bulk Boxing later.
   ══════════════════════════════════════════════════════════════════════════ */

.ba2-audit-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 1rem;
}

.ba2-audit-tile {
    border: 1px solid #dee2e6;
    border-radius: .5rem;
    background: #fff;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
[data-bs-theme="dark"] .ba2-audit-tile { background: #2b2b30; border-color: #495057; }

.ba2-audit-tile-photowrap {
    position: relative;
    width: 100%;
    aspect-ratio: 3 / 4;
    background: #f1f3f5;
    cursor: pointer;
}
[data-bs-theme="dark"] .ba2-audit-tile-photowrap { background: #1f1f23; }

.ba2-audit-tile-photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: filter .2s ease;
}

/* Shown instead of a broken-image icon when a book's photo file is missing
   (buildbox's product-images gap — see 12 Aug 2026 tiles spec §6). */
.ba2-audit-tile-photo-missing {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .25rem;
    color: #868e96;
    font-size: .75rem;
    text-align: center;
}
.ba2-audit-tile-photo-missing i { font-size: 1.6rem; }
[data-bs-theme="dark"] .ba2-audit-tile-photo-missing { color: #adb5bd; }

/* Done (ticked/actioned) — grey never alone: also a check icon + Undo button. */
.ba2-audit-tile.is-done .ba2-audit-tile-photo {
    filter: grayscale(1) brightness(.65);
}
.ba2-audit-tile-done-overlay {
    position: absolute;
    inset: 0;
    z-index: var(--ba2-z-base);
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    background: rgba(0, 0, 0, .15);
    /* The overlay itself never captures clicks — a tap anywhere else on a done tile
       does nothing (see JS), but the magnifier/camera corner buttons (z-index 4)
       must stay reachable on a greyed-out tile too. Only the Undo button, below,
       opts itself back in to pointer events. */
    pointer-events: none;
}
.ba2-audit-tile.is-done .ba2-audit-tile-done-overlay { display: flex; }
.ba2-audit-tile-tick-icon {
    font-size: 2.4rem;
    color: #2f9e44;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,.6));
}
.ba2-audit-tile-undo-btn {
    background: #fff;
    color: #000;
    border: 1px solid #000;
    font-weight: 600;
    padding: .25rem .75rem;
    border-radius: .35rem;
    pointer-events: auto;
}
[data-bs-theme="dark"] .ba2-audit-tile-undo-btn { background: #adb5bd; color: #000; border-color: #000; }

/* Count pills — copies (left) / volumes (right). Only rendered when > 1.
   Orlando: "Needs to stand out!!!!" — solid colour + white text + a white
   ring so it reads over any photo, in either theme. */
.ba2-audit-pill {
    position: absolute;
    top: .35rem;
    z-index: var(--ba2-z-base);
    font-size: .78rem;
    font-weight: 800;
    color: #fff;
    padding: .15rem .45rem;
    border-radius: .35rem;
    box-shadow: 0 0 0 2px #fff, 0 1px 3px rgba(0,0,0,.7);
    line-height: 1.3;
}
.ba2-audit-pill-copies { left: .35rem; background: #d97706; }
.ba2-audit-pill-volumes { right: .35rem; background: #0d6efd; }

/* Magnifier (bottom-LEFT) / camera (bottom-RIGHT) corner buttons — always on
   top of the greyed-out overlay so they stay usable after a tile is ticked. */
.ba2-audit-tile-corner-btn {
    position: absolute;
    bottom: .35rem;
    z-index: var(--ba2-z-base);
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255,255,255,.92);
    color: #212529;
    box-shadow: 0 1px 3px rgba(0,0,0,.5);
}
.ba2-audit-tile-corner-btn:hover { background: #fff; }
.ba2-audit-tile-magnifier-btn { left: .35rem; }
.ba2-audit-tile-camera-btn { right: .35rem; }
.ba2-audit-tile-camera-btn.is-flagged {
    background: #d97706;
    color: #fff;
    box-shadow: 0 0 0 2px #fff, 0 1px 3px rgba(0,0,0,.7);
}

.ba2-audit-tile-title {
    font-size: .78rem;
    color: #495057;
    padding: .3rem .5rem 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.1rem;
}
[data-bs-theme="dark"] .ba2-audit-tile-title { color: #ced4da; }

.ba2-audit-tile-bottomrow {
    display: flex;
    align-items: center;
    gap: .4rem;
    padding: .35rem .5rem;
}
.ba2-audit-tile-sku {
    font-family: var(--bs-font-monospace, monospace);
    font-weight: 700;
    font-size: .92rem;
}
.ba2-audit-tile-price {
    font-weight: 600;
    font-size: .85rem;
    color: #495057;
    flex: 1 1 auto;
    text-align: center;
}
[data-bs-theme="dark"] .ba2-audit-tile-price { color: #ced4da; }
.ba2-audit-tile-cantfind-btn {
    font-size: .78rem;
    padding: .15rem .5rem;
    white-space: nowrap;
}

.ba2-audit-tile-weightrow {
    display: flex;
    align-items: center;
    gap: .3rem;
    padding: 0 .5rem .4rem;
}
.ba2-audit-tile-weightrow select {
    font-size: .78rem;
    padding: .15rem .3rem;
}
.ba2-audit-tile-weightrow button {
    font-size: .78rem;
    padding: .15rem .4rem;
}

.ba2-audit-tile-flag-note {
    font-size: .7rem;
    color: #d97706;
    padding: 0 .5rem .35rem;
}
[data-bs-theme="dark"] .ba2-audit-tile-flag-note { color: #ffb454; }

/* ── Shared photo magnifier / photo-switch modal (reusable control) ── */
.ba2-magnifier-main-wrap {
    position: relative;
    background: #f1f3f5;
    border-radius: .4rem;
    overflow: hidden;
}
[data-bs-theme="dark"] .ba2-magnifier-main-wrap { background: #1f1f23; }
.ba2-magnifier-main-photo { width: 100%; max-height: 55vh; object-fit: contain; display: block; margin: 0 auto; }
.ba2-magnifier-thumbs {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin-top: .75rem;
}
.ba2-magnifier-thumb {
    width: 72px;
    height: 96px;
    object-fit: cover;
    border: 2px solid #dee2e6;
    border-radius: .3rem;
    cursor: pointer;
    background: #f1f3f5;
}
.ba2-magnifier-thumb.is-main { border-color: #2f9e44; }
.ba2-magnifier-thumb.is-selected { border-color: #0d6efd; box-shadow: 0 0 0 2px #0d6efd; }
[data-bs-theme="dark"] .ba2-magnifier-thumb { background: #1f1f23; border-color: #495057; }

.ba2-magnifier-side-panel {
    border: 1px solid #dee2e6;
    border-radius: .4rem;
    padding: .5rem;
}
[data-bs-theme="dark"] .ba2-magnifier-side-panel { border-color: #495057; }
.ba2-magnifier-side-title { font-weight: 600; font-size: .85rem; margin-bottom: .4rem; }
.ba2-magnifier-side-photos { display: flex; flex-wrap: wrap; gap: .5rem; min-height: 96px; }
.ba2-magnifier-side-photos .ba2-magnifier-thumb.is-pick-source { box-shadow: 0 0 0 3px #d97706; }

.ba2-magnifier-neighbour-card {
    border: 1px solid #dee2e6;
    border-radius: .4rem;
    padding: .4rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: .5rem;
}
.ba2-magnifier-neighbour-card:hover { background: #f8f9fa; }
[data-bs-theme="dark"] .ba2-magnifier-neighbour-card { border-color: #495057; }
[data-bs-theme="dark"] .ba2-magnifier-neighbour-card:hover { background: #343a40; }
.ba2-magnifier-neighbour-card img { width: 40px; height: 54px; object-fit: cover; border-radius: .2rem; }



/* JOB 4 (15 Aug 2026, claim ba2-shopfront-navbar-0815, admin navbar search box ONLY):
   10px wider (210px -> 220px), no padding above/below, text sized up to match the
   tighter, wider box. Mirrors the inline <style> block in _AdminLayout.cshtml —
   the served bundle (ba2-admin-core.min.css) does not get rebuilt on this box, so
   this rule is appended here by hand as the established workaround. Source of truth
   is this file (site.css); the two bundle copies below carry the same rule verbatim. */
.ba-nav-search .form-control {
    font-size: .95rem;
    padding: 0 .7rem;
}
.ba-topnav .ba-nav-search #globalSearchInput {
    width: 220px;
}
@media (min-width: 1200px) {
    .ba-topnav .ba-nav-search #globalSearchInput { width: 100% !important; max-width: 220px; }
}


/* ba2-shipping-choice-0816 - hover/tap trigger for the product-page delivery popup */
.pd-free-shipping-trigger {
    cursor: help;
    border-bottom: 1px dotted currentColor;
}


/* ============================================================================
   THE UNANSWERED INSURANCE QUESTION (Orlando, 18 Aug 2026)
   ----------------------------------------------------------------------------
   Plain English: on a busy packing bench a question that merely sits there in a
   red box gets walked straight past. Orlando was explicit that a red background
   on its own is NOT enough. So an unanswered insurance question gets FOUR things
   at once, and every one of them stops the moment it is answered:

     1. a thick dark-red edge all the way round the panel, and a much thicker
        bar down its left-hand side;
     2. white bold lettering on a dark red headline strip inside the panel;
     3. a slow, gentle pulse around the panel, so movement catches the eye
        across the room;
     4. a dark red bar that sticks to the top of the screen as the page is
        scrolled, saying the order cannot be processed and offering a link that
        jumps straight down to the question.

   The yellow-box-with-black-text style is deliberately NOT reused here. That
   one belongs to typo alerts, which never block anything, and the two must
   never look alike.

   The sticky bar takes its height on the screen from the one named ladder in
   ba2-layers.css -- rung 3, "notice" -- so it can never end up covering the
   admin menu.

   Anyone who has switched off screen animations in their operating system gets
   the other three, without the pulse.
   ============================================================================ */

.ba2-insurance-unanswered {
    border: 3px solid #8b1a25;
    border-left: 14px solid #8b1a25;
    background-color: #fdf2f3;
    animation: ba2-insurance-attention 1.7s ease-in-out infinite;
}

@keyframes ba2-insurance-attention {
    0%   { box-shadow: 0 0 0 0 rgba(139, 26, 37, 0.55); }
    70%  { box-shadow: 0 0 0 12px rgba(139, 26, 37, 0); }
    100% { box-shadow: 0 0 0 0 rgba(139, 26, 37, 0); }
}

.ba2-insurance-headline {
    background-color: #8b1a25;
    color: #ffffff;
    font-weight: 700;
    padding: 0.6rem 0.9rem;
    border-radius: 0.25rem;
}

.ba2-insurance-headline .bi {
    color: #ffffff;
}

.ba2-insurance-blocked-bar {
    position: sticky;
    top: 0;
    z-index: var(--ba2-z-notice);
    background-color: #8b1a25;
    color: #ffffff;
    font-weight: 700;
    padding: 0.65rem 1rem;
    margin-bottom: 1rem;
    border-radius: 0.25rem;
}

/* The bar is dark red, so its link must be white to be readable. The admin-wide link
   colour rule (main.container-fluid a:not(...)) carries a long exclusion list, which makes
   it outrank any ordinary component rule, so this override has to be forced or the link
   renders dark purple on dark red and cannot be read. */
.ba2-insurance-blocked-bar a,
.ba2-insurance-blocked-bar a:link,
.ba2-insurance-blocked-bar a:visited,
.ba2-insurance-blocked-bar a:hover,
.ba2-insurance-blocked-bar a:focus {
    color: #ffffff !important;
    text-decoration: underline;
}

/* Answered -- calm, plain, and no movement at all. */
.ba2-insurance-answered {
    border: 1px solid #cfd4d9;
    background-color: #f8f9fa;
}

/* The goods value itself, shown in red once it is over the hundred-pound mark. */
.ba2-insurance-value-over {
    color: #8b1a25;
    font-weight: 700;
}

@media (prefers-reduced-motion: reduce) {
    .ba2-insurance-unanswered { animation: none; }
}


/* ============================================================================
   SHIPPING PAGE: MULTI-BOOK GROUPING AND THE TWO CARRIER COUNTERS
   Added 18 Aug 2026 (Orlando, phases 4 and 5 of the shipping bench job).

   Plain English:
   - A box is drawn round all the books belonging to one order, so a packer can
     see at a glance that they travel together in one parcel. There are 369
     multi-book orders, so this is the normal case, not a rare one.
   - The two counters at the top are the Transglobal and Royal Mail piles
     waiting to be closed for the day.

   Stacking heights use the NAMES from ba2-layers.css. No raw numbers: the build
   refuses to compile if it finds one outside that file.
   ============================================================================ */

/* -- the box round one order's books -- */
.ba2-order-group-top > td,
.ba2-order-group-item > td,
.ba2-order-group-bottom > td {
    border-left: 0;
    border-right: 0;
}
.ba2-order-group-top > td:first-child,
.ba2-order-group-item > td:first-child,
.ba2-order-group-bottom > td:first-child {
    border-left: 3px solid #4a1942;
}
.ba2-order-group-top > td:last-child,
.ba2-order-group-item > td:last-child,
.ba2-order-group-bottom > td:last-child {
    border-right: 3px solid #4a1942;
}
.ba2-order-group-top > td {
    border-top: 3px solid #4a1942;
}
.ba2-order-group-bottom > td {
    border-bottom: 3px solid #4a1942;
}
.ba2-order-group-top,
.ba2-order-group-item,
.ba2-order-group-bottom {
    background-color: rgba(74, 25, 66, .035);
}
/* the little "3 books - one parcel" label inside the box */
.ba2-order-group-note {
    display: inline-block;
    background: #4a1942;
    color: #fff;
    font-size: .75rem;
    font-weight: 600;
    padding: .1rem .5rem;
    border-radius: 4px;
    margin-left: .35rem;
}
.ba2-order-group-bottom-note {
    font-size: .78rem;
    color: #4a1942;
    font-style: italic;
}

/* -- the yellow "worth knowing" note: YELLOW ALWAYS TAKES BLACK TEXT -- */
.ba2-yellow-note {
    background: #fff3cd;
    color: #000;
    border: 1px solid #ffe69c;
    border-radius: 6px;
    padding: .5rem .75rem;
    font-size: .85rem;
}
.ba2-yellow-note a { color: #000; text-decoration: underline; }

/* -- the two carrier counters -- */
.ba2-manifest-pill {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    border: 2px solid transparent;
    border-radius: 8px;
    padding: .5rem .9rem;
    font-weight: 600;
    font-size: .95rem;
    cursor: pointer;
    text-align: left;
    line-height: 1.25;
}
.ba2-manifest-pill .ba2-manifest-count {
    font-size: 1.35rem;
    font-weight: 700;
    line-height: 1;
}
.ba2-manifest-pill:focus-visible {
    outline: 3px solid #000;
    outline-offset: 2px;
}
/* Royal Mail: the house purple, white text on a dark fill */
.ba2-manifest-pill-rm {
    background: #4a1942;
    border-color: #4a1942;
    color: #fff;
}
.ba2-manifest-pill-rm:hover { background: #35122f; }
/* Transglobal: yellow fill, and yellow ALWAYS takes black text (standing rule) */
.ba2-manifest-pill-tg {
    background: #ffc107;
    border-color: #d39e00;
    color: #000;
}
.ba2-manifest-pill-tg:hover { background: #e0a800; color: #000; }
/* nothing waiting: plainly not a button to press */
.ba2-manifest-pill-empty {
    background: #f1f1f1;
    border-color: #d7d7d7;
    color: #555;
    cursor: not-allowed;
}
.ba2-manifest-pill-empty:hover { background: #f1f1f1; }

