/* =========================================================================
   Diamond Offer Sheets — application shell stylesheet
   Keep this file lean. Component-level styling should come from the
   Syncfusion bootstrap5.3 theme. Only the shell + page primitives live here.
   ========================================================================= */

.auth-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    color: #6b7a90;
    font-size: 0.95rem;
}

:root {
    color-scheme: light;

    /* Surface */
    --surface-page:       #f5f7fb;
    --surface-card:       #ffffff;
    --surface-sunken:     #eef2f7;
    --surface-overlay:    rgba(15, 23, 42, 0.04);

    /* Ink */
    --ink-strong:         #0f172a;
    --ink:                #1e293b;
    --ink-muted:          #64748b;
    --ink-faint:          #94a3b8;
    --on-dark:            #e2e8f0;
    --on-dark-muted:      #94a3b8;

    /* Brand / accents */
    --brand:              #0b2545;
    --brand-deep:         #061734;
    --brand-accent:       #2563eb;
    --brand-accent-soft:  #dbeafe;

    /* Status */
    --ok:                 #047857;
    --ok-soft:            #d1fae5;
    --warn:               #b45309;
    --warn-soft:          #fef3c7;
    --danger:             #b91c1c;
    --danger-soft:        #fee2e2;
    --info:               #1d4ed8;
    --info-soft:          #dbeafe;
    --ready:              #7c3aed;
    --ready-soft:         #ede9fe;

    /* Lines + elevation */
    --line:               #e2e8f0;
    --line-strong:        #cbd5e1;
    --shadow-sm:          0 1px 2px rgba(15, 23, 42, 0.05);
    --shadow-md:          0 4px 12px rgba(15, 23, 42, 0.06);
    --shadow-lg:          0 18px 38px rgba(15, 23, 42, 0.10);

    /* Geometry */
    --radius-sm: 6px;
    --radius:    10px;
    --radius-lg: 14px;

    --sidebar-w:  248px;
    --topbar-h:   60px;
}

* { box-sizing: border-box; }

html, body {
    height: 100%;
    margin: 0;
    color: var(--ink);
    background: var(--surface-page);
    font-family: "Inter", "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
    font-size: 14px;
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, p { margin: 0; }
h1 { font-size: 1.4rem;  font-weight: 600; letter-spacing: -0.01em; color: var(--ink-strong); }
h2 { font-size: 1rem;    font-weight: 600; color: var(--ink-strong); }
h3 { font-size: 0.875rem; font-weight: 600; color: var(--ink); text-transform: uppercase; letter-spacing: 0.04em; }

a { color: var(--brand-accent); text-decoration: none; }
a:hover { text-decoration: underline; }

code { font-family: "JetBrains Mono", Consolas, monospace; font-size: 0.85em; color: var(--brand-accent); }

/* =========================================================================
   App shell
   ========================================================================= */

.app-shell {
    display: grid;
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
    height: 100vh;
    overflow: hidden;
}

/* ---------- Sidebar ---------- */

.sidebar {
    background: linear-gradient(180deg, var(--brand) 0%, var(--brand-deep) 100%);
    color: var(--on-dark);
    display: flex;
    flex-direction: column;
    border-right: 1px solid rgba(0, 0, 0, 0.2);
}

.brand-block {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 18px 20px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.brand-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
}

.brand-name {
    font-size: 0.95rem; font-weight: 600; color: #fff;
    letter-spacing: 0.01em;
    line-height: 1.2;
}

.brand-subtitle {
    font-size: 0.72rem;
    color: var(--on-dark-muted);
    text-transform: uppercase;
    letter-spacing: 0.08em;
    margin-top: 1px;
    line-height: 1.2;
}

.nav-stack {
    display: flex; flex-direction: column;
    padding: 14px 12px;
    gap: 2px;
    flex: 1;
    overflow-y: auto;
    /* Pin items to the top — without this some browsers' default
       align-content stretches column-flex children vertically when the
       container has spare space. */
    justify-content: flex-start;
    align-content: flex-start;
}

.nav-stack .nav-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    color: var(--on-dark);
    font-weight: 500;
    font-size: 0.875rem;
    cursor: pointer;
    transition: background-color 120ms ease, color 120ms ease;
    text-decoration: none;
    /* Lock the row to a content-driven fixed height. flex:0 0 auto means
       don't grow, don't shrink, basis = auto. Without this the row would
       stretch to fill the column-flex parent on tall sidebars. */
    flex: 0 0 auto;
    min-height: 48px;
}

.nav-stack .nav-item:hover {
    background: rgba(255, 255, 255, 0.06);
    color: #fff;
    text-decoration: none;
}

.nav-stack .nav-item.active {
    background: rgba(59, 130, 246, 0.18);
    color: #fff;
    box-shadow: inset 2px 0 0 #60a5fa;
}

/* Active row: keep the title/caption text colors as they were, but flip just
   the icon to dark. The SVG inherits via fill="currentColor", so overriding
   the color on the .nav-icon element alone affects only the icon line art. */
.nav-stack .nav-item.active .nav-icon {
    color: var(--ink-strong);
}

/* Sidebar nav icon. We use <i class="bi bi-…"> from Bootstrap Icons (loaded
   via CDN in index.html). The .bi class sets font-family + line-height; we
   only need to size and color the container. inline-flex with center
   alignment is the conventional pattern for icon spans and avoids the grid
   layout quirks I hit with the Syncfusion e-icons font. */
.nav-item .nav-icon {
    width: 20px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    color: inherit;
    opacity: 0.85;
    line-height: 1;
}

.nav-item.active .nav-icon { opacity: 1; }

.nav-item .nav-text {
    display: flex; flex-direction: column; min-width: 0;
}

.nav-title {
    font-weight: 500;
    font-size: 0.875rem;
    line-height: 1.2;
}

/* Caption colors use !important to defeat any higher-specificity rule from
   the Syncfusion bootstrap5.3 theme that's been overriding them silently.
   Once we've confirmed the styling visibly changes between inactive/active,
   we can investigate which third-party rule was winning and remove these. */
.nav-stack .nav-item .nav-caption {
    color: var(--on-dark-muted) !important;
    font-size: 0.72rem;
    margin-top: 1px;
    opacity: 0.75 !important;
    font-weight: 400;
    transition: opacity 120ms ease, color 120ms ease, font-weight 120ms ease;
}

.nav-stack .nav-item.active .nav-caption {
    color: #fff !important;
    opacity: 1 !important;
    font-weight: 500 !important;
}

/* Sidebar group label — small uppercase divider above a cluster of nav items. */
.nav-stack .nav-section {
    padding: 16px 14px 5px;
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--on-dark-muted);
    opacity: 0.7;
}
.nav-stack .nav-section:first-child { padding-top: 4px; }

.nav-footer {
    padding: 14px 20px 18px;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
    color: var(--on-dark-muted);
    font-size: 0.72rem;
}

.nav-footer .small-label {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.65rem;
    color: var(--on-dark-muted);
    margin-bottom: 4px;
}

.nav-footer .storage-line { color: #cbd5e1; }
.nav-footer .storage-line.muted { color: var(--on-dark-muted); }

/* ---------- Main column ---------- */

.workspace {
    display: grid;
    grid-template-rows: var(--topbar-h) minmax(0, 1fr);
    min-width: 0;
    min-height: 0;
    height: 100%;
    overflow: hidden;
    background: var(--surface-page);
    /* Positioned ancestor so .app-busy-overlay (position:absolute) fills only
       the content area, leaving the sidebar/navbar uncovered. */
    position: relative;
}

.topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 0 28px;
    background: var(--surface-card);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-sm);
}

.topbar-title {
    display: flex; flex-direction: column; min-width: 0;
}

.topbar-title h1 { font-size: 1.15rem; }
.topbar-title p  { color: var(--ink-muted); font-size: 0.8rem; margin-top: 2px; }

.topbar-actions {
    display: flex; align-items: center; gap: 8px;
    flex-wrap: nowrap;
}

.page {
    padding: 24px 28px;
    overflow-y: auto;
    min-height: 0;
}

.page.no-scroll {
    overflow: hidden;
    padding-bottom: 0;
}

.page.flex-page {
    display: flex; flex-direction: column;
    gap: 16px;
    padding-bottom: 28px;
}

/* =========================================================================
   Reusable surface primitives
   ========================================================================= */

.card-surface {
    background: var(--surface-card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
}

.card-pad     { padding: 18px 20px; }
.card-pad-sm  { padding: 12px 16px; }

.toolbar {
    display: flex;
    align-items: end;
    justify-content: space-between;
    gap: 16px;
    background: var(--surface-card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 14px 16px;
    box-shadow: var(--shadow-sm);
}

.toolbar .filters {
    display: grid;
    /* Search column takes ~2x the width of each dropdown; the other columns
       auto-flow horizontally and never wrap. minmax(0, 1fr) lets them shrink
       below their content width on narrow viewports instead of pushing onto
       a second row. */
    grid-template-columns: 2fr repeat(auto-fit, minmax(0, 1fr));
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 10px;
    flex: 1;
    min-width: 0;
}

.field {
    display: flex; flex-direction: column; gap: 4px;
    min-width: 0;
}

.field-label {
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--ink-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

/* Workspace = page hero header */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
}

.page-header h1 { font-size: 1.5rem; }
.page-header p  { color: var(--ink-muted); margin-top: 4px; font-size: 0.875rem; max-width: 64ch; }

.page-actions {
    display: flex; gap: 8px; align-items: center;
}

/* Two-pane workbench (source preview + parsed grid).

   The splitter sits inside a positioned host and fills it absolutely. This is
   the reliable way to give a Syncfusion splitter a definite pixel height in a
   flex column: a flex-derived height alone leaves the splitter (and therefore
   its panes and the SfGrid inside, which is Height="100%") unable to resolve a
   height, so the grid falls back to its natural 20-row size and pushes the pane
   footer (the Save / Delete buttons) below the fold on shorter viewports. The
   host is the flex:1 child; inset:0 pins the splitter to the host's measured
   box. */
.workbench-host {
    flex: 1;
    min-height: 0;
    position: relative;
}

.workbench {
    position: absolute;
    inset: 0;
    border: 0;
    background: transparent;
}

.workbench.e-splitter.e-splitter-horizontal {
    border: 0;
}

.workbench .e-pane,
.designer-split .e-pane {
    min-height: 0;
    overflow: hidden;
    /* Flex column so the child .pane (height:100%) reliably fills the pane's
       measured height across browsers — keeps the pane footer (action buttons)
       pinned and visible instead of being pushed below the fold. Without this,
       a child SfSpreadsheet with Height="100%" collapses to 0px and renders
       invisibly (the Mapping Designer hit exactly that). */
    display: flex;
    flex-direction: column;
}

.workbench .e-pane > .pane,
.designer-split .e-pane > .pane {
    flex: 1;
    min-height: 0;
}

.workbench-page {
    position: relative;
}

/* Transient status messages — a toast pinned to the very top of the viewport.
   position:fixed keeps it above all content and out of layout flow, so nothing
   gets pushed down. No left color bar — status is conveyed by the soft
   background tint alone. Any page can render a .app-toast. */
.app-toast {
    position: fixed;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1000;
    max-width: min(680px, calc(100vw - 32px));
    margin: 0;
    padding: 10px 16px;
    border-radius: var(--radius-sm);
    background: var(--info-soft);
    color: #1e3a8a;
    font-size: 0.82rem;
    line-height: 1.3;
    box-shadow: var(--shadow-lg);
    display: inline-flex;
    align-items: center;
    gap: 12px;
    text-align: left;
}

/* Stack wrapper (AppToastHost): owns the fixed top-center positioning so
   multiple simultaneous toasts pile vertically instead of overlapping. Toasts
   inside it drop their own fixed positioning; a bare .app-toast rendered
   directly by a page keeps the legacy single-toast behavior. */
.app-toast-stack {
    position: fixed;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1000;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    max-width: min(680px, calc(100vw - 32px));
}

.app-toast-stack .app-toast {
    position: static;
    transform: none;
    max-width: 100%;
}

/* Inline page-level load failure with a retry action (e.g. the library's
   initial fetch failing while the relay-fronted API warms up). */
.load-error-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 14px;
    margin-bottom: 12px;
    border: 1px solid color-mix(in srgb, var(--danger) 34%, var(--line));
    border-radius: 8px;
    background: var(--danger-soft);
    color: #7f1d1d;
}

.app-toast.danger { background: var(--danger-soft); color: #7f1d1d; }
.app-toast.info   { background: var(--info-soft);   color: #1e3a8a; }
.app-toast.ok     { background: var(--ok-soft);     color: #064e3b; }
.app-toast.warn   { background: var(--warn-soft);   color: #78350f; }

.app-toast-close {
    width: 24px;
    height: 24px;
    flex: 0 0 24px;
    display: inline-grid;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: currentColor;
    cursor: pointer;
    opacity: 0.72;
}

.app-toast-close:hover,
.app-toast-close:focus-visible {
    opacity: 1;
    background: rgba(255, 255, 255, 0.5);
    outline: none;
}

.pane {
    display: flex; flex-direction: column;
    background: var(--surface-card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

.pane-header {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--line);
    background: linear-gradient(180deg, #fbfcfe 0%, #f5f7fb 100%);
}

.pane-header-wrap {
    align-items: flex-end;
    flex-wrap: wrap;
}

.parsed-rows-header {
    display: grid;
    grid-template-columns: minmax(260px, 1fr) auto;
    align-items: center;
}

.pane-header h2 { font-size: 0.95rem; }
.pane-header .pane-sub { color: var(--ink-muted); font-size: 0.78rem; }

.pane-body {
    flex: 1;
    min-height: 0;
    overflow: hidden;
    position: relative;
}

.pane-body.padded { padding: 14px 18px; overflow: auto; }

.pane-footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    padding: 10px 14px;
    border-top: 1px solid var(--line);
    background: #fbfcfe;
}

.workbench-grid-primary-tools {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex-wrap: nowrap;
}

.parsed-rows-header > .topbar-actions {
    justify-content: flex-end;
}

/* Lost-sales workbench grid header. Its toolbar keeps local row filters in the
   panel header, so it uses a wrapping flex row instead of the offer Workbench's
   compact two-column parsed-rows header. */
.lost-sales-rows-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 14px;
}

.lost-sales-rows-header > div:first-child {
    flex: 1 1 240px;
    min-width: 200px;
}

.lost-sales-rows-header > .topbar-actions {
    margin-left: auto;
}

.template-picker {
    display: flex;
    align-items: center;
    gap: 8px;
    width: min(280px, 100%);
}

.template-picker > .metric-label { flex: 0 0 auto; white-space: nowrap; }
.template-picker > .e-ddl { flex: 1 1 auto; min-width: 0; }

/* Inline template switcher: top-ranked templates as toggle buttons. The active
   (currently-applied) one renders as e-primary; the rest as e-outline. */
.template-toggle-group {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    min-width: 0;
}

/* On-demand workbook loader — shown in the Source Workbook pane until the user
   clicks "Load workbook" so the page opens without waiting on the blob. */
.workbook-load-prompt {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 32px;
    text-align: center;
    color: var(--ink-muted);
}

.workbook-load-prompt strong { color: var(--ink-strong); }
.workbook-load-prompt span { max-width: 36ch; font-size: 0.85rem; }
.workbook-load-prompt .e-btn { margin-top: 6px; }

/* Library / Workbench: detail rail.
   grid-template-rows: minmax(0, 1fr) pins both children (the data grid pane
   and the rail) to the height of the container instead of letting tall rail
   content stretch the row and push the data grid out of view. */
.content-with-rail {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    grid-template-rows: minmax(0, 1fr);
    gap: 16px;
    flex: 1;
    min-height: 0;
}

/* Rail scrolls internally when its cards exceed the available height instead
   of pushing the parent. min-height: 0 is required so the flex/grid child
   can actually shrink below its content size. */
.rail {
    display: flex; flex-direction: column;
    gap: 16px;
    min-height: 0;
    overflow-y: auto;
}

/* Mapping designer 2-col layout */
.designer-grid {
    display: grid;
    grid-template-columns: 320px minmax(0, 1fr);
    gap: 16px;
    flex: 1;
    min-height: 0;
}

/* Workbook loading overlay — sits on top of SfSpreadsheet while it mounts. */
.workbook-loading-overlay {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 10px;
    background: linear-gradient(180deg, #fbfcfe 0%, #f5f7fb 100%);
    color: var(--ink-muted);
    text-align: center;
    padding: 32px;
    animation: workbook-overlay-fade 250ms ease-in;
}

.workbook-loading-overlay strong { color: var(--ink-strong); font-size: 1rem; }
.workbook-loading-overlay span   { font-size: 0.85rem; max-width: 38ch; }

.workbench-operation-overlay {
    position: absolute;
    inset: 0;
    z-index: 6;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 10px;
    background: rgba(251, 252, 254, 0.88);
    color: var(--ink-muted);
    text-align: center;
    padding: 32px;
    backdrop-filter: blur(2px);
    animation: workbook-overlay-fade 180ms ease-in;
}

.workbench-operation-overlay strong { color: var(--ink-strong); font-size: 1rem; }
.workbench-operation-overlay span   { font-size: 0.85rem; max-width: 42ch; }

/* Full-screen busy overlay — shown only when an action (e.g. sending an
   email) lags after its modal has already closed. */
.app-busy-overlay {
    /* Scoped to .workspace (its positioned ancestor) so the spinner covers the
       page content but not the sidebar — clicking a nav item no longer makes
       the navbar appear to flash/reload. */
    position: absolute;
    inset: 0;
    z-index: 2000;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 10px;
    background: rgba(251, 252, 254, 0.78);
    color: var(--ink-muted);
    text-align: center;
    padding: 32px;
    backdrop-filter: blur(2px);
    animation: workbook-overlay-fade 180ms ease-in;
}

.app-busy-overlay strong { color: var(--ink-strong); font-size: 1rem; }
.app-busy-overlay span   { font-size: 0.85rem; max-width: 42ch; }

.boot-spinner-wrap { width: 48px; height: 48px; }

@keyframes workbook-overlay-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Email-request dialog: flex footer so a left-aligned note can sit vertically
   centered beside the right-aligned Cancel/Send buttons. */
.email-request-dialog .e-footer-content {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}

.email-request-dialog .e-footer-content .footer-note {
    margin-right: auto;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    text-align: left;
}

/* =========================================================================
   Pills / badges / metrics
   ========================================================================= */

.status-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    /* Outline in the pill's own hue so the chip keeps definition even when it
       sits on a row tinted the same soft color (e.g. a "No cost" danger pill on
       a no-cost row's danger wash). currentColor = the per-variant text color. */
    border: 1px solid color-mix(in srgb, currentColor 40%, transparent);
}

.status-pill.ok       { color: var(--ok);      background: var(--ok-soft); }
.status-pill.warn     { color: var(--warn);    background: var(--warn-soft); }
.status-pill.danger   { color: var(--danger);  background: var(--danger-soft); }
.status-pill.info     { color: var(--info);    background: var(--info-soft); }
.status-pill.ready    { color: var(--ready);   background: var(--ready-soft); }
.status-pill.neutral  { color: var(--ink-muted); background: var(--surface-sunken); }

/* A status-pill that doubles as a one-click status filter (e.g. the Lost Sales
   workbench File panel). Resets the <button> chrome the chip doesn't want and
   adds hover/selected affordances; the active chip keeps full strength while
   the rest dim back so the chosen filter reads at a glance. */
.filter-pill {
    font-family: inherit;
    appearance: none;
    cursor: pointer;
    opacity: 0.72;
    transition: opacity .12s ease, box-shadow .12s ease, transform .12s ease;
}
.filter-pill:hover     { opacity: 1; transform: translateY(-1px); }
.filter-pill.is-active {
    opacity: 1;
    box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 55%, transparent);
}

.workbench-status-filters {
    margin-left: auto;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    flex: 1 1 420px;
    min-width: min(100%, 320px);
    flex-wrap: wrap;
}

.metric-row {
    display: flex; justify-content: space-between; align-items: center;
    padding: 10px 0;
    border-bottom: 1px dashed var(--line);
}

.metric-row:last-child { border-bottom: 0; }
.metric-row .metric-label { color: var(--ink-muted); font-size: 0.82rem; }
.metric-row .metric-value { font-weight: 600; color: var(--ink-strong); font-variant-numeric: tabular-nums; }

/* Workbench header meta fields — small uppercase label stacked above its value,
   matching the "File" item so Vendor/Region/Brand/Effective align with it. */
.wb-meta-label { font-size: 0.72rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; }
.wb-meta-value { font-weight: 600; color: var(--ink-strong); }

/* Brand grid cell — value plus a small info/warn icon that explains an alias
   mapping or an unresolved brand. The icon carries a native title tooltip. */
.wb-brand-cell { display: inline-flex; align-items: center; gap: 6px; }
.wb-brand-info,
.wb-brand-warn { font-size: 0.9rem; cursor: help; }
.wb-brand-info { color: var(--brand-accent); }
.wb-brand-warn { color: var(--danger, #c00); }
.wb-brand-unresolved-text { color: var(--danger, #c00); font-style: italic; }

/* Status grid cell — the pill plus a small pencil affordance that opens the
   row editor (or the UPC picker for Multiple Matches). The pencil only appears
   for editable rows, so the column stays quiet for already-clean rows. */
.wb-status-cell { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; }
.wb-row-edit {
    border: none;
    background: transparent;
    color: var(--ink-muted);
    cursor: pointer;
    padding: 2px;
    line-height: 1;
    border-radius: 4px;
    display: inline-flex;
}
.wb-row-edit:hover { color: var(--brand-accent); background: var(--surface-sunken); }

/* Edit-row modal — a compact stacked form. Two-up rows for the short fields,
   a separated Diamond-UPC mapping row, and a live saveability hint. */
.wb-edit-form { display: flex; flex-direction: column; gap: 12px; }
.wb-edit-readonly { display: flex; gap: 24px; }
.wb-edit-field { display: flex; flex-direction: column; gap: 4px; }
.wb-edit-field > span { font-size: 0.74rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.05em; }
.wb-edit-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.wb-edit-price-note { font-size: 0.76rem; color: var(--ink-muted); margin-top: -6px; }
.wb-edit-upc {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border, #e3e3e3);
    border-radius: 6px;
    background: var(--surface-sunken);
}
.wb-edit-hint {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.82rem;
    padding: 8px 10px;
    border-radius: 6px;
}
.wb-edit-hint.ok { color: var(--ok-strong, #1a7f37); background: var(--ok-soft, rgba(26,127,55,0.08)); }
.wb-edit-hint.warn { color: var(--warn-strong, #8a6d00); background: var(--warn-soft, rgba(184,134,11,0.1)); }

.metric-tiles {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
}

.metric-tile {
    background: var(--surface-sunken);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    text-align: center;
}

.metric-tile .v { font-size: 1.25rem; font-weight: 700; color: var(--ink-strong); font-variant-numeric: tabular-nums; }
.metric-tile .l { font-size: 0.7rem;  color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 2px; }

/* Detail list */
.detail-list { display: grid; gap: 10px; margin: 0; }
.detail-list dt { font-size: 0.7rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.detail-list dd { margin: 2px 0 0; font-size: 0.86rem; color: var(--ink); overflow-wrap: anywhere; }

/* Drag-and-drop target */
.drop-zone {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 6px;
    padding: 22px;
    border: 1.5px dashed var(--line-strong);
    border-radius: var(--radius);
    background: var(--surface-sunken);
    color: var(--ink-muted);
    text-align: center;
    transition: border-color 120ms ease, background-color 120ms ease;
}

.drop-zone.is-hover {
    border-color: var(--brand-accent);
    background: var(--brand-accent-soft);
    color: var(--ink);
}

.drop-zone strong { color: var(--ink-strong); font-size: 0.95rem; }
.drop-zone span   { font-size: 0.8rem; }

/* Template cards (Mapping page) */
.template-list { display: flex; flex-direction: column; gap: 8px; padding: 14px; overflow-y: auto; }
.template-card {
    display: flex; flex-direction: column; gap: 4px;
    padding: 12px 14px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
    background: var(--surface-card);
    cursor: pointer;
    transition: all 120ms ease;
    text-align: left;
}

.template-card:hover {
    border-color: var(--line-strong);
    box-shadow: var(--shadow-sm);
}

.template-card.is-active {
    border-color: var(--brand-accent);
    background: var(--brand-accent-soft);
    box-shadow: var(--shadow-sm);
}

.template-card .t-name { font-weight: 600; color: var(--ink-strong); font-size: 0.9rem; }
.template-card .t-meta { color: var(--ink-muted); font-size: 0.78rem; }

/* Compact grid row actions */
.grid-row-actions {
    display: flex;
    gap: 6px;
    align-items: center;
}

.grid-action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    min-height: 28px;
    padding: 5px 9px;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface-card);
    color: var(--ink);
    font-size: 0.76rem;
    font-weight: 400;
    line-height: 1;
    cursor: pointer;
    transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
}

.grid-action svg {
    flex: 0 0 auto;
}

.grid-action:hover {
    box-shadow: var(--shadow-sm);
}

.grid-action--open {
    border-color: var(--brand-accent);
    background: var(--brand-accent);
    color: #fff;
}

.grid-action--open:hover {
    border-color: #1d4ed8;
    background: #1d4ed8;
    color: #fff;
    box-shadow: 0 2px 6px rgba(37, 99, 235, 0.28);
}

.grid-action--edit {
    border-color: color-mix(in srgb, var(--info) 34%, var(--line));
    background: var(--info-soft);
    color: #1e3a8a;
}

.grid-action--edit:hover {
    border-color: var(--info);
    background: color-mix(in srgb, var(--info-soft) 72%, white);
}

.grid-action--archive {
    border-color: color-mix(in srgb, var(--warn) 36%, var(--line));
    background: var(--warn-soft);
    color: #78350f;
}

.grid-action--archive:hover {
    border-color: var(--warn);
    background: color-mix(in srgb, var(--warn-soft) 72%, white);
}

.grid-action--delete {
    border-color: color-mix(in srgb, var(--danger) 34%, var(--line));
    background: var(--danger-soft);
    color: #7f1d1d;
}

.grid-action--delete:hover {
    border-color: var(--danger);
    background: color-mix(in srgb, var(--danger-soft) 72%, white);
}

/* Empty / placeholder states */
.empty-state {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 8px;
    padding: 48px 24px;
    color: var(--ink-muted);
    text-align: center;
}

.empty-state .icon { font-size: 2rem; opacity: 0.6; }
.empty-state strong { color: var(--ink-strong); font-size: 1rem; }

/* Validation strip */
.validation-strip {
    margin: 0 18px 18px;
    padding: 10px 14px;
    border-left: 3px solid var(--warn);
    border-radius: var(--radius-sm);
    background: var(--warn-soft);
    color: #78350f;
    font-size: 0.82rem;
}

.validation-strip.danger { border-left-color: var(--danger); background: var(--danger-soft); color: #7f1d1d; }
.validation-strip.info   { border-left-color: var(--info);   background: var(--info-soft);   color: #1e3a8a; }
.validation-strip.ok     { border-left-color: var(--ok);     background: var(--ok-soft);     color: #064e3b; }

/* =========================================================================
   Syncfusion theme touch-ups
   Tiny nudges so SF components blend with the shell.
   ========================================================================= */

.e-grid {
    border: 1px solid var(--line) !important;
    border-radius: var(--radius-sm) !important;
    overflow: hidden;
}

.e-grid .e-headercell,
.e-grid .e-detailheadercell {
    background: var(--surface-sunken) !important;
    color: var(--ink) !important;
    font-weight: 600 !important;
    font-size: 0.78rem !important;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.e-grid .e-rowcell { font-size: 0.85rem; }
.e-grid .e-row:hover .e-rowcell { background: var(--surface-sunken) !important; }

.e-btn.e-primary {
    background-color: var(--brand-accent);
    border-color: var(--brand-accent);
}

.e-btn.e-primary:hover {
    background-color: #1d4ed8;
    border-color: #1d4ed8;
}

.e-btn.e-outline {
    color: var(--ink);
    border-color: var(--line-strong);
}

/* =========================================================================
   Boot screen + error overlay
   ========================================================================= */

.app-boot {
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 12px;
    height: 100vh;
    background: var(--surface-page);
    color: var(--ink-muted);
    font-size: 0.85rem;
}

.boot-spinner { width: 44px; height: 44px; }
.boot-spinner circle {
    fill: none;
    stroke: var(--line);
    stroke-width: 4;
    transform-origin: 50% 50%;
    transform: rotate(-90deg);
}

.boot-spinner circle:last-child {
    stroke: var(--brand-accent);
    stroke-dasharray: 70, 200;
    stroke-linecap: round;
    animation: boot-spin 1.1s linear infinite;
}

@keyframes boot-spin {
    to { transform: rotate(270deg); }
}

#blazor-error-ui {
    background: #fff7ed;
    color: #7c2d12;
    border-top: 2px solid #f97316;
    bottom: 0;
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 12px 20px;
    position: fixed;
    width: 100%;
    z-index: 1000;
    font-size: 0.85rem;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 12px;
    top: 8px;
    font-size: 1.2rem;
}

#blazor-error-ui a.reload { margin: 0 8px; }

/* =========================================================================
   Responsive
   ========================================================================= */

@media (max-width: 1200px) {
    .content-with-rail { grid-template-columns: 1fr; }
}

@media (max-width: 920px) {
    .app-shell { grid-template-columns: 1fr; }
    .sidebar   { display: none; }
    .workbench { grid-template-columns: 1fr; }
    .designer-grid { grid-template-columns: 1fr; }
    .toolbar   { flex-direction: column; align-items: stretch; }
    .toolbar .filters {
        grid-template-columns: 1fr;
        grid-auto-flow: row;
        grid-auto-columns: auto;
    }
    .metric-tiles { grid-template-columns: 1fr 1fr 1fr; }
}

/* ---------------------------------------------------------------- */
/* Template Preview Lab — slide-out panel from the right edge.      */
/* ---------------------------------------------------------------- */

.preview-lab-scrim {
    position: fixed; inset: 0;
    background: rgba(15, 23, 42, 0.42);
    z-index: 1099;
    animation: fadeIn 120ms ease-out;
}
.preview-lab {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(960px, 90vw);
    background: #fff;
    box-shadow: -16px 0 40px rgba(15, 23, 42, 0.18);
    z-index: 1100;
    display: grid;
    grid-template-rows: auto 1fr auto;
    animation: slideInRight 180ms ease-out;
}
@keyframes slideInRight { from { transform: translateX(100%); } to { transform: translateX(0); } }
@keyframes fadeIn       { from { opacity: 0; }                  to { opacity: 1; } }

.preview-lab-head {
    padding: 18px 22px;
    border-bottom: 1px solid var(--line);
    display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
}

.preview-lab-body {
    display: grid;
    grid-template-columns: 280px 1fr;
    min-height: 0;
    overflow: hidden;
}

.preview-lab-list {
    border-right: 1px solid var(--line);
    overflow-y: auto;
    padding: 12px;
    background: #f8fafc;
}
.preview-lab-list-head {
    font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--ink-muted); padding: 6px 8px 10px;
}

/* Wrapping grid for template tiles inside the upload Preview modal —
   auto-fills 240–320px columns so every eligible template is visible at
   once, no horizontal scroll. Each tile still spans its own grid cell. */
.preview-tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 10px;
}

.preview-tile {
    display: block; width: 100%; text-align: left;
    padding: 12px 14px; margin-bottom: 8px;
    background: #fff; border: 1px solid var(--line);
    border-radius: 10px; cursor: pointer;
    transition: border-color 120ms, box-shadow 120ms, transform 120ms;
}
.preview-tile:hover {
    border-color: var(--brand-accent);
    transform: translateY(-1px);
    box-shadow: 0 6px 14px -8px rgba(37, 99, 235, 0.35);
}
.preview-tile.is-focused {
    border-color: var(--brand-accent);
    background: var(--brand-accent-soft);
    box-shadow: 0 8px 18px -10px rgba(37, 99, 235, 0.5);
}
.preview-tile-head {
    display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
    margin-bottom: 6px;
}
.preview-tile-name { font-size: 0.92rem; color: var(--ink); }
.preview-tile-score {
    font-family: "JetBrains Mono", Consolas, monospace;
    font-size: 0.78rem; color: var(--brand-accent);
    background: #fff; border: 1px solid var(--line);
    border-radius: 999px; padding: 1px 8px;
}
.preview-tile-badges {
    display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
    font-size: 0.7rem;
}
.preview-tile-meta { color: var(--ink-muted); font-size: 0.7rem; }

.preview-lab-detail {
    padding: 18px 22px;
    overflow-y: auto;
    min-height: 0;
}
.preview-detail-head { margin-bottom: 14px; }

.preview-counts {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    margin-bottom: 18px;
}
.preview-count {
    background: #f8fafc; border: 1px solid var(--line); border-radius: 10px;
    padding: 10px 12px; text-align: center;
}
.preview-count.ok     { background: #ecfdf5; border-color: #a7f3d0; }
.preview-count.warn   { background: #fffbeb; border-color: #fde68a; }
.preview-count.danger { background: #fef2f2; border-color: #fecaca; }
.preview-count-num   { font-size: 1.5rem; font-weight: 700; color: var(--ink); }
.preview-count-label { font-size: 0.72rem; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.06em; }

.preview-section-head {
    font-size: 0.74rem; letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--ink-muted); margin: 14px 0 8px;
}
.preview-sample-wrap { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.preview-explain {
    font-size: 0.85rem; color: var(--ink);
    background: #f8fafc; border: 1px solid var(--line); border-radius: 8px;
    padding: 10px 12px;
}
.preview-warnings {
    margin: 0; padding-left: 20px;
    font-size: 0.82rem; color: var(--ink);
}
.preview-warnings li { margin: 2px 0; }

.preview-lab-foot {
    padding: 14px 22px;
    border-top: 1px solid var(--line);
    background: #f8fafc;
    display: flex; justify-content: space-between; align-items: center; gap: 12px;
}

@media (max-width: 900px) {
    .preview-lab-body { grid-template-columns: 1fr; }
    .preview-lab-list { border-right: none; border-bottom: 1px solid var(--line); max-height: 36vh; }
}
