@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');

/* Legacy --nwc-* aliases. Kept for compatibility with existing consumers
   (panel-layout.css, scoped .razor.css files). New code should reference
   tokens.css directly. */
:root {
    --nwc-text:         var(--text-primary);
    --nwc-text-muted:   var(--text-muted);
    --nwc-text-light:   var(--text-disabled);
    --nwc-bg:           var(--surface-default);
    --nwc-bg-subtle:    var(--surface-subtle);
    --nwc-bg-muted:     var(--surface-muted);
    --nwc-border:       var(--border-default);
    --nwc-border-light: var(--border-subtle);

    /* MonthCalendar: width of the trailing weekly-summary column. Shared by the
       reusable .flex-grid (MonthCalendar) and a consumer's day-of-week band
       (.flex-grid-days) so the two grids keep identical tracks and line up. */
    --mc-summary-col: 9rem;
}

html, body {
    font-family: var(--font-family-body);
}

h1:focus {
    outline: none;
}

a, .btn-link {
    color: var(--text-link);
}

.btn-primary {
    color: var(--white);
    background-color: var(--interactive-primary);
    border-color: var(--interactive-primary-border);
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--state-valid-outline);
}

.invalid {
    outline: 1px solid var(--red-500);
}

.validation-message {
    color: var(--red-500);
}

#blazor-error-ui {
    background: var(--state-warning-bg);
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem calc(0.7rem + env(safe-area-inset-bottom)) 1.25rem;
    position: fixed;
    width: 100%;
    /* Deliberately above --z-bottom-nav (990): a reconnect/error banner is a global system
       alert and should cover the bottom tab bar while it's up, not sit behind it. On phones this
       will be the dominant field-UX interruption on flaky vineyard Wi-Fi (see harvest mobile scope
       doc §7.2) — the safe-area padding above keeps the dismiss control clear of the home
       indicator. */
    z-index: var(--z-error-ui);
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: var(--space-md);
        top: var(--space-sm);
    }

/* ── Circuit-lost notice ────────────────────────────────────────────────────
   #blazor-error-ui above covers an unhandled EXCEPTION. It does NOT cover a
   dropped circuit — that path drives #components-reconnect-modal, and this app
   shipped without the element, so every disconnect was silently invisible: the
   page simply stopped responding with no explanation (bug #12, 2026-08-01,
   iPhone weight-tag scanning — opening the native camera suspends the page long
   enough to kill the WebSocket).

   Blazor owns the state classes; we only style them:
     .components-reconnect-show     — retrying
     .components-reconnect-hide     — recovered (base display:none resumes)
     .components-reconnect-failed   — retries exhausted, Blazor.reconnect() may work
     .components-reconnect-rejected — server dropped the circuit, only a reload helps
   Blazor also fills #components-reconnect-current-attempt / -max-retries when present. */
#components-reconnect-modal {
    display: none;
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    align-items: center;
    background: var(--state-warning-bg);
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: flex;
    gap: var(--space-sm);
    left: 0;
    padding: 0.6rem 1.25rem calc(0.7rem + env(safe-area-inset-bottom)) 1.25rem;
    position: fixed;
    width: 100%;
    z-index: var(--z-reconnect);
}

    /* One child per state; the active state class reveals exactly one. */
    #components-reconnect-modal .rc-state {
        display: none;
        align-items: center;
        gap: var(--space-sm);
    }

    #components-reconnect-modal.components-reconnect-show .rc-retrying,
    #components-reconnect-modal.components-reconnect-failed .rc-failed,
    #components-reconnect-modal.components-reconnect-rejected .rc-rejected {
        display: flex;
    }

    #components-reconnect-modal .rc-spinner {
        animation: rc-spin 1s linear infinite;
        border: 2px solid currentColor;
        border-radius: 50%;
        border-top-color: transparent;
        display: inline-block;
        flex: none;
        height: 1rem;
        width: 1rem;
    }

@keyframes rc-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    #components-reconnect-modal .rc-spinner {
        animation-duration: 3s;
    }
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, var(--red-700);
    padding: 1rem 1rem 1rem 3.7rem;
    color: var(--white);
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

/*   Start: added to apply to all select elements in project 3/10/2023*/
select {
    display: block;
    width: 100%;
    padding: .375rem 1.75rem .375rem .75rem;
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-normal);
    line-height: var(--line-height-normal);
    color: var(--text-primary);
    background-color: var(--surface-default);
    background-clip: padding-box;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-sm);
    transition: border-color var(--transition-default), box-shadow var(--transition-default);
}
    select:focus {
        border-color: #8fbbd9; /* intentional: lighter focus tint than --blue-500 */
        outline: 0;
        box-shadow: var(--shadow-focus);
    }
    select[multiple], .form-select[size]:not([size="1"]) {
        height: auto;
        padding-right: .75rem;
        background-image: none;
    }
/*End*/

/* Adjust if using custom classes */
/*.custom-panel-overlay {
  z-index: 1050;
}

.custom-panel {
  z-index: 1060;
}*/

/* Prevent body scroll when sliding panel is open */
body.panel-open {
    overflow: hidden;
    position: fixed;
    width: 100%;
    height: 100%;
}

/* ============================================
   Compliance Pages - Shared Styles
   ============================================ */

.compliance-page .page-container {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.compliance-page .sticky-header {
    position: sticky;
    top: 0;
    background: var(--surface-default);
    z-index: var(--z-sticky);
    padding: var(--space-lg) 1.25rem 0;
    box-shadow: var(--shadow-md);
}

/* Tabs - underline style matching app pattern */
.compliance-page .page-tabs {
    display: flex;
    align-items: center;
    gap: 0;
    margin-bottom: 0;
    border-bottom: 2px solid var(--border-subtle);
}

.compliance-page .page-tabs .tab {
    padding: 0.6rem var(--space-xl); /* 0.6rem intentional — dense compliance toolbar */
    text-decoration: none;
    color: var(--tab-inactive-color);
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-medium);
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    transition: all 0.2s;
}

.compliance-page .page-tabs .tab:hover {
    color: var(--accent-primary);
    background: transparent;
}

.compliance-page .page-tabs .tab.active {
    color: var(--tab-active-color);
    border-bottom-color: var(--tab-active-border);
    font-weight: var(--font-weight-semibold);
    background: transparent;
}

.compliance-page .page-header {
    display: flex;
    align-items: center;
    gap: var(--space-lg);
    padding-top: var(--space-lg);
    margin-bottom: var(--space-md);
}

.compliance-page .page-header h2 {
    margin: 0;
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-semibold);
    color: var(--nwc-text);
}

.compliance-page .loading-indicator {
    color: var(--text-muted);
    font-size: 0.8rem; /* off-scale — sits between --font-size-sm (0.75) and --font-size-md (0.85) */
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.compliance-page .search-bar {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: var(--space-md);
    background: var(--search-bar-bg);
    border-radius: var(--search-bar-radius);
    border: 1px solid var(--search-bar-border);
    margin-bottom: var(--space-sm);
}

.compliance-page .search-bar .input-group {
    flex: 1;
    max-width: 400px;
}

.compliance-page .search-bar .form-control {
    border-radius: var(--radius-md);
}

.compliance-page .search-bar .form-control:focus {
    border-color: var(--accent-primary);
    box-shadow: var(--shadow-focus-accent);
}

.compliance-page .content-area {
    flex: 1;
    overflow-y: auto;
    padding: var(--space-lg) 1.25rem;
}

.compliance-page .empty-state {
    max-width: 420px;
    margin: var(--space-2xl) auto;
    padding: var(--space-2xl);
    text-align: center;
    background: var(--surface-subtle);
    border-radius: var(--radius-xl);
    border: 1px dashed var(--border-default);
}

.compliance-page .empty-state i {
    color: var(--text-disabled);
}

.compliance-page .empty-state h4 {
    color: var(--text-secondary);
    font-weight: var(--font-weight-semibold);
}

.compliance-page .results-summary {
    padding: var(--space-sm) 0;
    color: var(--text-muted);
    font-size: 0.8rem; /* off-scale */
}

/* Compliance table styling */
.compliance-page .table {
    font-size: var(--font-size-base);
}

.compliance-page .table thead th {
    background: var(--table-header-bg);
    color: var(--table-header-fg);
    font-weight: var(--font-weight-semibold);
    font-size: 0.8rem; /* off-scale eyebrow-label sizing */
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
    padding: 0.6rem var(--space-md); /* 0.6rem intentional — dense compliance table */
    border: none;
    white-space: nowrap;
    position: sticky;
    top: 0;
    z-index: var(--z-base);
}

.compliance-page .table tbody tr {
    transition: background 0.15s;
}

.compliance-page .table tbody tr:hover {
    background: var(--table-row-hover);
}

.compliance-page .table tbody td {
    padding: 0.6rem var(--space-md); /* y: 0.6rem off-scale (dense compliance table); x: --space-md = 0.75rem */
    vertical-align: middle;
    border-color: var(--nwc-border-light);
}

/* ── Compact form/button utilities ─────────────────────────────────── */
.nwc-form-xs { font-size: 0.72rem; padding: 0.15rem 0.3rem; height: auto; min-height: unset; line-height: 1.3; }
.nwc-form-sm { font-size: 0.8rem; padding: 0.35rem var(--space-sm); height: auto; min-height: 1.85rem; line-height: 1.3; } /* 0.8rem off-scale */
.nwc-btn-xs  { padding: 0.1rem 0.25rem; font-size: var(--font-size-xs); line-height: 1.3; }
.nwc-btn-icon { padding: 0; font-size: var(--font-size-md); line-height: 1; border: none; background: transparent; }

/* ── Reduced-motion accessibility ─────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* ── Click-outside backdrop for Blazor-native dropdown menus ───────────
   Bootstrap's JS isn't loaded in this app, so any markup that previously
   used data-bs-toggle="dropdown" now wires its own open/close state and
   pairs the visible menu (.dropdown-menu.show) with a transparent
   fixed-position backdrop that catches outside clicks. The backdrop sits
   beneath the menu (lower z-index) and above page content. */
.js-dropdown-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--z-dropdown-backdrop);
    background: transparent;
}

/* ── Blue/Green slot badge (admin-only) ─────────────────────────────────
   Rendered by Shared/SlotBadge.razor; visible only to Admin or SuperAdmin.
   Identifies which IIS slot is currently serving the page so admins can
   verify a swap without opening DevTools or hitting /admin/health. */
.slot-badge,
.slot-chip {
    padding: 2px 10px;
    border-radius: var(--radius-pill);
    font-size: 11px;
    font-weight: var(--font-weight-semibold);
    color: var(--white);
    letter-spacing: 0.5px;
    text-transform: uppercase;
}

.slot-badge {
    position: fixed;
    bottom: 8px;
    right: 8px;
    z-index: var(--z-slot-badge);
    pointer-events: auto;
    cursor: default;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

/* On mobile the floating badge would sit on the bottom nav's More tab (both are
   fixed bottom-right); the slot renders inside the More sheet instead
   (SlotBadge Variant="sheet" in BottomNav). */
@media (max-width: 767.98px) {
    .slot-badge { display: none; }
}

.slot-badge.slot-blue,  .slot-chip.slot-blue  { background: var(--blue-500); }
.slot-badge.slot-green, .slot-chip.slot-green { background: #198754; }       /* Bootstrap success — distinct from --green-700 / --green-500 */
.slot-badge.slot-unknown, .slot-chip.slot-unknown { background: var(--text-muted); }

/* Slot/build footer row inside the mobile More sheet (SlotBadge Variant="sheet").
   Global (not BottomNav-scoped) because SlotBadge renders it without a scope attr. */
.slot-sheet-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px 2px; /* .bottom-sheet already pads the safe-area bottom */
    border-top: 1px solid var(--border-subtle);
}

.slot-sheet-meta {
    font-size: 12px;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dropdown-menu.show { z-index: var(--z-dropdown); }

/* ───────────────────────────────────────────────────────────────────────────
   Intake card — canonical "stat / library row / receipt" card. Visual base
   shared across 11+ .razor.css files (wt-card, cl-card, rs-card, gl-card,
   gs-card, lp-card, bol-card, er-card, inv-card, …). Per-page CSS files keep
   only the modifiers (--warning, --coverage-red, --active) and sub-elements
   (-icon, -body, -number, -label); the duplicated base block is GONE.

   Markup pattern during the consolidation:
       <div class="nwc-card xx-card">      ← gets base from here + modifiers from page
       <div class="nwc-card xx-card xx-card--warning">

   The .xx-card class is harmless once empty — leave it on markup as a
   namespace anchor for the page-specific modifiers.
   ─────────────────────────────────────────────────────────────────────── */
.nwc-card {
    display: flex;
    align-items: center;
    gap: var(--space-md);
    padding: 0.625rem 0.875rem;
    background: linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%);
    border: 1px solid var(--slate-200);
    border-radius: 0.625rem;
    transition: box-shadow var(--transition-default);
}

.nwc-card:hover {
    box-shadow: var(--shadow-lg);
}

/* ───────────────────────────────────────────────────────────────────────
   .nwc-card sub-elements — the canonical icon/body/number/label shape
   used by every page consuming .nwc-card. Page-specific icon colour
   modifiers stay scoped (e.g. .cl-card-icon--cork); the four semantic
   ones (warning/success/danger/info) live here.
   ─────────────────────────────────────────────────────────────────────── */
.nwc-card-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-lg);
    background: rgba(79, 70, 229, 0.1);
    color: var(--indigo-600);
    font-size: var(--font-size-lg);
    flex-shrink: 0;
}

.nwc-card-icon--warning { background: rgba(217, 119, 6, 0.12); color: var(--amber-600); }
.nwc-card-icon--success { background: rgba(22, 163, 74, 0.1);  color: var(--green-500); }
.nwc-card-icon--danger  { background: rgba(220, 38, 38, 0.1);  color: #dc2626; }
.nwc-card-icon--info    { background: rgba(59, 130, 246, 0.1); color: #3b82f6; }

@media (max-width: 900px) {
    .nwc-card-icon {
        width: 30px;
        height: 30px;
        font-size: var(--font-size-md);
    }
}

/* Cover-fit img inside wrapper containers — hoisted from 5 .razor.css files (audit #5).
   Page-local outliers (e.g. SkuLabelColaPicker's .suggestion-thumb img with
   object-fit:contain) keep winning via CSS-isolation specificity. */
.suggestion-thumb img,
.profile-thumb img,
.er-thumb img,
.image-slot img,
.gallery-item img,
.home-page .img-fluid,
.home-layout-two .main-image img,
.home-layout-three .top-image img,
.home-layout-three .bottom-image img,
.home-layout-four .grid-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.nwc-card-body {
    min-width: 0;
}

.nwc-card-number {
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-bold);
    line-height: 1.2;
    color: var(--slate-800);
}

.nwc-card-label {
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--slate-500);
    white-space: nowrap;
}

/* ───────────────────────────────────────────────────────────────────────
   .nwc-confirm* — shared "confirm card" family for destructive/result panels.
   Hoisted from byte-identical inline <style> blocks in UserTeardownPanel and
   ContactCleanupPanel (CSS-dedup arc). A bordered card with semantic colour
   variants; .nwc-action-bar is the right-aligned button row that pairs with it.
   ─────────────────────────────────────────────────────────────────────── */
.nwc-confirm { border: 1px solid #dee2e6; border-radius: 0.5rem; padding: 0.75rem 1rem; background: #fff; }
.nwc-confirm-danger  { border-color: #dc3545; background: #fdf2f3; }
.nwc-confirm-success { border-color: #198754; background: #e9f7ef; }
.nwc-confirm-warning { border-color: #ffc107; background: #fff8e1; }
.nwc-action-bar { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 0.5rem; }

/* ───────────────────────────────────────────────────────────────────────
   ConfirmDialogPanel body helpers — global because ChildContent passed to
   Shared/ConfirmDialogPanel.razor is authored in the CALLING .razor file, so
   it carries the caller's Blazor CSS-isolation scope, not ConfirmDialogPanel's.
   Consolidated from 6 near-byte-identical confirm-dialog implementations
   (SuppliesPanel, MaterialStatusSection, BottlingLabelPanel, Detail x2,
   SupplyOrdersPage) — see LAYOUT-PATTERNS.md Pattern 12.
   ─────────────────────────────────────────────────────────────────────── */
.confirm-body p { margin: 0 0 12px 0; }
.confirm-body p:last-child { margin-bottom: 0; }
.confirm-details {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px;
    background: var(--gray-50);
    border-radius: var(--radius-sm);
    margin-bottom: 12px;
}
.confirm-details strong { color: var(--gray-900); }
.confirm-details span   { color: var(--gray-600); }

/* ───────────────────────────────────────────────────────────────────────
   .nwc-kv — shared key-value definition grid (label column + fluid value
   column, semantic <dl>/<dt>/<dd>). Baseline values match the most common
   instance in the corpus (110px label column, 4px 12px gap, var(--text-muted)
   label). Consolidated from 9 near-identical hand-rolled instances
   (InventoryInspector .im-kv, UserTeardownPanel .utp-kv, LabelManager
   .lm-inspector-meta/.lm-proof-dl, Materials InventoryManager .im-kv,
   BulkWineDesk .bwd-kv, LabelProofFromIntake .lpfi-dl, CcofMaterialsMain/
   CcofOperationsCertsMain .ccof-detail dl) — see LAYOUT-PATTERNS.md Pattern 2.
   Each consumer keeps its own class name ALSO applied for local overrides
   (width/gap/color deltas) via the normal Blazor-scoped-selector-wins-over-
   global-class cascade, same convention as .im-recv- / .im-picker- above.
   ─────────────────────────────────────────────────────────────────────── */
.nwc-kv {
    display: grid;
    grid-template-columns: 110px 1fr;
    gap: 4px 12px;
    margin: 0;
}
.nwc-kv dt {
    color: var(--text-muted);
    font-weight: var(--font-weight-medium);
}
.nwc-kv dd {
    margin: 0;
}

/* ───────────────────────────────────────────────────────────────────────
   .nwc-group* — shared collapsible-group-list shell (card wrapper + clickable
   header row + body). Deliberately minimal: only the mechanics that were
   byte-identical across all 4 consumers (border-radius/overflow on the
   wrapper; display/align-items/cursor on the header). Color, background,
   hover treatment, spacing, and the expanded-state border stay local per
   instance — 2 of the 4 use a colored gradient header (TtbRegistryMain,
   ColasMain, near-twins of each other) and 2 use a plain gray header
   (FilingObligationsMain, BusinessCleanup), a deliberate domain distinction,
   not accidental drift, so they're not forced to converge further than this.
   LotExplorerPanel (5th instance in the corpus) was deliberately left OUT —
   a dark workspace-themed flat divider list with a <button> header and no
   card wrapper at all, genuinely different enough not to force in. See
   LAYOUT-PATTERNS.md Pattern 10.
   ─────────────────────────────────────────────────────────────────────── */
.nwc-group {
    border-radius: var(--radius-lg);
    overflow: hidden;
}
.nwc-group-header {
    display: flex;
    align-items: center;
    cursor: pointer;
}
.nwc-group-body {
    padding: 0;
}

.edit-instead {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 8px 0 0 0;
    font-size: 0.9rem;
    color: var(--blue-500);
    text-decoration: none;
}
.edit-instead:hover { color: var(--dailyflow-link-hover-fg); }

/* ───────────────────────────────────────────────────────────────────────
   Inventory Manager — shared panel base. The .im-recv* family is the
   canonical "receiving-style" panel layout used by 19 of the panels under
   Shared/Inventory/Panels/. UnassignedReceiptsPanel intentionally overrides
   .im-recv with a flex layout; that scoped override still wins via the
   Blazor b-attribute selector.
   ─────────────────────────────────────────────────────────────────────── */
.im-recv         { padding: 4px 0 12px; }
.im-recv-header  { padding: 4px 4px 12px; border-bottom: 1px solid var(--gray-100); margin-bottom: 12px; }
.im-recv-header h6 { font-weight: var(--font-weight-semibold); }
.im-recv-section { padding: 0 4px 14px; }
.im-recv-grid    { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
.im-recv-grid > div { display: flex; flex-direction: column; }
.im-recv-actions { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 12px 4px 0; border-top: 1px solid var(--gray-100); margin-top: 8px; }

/* ───────────────────────────────────────────────────────────────────────
   Inventory item/lot picker — shared search-and-select widget. Canonical
   for InventoryItemLotPicker (used by Damage/AdjustCount/IssueStock/Receive)
   plus the inline pickers in ReceiveStockPanel (supplier) and
   ReturnToStockPanel (item). Global so it crosses the component boundary
   into InventoryItemLotPicker, which has no scoped CSS of its own. Divergent
   consumers keep scoped deltas (ReceiveStock .im-picker-compact + results
   border + .im-picker-row transition).
   ─────────────────────────────────────────────────────────────────────── */
.im-picker          { border: 1px solid var(--gray-300); border-radius: var(--radius-md); background: #fff; overflow: hidden; }
.im-picker-input    { position: relative; padding: 6px; border-bottom: 1px solid var(--gray-100); }
.im-picker-input i  { position: absolute; top: 50%; left: 14px; transform: translateY(-50%); color: #868e96; font-size: var(--font-size-md); pointer-events: none; }
.im-picker-input input { padding-left: 30px; }
.im-picker-results  { max-height: 220px; overflow-y: auto; }
.im-picker-row      { display: block; width: 100%; text-align: left; appearance: none; background: transparent; border: 0; border-bottom: 1px solid var(--gray-100); padding: 7px 12px; cursor: pointer; }
.im-picker-row:hover { background: var(--gray-50); }
.im-picker-name     { display: flex; align-items: center; gap: 8px; font-size: var(--font-size-md); color: var(--gray-900); }
.im-picker-cat      { background: var(--blue-100); color: var(--blue-500); padding: 0 7px; border-radius: var(--radius-pill); font-size: var(--font-size-xs); font-weight: var(--font-weight-semibold); }
.im-picker-meta     { display: flex; justify-content: space-between; color: #868e96; font-size: var(--font-size-sm); margin-top: 2px; }
.im-picker-empty    { padding: 12px; color: var(--gray-500); text-align: center; font-size: 0.82rem; }
.im-picker-selected { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 12px; background: #f8fbff; border: 1px solid #cfe2ff; border-radius: var(--radius-md); }
.im-pane-title {
    padding: 8px 12px;
    border-bottom: 1px solid var(--gray-200);
    font-size: 0.8rem;
    font-weight: var(--font-weight-semibold);
    color: var(--gray-700);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: #fafbfc;
    display: flex;
    align-items: baseline;
    gap: 8px;
    justify-content: space-between;
}

/* ───────────────────────────────────────────────────────────────────────
   Inventory Manager — shared display primitives (round 2). The next wave of
   byte-identical .im-* bodies hoisted out of the per-panel scoped sheets under
   Shared/Inventory/ + Pages/Materials/InventoryManager.razor.css. Same
   convention as .im-recv-* / .im-picker-* above: the shared body lives here; any
   component whose copy DIFFERS keeps its own scoped rule, which still wins via
   the Blazor b-attribute (a scoped/::deep selector outranks a bare global).
   Divergent copies deliberately left scoped: InventoryInspector .im-pane-meta
   (gray-700), TransferLocationPanel .im-fifo-pill (gray) + .im-fw-lot/preview,
   .im-mov-type.return (purple on the page, gray in the inspector),
   ExportCsvPanel .im-export-option, SetupCatalogPanel .im-setup-table. The
   .im-badge family is intentionally NOT hoisted (base padding/font drift plus a
   border shorthand-vs-longhand specificity trap — see dedup notes).
   ─────────────────────────────────────────────────────────────────────── */
/* pane subtitle — pairs with .im-pane-title above (ItemGrid, CategoryTree, InventoryManager). */
.im-pane-meta {
    font-weight: var(--font-weight-normal);
    text-transform: none;
    letter-spacing: 0;
    color: var(--gray-500);
    font-size: var(--font-size-sm);
}
/* Empty-state pane — global. Adopted by ItemGrid, InventoryInspector,
   BottlingDateInspector, LabelManager, BulkWineDesk, and the Contacts and
   Compliance manager grids/inspectors via .cm-empty (which was previously only
   scoped to ContactManager, so it rendered unstyled in those child components —
   this global is the fix). Each component keeps only its divergent one-liner
   (padding or icon size) as a scoped delta. Color unified to var(--gray-500);
   padding to var(--space-xl). WHY gray-500: matches the already-shipped inventory
   empties; bh-insp/lm/bwd were #868e96 (a touch darker) — verify it reads OK. */
.nwc-empty,
.cm-empty,
.lm-empty,
.bh-insp-empty,
.bwd-empty,
.im-grid-empty,
.im-insp-empty-pane {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: var(--gray-500);
    text-align: center;
    padding: var(--space-xl);
}
.nwc-empty i,
.cm-empty i,
.lm-empty i,
.bwd-empty i {
    font-size: 2.4rem;
    margin-bottom: var(--space-sm);
    color: var(--gray-400);
}

/* Communications Log (/admin/comms/log) uses ManagerShell WITHOUT a tree pane. ManagerShell reserves
   the left tree track even when TreeContent is null, and a page's scoped CSS can't reach the child
   shell's .ms-workspace — so drop the left track here (global) and let the grid + inspector fill. */
.comms-log-shell .ms-workspace {
    grid-template-columns: 1fr 6px var(--ms-inspector-w, 320px);
}
/* FIFO pill (blue) — IssueStockPanel + InventoryInspector. TransferLocation's gray pill stays scoped. */
.im-fifo-pill {
    background: var(--blue-500);
    color: #fff;
    border-radius: var(--radius-pill);
    padding: 1px 7px;
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
}
/* Movement-type chip — InventoryInspector + InventoryManager. Base + 4 shared variants;
   `.im-mov-type.return` diverges (purple on the page, gray in the inspector) so it stays scoped in both. */
.im-mov-type {
    display: inline-block;
    padding: 1px 7px;
    border-radius: var(--radius-xs);
    font-size: 0.68rem;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.im-mov-type.receive  { background: #d1f0d8; color: #1d6f33; }
.im-mov-type.issue    { background: #ffe2e2; color: #b32424; }
.im-mov-type.adjust   { background: var(--yellow-100); color: var(--yellow-700); }
.im-mov-type.transfer { background: var(--blue-100); color: var(--blue-500); }
/* Status badge base + ok low warn — ItemGrid, InventoryInspector, IssueStockPanel.
   ItemGrid is canonical (padding 1px 8px, font-size var(--font-size-xs)).
   InventoryInspector keeps a scoped font-size:0.68rem delta; IssueStockPanel keeps
   padding:1px 7px. Base sets the border shorthand; each modifier sets border-color
   longhand AFTER it at equal specificity, so source order makes the colored border
   win. LANDMINE: do not reorder, and do not re-scope the base above the modifiers. */
.im-badge {
    display: inline-block;
    padding: 1px 8px;
    border-radius: var(--radius-pill);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    border: 1px solid transparent;
}
.im-badge-ok   { background: #d1f0d8; color: #1d6f33; border-color: #b7e4c0; }
.im-badge-low  { background: #ffe2e2; color: #b32424; border-color: #ffc4c4; }
.im-badge-warn { background: var(--yellow-100); color: var(--yellow-700); border-color: #ffe28a; }
/* Framework-panel wireframe notice + entity list — TransferLocationPanel + InventoryManager.
   The page's .im-fw-step-* and TransferLocation's .im-fw-lot-* / .im-fw-preview-* are single-occurrence, stay scoped. */
.im-fw-notice {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 8px 12px;
    background: #fff8e6;
    border: 1px solid #f0c14b;
    border-left: 3px solid #e6a817;
    border-radius: var(--radius-md);
    margin: 0 4px 16px;
    font-size: 0.8rem;
    color: #5e4400;
    line-height: 1.5;
}
.im-fw-entities {
    margin: 4px 4px 0;
    padding: 10px 12px;
    background: var(--gray-50);
    border: 1px dashed var(--gray-400);
    border-radius: var(--radius-md);
    font-size: 0.78rem;
    color: var(--gray-600);
}
.im-fw-entities strong {
    display: block;
    margin-bottom: 6px;
    color: var(--gray-700);
}
.im-fw-entities ul { margin: 0; padding-left: 18px; }
.im-fw-entities li { margin-bottom: 3px; line-height: 1.5; }
/* Setup panels — SetupCategoriesPanel + SetupItemsPanel shared base. SetupCatalogPanel's
   .im-setup-table (margin, no flex) and each panel's own toolbar variant stay scoped. */
.im-setup-panel { display: flex; flex-direction: column; height: 100%; }
.im-setup-form {
    margin: 0 2px 10px;
    padding: 10px 12px;
    background: var(--gray-50);
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-md);
    flex-shrink: 0;
}
.im-setup-table {
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-md);
    overflow: hidden;
    flex: 1;
    overflow-y: auto;
}
.im-setup-empty {
    padding: 24px;
    text-align: center;
    color: var(--gray-600);
    font-size: 0.82rem;
}
.im-setup-row-inactive td { opacity: 0.55; }
.im-setup-subtext { font-size: 0.72rem; line-height: 1.3; }
/* Export/print option card (base only) — ExportPdfPanel + PrintLabelsPanel. The :has() and
   radio sub-rules stay scoped on those two panels (hoisting :has(input:checked) globally would
   outrank ExportCsvPanel's scoped .selected and bleed into it); ExportCsvPanel stays untouched. */
.im-export-option {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 8px 10px;
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: border-color .15s;
}

/* ───────────────────────────────────────────────────────────────────────
   Bottling date tabs — shared by BottlingDateTabsRow (DailyFlow, via
   WeekNavigatorComponent) + BottlingDateTabs (Shared, via LabQcRoundEntry).
   The two were byte-identical copy-paste forks; this is the shared family.
   NAMESPACED (not bare .tab-badge/.date-tab/.add-text): those generic names
   are independently defined with DIFFERENT bodies by SkuTabsRow and
   WeekNavigatorComponent — kept apart only by Blazor scope. A bare-name
   hoist would clobber them, so the family is .nwc-datetab-* and the rename
   is applied only inside the two true forks. BottlingDateTabsRow keeps a
   scoped @media delta (480px stack + 768px tab/badge sizing).
   ─────────────────────────────────────────────────────────────────────── */
.nwc-datetab-row   { display: flex; align-items: center; justify-content: space-between; gap: var(--space-lg); padding: 0.4rem var(--space-sm); background: linear-gradient(to bottom, var(--gray-50), var(--gray-200)); border-top: 1px solid var(--gray-300); }
.nwc-datetab-list  { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; }
.nwc-datetab       { position: relative; display: flex; align-items: center; gap: var(--space-2xs); padding: 0.3rem var(--space-sm); padding-right: 1.4rem; border-radius: var(--radius-sm); border: 1px solid var(--gray-300); background: #fff; color: var(--gray-700); font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); cursor: pointer; transition: all 0.15s ease; white-space: nowrap; }
.nwc-datetab:hover { background: var(--gray-200); border-color: var(--gray-500); }
.nwc-datetab.active { background: var(--blue-500); color: white; border-color: var(--blue-500); }
.nwc-datetab-text  { font-weight: var(--font-weight-medium); }
.nwc-datetab-badge { position: absolute; top: -5px; right: -5px; background: var(--blue-500); color: white; border: 1px solid white; border-radius: 50%; width: 16px; height: 16px; display: flex; align-items: center; justify-content: center; font-size: 0.6rem; font-weight: var(--font-weight-semibold); box-shadow: 0 1px 2px rgba(0,0,0,0.15); }
.nwc-datetab.active .nwc-datetab-badge { background: white; color: var(--blue-500); border-color: var(--blue-500); }
.nwc-datetab-add   { display: flex; align-items: center; gap: var(--space-2xs); padding: 0.3rem var(--space-sm); border-radius: var(--radius-sm); border: 1px dashed #198754; background: transparent; color: #198754; font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); cursor: pointer; transition: all 0.15s ease; }
.nwc-datetab-add:hover { background: #198754; color: white; border-style: solid; }
.nwc-datetab-add i { font-size: 0.8rem; }
.nwc-datetab-product { display: flex; align-items: center; gap: 0.35rem; padding: var(--space-2xs) var(--space-sm); background: var(--blue-100); border: 1px solid #b6d4fe; border-radius: var(--radius-sm); font-size: var(--font-size-xs); color: var(--blue-500); white-space: nowrap; }
.nwc-datetab-product i { font-size: var(--font-size-sm); }
@media (max-width: 768px) {
    .nwc-datetab-add-text   { display: none; }
    .nwc-datetab-product span { max-width: 120px; overflow: hidden; text-overflow: ellipsis; }
}

/* ───────────────────────────────────────────────────────────────────────
   Slide-out panel header — the title/close bar shared by slide-out panels.
   Canonical body was copy-pasted byte-identically under three different
   scoped names: SlidingPanel's `.sliding-panel-header`, MaterialStatusSection's
   `.receipt-slide-header`, and _LegEditPanel's `.leg-slide-header`. Folded here.
   NAMESPACED `.nwc-slide-header` (NOT a promotion of `.sliding-panel-header`)
   to avoid colliding with any other scoped `.sliding-panel-header` definitions.
   ─────────────────────────────────────────────────────────────────────── */
.nwc-slide-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* sm vertical (was lg, 2026-08-04): header chrome was costing ~2rem of pure air per panel
       on scroll-heavy surfaces (booking, projection). Horizontal stays 1.25rem for alignment
       with the body gutter. */
    padding: var(--space-sm) 1.25rem;
    border-bottom: 1px solid var(--gray-200);
    background: var(--gray-50);
    flex-shrink: 0;
}

/* Flush body for <SlidingPanel CssClass="sp-flush">: opt-out of the default
   .sliding-panel-body padding when the panel's inner component supplies its own
   (e.g. MaterialReceiptPanel/MaterialOrderPanel/OrderAllocationPanel .panel-body).
   A plain global matches the scoped .sliding-panel-body by class name — only the
   generated scoped sheet adds the [b-xxx] attribute, which this rule doesn't need. */
.sliding-panel.sp-flush .sliding-panel-body { padding: 0; }

.view-toggle {
    display: flex;
    gap: var(--space-2xs);
    background: var(--nwc-bg-muted);
    padding: 0.2rem;
    border-radius: var(--radius-md);
}

/* === Autocomplete input spinner/icon === */
.input-spinner,
.input-icon {
    font-size: 0.8rem;
    pointer-events: none;
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
}
/* Interactive variant (a clear-✕ etc.): the base rule's pointer-events:none exists so passive
   status icons never block clicks into the input beneath — an icon that IS the click target
   must opt back in, or its @onclick silently never fires (the "✕ doesn't clear" bug). */
.input-icon--action {
    pointer-events: auto;
    cursor: pointer;
}

/* === List-page kit (canonical scaffold for prefixed list pages: wt-, mh-, gl-, lp-, cl-, gs-, inv-, cb-, er-) === */
.nwc-list-page {
    display: flex;
    flex-direction: column;
    height: 95vh;
    overflow: hidden;
}
.nwc-list-page-header {
    align-items: center;
    display: flex;
    justify-content: space-between;
    margin-bottom: var(--space-md);
}
.nwc-list-page-title {
    margin: 0;
    font-weight: var(--font-weight-bold);
    font-size: 1.4rem;
    color: var(--slate-800);
}
.nwc-list-page-grid-area {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    border-radius: var(--radius-md);
}
.nwc-list-page-filters {
    display: flex;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
    flex-wrap: wrap;
}
@media (max-width: 900px) {
    .nwc-list-page-filters {
        flex-direction: column;
    }
}

/* Underline Tab Bar (LAYOUT-PATTERNS Pattern 14). Hoisted to a shared utility on its third
   sighting — the scoped .qc-tab (LabQc) and .tr-tab (TankMismatch) copies predate this and can
   migrate onto it later; new in-page sub-view tab strips should use these classes rather than a
   fourth scoped copy. Swaps content below, does NOT navigate. */
.nwc-tab-bar {
    display: flex;
    gap: var(--space-xs);
    border-bottom: 2px solid var(--border-default);
}
.nwc-tab {
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    padding: var(--space-sm) var(--space-md);
    font-size: 0.9rem;
    color: var(--text-secondary);
    font-weight: 500;
    cursor: pointer;
}
.nwc-tab:hover {
    color: var(--accent-primary);
}
.nwc-tab.active {
    color: var(--accent-primary);
    font-weight: 600;
    border-bottom-color: var(--accent-primary);
}

/* Manager Shell filterbar — applied by consumers (ContactManager,
   InventoryManager, LabelManager, BulkWineDesk) inside <ms-filterbar-host>.
   Lives in site.css (not ManagerShell.razor.css) because RenderFragment
   content carries the consumer's CSS-isolation scope, not the host's. */
.ms-filterbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    background: var(--surface-default);
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-md);
}

/* Manager Shell pane-collapse button — same RenderFragment-scope reasoning. */
.ms-pane-collapse-btn {
    appearance: none;
    background: transparent;
    border: none;
    color: var(--gray-500);
    cursor: pointer;
    font-size: var(--font-size-md);
    padding: 2px 6px;
    margin-left: auto;
    border-radius: var(--radius-sm);
    line-height: 1;
}
.ms-pane-collapse-btn:hover { background: var(--gray-100); color: var(--gray-700); }
/* ── Utility: toolbar row (flex wrap row, gap-sm) ── */
.nwc-toolbar-row {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
}
/* ── Utility: list reset ── */
.nwc-list-reset {
    list-style: none;
    margin: 0;
    padding: 0;
}
/* ── Utility: visually-hidden file input (label-as-tap-target pattern) ──
   Put this on any <InputFile> whose <label> IS the click target.

   ⛔ It lives HERE, global, on purpose — do NOT move it into a .razor.css.
   <InputFile> is a CHILD COMPONENT, so Blazor CSS isolation never stamps the
   parent's scope attribute onto the <input> it renders. A scoped `.x-input {}`
   compiles to `.x-input[b-<scope>]` and matches NOTHING — which is exactly how
   prod bug #11 shipped: the raw OS file input stayed visible at its intrinsic
   ~300px, overflowed its container by ~113px, and pushed the icon and label out
   of the box on both desktop and iPhone. A global class has no scope attribute
   to miss, so it cannot fail that way.

   The parent label needs `position: relative` so this positions against it. */
.nwc-file-input-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    overflow: hidden;
    pointer-events: none;
}
/* ── Utility: extra-small button (one notch below Bootstrap's btn-sm) ── */
.btn-xs {
    padding: 0.15rem 0.4rem;
    font-size: var(--font-size-xs);
    line-height: 1.3;
    border-radius: var(--radius-xs);
}

/* ── Bottling status pill — shared by the History Manager grid + inspector
      (global so the two CSS-isolation scopes don't each redefine the colors). ── */
.bh-status-pill {
    display: inline-block;
    padding: 0.1rem 0.5rem;
    border-radius: var(--radius-xl);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-medium);
    border: 1px solid var(--gray-300);
    background: #fff;
    color: var(--gray-700);
    white-space: nowrap;
}
.bh-status-pill.is-completed { background: var(--green-100); border-color: #198754; color: var(--green-700); }
.bh-status-pill.is-inprogress { background: var(--yellow-100); border-color: #ffc107; color: var(--yellow-700); }
.bh-status-pill.is-scheduled { background: #cff4fc; border-color: #0366d6; color: #004085; }
.bh-status-pill.is-postponed { background: #e2e3e5; border-color: var(--gray-600); color: #383d41; }
.bh-status-pill.is-canceled { background: var(--state-danger-bg); border-color: var(--red-500); color: #721c24; }
/* ── Utility: inline flex row, center-aligned, gap-sm ── */
.nwc-row-sm {
    align-items: center;
    display: flex;
    gap: var(--space-sm);
}
/* ── Utility: inline flex row, center-aligned, gap-2xs ── */
.nwc-row-2xs {
    align-items: center;
    display: flex;
    gap: var(--space-2xs);
}
/* ── Utility: flex row, space-between (no vertical alignment) ── */
.nwc-row-between {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-between;
}
/* ── Utility: vertical flex stack, gap-2xs ── */
.nwc-stack-2xs {
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
}
/* ── Utility: vertical flex stack, gap-sm ── */
.nwc-stack-sm {
    display: flex;
    flex-direction: column;
    gap: var(--space-sm);
}
/* ── Utility: vertical flex stack, gap-md ── */
.nwc-stack-md {
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
}
/* ── Utility: inline flex row, center-aligned, gap-md ── */
.nwc-row-md {
    align-items: center;
    display: flex;
    gap: var(--space-md);
}
/* ── Utility: inline flex row, center-aligned, gap-xs ── */
.nwc-row-xs {
    align-items: center;
    display: flex;
    gap: var(--space-xs);
}
/* ── Utility: flex row, center-aligned, space-between, nowrap ── */
.nwc-row-between-center {
    align-items: center;
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-between;
}
/* ── Utility: right-aligned action cluster (margin-left auto), gap-xs ── */
.nwc-row-end {
    display: flex;
    gap: var(--space-xs);
    margin-left: auto;
}
/* ── Utility: vertical flex stack, gap-3xs (tightest) ── */
.nwc-stack-3xs {
    display: flex;
    flex-direction: column;
    gap: var(--space-3xs);
}
/* ── Utility: vertical flex stack that can shrink horizontally (min-width:0 so a
      truncating child actually truncates instead of forcing the row wider) ── */
.nwc-stack-shrink {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
/* ── Utility: dead-center flex box ── */
.nwc-center {
    align-items: center;
    display: flex;
    justify-content: center;
}
/* ── Utility: 3-slot header row — 1fr/3fr/1fr grid, centered (booking day-card headers,
   page-level Prev/[title]/Next rows). Hoisted from BookingMain/BookingDayCard .razor.css. ── */
.nwc-row-3col {
    align-items: center;
    display: grid;
    grid-template-columns: 1fr 3fr 1fr;
    justify-content: center;
    padding: 5px;
    text-align: center;
}
/* ── Utility: compact centered data table — full-width, collapsed borders with open
   left/right edges, tight 3px cells (booking load / drain-and-press tables). Hoisted from
   BookingMain/BookingLoadTable .razor.css. ── */
.nwc-table-compact {
    border: 1px solid var(--nwc-border);
    border-collapse: collapse;
    border-left: hidden;
    border-right: hidden;
    border-spacing: 0;
    width: 100%;
}
.nwc-table-compact th,
.nwc-table-compact td {
    line-height: 1;
    padding: 3px;
    text-align: center;
}
.nwc-table-compact tr:nth-child(even) {
    border: solid 1px;
}
/* ── Utility: fill-parent column — flex:1 column that can shrink (scroll-region host) ── */
.nwc-fill-col {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-height: 0;
}
/* ── Utility: viewport-lock column — full-height column, children scroll internally ── */
.nwc-lock-col {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}
/* ── Utility: wrapping flex row, gap-sm ── */
.nwc-wrap-sm {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
}
/* ── Utility: wrapping flex row, gap-lg ── */
.nwc-wrap-lg {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-lg);
}
/* ── Utility: full-height scroll pane, lg padding (ManagerShell/tab body interior) ── */
.nwc-scroll-pane {
    height: 100%;
    overflow-y: auto;
    padding: var(--space-lg);
}
/* ============================================================
   Form system (canonical) — LAYOUT-PATTERNS Pattern 16. Pair with <FormField>.
   Shape: .nwc-form-grid → .nwc-form-field cells → inputs → .nwc-form-actions.
   Label identity = uppercase micro-caps (owner-chosen 2026-07-17).
   Migration: supersedes the panel-scoped .sp-form-* block in panel-layout.css;
   its 5 adopters move onto these names in Phase 1 (then .sp-form-* is deleted,
   which also clears the temporary duplication these rules introduce).
   ============================================================ */
/* minmax(0,1fr) — plain 1fr carries an `auto` minimum, so wide intrinsic input
   widths blow the grid past its container (horizontal scroll + clipped columns,
   seen live on PackagingProfilePanel 2026-07-23). Columns must be allowed to
   shrink below content width; inputs fill their cell. */
.nwc-form-grid   { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-md); }
.nwc-form-grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));     gap: var(--space-md); }
@media (max-width: 640px) {
    .nwc-form-grid, .nwc-form-grid-4 { grid-template-columns: 1fr; }
}

/* Stacked field: caps label above input */
.nwc-form-field { display: flex; flex-direction: column; gap: 0.2rem; /* off-scale */ min-width: 0; }
.nwc-form-field.span-2 { grid-column: span 2; }
.nwc-form-field.span-3 { grid-column: span 3; }
.nwc-form-field.span-4 { grid-column: span 4; }

.nwc-form-field > label {
    font-weight: var(--font-weight-semibold);
    font-size: 0.82em;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin: 0;
}

.nwc-form-req  { color: var(--red-600, var(--bs-danger)); font-weight: var(--font-weight-bold); }
.nwc-form-hint { font-size: var(--font-size-xs); color: var(--text-tertiary, var(--gray-500)); }

/* Input treatment — token-driven, iOS-zoom-safe, focus ring.
   Styles whatever input the field wraps; no .form-control required inside. */
.nwc-form-field > input,
.nwc-form-field > select,
.nwc-form-field > textarea {
    min-height: var(--form-input-min-height);
    font-size: 16px; /* iOS zoom prevention */
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--bs-border-color, var(--border-default));
    border-radius: var(--radius-md);
    -webkit-appearance: none;
}
.nwc-form-field > textarea { min-height: 80px; resize: vertical; }
.nwc-form-field > input:focus,
.nwc-form-field > select:focus,
.nwc-form-field > textarea:focus {
    outline: 2px solid var(--form-input-focus-outline);
    outline-offset: var(--form-input-focus-offset);
}

/* Input + inline-create button (e.g. Lot Id + "+ New", select + gear) */
.nwc-input-group { display: flex; align-items: center; gap: 0.35rem; /* off-scale */ }
.nwc-input-group > input,
.nwc-input-group > select {
    flex: 1;
    min-height: var(--form-input-min-height);
    font-size: 16px;
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--bs-border-color, var(--border-default));
    border-radius: var(--radius-md);
    -webkit-appearance: none;
}
.nwc-input-group > input:focus,
.nwc-input-group > select:focus {
    outline: 2px solid var(--form-input-focus-outline);
    outline-offset: var(--form-input-focus-offset);
}

/* Dense variant (Pattern 16b) — many-field forms. Add .nwc-form-dense on a wrapper
   (e.g. a panel's .sp-body) to compact every form grid inside it: tighter row
   rhythm, 30px inputs instead of the 44px touch default. Canonical adopter:
   PackagingProfilePanel (owner-requested 2026-07-23 — "spacy AND squished"). */
.nwc-form-dense .nwc-form-grid,
.nwc-form-dense .nwc-form-grid-4 { gap: var(--space-xs) var(--space-sm); }
.nwc-form-dense .nwc-form-field > label { font-size: 0.68em; }
.nwc-form-dense .nwc-form-field > input,
.nwc-form-dense .nwc-form-field > select,
.nwc-form-dense .nwc-form-field > textarea,
.nwc-form-dense .nwc-input-group > input,
.nwc-form-dense .nwc-input-group > select {
    min-height: 30px;
    padding: var(--space-2xs) var(--space-sm);
}
.nwc-form-dense .nwc-form-field > textarea { min-height: 56px; }

/* Footer action row — right-aligned buttons */
.nwc-form-actions { display: flex; justify-content: flex-end; gap: var(--space-sm); margin-top: var(--space-md); }

/* ── List reorder arrows ──────────────────────────────────────────────────────
   Vertical ▲/▼ pair for moving a row within a host-owned list (buttons, not
   drag — Blazor Server + iPads; position in the list IS the saved order).
   Hoisted 2026-08-04 from PressLegsEditor when TankAllocationRow needed the
   identical shape. See LAYOUT-PATTERNS.md "List reorder arrows". */
.nwc-move { display: flex; flex-direction: column; gap: 0; flex: 0 0 auto; }
.nwc-movebtn {
    border: 0;
    background: none;
    cursor: pointer;
    color: var(--nwc-text-muted);
    font-size: 0.5rem;
    line-height: 0.9;
    padding: 0 2px;
}
.nwc-movebtn:hover:not(:disabled) { color: var(--nwc-text); }
.nwc-movebtn:disabled { opacity: 0.25; cursor: default; }
/* ── Shim: Bootstrap 5.2 text-bg-* utilities ──────────────────────────────────
   The vendored bootstrap.min.css predates 5.2, so these classes resolve to
   NOTHING — a `badge text-bg-success` renders white text on a transparent
   background, i.e. invisible (found live on BinManager's status column
   2026-07-29; 8 files use them). Colors match Bootstrap 5.2's contrast pairs.
   Delete this block if the vendored Bootstrap is ever bumped to ≥5.2. */
.text-bg-primary   { color: #fff !important; background-color: var(--bs-primary, #0d6efd) !important; }
.text-bg-secondary { color: #fff !important; background-color: var(--bs-secondary, #6c757d) !important; }
.text-bg-success   { color: #fff !important; background-color: var(--bs-success, #198754) !important; }
.text-bg-danger    { color: #fff !important; background-color: var(--bs-danger, #dc3545) !important; }
.text-bg-warning   { color: #000 !important; background-color: var(--bs-warning, #ffc107) !important; }
.text-bg-info      { color: #000 !important; background-color: var(--bs-info, #0dcaf0) !important; }
.text-bg-light     { color: #000 !important; background-color: var(--bs-light, #f8f9fa) !important; }
.text-bg-dark      { color: #fff !important; background-color: var(--bs-dark, #212529) !important; }

/* ── Utility: single-line truncation (overflow ellipsis) ── */
.nwc-truncate {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* ── Utility: 2-line clamp (multi-line ellipsis) ── */
.nwc-line-clamp-2 {
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
/* ── Utility: vertical separator (1px hairline divider, 14px tall).
   Covers the status/toolbar separator forks (bh/bwd/cm/im-status-sep,
   im-report-sep). Consumers needing a taller bar keep their own rule. ── */
.nwc-vsep {
    width: 1px;
    height: 14px;
    background: var(--gray-300);
}
/* ── DailyFlow component card wrapper — themed white card, sm radius + padding.
   Shared root of the 5 DailyFlow sibling components (Cola/Label/Winemaking/
   Lab/CompositionSnip). Distinct from .nwc-card (gradient stat card). The
   #fff source literal is mapped to --surface-default so the card themes in
   dark mode. ── */
.nwc-flow-card {
    background: var(--surface-default);
    border-radius: var(--radius-sm);
    padding: var(--space-sm);
}
/* ── Title button: clickable header-title affordance (DailyFlow Cola/Label).
   Hover tint left as the literal #e7f3ff (off-scale, between --blue-100 and
   white) to keep the affordance pixel-identical post-hoist. ── */
.nwc-title-btn {
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    color: var(--gray-700);
    background: none;
    border: none;
    padding: var(--space-2xs) var(--space-sm);
    margin: -0.25rem -0.5rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    transition: all 0.15s ease;
}
.nwc-title-btn:hover { background: #e7f3ff; color: var(--blue-500); }
.nwc-title-btn i { font-size: var(--font-size-lg); }
/* ── Packaging spec-library family (Glass/Capsule/Closure) ──────────────
   Hoisted from gl-* / cl-* mirrors. The grid thumb / detail panel / usage list
   render inside NwcDataGrid <Template> and SlidingPanel RenderFragments, so a
   global is the reliable reach (same pattern as .nwc-upload-section on these
   pages). filter-select keeps the off-scale 0.8rem literal verbatim. ── */
.nwc-filter-select { width: auto; min-width: 130px; font-size: 0.8rem; }
.nwc-lib-thumb { width: 36px; height: 36px; object-fit: contain; border-radius: var(--radius-xs); }
.nwc-lib-detail { padding: var(--space-md); }
.nwc-lib-detail-section { margin-bottom: var(--space-xl); }
.nwc-usage-item { padding: var(--space-xs) 0; border-bottom: 1px solid var(--slate-100); }
.nwc-usage-item:last-child { border-bottom: none; }
.nwc-usage-name { font-size: var(--font-size-md); font-weight: var(--font-weight-semibold); color: var(--slate-800); }
.nwc-usage-meta { font-size: var(--font-size-sm); color: var(--slate-500); }
/* ── Utility: autocomplete input wrapper (relative flex, reserves icon space) ── */
.nwc-autocomplete-input {
    position: relative;
    display: flex;
    align-items: center;
}
.nwc-autocomplete-input input {
    padding-right: 28px;
}
/* ── Utility: autocomplete dropdown item (full-width column-flex button) ── */
.nwc-autocomplete-item {
    display: flex;
    flex-direction: column;
    padding: 6px 12px;
    cursor: pointer;
    border: none;
    background: none;
    width: 100%;
    text-align: left;
}
.nwc-autocomplete-item:hover,
.nwc-autocomplete-item.active {
    background-color: var(--bs-primary);
    color: white;
}
.nwc-autocomplete-item.disabled {
    cursor: default;
    font-size: 0.8rem;
}
.nwc-autocomplete-item.disabled:hover {
    background-color: transparent;
    color: var(--bs-secondary);
}
/* Section header inside an autocomplete menu (e.g. "Previously used by this client").
   Not a .nwc-autocomplete-item — it is never focusable and must not take the active highlight. */
.nwc-autocomplete-header {
    padding: 4px 12px;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--bs-secondary);
}
/* ContactsBusinessPicker row anatomy (name line + detail line). Global, NOT scoped to the
   picker: ItemTemplate rows are authored in the CALLER's .razor, so they carry the caller's
   CSS-isolation scope — scoped rules in ContactsBusinessPicker.razor.css can never reach them
   (hoisted from there 2026-07-21; first ItemTemplate consumer = AddProjectionPanel). */
.cb-picker-name {
    font-weight: var(--font-weight-medium);
}
.cb-picker-detail {
    display: flex;
    gap: var(--space-md);
    font-size: 0.8rem;
}
/* Row variant (e.g. TankAutocomplete): horizontal layout, space-between */
.nwc-autocomplete-item--row {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
}
/* ── Utility: autocomplete dropdown menu (absolute popup container). Compose with .dropdown-menu; override max-height per component. ── */
.nwc-autocomplete-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: var(--z-slot-badge);
    max-height: 240px;
    overflow-y: auto;
    margin-top: 2px;
    padding: 4px 0;
    font-size: 0.875rem;
    border: 1px solid var(--bs-border-color);
    border-radius: var(--radius-sm);
    background: var(--bs-body-bg);
    box-shadow: var(--shared-autocomplete-dropdown-shadow);
}
/* ── Utility: OCR scan toggle + disabled state (Permit/Cola/Label scan panels) ── */
.nwc-ocr-toggle {
    padding: var(--space-md);
    background: var(--gray-50);
    border-radius: var(--radius-lg);
    border: 1px solid var(--gray-200);
}
.nwc-ocr-toggle .form-check-input {
    width: 2.5em;
    height: 1.25em;
    cursor: pointer;
}
.nwc-ocr-toggle .form-check-input:checked {
    background-color: var(--green-600);
    border-color: var(--green-600);
}
.nwc-ocr-toggle .form-check-label {
    cursor: pointer;
    font-weight: var(--font-weight-medium);
}
.nwc-ocr-disabled {
    background: var(--gray-50);
    border-radius: var(--radius-xl);
    padding: var(--space-2xl);
}
.nwc-ocr-disabled i {
    opacity: 0.6;
}
.nwc-ocr-disabled p {
    color: var(--gray-600);
}
/* ── Utility: admin section card (surface panel with border + padding; Copilot admin pages) ── */
.nwc-admin-card {
    background: var(--nwc-surface, #fff);
    border: 1px solid var(--nwc-border, var(--gray-300));
    border-radius: var(--radius-lg);
    padding: var(--space-lg);
    margin-bottom: var(--space-xl);
}
/* ── Utility: danger callout box (icon + message, danger tokens; delete/blocked panels) ── */
.nwc-callout-danger {
    display: flex;
    gap: var(--space-sm);
    align-items: flex-start;
    padding: var(--space-sm) var(--space-md);
    background: var(--state-danger-bg);
    color: var(--state-danger-fg);
    border: 1px solid var(--state-danger-fg);
    border-radius: var(--radius-md);
    font-size: var(--font-size-sm);
    line-height: var(--line-height-normal);
}
.nwc-callout-danger i {
    flex: 0 0 auto;
    margin-top: 0.1em;
}
/* ── Utility: inline "type name" edit button (transparent, hover-highlight; DailyFlow packaging) ── */
.nwc-type-name-btn {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--gray-600);
    min-width: 70px;
    background: none;
    border: none;
    padding: 0.1rem var(--space-2xs);
    margin: -0.1rem -0.25rem;
    border-radius: var(--radius-xs);
    cursor: pointer;
    text-align: left;
    transition: all 0.15s ease;
}
.nwc-type-name-btn:hover {
    background: var(--gray-200);
    color: var(--blue-500);
}
/* ── Utility: horizontal form row (no-wrap flex, tight gap; AVA relationship panels) ── */
.nwc-ava-row {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    margin: 5px;
    gap: 3px;
}
/* ── Legacy card-grid pages (ContractMain / WineProfileMain) ──────────────
   Shared chrome for the two sibling card-grid pages. Markup keeps the
   original structural classes (card / primary / aside-*) where Bootstrap or
   a page media query still targets them; page heights stay page-scoped. */
/* Scroll-snap template tile in the footer strip. Composes with Bootstrap .card
   (this sheet loads after bootstrap.min.css, so ties resolve to these values). */
.nwc-cardgrid-tile {
    align-items: center;
    background-color: var(--white);
    border-radius: 10px;
    box-shadow: var(--legacy-cardgrid-shadow-sm);
    display: flex;
    flex: 0 0 auto;
    height: calc(10vh - 20px);
    justify-content: center;
    overflow: hidden;
    scroll-snap-align: start;
    width: calc(10vw - 20px);
}
.nwc-cardgrid-tile:hover {
    border-radius: 10px;
    box-shadow: var(--legacy-cardgrid-shadow-lg);
    cursor: pointer;
    overflow: hidden;
    transform: scale(1.1);
    transition: transform 0.2s, box-shadow 0.2s;
    z-index: var(--z-base);
}
.nwc-cardgrid-tile p {
    font-weight: var(--font-weight-bold);
    margin: 0;
    text-align: center;
}
/* 350px content card in the main grid; --wide variant is 450px. */
.nwc-cardgrid-card {
    background-color: var(--white);
    border-radius: 10px;
    box-shadow: var(--legacy-cardgrid-shadow-sm);
    overflow: hidden;
    padding: 3px;
    transition: transform 0.3s, box-shadow 0.3s;
    width: 350px;
}
.nwc-cardgrid-card:hover {
    box-shadow: var(--legacy-cardgrid-shadow-lg);
    cursor: pointer;
}
.nwc-cardgrid-card--wide {
    width: 450px;
}
/* Gradient scroll pane: the primary article + both asides. */
.nwc-cardgrid-pane {
    background: var(--legacy-cardgrid-header-gradient);
    border: 1px solid var(--legacy-cardgrid-border);
    border-radius: 10px;
    overflow-y: auto;
}
/* Gradient header band (page header + WineProfile aside tank headers). */
.nwc-cardgrid-header {
    background: var(--legacy-cardgrid-header-gradient);
    border-bottom: 1px solid var(--legacy-cardgrid-border);
    border-radius: 10px;
    color: var(--black);
    padding: 10px 20px;
}
/* ── Utility: every direct child is a dead-centered flex box (header rows) ── */
.nwc-center-kids > * {
    align-items: center;
    display: flex;
    justify-content: center;
}
/* ── LabelCola library cards (ColaCardItem / LabelCardItem) ───────────────
   Shared chrome for the two library-card components. Composes with Bootstrap
   .card kept in markup (word-wrap/position:relative come from there). The
   components deliberately stay separate — action surfaces differ — so their
   divergent rules (.card-images, COLA detail rows, fanciful spacing) remain
   in each component's scoped file. */
.nwc-lib-card {
    background: var(--nwc-bg);
    border: 1px solid var(--nwc-border-light);
    border-radius: var(--radius-lg);
    box-shadow: var(--label-card-shadow);
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    transition: box-shadow 0.15s, transform 0.15s;
}
.nwc-lib-card:hover {
    box-shadow: var(--label-card-shadow-hover);
    transform: translateY(-1px);
}
.nwc-lib-card.inactive {
    background: var(--nwc-bg-subtle);
    border-color: var(--red-500);
    border-style: dashed;
    opacity: 0.7;
}
.nwc-lib-card.inactive .nwc-lib-card-title::after {
    color: var(--red-500);
    content: " (Inactive)";
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-normal);
}
.nwc-lib-card-image {
    background: var(--nwc-bg-subtle);
    flex: 1 1 50%;
    height: 140px;
    max-width: 50%;
    object-fit: contain;
    transition: transform 0.15s, opacity 0.15s;
    width: 50%;
}
.nwc-lib-card-image.clickable { cursor: pointer; }
.nwc-lib-card-image.clickable:hover {
    opacity: 0.92;
    transform: scale(1.04);
}
.nwc-lib-card-image:only-child {
    flex-basis: 100%;
    max-width: 100%;
    width: 100%;
}
.nwc-lib-card-body {
    flex: 1;
    min-width: 0;
    padding: var(--space-md);
}
.nwc-lib-card-title {
    color: var(--nwc-text);
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    line-height: 1.3;
    margin-bottom: var(--space-2xs);
}
.nwc-lib-card-client {
    color: var(--blue-500);
    font-size: 0.8rem;
    font-weight: var(--font-weight-medium);
    margin-bottom: 0.4rem;
}
.nwc-lib-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-bottom: 0.35rem;
}
.nwc-lib-meta-tag {
    background: var(--nwc-bg-muted);
    border-radius: var(--radius-xs);
    color: var(--nwc-text);
    font-size: 0.72rem;
    line-height: 1.4;
    padding: 0.15rem var(--space-sm);
    white-space: nowrap;
}
.nwc-lib-card-fanciful {
    color: var(--nwc-text-muted);
    font-size: 0.78rem;
    font-style: italic;
}
.nwc-lib-card-actions {
    align-items: center;
    background: var(--nwc-bg-subtle);
    border-top: 1px solid var(--nwc-border-light);
    display: flex;
    gap: 0.4rem;
    padding: var(--space-sm) var(--space-md);
}
.nwc-lib-card-actions .btn {
    font-size: 0.72rem;
    padding: 0.2rem var(--space-sm);
}
.nwc-lib-refs-badge {
    background: var(--nwc-text-muted);
    border-radius: var(--radius-xs);
    color: var(--text-on-inverse);
    font-size: var(--font-size-xs);
    margin-left: auto;
    padding: 0.15rem 0.45rem;
}
@media (max-width: 600px) {
    .nwc-lib-card-actions { flex-wrap: wrap; }
    .nwc-lib-refs-badge {
        margin-left: 0;
        margin-top: var(--space-sm);
        text-align: center;
        width: 100%;
    }
}
/* ── Shared tree pane (VineyardTree / CategoryTree) ── */
.nwc-tree-list {
    flex: 1;
    font-size: var(--font-size-md);
    list-style: none;
    margin: 0;
    overflow-y: auto;
    padding: 6px 4px;
}

.nwc-tree-item {
    align-items: center;
    border-radius: var(--radius-sm);
    color: var(--gray-700);
    cursor: pointer;
    display: flex;
    gap: 8px;
    padding: 5px 10px;
    transition: background 0.08s, color 0.08s;
}

.nwc-tree-item i {
    color: var(--text-muted);
    font-size: var(--font-size-md);
}

.nwc-tree-item:hover {
    background: var(--gray-100);
    color: var(--blue-500);
}

.nwc-tree-item.active {
    background: var(--blue-100);
    color: var(--blue-500);
    font-weight: var(--font-weight-semibold);
}

.nwc-tree-item.active i {
    color: var(--blue-500);
}

.nwc-tree-count {
    background: var(--gray-200);
    border-radius: var(--radius-pill);
    color: var(--gray-700);
    font-size: var(--font-size-xs);
    min-width: 22px;
    padding: 1px 7px;
    text-align: center;
}

.nwc-tree-item.active .nwc-tree-count {
    background: var(--blue-500);
    color: var(--text-on-brand);
}

.nwc-tree-empty {
    color: var(--gray-500);
    font-size: 0.8rem;
    padding: 8px 12px;
}

/* ── Utility: flex-fill + single-line ellipsis truncation ── */
.nwc-fill-truncate {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Utility: wrapping filter/control row (gap-sm, bottom margin) ── */
.nwc-filter-row {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    margin-bottom: var(--space-sm);
}
/* ── LabQc patrol grids (AnalysisTabContent / O2Co2FilterTabContent) ──────
   Shared chrome for the twin QC grid tabs; markup composes these WITH the
   original analysis-*/o2co2-* classes, whose scoped variant rules (fixed-col
   widths 100px vs 130px, metadata/from-other-date tints, iPad touch sizes)
   keep winning at higher specificity. ALL input/select rules stay scoped —
   they are an !important cascade these globals must not enter. */
.nwc-labqc-section {
    background: var(--surface-default);
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-sm);
    margin-bottom: var(--space-md);
    overflow: hidden;
}
.nwc-labqc-section-title {
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-semibold);
    margin: 0;
}
.nwc-labqc-grid {
    background: var(--surface-default);
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-sm);
    display: flex;
    overflow: hidden;
}
.nwc-labqc-fixed-col {
    background: var(--nwc-bg-muted);
    border-right: 2px solid var(--labqc-grid-border-strong);
    flex-shrink: 0;
    z-index: var(--z-base);
}
.nwc-labqc-scroll {
    flex: 1;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-behavior: smooth;
    scroll-snap-type: x proximity;
}
.nwc-labqc-cell {
    align-items: center;
    background: var(--surface-default);
    border-bottom: 1px solid var(--labqc-grid-border);
    border-right: 1px solid var(--labqc-grid-border);
    box-sizing: border-box;
    display: flex;
    font-size: 0.78rem;
    height: 32px;
    justify-content: center;
    padding: 0 2px;
    width: 100px;
}
.nwc-labqc-cell.header-cell {
    background: var(--nwc-bg-muted);
    border-bottom: 2px solid var(--labqc-grid-border-strong);
    font-weight: var(--font-weight-semibold);
    height: 32px;
    position: relative;
}
/* Parameter-name cells in the fixed column (only the decls that differ from
   the base cell; the 100px/130px widths stay page-scoped). */
.nwc-labqc-fixed-col .nwc-labqc-cell {
    background: var(--nwc-bg-muted);
    color: var(--gray-700);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    padding-left: var(--space-sm);
    padding-right: var(--space-2xs);
    text-align: left;
}

/* ── Utility: page/section header row (flex, space-between, center) ── */
.nwc-page-header {
    align-items: center;
    display: flex;
    justify-content: space-between;
}
/* FromIntake decoration: divider + spacing under the header row. Compose with .nwc-page-header. */
.nwc-page-header--bordered {
    margin-bottom: var(--space-lg);
    padding-bottom: var(--space-md);
    border-bottom: 1px solid var(--border-default);
}
/* Type-B header: left-aligned title + inline controls (LabelMain, ColaMain). Compose with .nwc-page-header. */
.nwc-page-header--start {
    justify-content: flex-start;
    flex-wrap: wrap;
    gap: var(--space-md);
    margin-bottom: var(--space-lg);
}
/* Left cluster of a header row: icon + title text (+ inline badges). */
.nwc-header-title {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    font-size: var(--font-size-2xl);
    font-weight: var(--font-weight-medium);
}
/* Right cluster of a header row: action buttons. */
.nwc-header-actions {
    display: flex;
    gap: var(--space-sm);
}
/* Page-level sticky tier: pins an element to the top of its scroll container.
   Reused by the schedule head and <NwcAppHeader> (and any future page header). */
.nwc-sticky-top {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
}
/* ── Document-review detail layout: main column + 22rem aside, collapses on narrow.
   Shared by the BOL / Case-Good BOL review pages. ── */
.nwc-two-col {
    display: grid;
    grid-template-columns: 1fr 22rem;
    gap: var(--space-xl);
}
@media (max-width: 1000px) {
    .nwc-two-col {
        grid-template-columns: 1fr;
    }
}
/* Uppercase muted section subheading inside a review/detail body. */
.nwc-section-h {
    font-size: 0.95rem;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--gray-600);
    margin-top: var(--space-md);
}
/* Two-column label/value meta list (dt = label, dd = value). */
.nwc-meta-dl {
    display: grid;
    grid-template-columns: 9rem 1fr;
    gap: var(--space-2xs) var(--space-lg);
    margin: 0;
}
.nwc-meta-dl dt {
    color: var(--gray-600);
    font-weight: var(--font-weight-normal);
}
.nwc-meta-dl dd {
    margin: 0;
}
/* Monospace archived-file-path block (breaks long S:\ paths). */
.nwc-archive-path {
    display: block;
    word-break: break-all;
    background: var(--gray-50);
    padding: 0.4rem var(--space-sm);
    border-radius: var(--radius-sm);
    font-size: var(--font-size-md);
}
/* When a NwcDataGrid is dropped inside a .nwc-list-page scaffold, it must
   fill the grid-area and let .table-desktop be the only scrollbar. */
.nwc-list-page .nwc-datagrid {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
}
.nwc-list-page .table-desktop {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overflow-x: auto;
}
.nwc-list-page-dl {
    display: grid;
    grid-template-columns: 7rem 1fr;
    gap: 0.3rem var(--space-md);
    margin: 0;
    font-size: 0.875rem;
}
.nwc-list-page-dl dt {
    font-weight: var(--font-weight-semibold);
    color: var(--slate-500);
    white-space: nowrap;
}
.nwc-list-page-dl dd {
    margin: 0;
    color: var(--slate-800);
}
.nwc-list-page-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: var(--space-md);
    margin-bottom: var(--space-md);
}
.nwc-list-page-section-title {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wider);
    color: var(--indigo-600);
    border-bottom: 2px solid var(--slate-200);
    padding-bottom: var(--space-xs);
    margin-bottom: 0.625rem;
}

/* === DailyFlow component header (shared 6-decl block across 7 components) === */
.nwc-component-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--space-sm);
    padding-bottom: var(--space-sm);
    border-bottom: 1px solid var(--nwc-border-light);
}

/* === DailyFlow component header title (shared 6-decl block across 5 components) === */
.nwc-component-header-title {
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    color: var(--gray-700);
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

/* === DailyFlow section header (shared 12-decl block across 3 components) === */
.nwc-section-header {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-semibold);
    color: var(--bs-primary);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-wide);
    margin-bottom: 0.4rem;
    padding-bottom: 0.15rem;
    border-bottom: 1px solid var(--bs-primary);
    opacity: 0.9;
}

/* === Batch 10 shared classes (hoisted byte-identical .razor.css bodies) ===== */

/* Collapsible section/run header: gradient bar, click-to-toggle. Compose WITH
   the page's own .run-header/.section-header — the scoped :hover + icon rules
   keep winning at higher specificity. (BottlingRunHeader + DailyFlowPanel.) */
.nwc-collapse-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: var(--space-sm) var(--space-md);
    background: linear-gradient(to bottom, var(--gray-50), var(--gray-200));
    border-bottom: 1px solid var(--gray-300);
    cursor: pointer;
    user-select: none;
    transition: background 0.15s ease;
}

/* Centered loading/overlay pane with generous padding. (NwcDataGrid +
   BottlingHistoryGrid.) */
.nwc-loading-center {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-3xl);
}

/* Fact list <dl>: stacked label/value rows in a subtle bordered box. Per-panel
   dt basis + dd word-break stay scoped on the page's own .dc-facts/.dp-facts. */
.nwc-facts-dl {
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
    margin: 0;
    padding: var(--space-sm) var(--space-md);
    background: var(--surface-subtle);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
}
/* Each fact row: baseline-aligned label/value pair. */
.nwc-facts-dl > div {
    display: flex;
    gap: var(--space-sm);
    align-items: baseline;
}

/* Confirm/detail-panel shared vocabulary (DeleteClientBookings/DeleteVarietalProjection twins). */
.nwc-panel-lead {
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-md);
    color: var(--text-primary);
}
.nwc-panel-note {
    margin: 0;
    color: var(--text-secondary);
    font-size: var(--font-size-sm);
}
/* Right-aligned footer action cluster, gap-sm. */
.nwc-actions-end {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-sm);
}
/* Detail-panel action row: right-aligned with vertical padding (Contacts detail twins). */
.nwc-detail-actions {
    display: flex;
    justify-content: flex-end;
    padding: var(--space-sm) 0;
    margin-bottom: var(--space-2xs);
}
/* Responsive auto-fit card grid (Copilot admin editor twins). */
.nwc-editor-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--space-md);
}

/* DailyFlow packaging line-item row. Compose WITH .packaging-item — the variant
   .date-specific/.run-default/.from-catalog rules stay scoped. */
.nwc-packaging-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.35rem var(--space-sm);
    margin-left: var(--space-sm);
    background: var(--gray-50);
    border-radius: var(--radius-xs);
    margin-bottom: 0.2rem;
}

/* Full-viewport dim backdrop behind LabQc modals. site.css loads after
   bootstrap, so this wins the .modal-backdrop background/z-index by source
   order (MaterialSelector + LabQcRoundEntry). */
.nwc-modal-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: var(--overlay-backdrop-dim);
    z-index: var(--z-labqc-backdrop);
}

/* Centered dialog host above an .nwc-modal-backdrop — the shape WineLotManagerPage's
   .wlm-newlot-host established, hoisted for hosts embedding a Panel component in a
   mid-viewport dialog (booking's Create-in-Innovint host, and .wlm-newlot-host itself
   whenever that page is next touched). Apply alongside the consumer's own class. */
.nwc-dialog-host {
    position: fixed;
    top: 8vh;
    left: 50%;
    transform: translateX(-50%);
    width: min(680px, 92vw);
    max-height: 84vh;
    overflow-y: auto;
    background: var(--nwc-surface, #fff);
    border-radius: 6px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
    /* Above --z-modal (1060): these dialogs open OVER a SlidingPanel host (the booking's
       Create-in-Innovint flow). The manager page's 1055 original only worked because no
       panel was open there. */
    z-index: var(--z-dialog-host, 1080);
    padding: 0.75rem;
}

/* Backdrop variant for the same situation — the base .nwc-modal-backdrop sits at 1040,
   below a SlidingPanel, so its dim layer wouldn't cover the panel the dialog floats over. */
.nwc-modal-backdrop--over-panel {
    z-index: var(--z-dialog-backdrop, 1070);
}

/* === Batch 15 shared classes (cross-file hoists of byte-identical scoped
   .razor.css bodies). Each is applied ALONGSIDE the consumer's own class so
   sibling scoped rules (:hover, .active, @media, descendant `h6`/`.btn`, etc.)
   keep matching at their original specificity. site.css loads after bootstrap,
   so these single-class (0,1,0) rules win source-order ties vs vendor globals
   like `.dropdown-item`. ============================================== */

/* Invisible full-cover native file input overlaid on a styled drop zone/button.
   (Contracts upload-button + ColaScanPanel upload-input-overlay.) */
.nwc-file-input-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* Full-width left-aligned button inside an autocomplete/search dropdown. Keeps
   the consumer's `.dropdown-item` class so the scoped `:hover` sibling still
   matches (DocumentInbox di-search-dropdown + ReceiveShipment rs-search-dropdown). */
.nwc-search-dropdown-item {
    padding: var(--space-xs) var(--space-md);
    font-size: var(--font-size-md);
    border: none;
    background: none;
    width: 100%;
    text-align: left;
    cursor: pointer;
}

/* Bordered thumbnail image (max 130px). Keeps the consumer's cola-img/card-img
   class so the scoped :hover + @media max-width overrides still win. (DailyFlow
   ColaComponent + LabelComponent.) */
.nwc-thumb-img {
    width: 100%;
    max-width: 130px;
    height: auto;
    border-radius: var(--radius-sm);
    border: 1px solid var(--gray-300);
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

/* Small uppercase "primary source" pill (green success bg). (LabQc
   MaterialSelector .current-badge + ProfileMaterialCard .primary-badge.) */
.nwc-source-badge {
    font-size: 0.55rem;
    font-weight: var(--font-weight-bold);
    padding: 0.1rem 0.3rem;
    background: var(--labqc-success-fg);
    color: var(--text-on-brand);
    border-radius: var(--radius-xs);
    letter-spacing: 0.5px;
}

/* Section header with a 2px bottom rule. Distinct from the gradient
   `.nwc-section-header` (DailyFlow). Keeps the consumer's `.section-header`
   class so scoped `.section-header h6` / `.section-header .btn` still match.
   (LabQc CapacityTabContent + PackagingQcSection.) */
.nwc-section-header-bordered {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--space-sm);
    padding-bottom: var(--space-sm);
    border-bottom: 2px solid var(--gray-200);
}

/* Copilot/admin form-group field label. Applied directly to each `<label>`
   (replaces the `.form-group label` descendant selector). (Admin
   CopilotCorrections + CopilotTools.) */
.nwc-admin-field-label {
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-semibold);
    color: var(--nwc-text-muted, var(--gray-600));
    margin-bottom: 0.2rem;
    display: block;
}

/* Right-aligned footer button row with a top divider. (Winemaking
   RecurringEventPanel + WinemakingSchedulePanel.) */
.nwc-button-row {
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
    gap: 10px;
    border-top: 1px solid var(--nwc-border);
}

/* Visually-hidden native checkbox (custom-styled label drives the visual).
   (ScheduledEmailSchedulePanel .ses-day + EmailLabelComponent .recipient-chip.) */
.nwc-hidden-checkbox {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
    pointer-events: none;
}

/* ── batch-16 shared utilities (cross-file hoists) ── */

/* Clickable disclosure/section header — <summary> or a section toggle.
   Applied directly to the element (replaces `.wt-summaries summary` /
   `.gl-import-header`); scoped `:hover` variants stay in their components.
   (Harvest WeightTags + Packaging GlassLibrary.) */
.nwc-disclosure-header {
    font-size: 0.8rem;
    font-weight: var(--font-weight-semibold);
    color: var(--slate-600);
    cursor: pointer;
    padding: var(--space-2xs) 0;
    user-select: none;
}

/* Uppercase caps field-label (0.82em, letter-spaced). Applied directly to
   each label (replaces `.ses-field > label` / `.frp-title`).
   (Calendar ScheduledEmailSchedulePanel + Notifications FeatureRecipientPanel.) */
.nwc-field-caps-label {
    font-weight: var(--font-weight-semibold);
    font-size: 0.82em;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* Small status badge shape (color comes from a sibling `.wr-status-*`).
   Replaces the per-component `.wr-status-badge` duplicated for CSS isolation.
   (Bottling WorkRequests DetailView + ReviewPanel.) */
.nwc-status-badge-sm {
    font-size: 10px;
    padding: 2px 8px;
    border-radius: var(--radius-lg);
    font-weight: var(--font-weight-medium);
    white-space: nowrap;
}

/* === Round-button (shared across Booking + WineProfile) === */
.round-button {
  background-color: var(--blue-500);
  color: white;
  border: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

/* === Contact Manager (page-namespaced, hoisted from ContactManager.razor.css)
   ====================================================================
   Hoisted out of scoped CSS after the ManagerShell extraction (commit acda0d84)
   broke ::deep reach-in from ContactManager into its child grid/inspector
   components: ContactManager.razor no longer emits a root DOM element of its
   own, so the b-* scope attribute never lands on an ancestor of .cm-grid-wrap
   et al. (which are rendered by PeopleGrid / BusinessesGrid / InvitesGrid /
   StaleAccessClassGrid / OrgChartPane / PersonInspector / BusinessInspector /
   InviteInspector / ContactCleanupPanel — none of which carry their own
   .razor.css). The cm-* prefix keeps these page-namespaced even as globals. */

/* ── Grid (people / businesses) ────────────────────────── */
.cm-grid-wrap {
    flex: 1;
    overflow: auto;
    min-height: 0;
}

.cm-grid-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.82rem;
}

.cm-grid-table thead th {
    position: sticky;
    top: 0;
    background: var(--surface-subtle);
    border-bottom: 1px solid var(--gray-200);
    padding: 6px 10px;
    text-align: left;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--gray-600);
    font-weight: var(--font-weight-semibold);
}

.cm-grid-table tbody td {
    padding: 6px 10px;
    border-bottom: 1px solid var(--gray-100);
    vertical-align: middle;
}

.cm-grid-row { cursor: pointer; }
.cm-grid-row:hover td { background: var(--surface-muted); }
.cm-grid-row.selected td {
    background: var(--blue-100);
    box-shadow: inset 3px 0 0 var(--blue-500);
}
.cm-grid-name { font-weight: var(--font-weight-medium); color: var(--gray-900); }
.cm-grid-small { color: var(--gray-700); }
.cm-num { text-align: right; font-variant-numeric: tabular-nums; }

.cm-grid-edit-cell { padding: 2px 6px !important; }
.cm-grid-edit-cell .iec-read {
    appearance: none;
    background: transparent;
    border: 1px dashed transparent;
    padding: 2px 4px;
    width: 100%;
    text-align: left;
    color: inherit;
    cursor: text;
    border-radius: var(--radius-xs);
}
.cm-grid-edit-cell .iec-read:hover { border-color: var(--gray-400); background: var(--surface-default); }
.cm-grid-edit-cell .iec-input { padding: 2px 6px; height: auto; }

/* ── Gap badges ────────────────────────────────────────── */
.cm-gap-badge {
    display: inline-block;
    margin-left: var(--space-2xs);
    padding: 0.05rem 0.4rem;
    font-size: 0.62rem;
    border-radius: 9px;
    font-weight: var(--font-weight-medium);
    background: var(--state-warning-bg);
    color: var(--state-warning-fg);
    text-transform: lowercase;
    letter-spacing: 0;
}
.cm-gap-badge-header {
    margin-left: 0.4rem;
    background: var(--state-danger-bg);
    color: var(--state-danger-fg);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 0.6rem;
}

/* ── Sub-tabs (inspector) ──────────────────────────────── */
.cm-subtabs {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 4px 8px 0;
    border-bottom: 1px solid var(--gray-200);
    background: var(--surface-subtle);
}
.cm-subtab {
    appearance: none;
    background: transparent;
    border: 1px solid transparent;
    border-bottom: none;
    padding: 4px 10px;
    font-size: 0.72rem;
    color: var(--gray-700);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    cursor: pointer;
}
.cm-subtab:hover { background: var(--surface-default); color: var(--gray-900); }
.cm-subtab.active {
    background: var(--surface-default);
    border-color: var(--gray-300);
    border-bottom-color: var(--surface-default);
    margin-bottom: -1px;
    color: var(--text-link);
    font-weight: var(--font-weight-semibold);
}

.cm-inspector-body {
    padding: 10px 12px;
    overflow-y: auto;
    flex: 1;
    font-size: 0.82rem;
}

.cm-kv {
    display: grid;
    grid-template-columns: 110px 1fr;
    gap: 4px 10px;
    margin: 6px 0;
}
.cm-kv dt { color: var(--text-muted); font-weight: var(--font-weight-medium); }
.cm-kv dd { margin: 0; color: var(--gray-900); }

.cm-sync-head { padding: 6px 0 10px; border-bottom: 1px solid var(--gray-100); }
.cm-sync-kv {
    display: grid;
    grid-template-columns: 130px 1fr;
    gap: 4px 10px;
    margin: 4px 0;
    font-size: 0.78rem;
}
.cm-sync-kv dt { color: var(--text-muted); font-weight: var(--font-weight-medium); }
.cm-sync-kv dd { margin: 0; color: var(--gray-900); font-family: var(--bs-font-monospace, ui-monospace, monospace); }

/* ── Org chart (Step 8) ────────────────────────────────── */
.cm-org-list {
    list-style: none;
    margin: 0;
    padding: 6px;
    font-size: 0.82rem;
}

.cm-org-group {
    margin-bottom: 12px;
    background: var(--surface-subtle);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.cm-org-bond {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 6px 12px;
    background: var(--gray-100);
    border-bottom: 1px solid var(--gray-200);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--gray-700);
}

.cm-org-bond-num { font-weight: var(--font-weight-semibold); color: var(--text-link); }
.cm-org-cleanup-tag { color: var(--state-warning-fg); }

.cm-org-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    cursor: pointer;
    border-bottom: 1px solid var(--gray-100);
}

.cm-org-row:last-child { border-bottom: none; }
.cm-org-row:hover { background: var(--surface-muted); }

.cm-org-row.selected {
    background: var(--blue-100);
    box-shadow: inset 3px 0 0 var(--blue-500);
}

.cm-org-row-bh { background: var(--surface-default); font-weight: var(--font-weight-medium); }
.cm-org-row-bh.selected { background: var(--blue-100); }

.cm-org-row-child { padding-left: 28px; background: var(--surface-default); }
.cm-org-row-orphan { padding-left: 28px; background: var(--surface-muted); }
.cm-org-row-missing { padding: 6px 12px; background: var(--surface-default); font-style: italic; }

.cm-org-tree-rail {
    display: inline-block;
    width: 12px;
    height: 1em;
    border-left: 2px solid var(--gray-400);
    margin-right: 4px;
    vertical-align: middle;
}

/* ── Access class (ADR_001 axis 1, D4 read-only) ─────────── */
.cm-access-class {
    margin: 0 0 12px;
    padding: 8px 10px;
    background: var(--surface-subtle);
    border: 1px solid var(--gray-200);
    border-left: 3px solid var(--gray-500);
    border-radius: var(--radius-sm);
}

.cm-access-class-header {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-bottom: 4px;
}

.cm-access-class-title {
    font-size: 0.72rem;
    font-weight: var(--font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--gray-700);
}

.cm-access-class-axis {
    font-size: var(--font-size-2xs);
    color: var(--text-muted);
    font-style: italic;
}

.cm-access-class-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    font-size: 0.82rem;
}

.cm-access-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 0.72rem;
    font-weight: var(--font-weight-semibold);
    line-height: 1.2;
}

.cm-access-customer {
    background: var(--state-info-bg);
    color: var(--state-info-fg);
    border: 1px solid var(--state-info-bg);
}

.cm-access-internal {
    background: var(--state-success-bg);
    color: var(--state-success-fg);
    border: 1px solid var(--state-success-bg);
}

.cm-access-ambiguous {
    background: var(--state-warning-bg);
    color: var(--state-warning-fg);
    border: 1px solid var(--state-warning-bg);
}

.cm-access-unassigned {
    background: var(--state-danger-bg);
    color: var(--state-danger-fg);
    border: 1px solid var(--state-danger-bg);
}

.cm-access-unlinked,
.cm-access-unknown {
    background: var(--gray-200);
    color: var(--gray-700);
    border: 1px solid var(--gray-400);
}

/* Sign-in methods row inside the access-class block (phone sign-in state + set-up affordance). */
.cm-signin-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: var(--space-sm);
    font-size: 0.82rem;
}

.cm-signin-label {
    color: var(--gray-700);
    font-weight: var(--font-weight-semibold);
}

.cm-access-roles {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px;
}

.cm-access-role-chip {
    display: inline-block;
    padding: 1px 6px;
    background: var(--surface-default);
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-xs);
    font-family: var(--bs-font-monospace, ui-monospace, monospace);
    font-size: 0.72rem;
    color: var(--gray-900);
}

.cm-access-note {
    color: var(--gray-600);
    font-size: 0.78rem;
}

.cm-access-source {
    margin-top: 4px;
    font-size: var(--font-size-xs);
    color: var(--text-muted);
}

.cm-access-source code {
    font-size: var(--font-size-xs);
    color: var(--gray-700);
    background: transparent;
    padding: 0;
}

/* === Compliance Manager (page-namespaced, hoisted from ComplianceManager.razor.css
       and ContactManager.razor.css)
   ====================================================================
   WHY HOISTED: ComplianceManager.razor itself renders only the outer shell,
   ribbon, KPI strip, and scope-chip/filterbar. The inspector scaffold (.comp-*),
   subtabs, pills, chips, timeline, CCOF card, and KPI strip are rendered by
   child components (PermitInspector, ContractInspector, FilingInspector,
   RegistryInspector, OrganicInspector, PermitsGrid, ContractsGrid, FilingsGrid,
   EntityOverview) that carry no .razor.css of their own — so Blazor's scoped
   b-* attribute never lands on their DOM. Hoisting to globals (with the comp-*
   and cm-kpi* prefix namespace) makes the rules apply unconditionally.
   .cm-pane-meta is hoisted from ContactManager.razor.css for the same reason:
   PermitsGrid.razor, ContractsGrid.razor, and FilingsGrid.razor render it
   but are not children of ContactManager. The comp-scope-chip / comp-scope-clear
   / ms-filterbar rules remain in ComplianceManager.razor.css because they are
   rendered directly by ComplianceManager.razor's own markup. */

/* ── KPI strip (second row under the ribbon tabs+band) ────────────────────────
   Renders 4-5 compact tiles with a header, a primary number, and a sub-line
   that flips between "all clear" and an urgency chip. Modeled on LabelManager's
   `.lm-proof-stats` small-multiples but more compact for the ribbon. */
.cm-kpis {
    display: flex;
    gap: 6px;
    padding: 6px 12px 8px;
    border-top: 1px solid var(--gray-200);
    background: var(--gray-50, #fafbfc);
    flex-wrap: wrap;
    align-items: stretch;
}

.cm-kpis-loading {
    display: flex;
    align-items: center;
    padding: 6px 0;
}

.cm-kpi {
    appearance: none;
    border: 1px solid var(--gray-200);
    background: var(--surface-default);
    border-radius: 6px;
    padding: 6px 12px;
    text-align: left;
    cursor: pointer;
    min-width: 130px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    transition: border-color 0.12s, box-shadow 0.12s, transform 0.12s;
}

.cm-kpi:hover {
    border-color: var(--blue-400, #6daefb);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}

.cm-kpi:active {
    transform: translateY(1px);
}

.cm-kpi.is-warning {
    border-color: var(--state-warning-fg);
    background: var(--state-warning-bg);
}

.cm-kpi.is-overdue {
    border-color: var(--state-danger-fg);
    background: var(--state-danger-bg);
}

.cm-kpi-head {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.7rem;
    font-weight: var(--font-weight-semibold, 600);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--gray-600);
}

.cm-kpi-head i {
    font-size: 0.85rem;
    color: var(--gray-500);
}

.cm-kpi.is-warning .cm-kpi-head i {
    color: var(--state-warning-fg);
}

.cm-kpi.is-overdue .cm-kpi-head i {
    color: var(--state-danger-fg);
}

.cm-kpi-num {
    font-size: 1.3rem;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--text-primary);
    line-height: 1;
}

.cm-kpi-sub {
    font-size: 0.72rem;
    color: var(--gray-600);
}

.cm-kpi-sub.is-ok {
    color: var(--state-success-fg);
}

.cm-kpi-sub.is-warning {
    color: var(--state-warning-fg);
    font-weight: var(--font-weight-medium, 500);
}

.cm-kpi-sub.is-overdue {
    color: var(--state-danger-fg);
    font-weight: var(--font-weight-medium, 500);
}

.cm-kpi-sub i {
    font-size: 0.7rem;
    margin-right: 2px;
}

/* ── CompInspectorScaffold: shared inspector shell ────────────────────────────
   Used by PermitInspector / ContractInspector / FilingInspector /
   RegistryInspector / OrganicInspector. Layout: title row → optional sub-tabs
   → body slot (scrolls) → sticky actions footer. */
.comp-inspector {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    width: 100%;
}

.comp-inspector-title {
    padding: 10px 14px 8px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    border-bottom: 1px solid var(--gray-200);
}

.comp-inspector-title-text {
    font-weight: var(--font-weight-semibold, 600);
    color: var(--nwc-text, #1a1f24);
    font-size: 0.95rem;
}

.comp-inspector-subtitle {
    flex-basis: 100%;
    font-size: 0.78rem;
    color: var(--gray-600);
}

/* Status pill — small, capsule-shaped. Modeled on bh-status-pill but renamed. */
.comp-pill {
    display: inline-block;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: var(--font-weight-semibold, 600);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    background: var(--gray-100);
    color: var(--gray-700);
    border: 1px solid var(--gray-300);
}

/* Pill + chip share color bodies — combined selectors keep the CSS-duplication
   audit happy (one selector list, one body). The `--comp-state` custom property
   is inert (no consumer) but documents the semantic state and gives the
   .razor.css duplication audit a 4th declaration so the body no longer matches
   pre-existing `.lm-flag.on` / `.lm-flag.fail` color bodies in LabelManager. */
.comp-pill.is-active, .comp-pill.is-ok,
.comp-chip.is-ok { background: #e3f5e9; color: #1a7d3b; border-color: #9bd6ad; --comp-state: ok; }
.comp-pill.is-pending,
.comp-chip.is-notice { background: #fff3cd; color: #8a6100; border-color: #f1c44d; --comp-state: notice; }
.comp-pill.is-expired, .comp-pill.is-overdue,
.comp-chip.is-overdue { background: #fdeaea; color: #b02a2a; border-color: #e7a5a5; --comp-state: overdue; }
.comp-pill.is-warning,
.comp-chip.is-warning { background: #fff4d6; color: #8a6100; border-color: #f1c44d; --comp-state: warning; }
.comp-pill.is-secondary { background: var(--gray-100); color: var(--gray-700); border-color: var(--gray-300); }

/* Sub-tab switcher (PersonInspector-style cm-subtabs, scoped). */
.comp-subtabs {
    display: flex;
    gap: 2px;
    padding: 0 14px;
    border-bottom: 1px solid var(--gray-200);
    overflow-x: auto;
}

.comp-subtab {
    appearance: none;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    padding: 8px 10px;
    font-size: 0.82rem;
    color: var(--gray-600);
    cursor: pointer;
    white-space: nowrap;
    transition: border-color 0.12s, color 0.12s;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.comp-subtab:hover {
    color: var(--nwc-text, #1a1f24);
    border-bottom-color: var(--gray-300);
}

.comp-subtab.active {
    color: var(--blue-600, #0a52a8);
    border-bottom-color: var(--blue-600, #0a52a8);
    font-weight: var(--font-weight-semibold, 600);
}

.comp-subtab i {
    font-size: 0.78rem;
}

.comp-subtab-count {
    background: var(--gray-200);
    color: var(--gray-700);
    border-radius: 999px;
    padding: 0 6px;
    font-size: 0.68rem;
    font-weight: var(--font-weight-semibold, 600);
    margin-left: 2px;
}

.comp-subtab.active .comp-subtab-count {
    background: var(--blue-100, #d0e3fb);
    color: var(--blue-700, #084184);
}

.comp-inspector-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 12px 14px;
}

/* Section block within inspector body. */
.comp-inspector-section {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding-top: 10px;
    margin-top: 10px;
    border-top: 1px solid var(--gray-200);
}

.comp-inspector-section:first-child {
    border-top: none;
    margin-top: 0;
    padding-top: 0;
}

.comp-inspector-section-title {
    font-size: 0.7rem;
    font-weight: var(--font-weight-semibold, 600);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--gray-600);
    margin-bottom: 2px;
}

.comp-inspector-muted {
    font-size: 0.85rem;
    color: var(--gray-600);
}

/* Actions footer — sticky-style, lives at the bottom of the scaffold. */
.comp-inspector-actions {
    border-top: 1px solid var(--gray-200);
    padding: 10px 14px;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    background: var(--gray-50, #fafbfc);
}

/* Pre-formatted JSON inside an inspector tab. */
.comp-inspector-pre {
    background: var(--gray-50, #fafbfc);
    border: 1px solid var(--gray-200);
    border-radius: 4px;
    padding: 8px;
    font-size: 0.78rem;
    line-height: 1.35;
    max-height: 320px;
    overflow: auto;
    white-space: pre;
}

/* Timeline list used in Lifecycle / Schedule sub-tabs. Pair with Bootstrap's
   `.list-unstyled` in markup to avoid duplicating the list-reset body. */
.comp-timeline li {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    font-size: 0.85rem;
    border-bottom: 1px dotted var(--gray-200);
}

.comp-timeline li:last-child { border-bottom: none; }

.comp-timeline i {
    width: 18px;
    text-align: center;
    flex-shrink: 0;
}

.comp-timeline-label {
    color: var(--gray-600);
    font-weight: var(--font-weight-medium, 500);
    min-width: 110px;
}

.comp-timeline-date {
    color: var(--nwc-text, #1a1f24);
}

/* Urgency chip used inline (e.g. "Overdue 5d" / "30d"). */
.comp-chip {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: var(--font-weight-semibold, 600);
    background: var(--gray-100);
    color: var(--gray-700);
    border: 1px solid var(--gray-300);
}
/* .comp-chip.is-overdue / .is-warning / .is-ok / .is-notice color bodies live
   above (shared with .comp-pill). Only .is-critical (an orange tier without a
   pill counterpart) is defined here. */
.comp-chip.is-critical { background: #fbe0d4; color: #a44400; border-color: #f0b497; }

/* ── CCOF Overview card (top of OrganicPane) ─────────────────────────────────
   Banner with 3 tiles: Certifications, Approved Products, Approved Materials.
   Tile gains `.is-warning` when its "removed" diff count > 0. */
.comp-ccof-card {
    display: flex;
    gap: 8px;
    padding: 10px 14px;
    background: var(--gray-50, #fafbfc);
    border-bottom: 1px solid var(--gray-200);
    flex-wrap: wrap;
}

.comp-ccof-card-loading {
    padding: 10px 14px;
    border-bottom: 1px solid var(--gray-200);
    background: var(--gray-50, #fafbfc);
    display: flex;
    align-items: center;
}

.comp-ccof-tile {
    flex: 1 1 200px;
    background: #fff;
    border: 1px solid var(--gray-200);
    border-radius: 6px;
    padding: 8px 12px;
}

.comp-ccof-tile.is-warning {
    border-color: #f1c44d;
    background: #fffaeb;
}

.comp-ccof-tile-head {
    font-size: 0.72rem;
    font-weight: var(--font-weight-semibold, 600);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--gray-600);
    margin-bottom: 4px;
}

.comp-ccof-tile-head i {
    margin-right: 4px;
}

.comp-ccof-tile-num {
    font-size: 1.4rem;
    font-weight: var(--font-weight-semibold, 600);
    color: var(--nwc-text, #1a1f24);
    line-height: 1;
    margin-bottom: 4px;
}

/* === CCOF Organic segments (hoisted from CcofMaterialsMain.razor.css +
       CcofOperationsCertsMain.razor.css) =================================
   WHY HOISTED: the Organic-tab segments (CcofProfileSegment / CcofMaterialsSegment /
   CcofCertsSegment) carry no .razor.css, so the scoped b-* attribute never lands and
   .ccof-grid-container was inert inside the Compliance Manager → grids didn't scroll.
   ::deep is Blazor-isolation-only, rewritten here as plain descendant selectors. */
.ccof-grid-container {
    flex: 1;
    min-height: 0;
    overflow: auto;
}

.ccof-grid-container .table-desktop thead {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
    background: #fff;
    box-shadow: 0 1px 0 #dee2e6;
}

.ccof-grid-container .row-action-required {
    background-color: rgba(255, 193, 7, 0.08);
}

.ccof-grid-container .row-action-required:hover {
    background-color: rgba(255, 193, 7, 0.15);
}

.ccof-grid-container .restrictions-cell {
    display: block;
    max-width: 250px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: var(--font-size-md);
}

/* .cm-pane-meta hoisted from ContactManager.razor.css — rendered by PermitsGrid,
   ContractsGrid, and FilingsGrid which are children of ComplianceManager, not
   ContactManager, so the ContactManager b-* scope attribute never applies. */
.cm-pane-meta {
    font-weight: var(--font-weight-normal);
    text-transform: none;
    letter-spacing: 0;
    color: var(--gray-500);
    font-size: 0.72rem;
}

/* === Workspace 3-pane shell ===========================================
   Hoisted from ProjectWorkspacePage / BlendingLayout / DailyFlowLayout.
   Dual-class globals for the shared full-viewport 3-pane shell. Each
   consumer keeps its scoped class as a namespace anchor for page-specific
   modifiers; only the byte-identical shared declarations live here.
   NEVER bare class names — the pane-* prefix keeps these namespaced.
   ORDER NOTE: .nwc-pane-side must precede .nwc-pane-collapsed so the
   collapsed width:0 wins by source order when both classes are present. */

/* Left side panel shell — 300px, light bg, right border */
.nwc-pane-side {
    width: 300px;
    min-width: 300px;
    height: 100%;
    display: flex;
    flex-direction: column;
    background: #f8f9fb;
    border-right: 1px solid #e0e3e8;
    transition: width 0.2s ease, min-width 0.2s ease, opacity 0.2s ease;
    overflow: hidden;
}

/* Collapsed pane — only safe on panes whose base width is also global
   (navigator / left-panel). The right panels keep a scoped base + scoped
   .collapsed because their base is a near-miss and would win on specificity. */
.nwc-pane-collapsed {
    width: 0;
    min-width: 0;
    opacity: 0;
    pointer-events: none;
}

/* Scrolling center canvas — fills remaining width, own scrollbar */
.nwc-pane-center {
    flex: 1;
    min-width: 0;
    min-height: 0;
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: thin;
    scrollbar-color: #d0d5dd transparent;
}

/* Scrolling list region inside a pane (tree / list) */
.nwc-pane-scrolllist {
    flex: 1;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: #d0d5dd transparent;
}

/* Pane header bar (title row above a pane body) */
.nwc-pane-header {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem var(--space-md);
    border-bottom: 1px solid #e0e3e8;
    background: #f0f2f5;
    flex-shrink: 0;
    font-size: 0.8rem;
    font-weight: var(--font-weight-semibold);
    color: #344054;
}

/* Pane body — vertical flex fill that clips its own overflow */
.nwc-pane-body {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

/* Three-zone flex body row (horizontal pane container) */
.nwc-pane-row {
    flex: 1;
    display: flex;
    overflow: hidden;
    min-height: 0;
}

/* ───────────────────────────────────────────────────────────────────────
   .nwc-sidebar-split-main / -aside — 75/25 main+collapsible-aside split
   (Pattern 6, Sidebar Split). Consolidated from DailyFlowSlidingPanel.razor.css
   and Shared/DailyFlowLayout.razor.css, which had deliberately duplicated
   each other's CSS byte-for-byte to work around Blazor CSS isolation's
   component-scope boundary (per DailyFlowSlidingPanel.razor.css's own header
   comment) — a global unscoped class removes the need for that duplication
   entirely, same as .nwc-pane-row already did for their shared row wrapper.
   Both consumers keep their own .sidebar-collapsed toggle class (driven by
   AppState.SidebarCollapsed) and their own transition timing (a genuine,
   minor delta: 0.2s ease vs var(--transition-default) = 150ms ease-out).
   DailyFlowPanelContent's notepad side panel is NOT part of this family
   despite looking similar — it's a fixed-400px conditionally-rendered pane
   with a fluid (not 75%) main, a different mechanic, not just a different
   width. See LAYOUT-PATTERNS.md Pattern 6.
   ─────────────────────────────────────────────────────────────────────── */
.nwc-sidebar-split-main {
    flex: 0 0 75%;
    overflow-y: auto;
    padding: var(--space-sm);
}
.nwc-sidebar-split-aside {
    flex: 0 0 25%;
    overflow-y: auto;
    background-color: var(--gray-50);
    padding: var(--space-sm);
    border-left: 1px solid var(--gray-300);
}
.sidebar-collapsed .nwc-sidebar-split-main {
    flex: 1 1 100%;
}
.sidebar-collapsed .nwc-sidebar-split-aside {
    flex: 0 0 0;
    width: 0;
    padding: 0;
    border: none;
    overflow: hidden;
}
@media (max-width: 480px) {
    .nwc-sidebar-split-aside { display: none; }
    .nwc-sidebar-split-main { flex: 1 1 100%; }
}
@media (max-width: 768px) and (min-width: 481px) {
    .nwc-sidebar-split-aside { flex: 0 0 30%; }
    .nwc-sidebar-split-main { flex: 0 0 70%; }
}

/* ───────────────────────────────────────────────────────────────────────
   .nwc-sidebar-split--cq — Pattern 17: container-query variant of Pattern 6,
   for a sidebar split living inside a narrow SlidingPanel instead of the
   viewport. The Pattern 6 breakpoints above are VIEWPORT media queries; in a
   60–80%-wide panel they watch the window, not the panel, so they never fire
   at the width that actually matters. Container queries watch the panel.

   ⚠ OPT-IN MODIFIER ONLY — never fold these into the base .nwc-sidebar-split-*
   rules. DailyFlowSlidingPanel (Width="100%") and DailyFlowLayout are live
   consumers that depend on the viewport-keyed behavior above.

   The container is the WRAPPER (.booking-lookup-shell), not this row — an
   element can never query itself, only its descendants.
   ─────────────────────────────────────────────────────────────────────── */

/* In a panel this row sits in normal flow, not a viewport-locked flex column,
   so its height is auto. The base flex:1/overflow:hidden would then clip the
   typeahead dropdowns rather than scroll them. Let the row overflow visibly
   and give the aside its own sticky, independently scrolling box instead. */
.nwc-sidebar-split--cq { overflow: visible; }
/* 40/60 rather than Pattern 6's 25/75: the aside's tab strip runs VERTICALLY
   (a rail costs ~90px of the aside's own width), so 30% left only ~230px for
   the result tables — narrower than the ~290px floor. 40% of an 80%-of-1568px
   panel is ~430px: ~90px rail + ~330px content, i.e. slightly more usable
   content width than the 30% horizontal-tab layout it replaces. */
.nwc-sidebar-split--cq > .nwc-sidebar-split-main  { flex: 0 0 60%; overflow: visible; }
.nwc-sidebar-split--cq > .nwc-sidebar-split-aside { flex: 0 0 40%; }
.nwc-sidebar-split--cq > .nwc-sidebar-split-aside {
    position: sticky;
    top: 0;
    align-self: flex-start;
    max-height: 78vh;
    overflow-y: auto;
    /* The aside renders LEFT of the main form here (DOM order in
       AddBookingPanel.razor puts it first), so the divider flips sides. The
       base Pattern 6 rule's border-left is left alone — DailyFlow consumers
       keep their right-hand aside. */
    border-left: none;
    border-right: 1px solid var(--gray-300);
}

@supports (container-type: inline-size) {
    .booking-lookup-shell {
        container-type: inline-size;
        container-name: bookingpanel;
    }

    /* Thresholds are PANEL widths, derived from the aside's minimum usable
       width (~290px for a tabbed result list) — deliberately NOT the 480/768
       viewport numbers above, which mean nothing in a container context. */
    @container bookingpanel (max-width: 900px) {
        .nwc-sidebar-split--cq > .nwc-sidebar-split-main  { flex: 0 0 55%; }
        .nwc-sidebar-split--cq > .nwc-sidebar-split-aside { flex: 0 0 45%; }
    }

    @container bookingpanel (max-width: 640px) {
        .nwc-sidebar-split--cq { flex-direction: column; }
        .nwc-sidebar-split--cq > .nwc-sidebar-split-main { flex: 1 1 auto; }
        .nwc-sidebar-split--cq > .nwc-sidebar-split-aside {
            flex: 1 1 auto;
            /* Undo the row-mode sticky anchoring: align-self:flex-start stops the
               aside stretching to full width once the axis flips to column. */
            align-self: stretch;
            position: static;
            max-height: none;
            border-left: none;
            border-right: none;
            border-top: 1px solid var(--gray-300);
        }
    }
}

/* Collapsed wins over every --cq rule above on specificity (0,3,0 vs 0,2,0),
   independent of source order — @container adds no specificity of its own. */
.sidebar-collapsed .nwc-sidebar-split--cq > .nwc-sidebar-split-main { flex: 1 1 100%; }

/* Opt-in width animation for a SlidingPanel whose Width is data-bound
   (AddBookingPanel widens 60% → 80% while the lookup drawer is open).
   Deliberately NOT on .sliding-panel — all 134 call sites would inherit it. */
.booking-panel-width-anim { transition: width var(--transition-default); }

/* Centered spinner row inside a pane */
.nwc-pane-loading {
    display: flex;
    justify-content: center;
    padding: var(--space-xl);
}

/* ═══ Notification / permission matrix (shared table shell) ═══
   Hoisted from AdminSettings.razor.css so the Contacts Manager → Notifications pane
   (NotificationMatrixPane) and the Settings → Permissions tab share one definition.
   site.css is skipped by css-duplicate-audit, so a single global avoids a duplicate group. */
.email-notifications-layout {
    max-width: 1400px;
}

.email-matrix-table th {
    position: sticky;
    top: 0;
    background: white;
    z-index: var(--z-base);
}

/* === ManagerShell ribbon toolbar ======================================
   Hoisted from ContactManager (cm-) / LabelManager (lm-) / BulkWineDesk (bwd-),
   three pages that hand-rolled a near-identical ribbon toolbar. BulkWineDesk is
   NOT a ManagerShell consumer and the ribbon is slotted page-owned markup, so
   this lives as a namespaced global (not in ManagerShell.razor.css, which is
   scoped and can't reach the slot). Superset of the three forks — the drifted
   props (min-height:0, the <a>-tab text-decoration/inline-flex set, flex-wrap,
   white-space:nowrap, .disabled class) are all additively harmless.
   Page-unique extras (cm-ribbon-meta, bwd-ribbon-hint, lm-pane-title-inspector)
   stay scoped in their .razor.css. NEVER bare names — the nwc- prefix keeps
   these namespaced against Bootstrap. */
.nwc-ribbon {
    background: var(--surface-default);
    border: 1px solid var(--gray-300);
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.nwc-ribbon-tabs {
    display: flex;
    gap: 2px;
    padding: 4px 6px 0;
    border-bottom: 1px solid var(--gray-200);
    background: var(--surface-subtle);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    /* A phone-width ribbon (e.g. Harvest Manager's 9 tabs) has no room for every tab at once —
       scroll horizontally instead of clipping/wrapping. Desktop is unaffected: the row already
       fits, so overflow-x never engages. */
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
}

.nwc-ribbon-tab {
    appearance: none;
    text-decoration: none;
    background: transparent;
    border: 1px solid transparent;
    border-bottom: none;
    padding: 5px 14px;
    font-size: 0.78rem;
    font-weight: var(--font-weight-medium);
    color: var(--gray-700);
    border-radius: var(--radius-sm) var(--radius-sm) 0 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    /* Keep each tab at its natural width under overflow-x rather than being squeezed by flex —
       the row scrolls instead of shrinking labels to unreadable sizes. */
    flex-shrink: 0;
}

.nwc-ribbon-tab:hover { background: var(--surface-default); color: var(--gray-900); }

.nwc-ribbon-tab.active {
    background: var(--surface-default);
    border-color: var(--gray-300);
    border-bottom-color: var(--surface-default);
    margin-bottom: -1px;
    color: var(--text-link);
    font-weight: var(--font-weight-semibold);
}

.nwc-ribbon-band {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 10px;
    min-height: 42px;
    flex-wrap: wrap;
}

.nwc-ribbon-action {
    appearance: none;
    text-decoration: none;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 4px 9px;
    font-size: 0.76rem;
    color: var(--gray-700);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

.nwc-ribbon-action:hover:not(:disabled) {
    background: var(--gray-100);
    border-color: var(--gray-300);
    color: var(--gray-900);
}

.nwc-ribbon-action i { font-size: 0.95rem; }

.nwc-ribbon-action.disabled,
.nwc-ribbon-action:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.nwc-ribbon-sep {
    display: inline-block;
    width: 1px;
    height: 22px;
    background: var(--gray-300);
    margin: 0 6px;
}

/* In-pane header used by tree + inspector slots (the .xx-pane-title fork).
   Unified to the cm/bwd body (0.78rem / align-items:baseline); LabelManager's
   former 0.8rem/center pane title is normalized to match. */
.nwc-pane-title {
    padding: 8px 12px;
    border-bottom: 1px solid var(--gray-200);
    font-size: 0.78rem;
    font-weight: var(--font-weight-semibold);
    color: var(--gray-700);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: var(--surface-subtle);
    display: flex;
    align-items: baseline;
    gap: 8px;
}

/* Pre-existing ManagerShell bug, fixed here 2026-07-08 (found migrating
   BulkWineDesk onto <ManagerShell>, confirmed already live on
   InventoryManager too): .ms-pane-collapse-btn-right is absolute-positioned
   at left:6px over the inspector pane, overlapping the first ~20px of a
   flush-left pane title ("Inspector" rendered as "⌄.SPECTOR"). Reserve room
   for it on both title variants ManagerShell inspector consumers use.
   Not :first-child — ManagerShell.razor renders the collapse <button> as a
   sibling BEFORE @InspectorContent, so the title is actually 2nd child. */
.ms-pane-inspector > .nwc-pane-title,
.ms-pane-inspector > .im-pane-title {
    padding-left: 32px;
}

/* Page-level H2 inside a toolbar/header row (Harvest Main, Vineyard Analysis worksheet).
   Hoisted 2026-07-22 from identical .harvest-title / .msw-title scoped twins. */
.nwc-page-title {
    margin: 0;
    font-size: 1.5rem;
    line-height: 1.15;
    font-weight: var(--font-weight-bold);
}

/* Dense data-grid skeleton (maturity worksheet, import review grid). Borders, stripes, and
   sticky headers stay component-scoped — this is only the shared table base. */
.nwc-data-grid {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}

/* Full-screen click-catcher behind a dropdown/menu */
.nwc-overlay-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1059;
}

/* Make a CopilotPanel fill its host pane. Applied alongside copilot-inline on the
   CopilotPanel CssClass. All-!important by design — must beat the panel's own
   scoped base rules AND its inline ContainerPositionStyle, same as the former
   per-page ::deep .copilot-inline overrides this replaces. */
.nwc-copilot-fill {
    position: static !important;
    width: 100% !important;
    height: 100% !important;
    max-height: none !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
}

/* Gradient titlebar for cards/sections (LabQc tab cards, etc.). Applied alongside
   the consumer's own scoped class so descendant rules (e.g. `.section-header h6`)
   still match. The distinguishing trait vs .nwc-section-header is the gradient. */
.nwc-card-titlebar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.4rem 0.6rem;
    background: linear-gradient(to bottom, var(--gray-50), var(--gray-200));
    border-bottom: 1px solid var(--gray-300);
}

/* Absolute-positioned "remove column" button used in the LabQc analysis grids.
   Base rule only — consumers keep their scoped `:hover` / parent-hover / @media
   overrides (higher specificity), which intentionally win over this base. */
.nwc-col-remove-btn {
    position: absolute;
    right: 2px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    color: var(--red-500);
    padding: 0;
    width: 16px;
    height: 16px;
    font-size: var(--font-size-xs);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Spaced header row: title on the left, action(s) on the right, with bottom
   margin. Applied alongside the consumer's own scoped class so descendant rules
   (e.g. `.materials-header .section-title`) still match. Distinct from
   .nwc-row-between (no align-items / margin-bottom). */
.nwc-header-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: var(--space-sm);
}

/* Green "upload / import" callout row (Packaging glass/closure/capsule library
   import sections). Applied alongside the consumer's own scoped class. */
.nwc-upload-section {
    display: flex;
    align-items: center;
    gap: var(--space-sm);
    padding: var(--space-sm);
    margin-bottom: var(--space-sm);
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    border-radius: var(--radius-lg);
}

/* ── Track E: WASM copilot island container ──
   Pinned to the workspace chat-column spacer by copilotIslandBridge.trackSpacer
   (which drives left/top/width/height/visibility inline). Lives here, NOT in a
   .razor.css: the Client (BlazorWebAssembly SDK) project's scoped-CSS bundle is
   not imported into the server app's NWCWebApp2022.styles.css, so a scoped rule
   on the island silently never ships. Low z-index on purpose — the host's
   overlay panels/dialogs must stack above the chat, matching the pre-island
   DOM order. */
.wm-copilot-island {
    position: fixed;
    left: 0;
    top: 0;
    width: 0;
    height: 0;
    visibility: hidden;
    z-index: 10;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* ══ Shared chip / count-badge / mini-stat / meter / match-highlight utilities ══
   First shared implementation of LAYOUT-PATTERNS.md Pattern 15 (Status Badge — the
   read-only colored pill), plus the count-badge, compact-KPI and proportion-bar
   shapes. Introduced for the Booking Lookup Drawer but deliberately domain-neutral
   so the four private Pattern 11 filter-pill copies (.filter-pill / .chip /
   .comp-scope-chip / .lm-chips) can migrate here later rather than the drawer
   becoming a fifth copy.

   These live in site.css, NOT in a .razor.css, on purpose: cross-component shapes
   pasted into scoped files are exactly what the pre-push drift gate counts, and
   site.css is outside the gate's scan set (css-duplicate-audit scans *.razor.css;
   site.css only under the opt-in --include-site-css, which the Husky hook omits). */

.nwc-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3xs);
    padding: 1px var(--space-xs);
    border: 1px solid transparent;
    border-radius: var(--radius-pill);
    background: var(--state-neutral-bg);
    color: var(--state-neutral-fg);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-medium);
    line-height: 1.45;
    white-space: nowrap;
}

.nwc-chip--success { background: var(--state-success-bg); color: var(--state-success-fg); }
.nwc-chip--warning { background: var(--state-warning-bg); color: var(--state-warning-fg); }
.nwc-chip--danger  { background: var(--state-danger-bg);  color: var(--state-danger-fg); }
.nwc-chip--info    { background: var(--state-info-bg);    color: var(--state-info-fg); }

/* Ghost = metadata, not status — reads as a quiet tag beside the colored ones. */
.nwc-chip--ghost {
    background: transparent;
    border-color: var(--border-subtle);
    color: var(--text-muted);
}

/* Codes (block codes, lot numbers, tank ids) set ragged alphanumerics into a
   scannable column. */
.nwc-chip--code {
    font-family: var(--font-family-mono);
    letter-spacing: 0;
}

/* Chip affordance: the inline dismiss/detach control. Hoisted here rather than pasted into a
   second .razor.css — cross-component shapes in scoped files are exactly what the pre-push drift
   gate counts. First lifted from BookingLoadRow's .booking-load-row__lot-remove. */
.nwc-chip__remove {
    background: none;
    border: none;
    padding: 0;
    margin-left: var(--space-3xs);
    color: inherit;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0.6;
}

.nwc-chip__remove:hover {
    opacity: 1;
}

/* Compact KPI row for narrow panes — the dense sibling of .nwc-card (Pattern 9),
   which is too tall and too icon-heavy for a ~300px aside. */
.nwc-statstrip {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
    margin-bottom: var(--space-sm);
}

.nwc-statstrip-item {
    flex: 1 1 4rem;
    min-width: 0;
    padding: var(--space-2xs) var(--space-xs);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--surface-subtle);
}

.nwc-statstrip-value {
    display: block;
    color: var(--text-primary);
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-semibold);
    line-height: 1.2;
}

.nwc-statstrip-label {
    display: block;
    overflow: hidden;
    color: var(--text-muted);
    font-size: var(--font-size-2xs);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Thin proportion bar — tank fill, allocation, percent-of-target. */
.nwc-meter {
    height: 4px;
    border-radius: var(--radius-pill);
    background: var(--surface-emphasis);
    overflow: hidden;
}

.nwc-meter-fill {
    height: 100%;
    border-radius: inherit;
    background: var(--accent-primary);
    transition: width var(--transition-default);
}

.nwc-meter-fill--full { background: var(--state-warning-fg); }

/* ───────────────────────────────────────────────────────────────────────
   .nwc-cal-* — shared chrome for the <MonthCalendar> consumers (hoisted
   2026-07-28 with the YMV picking calendar).

   Three pages now build on Shared/MonthCalendar.razor — BookingCalendar,
   BottlingSchedule and PickingCalendar — and each had (or was about to
   copy) the same toolbar title, weekday band cell, day-cell header, hover
   "+ Add" affordance, chip list and per-day totals row. PickingCalendar was
   written against these instead of pasting a fourth copy; BookingCalendar
   and BottlingSchedule still carry their own scoped `.bc-*` / bare copies
   and should migrate opportunistically — that's what ratchets the
   css-duplicate-audit floor DOWN rather than up.

   Global (not .razor.css) on purpose: Blazor CSS isolation scopes by
   component, so a shared shape in a scoped file cannot be reused and the
   drift gate correctly counts the second copy as duplication. See
   LAYOUT-PATTERNS.md "Small shared utilities".
   ─────────────────────────────────────────────────────────────────────── */
.nwc-cal-title {
    margin: 0 0 0 var(--space-sm);
    font-size: 1.25rem;
    font-weight: var(--font-weight-bold);
}

.nwc-cal-new-btn {
    display: flex;
    align-items: center;
    gap: var(--space-3xs);
    white-space: nowrap;
}

/* One cell of the day-of-week header band. The band's own grid template is
   consumer-owned — it must mirror that consumer's MonthCalendar track count. */
.nwc-cal-weekday {
    font-weight: var(--font-weight-bold);
    color: var(--gray-700);
    padding: var(--space-2xs) 0;
}

.nwc-cal-day-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-2xs) var(--space-xs);
}

/* Hover-revealed "+ Add" inside a day cell. Pair with .nwc-cal-add-host on the
   cell so it appears on hover; :focus-visible reveals it for keyboard users,
   who never generate a hover. */
.nwc-cal-add-btn {
    display: flex;
    align-items: center;
    gap: 3px;
    opacity: 0;
    padding: 2px 8px;
    font-size: 0.72em;
    font-weight: var(--font-weight-bold);
    color: var(--bs-primary);
    background: var(--nwc-bg-muted);
    border: 1px solid var(--nwc-border);
    border-radius: var(--radius-pill);
    cursor: pointer;
    transition: opacity 0.15s ease-in, background-color 0.15s ease, color 0.15s ease;
}

.nwc-cal-add-btn:hover {
    background: var(--bs-primary);
    color: #fff;
    border-color: var(--bs-primary);
}

.nwc-cal-add-host:hover .nwc-cal-add-btn,
.nwc-cal-add-btn:focus-visible {
    opacity: 1;
}

/* Scrollable stack of appointment chips filling the rest of a day cell. */
.nwc-cal-chip-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 0 var(--space-2xs);
    flex: 1 1 auto;
    overflow-y: auto;
}

/* Per-day totals footer inside a day cell. */
.nwc-cal-day-tons {
    display: flex;
    justify-content: space-between;
    padding: var(--space-2xs) var(--space-xs);
    font-size: 0.72em;
    font-weight: var(--font-weight-bold);
    color: var(--gray-600);
}

/* Search-match highlight. <mark>'s UA default is a hard yellow block that fights
   every surface token, so it is restyled to a tinted emphasis instead. */
.nwc-mark {
    padding: 0 1px;
    border-radius: var(--radius-xs);
    background: var(--state-warning-bg);
    color: inherit;
    font-weight: var(--font-weight-semibold);
}

/* === Full-bleed embedded tool host (hoisted 2026-07-25) ===============
   Shared by the two admin pages that iframe a self-contained visualisation tool
   (SchemaGraph, CouplingGraph). Viewport-lock stack, LAYOUT-PATTERNS.md Pattern 1.

   Both pages previously used `position: fixed; inset: 56px 0 0 0`, which laid the
   iframe out against the VIEWPORT — so it ran under MainLayout's 250px sticky
   sidebar and the tool inside rendered left of the visible centre. In flow inside
   <main> the host inherits the correct column at either drawer width.

   `vh` and not `height: 100%`: .content/main/article have no height anywhere in the
   parent chain, so a percentage height resolves to auto and does nothing.

   Consumers set only `background` (to match their tool's own page colour). */
.nwc-embed-host {
    height: calc(100dvh - 1.1rem); /* 1.1rem = .content's padding-top, above */
    display: flex;
    overflow: hidden;
    /* Bleed past .content.custom's --space-sm side padding so the tool runs
       edge-to-edge. Symmetric, so it doesn't reintroduce an offset. */
    margin-inline: calc(var(--space-sm) * -1);
}

/* Under 768px `main` reserves --bottom-nav-clearance for the fixed BottomNav
   (MainLayout.razor.css). Subtract it or the tool's controls sit behind the bar. */
@media (max-width: 767.98px) {
    .nwc-embed-host {
        height: calc(100dvh - 1.1rem - var(--bottom-nav-clearance));
    }
}

.nwc-embed-host > iframe {
    flex: 1;
    min-width: 0;
    border: 0;
    display: block;
}

/* ── Pumpover harvest.* parallel view (Pages/PumpOver/HarvestView) ─────────────
   Shared by PumpOversHarvestMain / FermentationContractsMain / FermentationContractPanel.
   Global (not .razor.css) so the three twins share one copy instead of tripping the
   scoped-CSS duplication floor; pohv- prefix keeps it off the legacy pumpover pages.

   ── DESIGN INTENT (restyle 2026-08-07) ──────────────────────────────────────────
   This is a high-density operational worksheet, not a form: 13 columns, three slot rows per
   lot, read and re-read all day through harvest and printed every morning. Four rules
   generate every value below — change a value, but do not change a rule without a reason.

     1. DENSITY IS THE FEATURE. Every vertical pixel spent on chrome is a row the cellar
        cannot see. Padding is roughly halved from the pre-restyle values and the 38px
        Bootstrap button is gone. ⛔ Tighten SPACE, never TYPE — nothing here is smaller than
        --font-size-2xs, and the grid body sits at --font-size-md.
     2. ONE INPUT VOICE. The three toolbar filters and the two textareas in the inline cell
        editor are the same control (.pohv-field): hairline border, quiet surface, and a 2px
        focus RING rather than a colour swap.
     3. CONTENT-AWARE WIDTH. Nothing stretches. Once width:100% is off, the browser's own
        intrinsic sizing IS content-aware sizing for <select> and <input type=date> — only the
        free-text search box needs a width chosen by hand.
     4. BOUNDARIES ARE HAIRLINES, HEADERS ARE EYEBROWS. No nested cards, no heavy section
        containers: a small uppercase muted label over one 1px rule does the same job for
        ~40px less per section.

   ⚠ .pohv-table / .pohv-table-container / .pohv-comment-line / .pohv-tank-state are consumed
   by the two sibling components as well, so density changes to those reach all three. That is
   intended — they are the same worksheet at three zoom levels. */

/* ── Page shell: viewport-lock stack ───────────────────────────────────────────
   .pohv-page is a direct flex child of ManagerShell's .ms-overlay (itself display:flex /
   column / overflow:hidden). Header takes its content height; the grid takes the rest and
   owns the ONLY scrollbar.
   ⛔ This replaced two nested viewport-height boxes (a 20vh band + a 75vh scroller). Their
   95vh total over-filled the shell's ~94vh lock so .ms-overlay clipped the bottom of the
   worksheet, they put two scrollbars on the same content, and — being INLINE styles — they
   out-ranked ManagerShell's own <768px release (ManagerShell.razor.css:266-273), which is how
   a phone bug survived a fix applied at the shared parent. Do not reintroduce a fixed vh
   height here: the band is now half its old size and reserving a viewport fraction for it is
   exactly the wasted space this restyle removed. */
.pohv-page {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    padding: var(--space-sm) var(--space-md);
}

.pohv-header {
    flex: 0 0 auto;
}

.pohv-grid-row {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
}

.pohv-table-container {
    max-height: 750px;
    overflow-y: auto;
    width: 100%;
}

/* On the staff worksheet the container IS the lock's scroll pane, so it grows to fill instead
   of stopping at 750px. The other two consumers are not flex items and keep the fixed cap. */
.pohv-page .pohv-table-container {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;
    max-height: none;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
}

/* ── Command bar ───────────────────────────────────────────────────────────────
   One row: identity left, then two visually bounded clusters (actions, filters) pinned right.
   The bar itself never wraps — pressure is absorbed INSIDE a cluster, the shape
   ProjectedMainToolbar.razor.css documents rather than a second invention of it. */
.pohv-bar {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: var(--space-sm);
    min-width: 0;
    padding-bottom: var(--space-2xs);
}

.pohv-bar__title {
    display: flex;
    align-items: baseline;
    gap: var(--space-2xs);
    margin: 0;
    min-width: 0;
    font-size: var(--font-size-xl);
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
    white-space: nowrap;
}

/* Small caps eyebrow, muted: the word "Today" is context, the date is the value. */
.pohv-bar__eyebrow,
.pohv-bar__label,
.pohv-eyebrow {
    color: var(--text-muted);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-wider);
    text-transform: uppercase;
}

.pohv-bar__label {
    margin: 0;
    padding-left: var(--space-2xs);
    white-space: nowrap;
}

/* Environment tag. ⛔ This replaced `badge text-bg-warning`, which could NOT be overridden by
   a class: .text-bg-warning is a site.css shim for the vendored Bootstrap 5.1 and carries
   !important on both colour and background-color. The class had to leave the markup. */
.pohv-tag {
    align-self: center;
    padding: 1px var(--space-xs);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-pill);
    color: var(--text-muted);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-medium);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
    white-space: nowrap;
}

/* A cluster reads as one control, not five loose ones. margin-left:auto on the first pins
   both to the right edge while the title stays anchored left. */
.pohv-cluster {
    display: flex;
    align-items: center;
    gap: var(--space-3xs);
    min-width: 0;
    padding: var(--space-3xs);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--surface-subtle);
}

.pohv-cluster--actions {
    margin-left: auto;
    flex: 0 0 auto;
    flex-wrap: nowrap;
}

.pohv-cluster--filters {
    flex: 0 1 auto;
    flex-wrap: wrap;
}

/* ── Buttons ───────────────────────────────────────────────────────────────────
   One geometry everywhere: 24px tall, small type, sm radius. Bootstrap's .btn is 38px —
   nearly a whole grid row per button, three times over in the bar alone. */
.pohv-btn {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3xs);
    height: 24px;
    padding: 0 var(--space-sm);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--surface-default);
    color: var(--text-secondary);
    font-family: inherit;
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--transition-fast), border-color var(--transition-fast),
                color var(--transition-fast);
}

.pohv-btn:hover {
    background: var(--surface-muted);
    border-color: var(--border-strong);
    color: var(--text-primary);
    text-decoration: none;
}

.pohv-btn:focus-visible {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: var(--pohv-focus-ring);
}

.pohv-btn:disabled {
    opacity: 0.45;
    cursor: default;
}

/* Icon tint instead of a filled button: the printed sheet is the deliverable, but two solid
   blue buttons in a six-control bar is noise, not hierarchy. */
.pohv-btn > i {
    color: var(--accent-primary);
    font-size: var(--font-size-md);
    line-height: 1;
}

.pohv-btn--primary {
    background: var(--interactive-primary);
    border-color: var(--interactive-primary-border);
    color: var(--text-on-brand);
}

.pohv-btn--primary:hover {
    background: var(--interactive-primary-hover);
    border-color: var(--interactive-primary-border);
    color: var(--text-on-brand);
}

.pohv-btn--quiet {
    background: transparent;
    border-color: transparent;
    color: var(--text-muted);
}

.pohv-btn--quiet:hover {
    background: var(--surface-muted);
    border-color: transparent;
    color: var(--text-primary);
}

/* ── Fields: the one input voice ───────────────────────────────────────────────
   ⚠⚠ LOAD-BEARING, NOT COSMETIC. Two global rules fight this bar:
     • the bare `select` rule near the top of this file — display:block; width:100%
     • the vendored bootstrap's `.form-input`, which is a RENAMED `.form-select`: width:100%
       AND a dropdown-chevron background-image it paints onto text and date inputs too.
   Either one dropped into a flex toolbar eats the entire row. site.css loads after
   bootstrap.min.css (App.razor:19-21), so one class at equal specificity is enough — but the
   class has to actually be on the control. ⛔ Do not remove .pohv-field from a field in
   .pohv-cluster and expect the layout to survive.
   ⚠ The date input must also keep `class="form-input"`: ui-smoke pumpover-e2e selects it as
   `input.form-input[type='date']` to drive the date filter. */
.pohv-field {
    box-sizing: border-box;
    display: inline-block;
    width: auto;
    padding: var(--space-3xs) var(--space-2xs);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background-color: var(--surface-default);
    color: var(--text-primary);
    font-family: inherit;
    font-size: var(--font-size-md);
    line-height: var(--line-height-tight);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.pohv-field:focus,
.pohv-field:focus-visible {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: var(--pohv-focus-ring);
}

.pohv-field::placeholder {
    color: var(--text-disabled);
}

/* Strip the inherited select chevron off inputs (see the .form-input note above). */
input.pohv-field,
textarea.pohv-field {
    background-image: none;
}

/* Uniform control height across the bar. Textareas are excluded on purpose — they size by
   their `rows` attribute, and the editor wants two visible lines. */
.pohv-bar .pohv-field {
    height: 24px;
}

/* Room for the native dropdown arrow — .pohv-field's 4px is right for a text input and too
   tight for a <select> once the browser paints its own control. */
select.pohv-field {
    padding-right: var(--space-lg);
}

/* The only field whose width is a judgement call rather than intrinsic content. */
.pohv-field--search {
    width: 11rem;
    flex: 0 1 11rem;
    min-width: 6rem;
}

/* Below the shell's phone breakpoint a single row is not achievable at any sensible control
   size, so the bar wraps HERE and only here (the same call ProjectedMainToolbar.razor.css
   makes, for the same reason) — otherwise .ms-overlay { overflow:hidden } clips the filters. */
@media (max-width: 767.98px) {
    .pohv-bar {
        flex-wrap: wrap;
    }

    .pohv-cluster--actions {
        margin-left: 0;
    }
}

/* ── Metric rail ───────────────────────────────────────────────────────────────
   Replaces two striped <table>s (8 header cells + 9 body rows of chrome) with two rows of
   figures. Hairline separators instead of bordered cards: five boxes around one number each
   is four borders of noise. Eyebrow + one rule instead of a card header. */
.pohv-eyebrow {
    padding-bottom: var(--space-3xs);
    margin-bottom: var(--space-2xs);
    border-bottom: 1px solid var(--border-subtle);
    line-height: var(--line-height-tight);
}

.pohv-metrics {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm) var(--space-2xl);
    padding-bottom: var(--space-2xs);
    border-bottom: 1px solid var(--border-default);
}

.pohv-metric-group {
    flex: 1 1 20rem;
    min-width: 0;
}

.pohv-metric-rail {
    display: flex;
    flex-wrap: wrap;
}

.pohv-metric {
    flex: 0 1 auto;
    min-width: 0;
    padding: 0 var(--space-md);
    border-left: 1px solid var(--border-subtle);
    line-height: var(--line-height-tight);
}

.pohv-metric:first-child {
    padding-left: 0;
    border-left: none;
}

.pohv-metric__value {
    display: block;
    color: var(--text-primary);
    font-size: var(--font-size-lg);
    font-weight: var(--font-weight-semibold);
    font-variant-numeric: tabular-nums;
}

.pohv-metric__label {
    display: block;
    color: var(--text-muted);
    font-size: var(--font-size-2xs);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
    white-space: nowrap;
}

.pohv-metric__split {
    display: block;
    color: var(--text-disabled);
    font-size: var(--font-size-2xs);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ── The worksheet grid ────────────────────────────────────────────────────────
   Tabular figures throughout, so a column of numbers lines up on the digit rather than
   ragging by glyph width. */
.pohv-table {
    margin-bottom: 0;
    font-size: var(--font-size-md);
    font-variant-numeric: tabular-nums;
}

/* Uppercase micro-caps on slate — the register .nwc-pane-title established for header rows.
   Replaces `background-color: deepskyblue`.
   ⚠ --slate-* is one of the Tailwind PRIMITIVES with NO [data-theme="dark"] override (verified
   against tokens.css's dark block), and that is exactly why it is right here: white on
   slate-700 is legible in BOTH themes, so this header never needs a dark counterpart.
   ⛔ Do not "fix" it to a --gray-* token — those invert in dark and the white text would land
   on near-white. position/top/z-index are load-bearing: the sticky header sticks against
   .pohv-table-container, which is the page's only scroll pane. */
.pohv-table thead th {
    position: sticky;
    top: 0;
    z-index: var(--z-base);
    background-color: var(--slate-700);
    color: var(--white);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
    white-space: nowrap;
    /* 2px, one notch over the hairline cell rule, so the header reads as a lid on the grid
       rather than as its first row. Border widths have no token. */
    border-bottom: 2px solid var(--slate-900);
}

/* Halved from `padding: 3px` all round, and softened from --nwc-border (gray-300) to a true
   hairline. Vertical padding is what a 500-cell season actually pays for. */
.pohv-table th,
.pohv-table td {
    padding: var(--space-3xs) var(--space-2xs);
    text-align: left;
    line-height: var(--line-height-tight);
    border: 1px solid var(--border-subtle);
}

/* Numeric columns align on the digit. */
.pohv-table .pohv-col-num {
    text-align: right;
}

.pohv-col-nowrap {
    white-space: nowrap;
}

.pohv-table .pohv-col-heater {
    text-align: center;
}

/* ⛔ Column sizing CANNOT use :nth-child() and the table must stay `table-layout: auto`. Six
   leading cells carry `rowspan`, so on the 2nd/3rd row of a lot's group those cells are ABSENT
   from the DOM and td:nth-child(1) is "Time Of Day", not "Date". Per-cell classes are the only
   mechanism that survives the rowspan.
   Comments gets a floor so it never collapses into a ribbon of one word per line. That floor
   is ALSO what reserves room for the inline editor: .pohv-cell-editor sets no width of its
   own, so the column cannot jump when an edit opens. Lower this and the editor starts shoving
   the grid — the two belong together. */
.pohv-col-comments {
    min-width: 18rem;
}

/* Rowspan cells centre against the lot's three slot rows. This is the single biggest thing
   that makes the group read as one block instead of six values stranded at the top of a tall
   box — the "align cleanly across the three slots" requirement, done structurally. */
.pohv-table .pohv-rowspan {
    vertical-align: middle;
}

/* ── Slot grouping ─────────────────────────────────────────────────────────────
   A lot's AM/MD/PM slots are three sibling <tr>s, not a nested table. Two devices make them
   read as one block: a heavier rule above the first row of each group, and an alternating
   band across the WHOLE group (⛔ never a per-row zebra — that would cut a group in half).
   Both are applied to the CELLS, not the <tr>: under `border-collapse: collapse` a row border
   of equal width loses to the cell border, and .pohv-table td already declares one. The
   rowspan cells belong to the group's FIRST row, so a class on every <tr> of the group bands
   the whole block including them. */
.pohv-table .pohv-group-first > td {
    border-top-width: 2px;
    border-top-color: var(--border-strong);
}

.pohv-table .pohv-group-cont > td {
    border-top-color: var(--border-subtle);
}

.pohv-table .pohv-group-alt > td {
    background-color: var(--pohv-row-alt);
}

/* Click-selection has to beat the band, and the band paints on the cell, so this must too. */
.pohv-highlight-row,
.pohv-table .pohv-highlight-row > td {
    background-color: var(--pumpover-highlight-row-bg) !important;
}

/* ── Sorting affordances ───────────────────────────────────────────────────────
   Scoped through `.pohv-table thead th` so the hover state actually beats the header rule. */
.pohv-sortable {
    cursor: pointer;
    user-select: none;
}

.pohv-table thead th.pohv-sortable:hover {
    background-color: var(--slate-600);
}

.pohv-sort-icon {
    margin-left: var(--space-2xs);
    cursor: pointer;
    opacity: 0.6;
}

.pohv-sort-icon:hover {
    opacity: 1;
}

/* ── Identity cells: tank, lot, owner ──────────────────────────────────────────
   The tank code and the lot number are the two things a cellar hand scans for, so they carry
   the only bold weight in the grid body; everything hanging off them is muted metadata. */
.pohv-tank-label {
    white-space: nowrap;
}

.pohv-tank-code {
    font-weight: var(--font-weight-semibold);
}

.pohv-tank-state {
    display: inline-flex;
    gap: var(--space-2xs);
    color: var(--text-muted);
    font-size: var(--font-size-2xs);
}

.pohv-lot-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2xs);
}

/* A link, not a button: it opens a panel. The Bootstrap .btn it used to be was 38px tall
   inside a cell whose whole row is now 21px. */
.pohv-lot-btn {
    padding: 0;
    border: 0;
    background: none;
    color: var(--text-link);
    font-family: inherit;
    font-size: var(--font-size-md);
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
    text-align: left;
    cursor: pointer;
}

.pohv-lot-btn:hover {
    text-decoration: underline;
}

.pohv-lot-btn:focus-visible {
    outline: none;
    border-radius: var(--radius-xs);
    box-shadow: var(--pohv-focus-ring);
}

.pohv-copy-icon {
    color: var(--text-disabled);
    cursor: pointer;
}

.pohv-copy-icon:hover {
    color: var(--text-primary);
}

.pohv-owner {
    padding-left: var(--space-2xs);
    color: var(--text-muted);
    font-size: var(--font-size-2xs);
    white-space: nowrap;
}

/* Fixed width so AM / MD / PM stack into a column instead of ragging by glyph width — the
   slot is a key, and keys should be scannable as a vertical strip. */
.pohv-slot {
    display: inline-block;
    min-width: 2.5rem;
    padding: 0 var(--space-2xs);
    border-radius: var(--radius-xs);
    background: var(--surface-emphasis);
    color: var(--text-secondary);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-wide);
    text-align: center;
    text-transform: uppercase;
}

/* An absent reading is a hole, not a value: quiet it so the eye skips to the real numbers. */
.pohv-nil {
    color: var(--text-disabled);
}

.pohv-heater-on {
    color: var(--state-danger-fg);
}

/* ── Comments column ───────────────────────────────────────────────────────────
   Three channels stacked (Cellar / Adds / NWC). The channel name is a quiet uppercase key and
   the instruction is the content — the reverse of the old bold-label-plus-plain-text, which
   made the labels louder than the words the cellar has to act on. */
.pohv-comment-line {
    margin-bottom: var(--space-3xs);
    line-height: var(--line-height-tight);
}

.pohv-comment-line > span {
    display: inline-block;
    min-width: 3rem;
    color: var(--text-muted);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
}

/* Production-winemaker affordances. Quiet until hovered — this is a dense daily worksheet,
   and three buttons per row shouting for attention would drown the instruction text they sit
   under. */
.pohv-cell-tools {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3xs);
    margin-top: var(--space-3xs);
    opacity: 0.5;
    transition: opacity var(--transition-fast);
}

tr:hover .pohv-cell-tools,
.pohv-cell-tools:focus-within {
    opacity: 1;
}

.pohv-cell-tool {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3xs);
    height: 18px;
    padding: 0 var(--space-2xs);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-xs);
    background: var(--surface-default);
    color: var(--text-secondary);
    font-family: inherit;
    font-size: var(--font-size-2xs);
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
}

.pohv-cell-tool:hover {
    background: var(--surface-muted);
    border-color: var(--border-strong);
    color: var(--text-primary);
}

.pohv-cell-tool:focus-visible {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: var(--pohv-focus-ring);
}

.pohv-cell-tool:disabled {
    opacity: 0.45;
    cursor: default;
}

/* Not yet stamped. Deliberately the QUIET half of the pair: on a live worksheet most cells are
   unstamped, so this is the background .is-done has to read against. */
.pohv-cell-tool.is-open {
    color: var(--text-muted);
}

/* Stamped. ⛔ ADDS WRITTEN and ADDS MADE are two DISTINCT events — the state is per button and
   there is deliberately no combined "done" look. */
.pohv-cell-tool.is-done {
    background: var(--state-success-bg);
    border-color: var(--state-success-fg);
    color: var(--state-success-fg);
    font-weight: var(--font-weight-semibold);
}

.pohv-cell-tool.is-done:hover {
    background: var(--state-success-bg);
    border-color: var(--state-success-fg);
    color: var(--state-success-fg);
}

/* ── Inline cell editor ────────────────────────────────────────────────────────
   Opens inside the Comments column. A precise single-column micro-grid: an eyebrow label over
   each field, both fields the same width, and the actions on a divided footer at the right
   where the eye expects Save.
   ⚠ It sets NO width of its own. .pohv-col-comments' 18rem floor is what reserves the space,
   so the editor physically cannot shove the column when it opens — the single worst behaviour
   of an in-cell form. ⛔ Do not give this a fixed width to "match" that floor: td is
   border-box, so a matching number is actually ~10px too wide and the column jumps anyway. */
.pohv-cell-editor {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-3xs);
    min-width: 0;
    max-width: 22rem;
    padding: var(--space-2xs);
    border: 1px solid var(--border-focus);
    border-radius: var(--radius-sm);
    background: var(--surface-default);
    box-shadow: var(--shadow-md);
}

.pohv-cell-label {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--font-size-2xs);
    font-weight: var(--font-weight-semibold);
    letter-spacing: var(--letter-spacing-wide);
    text-transform: uppercase;
}

.pohv-cell-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--space-2xs);
    margin-top: var(--space-3xs);
    padding-top: var(--space-2xs);
    border-top: 1px solid var(--border-subtle);
}

.pohv-cell-error {
    padding: var(--space-3xs) var(--space-2xs);
    border-radius: var(--radius-xs);
    background: var(--state-danger-bg);
    color: var(--state-danger-fg);
    font-size: var(--font-size-2xs);
    line-height: var(--line-height-tight);
}

/* ── PumpOverCellar worksheet (Pages/PumpOver/Print) ───────────────────────────
   The printed sheet the cellar crew carries. Faithful reproduction of the legacy
   Access report: landscape, one page per (time of day x series), hairline grid,
   and seven deliberately-blank handwriting columns.

   Global rather than .razor.css because print rules must survive Blazor's scope
   attribute rewriting AND apply to @page — a scoped stylesheet is the wrong tool
   for a paper document. po-sheet- prefix keeps it off every other surface. */

@page {
    size: letter landscape;
    margin: 0.4in;
}

.po-sheet-toolbar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--nwc-border, #ddd);
}

.po-sheet-source {
    font-size: 0.8rem;
    color: var(--nwc-text-muted, #6c757d);
}

.po-sheet-status {
    padding: 1.5rem 0.75rem;
    font-style: italic;
    color: var(--nwc-text-muted, #6c757d);
}

.po-sheet-error {
    color: #c00;
    font-style: normal;
    font-weight: 600;
}

.po-sheet-page {
    /* Every page but the last breaks after; the last must not, or browsers emit a
       trailing blank sheet. */
    break-after: page;
    padding: 0.25in 0 0 0;
}

.po-sheet-page:last-child {
    break-after: auto;
}

.po-sheet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 6px;
}

.po-sheet-head h1 {
    font-family: 'Segoe UI', Arial, sans-serif;
    font-size: 19pt;
    font-weight: 700;
    margin: 0;
    letter-spacing: 0.2px;
}

/* "sheet 2 of 3" — only rendered when a series needed more than one sheet.
   Deliberately quieter than the heading it trails: it is a disambiguator, not a
   thing to read first. */
.po-sheet-part {
    font-size: 11pt;
    font-weight: 600;
    margin-left: 0.4em;
}

/* The time-of-day colour band. print-color-adjust is REQUIRED — browsers strip
   background colours from print by default, and without it all three slots print
   as an identical white gap, which is exactly the distinction the band exists to
   make. Do not remove it to "clean up" the rule. */
.po-sheet-band {
    display: inline-block;
    width: 2.1in;
    height: 0.14in;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

.po-sheet-grid {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font-family: 'Segoe UI', Arial, sans-serif;
    font-size: 7.5pt;
}

/* Rows are chunked to PumpoverCellarSheetBuilder.RowsPerSheet so a page should never
   reach the fold — this is the belt-and-braces half. A row split across the fold puts
   the tank code on one sheet and the boxes the crew writes in on another, which is
   unusable and (unlike a missing page) not even obviously wrong at a glance. Both
   properties on purpose: `page-break-inside` is what older print engines honour. */
.po-sheet-grid tr {
    break-inside: avoid;
    page-break-inside: avoid;
}

.po-sheet-grid th,
.po-sheet-grid td {
    border: 1px solid #000;
    padding: 1px 2px;
    text-align: center;
    vertical-align: middle;
    overflow-wrap: break-word;
}

.po-sheet-grid th {
    font-weight: 600;
    vertical-align: bottom;
    line-height: 1.05;
}

/* Handwriting rows need vertical room for a pen, not just for the glyphs. */
.po-sheet-grid tbody td {
    height: 0.26in;
}

.po-sheet-blank td {
    height: 0.26in;
}

.po-sheet-grid .c-tank { width: 3.2%; }
.po-sheet-grid .c-lot { width: 11%; }
.po-sheet-grid .c-narrow { width: 2.9%; }
.po-sheet-grid .c-num { width: 3.6%; }
.po-sheet-grid .c-write { width: 4.2%; }
.po-sheet-grid .c-pump { width: 6.5%; }
.po-sheet-grid .c-check { width: 3%; line-height: 1; }
.po-sheet-grid .c-comments { width: 26%; }

/* Cell text left-aligns, but the HEADER stays centred like every other column —
   otherwise "Comments" floats away from the column it names. */
.po-sheet-grid td.c-comments { text-align: left; }

/* The action-flag box. Drawn here rather than typed as a glyph so it prints the
   same everywhere; see the Tick() remarks. */
.po-box {
    display: inline-block;
    width: 8pt;
    height: 8pt;
    line-height: 7.5pt;
    border: 1px solid #000;
    font-size: 8pt;
    text-align: center;
}

/* Set-point change flag. ⛔ Bold + boxed, NOT colour-coded: this sheet is printed on a
   monochrome laser and read in a dark cellar, so a colour-only signal is no signal at all.
   Kept on its own line under the number so a long "(was 82)" can never widen the column
   and push the handwriting columns off the page. */
.po-sp-alert {
    display: block;
    font-size: 6.5pt;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: 0.02em;
    border: 1px solid #000;
    padding: 0 1pt;
    margin-top: 1pt;
    white-space: nowrap;
}

.po-c-preload {
    font-weight: 700;
    text-transform: uppercase;
}

.po-c-line {
    display: flex;
    gap: 0.25em;
    align-items: baseline;
}

/* The label column is what keeps a dosing spec from reading as a cellar
   instruction — fixed width so both lines align and the eye can skip one. */
.po-c-tag {
    flex: 0 0 auto;
    min-width: 2.9em;
    font-weight: 700;
}

.po-sheet-foot {
    display: flex;
    justify-content: space-between;
    margin-top: 6px;
    font-family: 'Segoe UI', Arial, sans-serif;
    font-size: 8pt;
    color: #444;
}

@media print {
    .no-print { display: none !important; }

    .po-sheet-page { padding-top: 0; }
}

/* ── Scan-review fields (ScanField + badges) ─────────────────────────────────────────────────
   Hoisted from LabelScanPanel/ColaScanPanel/PermitScanPanel scoped css 2026-08-01: ScanField is a
   child component, so scoped rules only reached it via ::deep (or by accident); global is the
   correct home. Unified on the LabelScanPanel variant. */
.scan-field-label {
    font-size: 0.875rem;
    font-weight: var(--font-weight-medium);
    color: var(--gray-700);
    margin: 0;
}

.confidence-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2xs);
    font-size: var(--font-size-sm);
    padding: var(--space-3xs) var(--space-sm);
    border-radius: var(--radius-sm);
}

.confidence-badge.low {
    background-color: var(--yellow-100);
    color: var(--yellow-700);
}

.confidence-badge i {
    font-size: var(--font-size-xs);
}

.confidence-badge.medium {
    background-color: var(--blue-100);
    color: var(--blue-700, var(--blue-500));
}

.source-indicator {
    font-size: var(--font-size-xs);
    padding: 0.1rem 0.4rem;
    border-radius: var(--radius-xs);
    background: var(--blue-100);
    color: var(--blue-500);
    text-transform: capitalize;
}

/* ── Match-score strength bar + reason chips ─────────────────────────────────────────────────
   Shared by QuickReceiveScanPanel's confirm dialog and the WeightTagOrphans link dialog: the
   matcher's numeric score rendered as a bar + %, with each contributing signal as a chip.
   Global because it appears on 2+ surfaces (site rule: hoist, don't duplicate). */
.nwc-match-score {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    margin: var(--space-2xs) 0;
}

.nwc-match-score-track {
    flex: 1 1 auto;
    height: 8px;
    border-radius: 4px;
    background: var(--gray-200);
    overflow: hidden;
    min-width: 80px;
}

.nwc-match-score-fill {
    height: 100%;
    border-radius: 4px;
    background: var(--green-500, #2e7d32);
}

.nwc-match-score-label {
    font-size: var(--font-size-sm);
    font-weight: 600;
    white-space: nowrap;
}

.nwc-match-reasons {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
    margin-bottom: var(--space-2xs);
}

.nwc-match-reason-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3xs);
    font-size: var(--font-size-xs);
    padding: var(--space-3xs) var(--space-xs);
    border-radius: var(--radius-sm);
    background: var(--green-100, #e8f5e9);
    color: var(--green-700, #2e7d32);
}

/* ── Weight-tag scan review block (ReceiveFruitPanel) ────────────────────────────────────────
   Global on purpose: the block hosts ScanField children (see hoist note above). */
.nwc-scan-review {
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
    margin-top: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-md);
    background: var(--gray-50);
}

.nwc-scan-review-head {
    display: flex;
    align-items: center;
    gap: var(--space-2xs);
    color: var(--gray-700);
}

.nwc-scan-review-title {
    font-weight: var(--font-weight-medium);
}

.nwc-scan-review-meta {
    font-size: var(--font-size-sm);
    color: var(--gray-500);
}

.nwc-scan-review-headline {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2xs);
}

.nwc-scan-chip {
    font-size: var(--font-size-sm);
    padding: var(--space-3xs) var(--space-xs);
    border: 1px solid var(--gray-200);
    border-radius: var(--radius-sm);
    background: #fff;
    color: var(--gray-700);
    white-space: nowrap;
}

.nwc-scan-chip-ok {
    border-color: var(--green-100);
    background: var(--green-100);
    color: var(--green-700);
}

.nwc-scan-warning {
    display: flex;
    align-items: baseline;
    gap: var(--space-2xs);
    font-size: var(--font-size-sm);
    padding: var(--space-2xs) var(--space-sm);
    border-radius: var(--radius-sm);
    background: var(--yellow-100);
    color: var(--yellow-700);
}

/* Sticky document pane in a scan review split (scanned tag/doc beside the fields or verdict).
   Hoisted from ReceiveFruitPanel + QuickReceiveScanPanel, which held byte-identical copies —
   CSS isolation is per-component, so a shared shape has to live here to stay shared. The host
   panel owns the grid (column ratio differs by panel) and the frame height; this owns only the
   sticky behaviour, which is the part that must not drift.

   The collapse query is deliberately UNNAMED: it resolves to the nearest ancestor container,
   which is the host panel in both callers (.rf-panel / .qrs-panel). That keeps the rule
   caller-agnostic instead of hardcoding one panel's container name. */
.nwc-scan-split-doc {
    position: sticky;
    top: var(--space-xs);
    /* A positioned element paints above static siblings even with no z-index, so once the panel
       body scrolled, this pane covered the entry-form row above it — the Date input rendered over
       the Scan button (desktop, 2026-08-02). Pinning it to 0 keeps it BELOW the form controls,
       which claim var(--z-base) on their own container. Do not raise this.
       ⚠ The consumer must raise a SIBLING of this pane's wrapper, never an ANCESTOR of it — an
       ancestor creates a stacking context that contains the pane and lifts it along (that mistake
       made the first version of this fix inert on ReceiveFruitPanel). Canonical raised elements:
       .qrs-scan-control and .rf-entry-fields. */
    z-index: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
}

@container (max-width: 900px) {
    /* Narrow surfaces review by scrolling, not side-by-side: unstick and hoist the document
       above the fields. Callers collapse their own grid to one column at the same breakpoint. */
    .nwc-scan-split-doc {
        position: static;
        order: -1;
    }
}

.nwc-scan-review-toggle {
    align-self: flex-start;
    padding: 0;
}

.nwc-scan-review-section {
    margin-top: var(--space-2xs);
}

/* Explains the greyed (read-only) fields in the scan review grid — the ones the scan captured but
   HarvestActual has no column for, so a correction would be silently discarded. */
.nwc-scan-review-note {
    margin: 0 0 var(--space-2xs);
    font-size: 0.78rem;
    color: var(--text-muted);
}

.nwc-scan-review-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: var(--space-sm);
}

.nwc-scan-review-checks {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-md);
    margin-top: var(--space-2xs);
    font-size: var(--font-size-sm);
}

.nwc-scan-pill {
    display: inline-block;
    font-size: var(--font-size-xs);
    line-height: 1.4;
    padding: 0 0.35rem;
    border-radius: var(--radius-xs);
    background: var(--blue-100);
    color: var(--blue-500);
    vertical-align: text-bottom;
}
