/* AbeTech brand colors — see Company-Branding skill */
:root {
    --ab-primary:       #243044;
    --ab-primary-light: #44546A;
    --ab-red:           #70181A;
    --ab-red-light:     #E03A3E;
    --ab-teal:          #458F9C;
    --ab-mint:          #38BDA0;
    --ab-gold:          #EEB959;
    --ab-orange:        #E98645;

    --ab-bg-page:       #F5F6F8;
    --ab-text:          #1a1a1a;
    --ab-text-muted:    #6b7585;
    --ab-border:        #dde1e7;

    /* Theme surface tokens — flipped under [data-theme="dark"] */
    --ab-surface:        #ffffff;   /* card / panel / source-panel background */
    --ab-surface-2:      #f4f7fb;   /* alt rows, summary header, secondary panels */
    --ab-surface-3:      #fafbfd;   /* table th, very subtle background */
    --ab-surface-hover:  #eef3fa;   /* clickable row / option hover */
    --ab-input-bg:       #ffffff;
    --ab-input-border:   var(--ab-border);
    --ab-shadow:         rgba(36, 48, 68, 0.10);
    --ab-heading:        var(--ab-primary); /* headings / labels — flips to light in dark mode */
    --ab-chip-bg:        #deeaf8;   /* soft brand-blue chip background */
    --ab-chip-text:      var(--ab-primary);
}

[data-theme="dark"] {
    --ab-bg-page:       #161b26;
    --ab-text:          #e8eaed;
    --ab-text-muted:    #9aa3b2;
    --ab-border:        #2d3548;
    --ab-surface:        #1f2533;
    --ab-surface-2:      #262d3d;
    --ab-surface-3:      #2a3142;
    --ab-surface-hover:  rgba(69, 143, 156, 0.12);  /* subtle teal-tint hover, not bright */
    --ab-input-bg:       #0f131c;
    --ab-input-border:   #3a4561;
    --ab-shadow:         rgba(0, 0, 0, 0.45);
    --ab-heading:        #c8d4e6;   /* readable on dark, retains brand cool tone */
    --ab-chip-bg:        rgba(69, 143, 156, 0.20);
    --ab-chip-text:      #bfdbfe;
}

*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: 'proxima-nova', Arial, sans-serif;
    font-size: 14px;
    color: var(--ab-text);
    background: var(--ab-bg-page);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

h1, h2, h3, h4, h5, h6 {
    font-family: 'aktiv-grotesk', Arial, sans-serif;
}

/* ── Brand icons (Lucide outline style) ── */
.ab-icon {
    width: 16px;
    height: 16px;
    color: var(--ab-teal);
    display: inline-block;
    vertical-align: -0.2em;
    flex-shrink: 0;
}

.ab-icon-on-dark { color: #fff; }
.ab-icon-warn    { color: var(--ab-gold); }

.mismatch-badge .ab-icon,
.field-conflict .ab-icon {
    width: 13px;
    height: 13px;
    vertical-align: -0.15em;
}

/* Inline icons inside text-bearing titles get a small right margin */
.po-summary-title .ab-icon,
.llm-panel-title .ab-icon,
.additional-notes-label .ab-icon,
.mismatch-badge .ab-icon,
.disambig-title .ab-icon,
.xref-notes-label .ab-icon,
.field-conflict .ab-icon,
.btn-secondary .ab-icon,
.timing-bar .ab-icon {
    margin-right: 6px;
}

/* ── Header ── */
.app-header {
    background: var(--ab-primary);
    color: #fff;
    padding: 14px 24px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
    flex-shrink: 0;
}

.header-inner {
    max-width: 1400px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

/* Non-production marker. margin-right:auto absorbs the free space so the badge hugs the
   title instead of centring itself between the title and the user block. Prod renders none. */
.env-badge {
    margin-right: auto;
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    background: #fff;
    color: var(--ab-primary);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    white-space: nowrap;
    flex-shrink: 0;
}

.header-left {
    display: flex;
    align-items: center;
    gap: 14px;
}

.header-home-link {
    text-decoration: none;
    color: inherit;
    border-radius: 4px;
    padding: 2px 6px;
    margin: -2px -6px;
    transition: background 0.15s ease;
}

.header-home-link:hover {
    background: rgba(255, 255, 255, 0.08);
}

.app-logo {
    height: 28px;
    width: auto;
    display: block;
}

.app-title-sep {
    font-size: 18px;
    color: rgba(255, 255, 255, 0.35);
    font-weight: 300;
}

.app-title {
    font-size: 18px;
    font-weight: 600;
    letter-spacing: 0.01em;
}

.app-subtitle {
    font-size: 12px;
    opacity: 0.65;
    align-self: baseline;
}

.header-user {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-shrink: 0;
}

.user-name {
    font-size: 13px;
    opacity: 0.85;
}

/* GP USERID badge — sits just left of the email in the header. Always shown ("GP ID: …") so the field is visible
   even before a value resolves; a muted variant marks the unresolved placeholder. */
.user-gpid {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 2px 8px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.28);
    color: #fff;
    white-space: nowrap;
}
.user-gpid-unset { opacity: 0.6; font-weight: 500; background: rgba(255, 255, 255, 0.06); }

.btn-signout {
    padding: 5px 12px;
    background: rgba(255, 255, 255, 0.15);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 4px;
    font-size: 12px;
    text-decoration: none;
    transition: background 0.15s;
}

.btn-signout:hover {
    background: rgba(255, 255, 255, 0.25);
}

/* ── Main ── */
.app-main {
    max-width: 1400px;
    width: 100%;
    margin: 24px auto;
    padding: 0 24px;
    flex: 1;
}

/* ── Footer ── */
.app-footer {
    text-align: center;
    padding: 14px;
    font-size: 12px;
    color: var(--ab-text-muted);
    border-top: 1px solid var(--ab-border);
    flex-shrink: 0;
}

/* ── Search card ── */
.search-card {
    background: var(--ab-surface);
    border-radius: 6px;
    padding: 20px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.09);
}

.search-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

.search-controls select,
.search-controls input[type="text"] {
    padding: 8px 12px;
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    font-size: 14px;
    font-family: inherit;
    background: var(--ab-surface);
    transition: border-color 0.15s, box-shadow 0.15s;
}

.search-controls select {
    min-width: 175px;
}

.search-controls input[type="text"] {
    flex: 1;
    min-width: 220px;
}

.search-controls select:focus,
.search-controls input[type="text"]:focus {
    outline: none;
    border-color: var(--ab-primary);
    box-shadow: 0 0 0 2px rgba(36, 48, 68, 0.15);
}

.search-controls button {
    padding: 8px 20px;
    border: none;
    border-radius: 4px;
    font-size: 14px;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s;
}

#searchBtn {
    background: var(--ab-primary);
    color: #fff;
    font-weight: 500;
}

#searchBtn:hover:not(:disabled) {
    background: var(--ab-primary-light);
}

#searchBtn:disabled {
    background: #8fa0b5;
    cursor: not-allowed;
}

#clearBtn {
    background: var(--ab-surface-2);
    color: var(--ab-text);
}

#clearBtn:hover {
    background: var(--ab-surface-3);
}

/* ── Progress row: stage-complete chips sit beside the active loading pill ── */
.progress-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

.stage-strip {
    display: none;
    align-items: center;
    gap: 8px;
    margin-top: 14px;
    margin-bottom: 18px;
}

.stage-step {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    transition: color 0.25s ease;
}

.stage-marker {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    flex-shrink: 0;
    transition: background-color 0.25s ease;
}

.stage-marker .ab-icon {
    width: 13px;
    height: 13px;
}

.stage-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    border: 2px solid currentColor;
    box-sizing: border-box;
}

.stage-spinner {
    width: 15px;
    height: 15px;
    border: 2px solid rgba(69, 143, 156, 0.30);
    border-top-color: var(--ab-teal);
    border-radius: 50%;
    animation: stage-spin 0.7s linear infinite;
}

/* Pending — muted, hollow */
.stage-pending { color: var(--ab-text-muted); }

/* Active — teal accent, spinner */
.stage-active { color: var(--ab-teal); }
.stage-active .stage-marker { background: rgba(69, 143, 156, 0.12); }

/* Complete — filled teal check */
.stage-complete { color: var(--ab-teal); }
.stage-complete .stage-marker { background: var(--ab-teal); color: #fff; }

.stage-connector {
    width: 28px;
    height: 2px;
    background: var(--ab-border);
    flex-shrink: 0;
    transition: background-color 0.25s ease;
}

.stage-connector-done { background: var(--ab-teal); }

[data-theme="dark"] .stage-active,
[data-theme="dark"] .stage-complete { color: #7dd3c0; }
[data-theme="dark"] .stage-complete .stage-marker { background: #2f8a7a; }

@keyframes stage-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .stage-spinner { animation: none; }
}

/* ── LLM thinking animation ──
   Pill container with subtle brand-tinted gradient + shimmer pass.
   Three brand-colored dots (teal / gold / orange) pulse in a wave with an expanding
   glow halo. Timer reads as a small teal-tinted live metric pill. */
.llm-thinking {
    display: inline-flex;
    flex: 1 1 auto;
    min-width: 0;
    align-items: center;
    gap: 14px;
    margin-top: 14px;
    margin-bottom: 18px;
    padding: 9px 16px 9px 14px;
    background:
        linear-gradient(135deg,
            rgba(69, 143, 156, 0.08) 0%,
            rgba(238, 185, 89, 0.06) 50%,
            rgba(233, 134, 69, 0.08) 100%);
    border: 1px solid var(--ab-border);
    border-radius: 999px;
    box-shadow: 0 2px 10px var(--ab-shadow);
    position: relative;
    overflow: hidden;
}

.llm-thinking::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(69, 143, 156, 0.14) 50%,
        transparent 100%);
    transform: translateX(-100%);
    animation: thinking-shimmer 2.6s ease-in-out infinite;
    pointer-events: none;
}

@keyframes thinking-shimmer {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

.llm-thinking > * { position: relative; }

.thinking-dots {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-shrink: 0;
    padding: 4px 2px;
}

.thinking-dots span {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    transform: scale(0.6);
    opacity: 0.35;
    animation: dot-wave 1.3s ease-in-out infinite;
    will-change: transform, opacity, box-shadow;
}

.thinking-dots span:nth-child(1) {
    background: var(--ab-teal);
    color: var(--ab-teal);
}
.thinking-dots span:nth-child(2) {
    background: var(--ab-gold);
    color: var(--ab-gold);
    animation-delay: 0.18s;
}
.thinking-dots span:nth-child(3) {
    background: var(--ab-orange);
    color: var(--ab-orange);
    animation-delay: 0.36s;
}

@keyframes dot-wave {
    0%, 100% {
        transform: scale(0.6);
        opacity: 0.35;
        box-shadow: 0 0 0 0 currentColor;
    }
    40% {
        transform: scale(1.15);
        opacity: 1;
        box-shadow: 0 0 12px 3px currentColor;
    }
    70% {
        transform: scale(0.85);
        opacity: 0.75;
        box-shadow: 0 0 4px 0 currentColor;
    }
}

.thinking-label {
    font-size: 13px;
    color: var(--ab-text);
    font-weight: 500;
    letter-spacing: 0.01em;
}

@media (prefers-reduced-motion: reduce) {
    .thinking-dots span {
        animation: dot-fade 1.6s ease-in-out infinite;
        transform: none;
    }
    @keyframes dot-fade {
        0%, 100% { opacity: 0.35; }
        50%      { opacity: 1; }
    }
}

/* ── Status areas ── */
.search-hint {
    margin-top: 8px;
    font-size: 12px;
    color: var(--ab-text-muted);
}

.error-area {
    margin-top: 14px;
    padding: 10px 14px;
    background: #fff5f5;
    border: 1px solid #f5a5a5;
    border-radius: 4px;
    color: var(--ab-red-light);
    font-size: 13px;
}

.loading-area {
    margin-top: 14px;
    padding: 8px 0;
    color: var(--ab-text-muted);
    font-style: italic;
    font-size: 13px;
}

.summary-area {
    margin-top: 14px;
    padding: 8px 12px;
    background: var(--ab-surface-2);
    border-radius: 4px;
    font-size: 13px;
    color: var(--ab-heading);
    font-weight: 500;
}

.no-results {
    margin-top: 16px;
    padding: 24px;
    text-align: center;
    color: var(--ab-text-muted);
    font-size: 13px;
}

/* ── Results table ── */
.table-wrap {
    margin-top: 14px;
    overflow-x: auto;
    border-radius: 4px;
    border: 1px solid var(--ab-border);
}

.results-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}

.results-table th {
    background: var(--ab-primary);
    color: #fff;
    padding: 9px 12px;
    text-align: left;
    font-weight: 500;
    white-space: nowrap;
    position: sticky;
    top: 0;
}

.results-table td {
    padding: 8px 12px;
    border-bottom: 1px solid var(--ab-border);
    vertical-align: top;
}

.results-table tbody tr:last-child td {
    border-bottom: none;
}

.results-table tbody tr:hover td {
    background: var(--ab-surface-2);
}

.col-source,
.col-custnum,
.col-soptype,
.col-sopnum,
.col-date,
.col-time {
    white-space: nowrap;
}

.col-custname {
    min-width: 140px;
}

/* Note text: readable, wrapping, not cramped */
.col-notetext {
    white-space: pre-wrap;
    word-break: break-word;
    min-width: 240px;
    max-width: 520px;
    line-height: 1.5;
}

/* ── LLM summary panel ── */
.summarize-bar {
    margin-top: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.summarize-bar select {
    padding: 7px 12px;
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    font-size: 13px;
    font-family: inherit;
    background: var(--ab-surface);
    min-width: 180px;
}

.summarize-bar select:focus {
    outline: none;
    border-color: var(--ab-primary);
    box-shadow: 0 0 0 2px rgba(36, 48, 68,0.15);
}

#summarizeBtn {
    background: var(--ab-primary);
    color: #fff;
    border: none;
    border-radius: 4px;
    padding: 8px 18px;
    font-size: 14px;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s;
}

#summarizeBtn:hover:not(:disabled) {
    background: var(--ab-primary-light);
}

#summarizeBtn:disabled {
    background: #8fa0b5;
    cursor: not-allowed;
}

.llm-panel {
    margin-top: 14px;
    background: var(--ab-surface-2);
    border: 1px solid #c5d3e8;
    border-left: 4px solid var(--ab-primary);
    border-radius: 4px;
    overflow: hidden;
}

.llm-panel-header {
    background: var(--ab-primary);
    color: #fff;
    padding: 8px 14px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.llm-panel-title {
    font-size: 13px;
    font-weight: 600;
}

.llm-panel-close {
    background: none;
    border: none;
    color: #fff;
    font-size: 18px;
    cursor: pointer;
    line-height: 1;
    padding: 0 4px;
    opacity: 0.8;
}

.llm-panel-close:hover {
    opacity: 1;
}

.llm-panel-content {
    padding: 16px 18px;
    font-size: 13px;
    line-height: 1.7;
    color: var(--ab-text);
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── Resolved fields table ── */
.resolve-table {
    width: 100%;
    border-collapse: collapse;
}

.resolve-table th {
    padding: 6px 0;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ab-heading);
    border-bottom: 2px solid var(--ab-border);
    text-align: left;
}

.resolve-table td {
    padding: 7px 0;
    border-bottom: 1px solid var(--ab-border);
    vertical-align: top;
    font-size: 13px;
}

.resolve-table tbody tr:last-child td {
    border-bottom: none;
}

.resolve-label {
    width: 160px;
    font-weight: 600;
    color: var(--ab-heading);
    padding-right: 16px;
    white-space: nowrap;
}

.resolve-value {
    color: var(--ab-text);
}

/* An OPTIONAL not-found field reads GRAY (muted) + italic. A REQUIRED not-found field is overridden back to red by the
   more-specific .resolve-row-required rule below, so "missing required" still stands out. */
.resolve-table td.resolve-empty {
    color: var(--ab-text-muted);
    font-style: italic;
}

#resolveBtn {
    background: var(--ab-surface-2);
    color: var(--ab-text);
    border: none;
    border-radius: 4px;
    padding: 8px 18px;
    font-size: 14px;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s;
}

#resolveBtn:hover:not(:disabled) {
    background: var(--ab-surface-3);
}

#resolveBtn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* ── Header nav ── */
.header-nav {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    padding-left: 28px;
}

.nav-link {
    display: inline-block;
    padding: 6px 16px;
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
    text-decoration: none;
    font-size: 13px;
    font-weight: 500;
    border-radius: 5px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    white-space: nowrap;
    transition: background 0.15s, border-color 0.15s;
}

.nav-link:hover {
    background: rgba(255, 255, 255, 0.2);
    border-color: rgba(255, 255, 255, 0.35);
}

.nav-active {
    background: rgba(255, 255, 255, 0.25);
    border-color: rgba(255, 255, 255, 0.45);
}

/* ── PO Parser card ── */
.po-card {
    background: var(--ab-surface);
    border-radius: 6px;
    padding: 24px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.09);
}

.po-section-title {
    font-size: 16px;
    font-weight: 600;
    color: var(--ab-heading);
    margin-bottom: 16px;
}

/* While a parse is in flight, disable interaction with the upload + port controls
   so the user can't change the file or port mid-request. */
#step1.is-loading {
    pointer-events: none;
    opacity: 0.55;
    filter: saturate(0.75);
    transition: opacity 0.15s, filter 0.15s;
}

.po-section-sub {
    font-size: 13px;
    font-weight: 600;
    color: var(--ab-heading);
    margin: 16px 0 8px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* ── Drop zone ── */
.drop-zone {
    border: 2px dashed #b8c4d4;
    border-radius: 10px;
    padding: 44px 24px 36px;
    text-align: center;
    cursor: pointer;
    background: var(--ab-surface-3);
    transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
    margin-bottom: 14px;
    user-select: none;
}

.drop-zone:hover {
    border-color: var(--ab-primary);
    background: var(--ab-surface-hover);
    box-shadow: 0 0 0 4px rgba(36, 48, 68, 0.07);
}

.drop-zone-active {
    border-color: var(--ab-primary);
    background: var(--ab-surface-hover);
    box-shadow: 0 0 0 4px rgba(36, 48, 68, 0.1);
}

.drop-zone-icon {
    margin-bottom: 12px;
    line-height: 1;
}

.drop-zone-icon .ab-icon {
    width: 44px;
    height: 44px;
    color: var(--ab-teal);
    opacity: 0.55;
}

.drop-zone-text {
    font-size: 15px;
    color: var(--ab-text);
    line-height: 1.6;
}

.drop-zone-hint {
    font-size: 13px;
    color: var(--ab-text-muted);
    text-decoration: underline;
    text-decoration-style: dotted;
    text-underline-offset: 2px;
}

.file-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 14px;
    font-size: 13px;
    color: var(--ab-heading);
    font-weight: 500;
    background: var(--ab-chip-bg);
    border: 1px solid #b3ccec;
    padding: 4px 14px;
    border-radius: 20px;
}

/* ── PO action row (model selector + parse button) ── */
.po-action-row {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    flex-wrap: wrap;
}

#parseBtn.btn-primary {
    background: var(--ab-mint);
    color: #0b1b1a;
}

#parseBtn.btn-primary:hover:not(:disabled) {
    background: #4DD0B3;
    color: #0b1b1a;
}

#parseBtn.btn-primary:disabled {
    background: #8fa0b5;
    color: #fff;
}

[data-theme="dark"] #parseBtn.btn-primary:disabled {
    background: #3a4156;
    color: var(--ab-text-muted);
}

.po-model-group {
    display: flex;
    align-items: center;
    gap: 8px;
}

.po-model-label {
    font-size: 13px;
    color: var(--ab-text-muted);
    font-weight: 500;
    white-space: nowrap;
}

.po-model-group select {
    padding: 7px 12px;
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    font-size: 13px;
    font-family: inherit;
    background: var(--ab-surface);
    min-width: 200px;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.po-model-group select:focus {
    outline: none;
    border-color: var(--ab-primary);
    box-shadow: 0 0 0 2px rgba(36, 48, 68, 0.15);
}

.po-spatial-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--ab-text-muted);
    font-weight: 500;
    cursor: pointer;
    user-select: none;
    white-space: nowrap;
}

.po-spatial-toggle input[type="checkbox"] {
    margin: 0;
    cursor: pointer;
}

/* ── PO controls (GP lookup row) ── */
.po-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    margin-top: 4px;
}

.po-controls input[type="text"] {
    flex: 1;
    min-width: 220px;
    padding: 8px 12px;
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    font-size: 14px;
    font-family: inherit;
    background: var(--ab-surface);
    transition: border-color 0.15s, box-shadow 0.15s;
}

.po-controls input[type="text"]:focus {
    outline: none;
    border-color: var(--ab-primary);
    box-shadow: 0 0 0 2px rgba(36, 48, 68, 0.15);
}

.btn-primary {
    padding: 8px 20px;
    background: var(--ab-primary);
    color: #fff;
    border: none;
    border-radius: 4px;
    font-size: 14px;
    font-family: inherit;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s;
}

.btn-primary:hover:not(:disabled) {
    background: var(--ab-primary-light);
}

.btn-primary:disabled {
    background: #8fa0b5;
    cursor: not-allowed;
}

.btn-secondary {
    padding: 8px 20px;
    background: var(--ab-surface-2);
    color: var(--ab-text);
    border: none;
    border-radius: 4px;
    font-size: 14px;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s;
}

.btn-secondary:hover:not(:disabled) {
    background: var(--ab-surface-3);
}

.btn-secondary:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* "+ Add line item" — a distinct dashed teal affordance so it reads as an ADD action and stays visible in dark mode
   (the plain btn-secondary grey blended into the dark card). Works in both themes off the teal token + transparent bg. */
.li-add-btn {
    background: transparent;
    color: var(--ab-teal);
    border: 1px dashed var(--ab-teal);
    font-weight: 600;
}
.li-add-btn:hover:not(:disabled) {
    background: rgba(69, 143, 156, 0.14);
}
[data-theme="dark"] .li-add-btn {
    color: #99e2eb;
    border-color: #5fb0bd;
    background: transparent;
}
[data-theme="dark"] .li-add-btn:hover:not(:disabled) {
    background: rgba(69, 143, 156, 0.22);
}

/* ── Review action buttons — AbeTech brand button system, mapped by intent (review header + footer) ── */
/* Review-screen action buttons (header + footer). ONE shared box so Save/Deny/Approve line up EXACTLY with
   Reprocess (identical height, padding, border, icon size); colors follow the AbeTech button system —
   Approve = primary slate (solid), Deny = jasper red (solid), Save = teal (solid), Reprocess = outlined teal. */
.btn-approve,
.btn-deny,
.btn-save,
.btn-reprocess {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    box-sizing: border-box;
    min-height: 38px;
    padding: 8px 16px;
    border: 1px solid transparent;
    border-radius: 6px;
    font-size: 14px;
    font-family: inherit;
    font-weight: 600;
    line-height: 1.2;
    color: #fff;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.04s;
}
.btn-approve .ab-icon,
.btn-deny .ab-icon,
.btn-save .ab-icon,
.btn-reprocess .ab-icon { width: 16px; height: 16px; margin-right: 0; }
.btn-approve:active:not(:disabled),
.btn-deny:active:not(:disabled),
.btn-save:active:not(:disabled),
.btn-reprocess:active:not(:disabled) { transform: translateY(1px); }

/* Approve = the primary action -> brand primary (dark slate blue) */
.btn-approve { background: var(--ab-primary); border-color: var(--ab-primary); }
.btn-approve:hover:not(:disabled) { background: var(--ab-primary-light); border-color: var(--ab-primary-light); }

/* Deny = destructive -> brand jasper red */
.btn-deny { background: var(--ab-red-light); border-color: var(--ab-red-light); }
.btn-deny:hover:not(:disabled) { background: var(--ab-red); border-color: var(--ab-red); }

/* Save = commit -> brand 1st accent (teal), solid */
.btn-save { background: var(--ab-teal); border-color: var(--ab-teal); }
.btn-save:hover:not(:disabled) { background: #3a7b86; border-color: #3a7b86; }

/* Save with work staged -> gold + a slow glow, so "you still have unsaved changes" is visible from anywhere on the
   page. With nothing staged the button is disabled by the generic .btn-save:disabled rule below, which removes the
   old dead end where clicking it only ever toasted "No unsaved changes to save." */
.btn-save-pending {
    background: var(--ab-gold);
    border-color: var(--ab-gold);
    color: #4a3410;
    animation: save-pending-glow 2.4s ease-in-out infinite;
}
.btn-save-pending:hover:not(:disabled) { background: #e0a83f; border-color: #e0a83f; }
@keyframes save-pending-glow {
    0%, 100% { box-shadow: 0 0 0 0 rgba(238, 185, 89, 0.0); }
    50%      { box-shadow: 0 0 0 4px rgba(238, 185, 89, 0.30); }
}
/* Forty POs into a shift a pulsing button is an irritant, not a hint — honour the OS setting and let the gold carry it. */
@media (prefers-reduced-motion: reduce) {
    .btn-save-pending { animation: none; }
}

/* Reprocess = cautious replay -> brand secondary (outlined teal) */
.btn-reprocess { background: transparent; color: var(--ab-teal); border-color: var(--ab-teal); }
.btn-reprocess:hover:not(:disabled) { background: rgba(69, 143, 156, 0.10); }

.btn-approve:disabled,
.btn-deny:disabled,
.btn-save:disabled,
.btn-reprocess:disabled { opacity: 0.5; cursor: not-allowed; }

/* Bottom action footer on the review/viewing screen */
.review-footer {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-top: 28px;
    padding-top: 18px;
    border-top: 1px solid var(--ab-border);
}
.review-footer .review-actions-group {
    display: inline-flex;
    gap: 10px;
    margin-left: auto;   /* Reprocess sits left; Save/Deny/Approve group right */
}

/* Tighter button row at the top of the review screen — same box for ALL of them so they stay aligned */
#reviewHeader .btn-secondary,
#reviewHeader .btn-approve,
#reviewHeader .btn-deny,
#reviewHeader .btn-save,
#reviewHeader .btn-reprocess {
    min-height: 34px;
    padding: 6px 14px;
    font-size: 13px;
}
#reviewHeader .ab-icon { width: 15px; height: 15px; }

/* ── Not-a-PO card ── */
.not-po-card {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 16px 18px;
    background: #fffbf0;
    border: 1px solid #f7dfa8;
    border-left: 4px solid var(--ab-gold);
    border-radius: 4px;
    margin-bottom: 16px;
}

.not-po-icon {
    flex-shrink: 0;
    line-height: 1;
}

.not-po-icon .ab-icon {
    width: 24px;
    height: 24px;
    color: var(--ab-gold);
}

.not-po-title {
    font-weight: 600;
    font-size: 14px;
    color: #7a5200;
    margin-bottom: 4px;
}

.not-po-reason {
    font-size: 13px;
    color: #5a3c00;
    line-height: 1.5;
}

/* ── PO summary card ── */
.po-summary-card {
    background: var(--ab-surface-2);
    border: 1px solid #c5d3e8;
    border-radius: 6px;
    padding: 16px 18px;
    margin-bottom: 16px;
}

.po-summary-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
}

.po-summary-title {
    font-size: 14px;
    font-weight: 600;
    color: var(--ab-heading);
}

.mismatch-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 10px;
    background: #fff3cd;
    border: 1px solid #ffc107;
    border-radius: 12px;
    font-size: 12px;
    color: #7a5200;
    font-weight: 500;
}

.po-meta-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 10px 20px;
    margin-bottom: 14px;
}

.po-meta-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.po-meta-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ab-text-muted);
}

.po-meta-value {
    font-size: 13px;
    color: var(--ab-text);
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── PO totals ── */
.po-totals {
    margin-top: 12px;
    border-top: 1px solid var(--ab-border);
    padding-top: 10px;
}

.po-tc-row {
    display: flex;
    justify-content: space-between;
    font-size: 13px;
    color: var(--ab-text-muted);
    padding: 3px 0;
}

.po-total-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 16px;
    padding: 8px 0 2px;
    margin-top: 2px;
}

.po-total-label {
    font-weight: 700;
    font-size: 16px;
    color: var(--ab-heading);
}

.po-total-value {
    font-weight: 800;
    font-size: 19px;
    color: var(--ab-heading);
}

/* The credit-usage line under the Computed Total — quiet background info, not a total. Stays muted and small;
   only an over-limit order colors the value red (the same signal that swaps in the acknowledgment dialog). */
.po-credit-row { padding: 0 0 2px; margin-top: 0; }
.po-credit-row .po-total-label,
.po-credit-row .po-total-value {
    font-size: 12px;
    font-weight: 400;
    color: var(--ab-text-muted);
}
.po-credit-row .po-total-value.po-credit-over {
    color: #c0392b;
    font-weight: 600;
}

/* ── GP lookup section ── */
.gp-lookup-section {
    border-top: 1px solid #edf0f4;
    padding-top: 16px;
    margin-top: 8px;
}

/* ── Step 3 actions ── */
.po-actions {
    margin-top: 14px;
}

/* ── Preview buttons (PO Document / GP Notes) — open the side panel ── */
.preview-buttons {
    display: flex;
    gap: 10px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}

.preview-btn {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-radius: 6px;
    cursor: pointer;
    text-align: left;
    transition: background 0.15s, border-color 0.15s, transform 0.05s;
    font-family: inherit;
}

.preview-btn:hover:not(:disabled) {
    background: var(--ab-surface-2);
    border-color: var(--ab-teal);
}

.preview-btn:active:not(:disabled) {
    transform: translateY(1px);
}

.preview-btn:disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

.preview-btn-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: rgba(69, 143, 156, 0.12);
    color: var(--ab-teal);
    flex-shrink: 0;
}

.preview-btn-icon .ab-icon {
    width: 16px;
    height: 16px;
}

.preview-btn-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.preview-btn-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--ab-heading);
}

.preview-btn-meta {
    font-size: 12px;
    color: var(--ab-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 240px;
}

/* GP notes side-panel formatting — left bar color matches the GP Notes pill background */
.source-panel-text .gp-note-block {
    font-family: 'proxima-nova', Arial, sans-serif;
    padding: 10px 12px;
    margin-bottom: 10px;
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-left: 3px solid #dbeafe;
    border-radius: 4px;
    font-size: 13px;
    line-height: 1.55;
}

[data-theme="dark"] .source-panel-text .gp-note-block {
    border-left-color: #1e3a64;
}

.source-panel-text .gp-note-header {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ab-heading);
    margin-bottom: 4px;
}

.source-panel-text .gp-note-text {
    color: var(--ab-text);
    white-space: pre-wrap;
    word-break: break-word;
    font-family: 'Courier New', Courier, monospace;
    font-size: 12px;
    line-height: 1.6;
}

/* ── Source badges ── */
.source-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    white-space: nowrap;
}

.source-po {
    background: #fef3c7;
    color: #854d0e;
}

.source-gp {
    background: #dbeafe;
    color: #1e3a8a;
}

.source-both {
    background: #dceaee;
    color: var(--ab-teal);
}

.source-none {
    background: #fee2e2;
    color: #b91c1c;
}

/* ── Account-status badges (/Users) ──
   Deliberately NOT the .source-* badges. Those encode where a FIELD VALUE came from (PO / GP Notes /
   derived) and are NEUTRALISED further down by design (`.source-badge.source-X` → grey). /Users was
   reusing `.source-gp` for "Active", so it inherited that grey — which is why an active account looked
   disabled. Own classes keep the two concerns apart in both directions: account status can be coloured
   without repainting the review screen's Source column, and the neutral rule can't bleed back in.
   Two-class selectors on purpose, matching the specificity of the neutralising rule below. */
.source-badge.status-active {
    background: #dcfce7;
    color: #166534;
}

.source-badge.status-inactive {
    background: #fee2e2;
    color: #b91c1c;
}

[data-theme="dark"] .source-badge.status-active {
    background: rgba(56, 189, 160, 0.20);
    color: var(--ab-mint);
}

[data-theme="dark"] .source-badge.status-inactive {
    background: rgba(224, 58, 62, 0.18);
    color: var(--ab-red-light);
}

/* ── Presence chips (who's online) ──
   Shared by the /Dashboard "Who's Online" card and the /Users Presence column, so they live here rather
   than in a page-local <style> block. Distinct from the ACCOUNT-status badges above: presence is "are
   they at their desk right now", account status is "are they allowed to use the app at all".
   Backgrounds are translucent brand tints so one value works in both themes; only the text needs a
   dark override. */
.presence-chip {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    white-space: nowrap;
}

.presence-active     { background: rgba(56, 189, 160, 0.16); color: #17705d; }
.presence-idle       { background: var(--ab-surface-3); color: var(--ab-text-muted); }
.presence-away       { background: rgba(238, 185, 89, 0.18); color: #6b4a12; }
.presence-signedout  { background: transparent; color: var(--ab-text-muted); font-weight: 400; }

[data-theme="dark"] .presence-active { color: var(--ab-mint); }
[data-theme="dark"] .presence-away   { color: var(--ab-gold); }

/* Muted dash shown in the Source column for an OPTIONAL field that wasn't found (vs the red "Not found" pill, which is
   reserved for required-and-empty fields). Plain text, not a pill — it just indicates "nothing here". */
.source-dash { color: var(--ab-text-muted); }

.source-lookup {
    background: #e0e7ff;
    color: #3730a3;
}

.source-derived {
    background: #ffedd5;
    color: #9a3412;
}

/* "Defaulted" — a value auto-filled from a GP default (Bill To Address ID -> customer's primary bill-to; Shipping
   Method -> matched ship-to's GP ship method). Rendered NEUTRAL gray like the other source badges (see the
   .source-badge.source-default override below, which wins on specificity); this base rule is kept for parity with the
   other per-source colors. */
.source-default {
    background: rgba(154, 103, 0, 0.14);
    color: #9a6700;
}

.resolve-source {
    white-space: nowrap;
    vertical-align: middle;
    padding-left: 12px;
}

.field-conflict {
    margin-top: 4px;
    font-size: 11px;
    color: #7a5200;
    font-style: italic;
}

/* Ship-to "already in GP for this customer?" flag, shown under the Ship To Address value.
   Translucent backgrounds so the same rule reads correctly in light and dark; text brightened in dark. */
.gp-addr-flag {
    display: inline-block;
    margin-top: 5px;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
}
.gp-addr-known { color: #1f7a64; background: rgba(56, 189, 160, 0.15); }
.gp-addr-new   { color: #9a6700; background: rgba(154, 103, 0, 0.14); }
.gp-addr-none  { color: var(--ab-text-muted); background: rgba(68, 84, 106, 0.10); }
.gp-addr-required { color: var(--ab-red-light); background: rgba(224, 58, 62, 0.12); border: 1px solid rgba(224, 58, 62, 0.40); }
.gp-addr-required .ab-icon { width: 13px; height: 13px; margin-right: 4px; vertical-align: -2px; }
[data-theme="dark"] .gp-addr-known { color: #6fd6bd; }
[data-theme="dark"] .gp-addr-new   { color: #e3b341; }
[data-theme="dark"] .gp-addr-none  { color: #9fb0c4; background: rgba(159, 176, 196, 0.14); }
[data-theme="dark"] .gp-addr-required { color: #f5878a; background: rgba(224, 58, 62, 0.22); }

/* Read-only Batch field — the routing decision pill + a click-to-toggle "why this batch" explanation. */
.batch-value { cursor: pointer; }
.batch-pill {
    display: inline-block; padding: 2px 10px; border-radius: 10px;
    font-size: 12px; font-weight: 700; letter-spacing: 0.02em;
}
.batch-pill-process { color: #1f7a64; background: rgba(56, 189, 160, 0.15); border: 1px solid rgba(56, 189, 160, 0.45); }
/* ABEINT-REVIEW is a warning / heads-up (needs a human look), not an error — gold, not red. Red is reserved for
   "action needed / blocked" states. */
.batch-pill-review  { color: #9a6700; background: rgba(238, 185, 89, 0.20); border: 1px solid rgba(238, 185, 89, 0.55); }
.batch-why-cue { margin-left: 8px; font-size: 11px; font-weight: 600; color: var(--ab-teal); white-space: nowrap; }
.batch-detail {
    margin-top: 8px; padding: 8px 12px; border-radius: 6px;
    background: rgba(68, 84, 106, 0.08); border: 1px solid var(--ab-border);
}
.batch-detail-title { font-size: 12px; font-weight: 700; color: var(--ab-text); margin-bottom: 4px; }
.batch-reasons { margin: 0; padding-left: 18px; }
.batch-reasons li { font-size: 12px; color: var(--ab-text); margin: 2px 0; }
.batch-reasons-clean { font-size: 12px; color: var(--ab-text-muted); }
[data-theme="dark"] .batch-pill-process { color: #6fd6bd; }
[data-theme="dark"] .batch-pill-review  { color: #e3b341; background: rgba(238, 185, 89, 0.18); border-color: rgba(238, 185, 89, 0.45); }
[data-theme="dark"] .batch-detail { background: rgba(159, 176, 196, 0.08); }

/* GP Payment Terms — now a compact pill next to the Payment Terms value (no longer its own row). Match uses the
   same green as the line-item "Price Validated" pill; a mismatch is amber; absent/none is muted. */
.gp-term-pill {
    display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 10px;
    font-size: 11px; font-weight: 600; white-space: nowrap; vertical-align: middle;
}
.gp-term-match { color: #1f7a64; background: rgba(56, 189, 160, 0.15); border: 1px solid rgba(56, 189, 160, 0.45); }
.gp-term-diff  { color: #9a6700; background: rgba(154, 103, 0, 0.14); }
.gp-term-muted { color: var(--ab-text-muted); background: rgba(68, 84, 106, 0.10); }
/* RED variant — a hard problem that BLOCKS approval (e.g. a G-part order's buyer isn't a verified active D365 contact). */
.gp-term-bad   { color: #b02a37; background: rgba(176, 42, 55, 0.14); border: 1px solid rgba(176, 42, 55, 0.40); }
[data-theme="dark"] .gp-term-match { color: #6fd6bd; background: rgba(56, 189, 160, 0.22); }
[data-theme="dark"] .gp-term-diff  { color: #e3b341; }
[data-theme="dark"] .gp-term-bad   { color: #f2a1a8; background: rgba(176, 42, 55, 0.26); }

/* Shipping Method cross-reference bubbles — the field text is PO-only; these two bubbles (GP notes, GP ship-to address)
   sit to its right. GREEN when the three sources reconcile, YELLOW when they don't (or the ship-to address has no GP
   ship method). A muted bubble = that source had no shipping method. Reuses the gp-term-pill palette. */
.sm-bubbles { display: inline; }
.sm-bubble {
    display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: 10px;
    font-size: 11px; font-weight: 600; white-space: nowrap; vertical-align: middle;
}
.sm-bubble-ok    { color: #1f7a64; background: rgba(56, 189, 160, 0.15); border: 1px solid rgba(56, 189, 160, 0.45); }
.sm-bubble-warn  { color: #9a6700; background: rgba(214, 158, 46, 0.16); border: 1px solid rgba(214, 158, 46, 0.50); }
.sm-bubble-muted { color: var(--ab-text-muted); background: rgba(68, 84, 106, 0.10); border: 1px solid transparent; }
[data-theme="dark"] .sm-bubble-ok   { color: #6fd6bd; background: rgba(56, 189, 160, 0.22); }
[data-theme="dark"] .sm-bubble-warn { color: #e3b341; background: rgba(214, 158, 46, 0.20); }

/* D365 Quote result cell — a clean stacked layout (matched line + "View in D365" link, then a pill row, then a note)
   so the quote #, status/expiry pills, and the deep link don't crowd onto one wrapping line. */
.d365-quote-result { display: flex; flex-direction: column; gap: 6px; }
.d365-quote-head { display: flex; align-items: center; justify-content: flex-start; gap: 10px; flex-wrap: wrap; }
.d365-quote-num { font-weight: 600; }   /* inherit the field-value text color (no special tint) */
.d365-quote-pills { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.d365-quote-pills .gp-addr-flag { margin-top: 0; }   /* the flex row spaces them — drop the default stacked margin */
.d365-quote-note { font-size: 12px; color: var(--ab-text-muted); }
/* "View in D365" — a secondary (outlined-teal) BUTTON, per the brand button style. */
.quote-view-link {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 4px 10px; border: 1px solid var(--ab-teal); border-radius: 6px;
    color: var(--ab-teal); background: transparent; text-decoration: none;
    font-size: 12px; font-weight: 600; white-space: nowrap;
}
.quote-view-link:hover { background: var(--ab-teal); color: #fff; text-decoration: none; }
/* "View in D365" on the Customer ID row sits inline beside the value — give it breathing room + smaller footprint. */
.customer-d365-link { margin-left: 10px; padding: 2px 8px; font-size: 11px; vertical-align: middle; }

/* ── Buyer row (merged) ──────────────────────────────────────────────────────────────────────────────────────────────
   ONE row carrying the buyer NAME and the buyer EMAIL as two value lines, then the D365 verdict, then the pick/create
   actions. Follows the .d365-quote-result stacking pattern above, which already solved this same crowding problem for
   the quote row. No new colours: verdicts reuse the .gp-term-pill palette, links reuse .quote-view-link, and the pick
   button reuses .buyer-pick-btn. */
.buyer-cell   { display: flex; flex-direction: column; gap: 6px; }
.bc-line      { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 22px; }
/* Quiet inline key ("Name:" / "Email:") so each line is self-describing now that the row label only reads "Buyer".
   Deliberately RECESSIVE — muted, lighter, smaller than the value: it's a hint about what belongs there, not information
   competing with the value itself. min-width aligns the two values into a column. */
.bc-key {
    color: var(--ab-text-muted);
    font-weight: 400;
    font-size: 11.5px;
    flex-shrink: 0;
    min-width: 40px;
    letter-spacing: 0.01em;
}
.bc-key::after { content: ':'; }
.bc-val       { font-weight: 500; }
.bc-val-empty { color: var(--ab-text-muted); font-style: italic; font-weight: 400; }
/* Per-line click-to-evidence. The row-level ::after "‹" cue is scoped to tr.resolve-row-clickable, so these lines need
   their own hover affordance. */
.bc-line-clickable { cursor: pointer; border-radius: 4px; margin: -2px -6px; padding: 2px 6px; }
.bc-line-clickable:hover { background: var(--ab-surface-hover); }
.bc-verdict   { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding-top: 2px; }
.bc-verdict .gp-term-pill { margin-left: 0; }   /* the flex gap spaces these — drop the inline pill's left margin */
.bc-note      { font-size: 12px; color: var(--ab-text-muted); line-height: 1.45; }
.bc-actions   { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; padding-top: 1px; }
.bc-actions .quote-pick { margin-top: 0; }
.buyer-pick-btn:disabled, .bc-create-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.buyer-pick-btn:disabled:hover { background: transparent; color: var(--ab-teal); }
/* "+ Create new contact in D365" — outlined teal like the pick button (brand secondary), DASHED to read as the additive
   option, and deliberately NOT a filled red CTA: it is the only write Order Handler makes to another system of record
   and it reaches GP through the 5-minute sync, so it must not look like the row's default action. */
.bc-create-btn {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 12px; font-weight: 600; padding: 3px 10px;
    border: 1px dashed var(--ab-teal); border-radius: 6px;
    color: var(--ab-teal); background: transparent; cursor: pointer; font-family: inherit;
}
.bc-create-btn:hover:not(:disabled) { background: var(--ab-teal); color: #fff; border-style: solid; }
.bc-create-btn:disabled:hover { background: transparent; color: var(--ab-teal); border-style: dashed; }
/* The source column stacks two badges so each value line keeps its own attribution (the name often comes from GP Notes
   while the email comes from the PO). Line heights match .bc-line so the badges sit beside their values. */
.bc-sources { display: flex; flex-direction: column; gap: 6px; }
.bc-sources > span { min-height: 22px; display: flex; align-items: center; }

/* Matched D365 Quote row: a "view details ›" cue (the row is click-to-open). */
.d365-quote-detail-cue { font-size: 11px; color: var(--ab-teal); font-weight: 600; white-space: nowrap; }
[data-theme="dark"] .d365-quote-detail-cue { color: #6fd6bd; }

/* D365 quote-detail pop-out — content styles. The PANEL itself reuses .source-panel (docks like the PO panel); these
   style the body content inside it. */
.quote-detail-body { padding: 16px 18px; overflow-y: auto; flex: 1 1 auto; }
.qd-meta { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.qd-meta-row { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; align-items: center; }
.qd-meta-label { color: var(--ab-text-muted); }
.qd-meta-val { font-weight: 600; text-align: right; }
/* Status / expiry state pills: green = good (Active / not expired), red = attention (Closed/Won/Draft / expired). */
.qd-pill-ok  { display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: 12px; color: #1f7a64; background: rgba(56, 189, 160, 0.15); }
.qd-pill-bad { display: inline-block; padding: 1px 8px; border-radius: 10px; font-size: 12px; color: var(--ab-red-light); background: rgba(224, 58, 62, 0.12); }
[data-theme="dark"] .qd-pill-ok  { color: #5fd081; }
[data-theme="dark"] .qd-pill-bad { color: #f5878a; background: rgba(224, 58, 62, 0.22); }
.qd-viewlink { display: inline-flex; margin-bottom: 14px; }
.qd-section-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ab-text-muted); font-weight: 700; margin: 8px 0 6px; }
.qd-lines { width: 100%; border-collapse: collapse; font-size: 13px; }
.qd-lines th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--ab-text-muted); border-bottom: 1px solid var(--ab-border); padding: 4px 6px; }
.qd-lines td { padding: 6px; border-bottom: 1px solid var(--ab-border); vertical-align: top; }
.qd-lines .col-num { text-align: right; white-space: nowrap; }
.qd-mfg { font-size: 11px; color: var(--ab-text-muted); margin-top: 2px; }
/* Quote total — bottom-right, under the per-line totals column. */
.qd-lines tfoot .qd-total-label { text-align: right; font-weight: 600; color: var(--ab-text-muted); border-bottom: none; padding-top: 8px; }
.qd-lines tfoot .qd-total-val { font-weight: 700; font-size: 14px; border-bottom: none; border-top: 2px solid var(--ab-border); padding-top: 8px; }
.qd-total-standalone { margin-top: 12px; text-align: right; font-size: 14px; }
.qd-empty { font-size: 13px; color: var(--ab-text-muted); font-style: italic; }

/* Source-column badges are NEUTRAL by design — only "Not found" (source-none) stays colored, to flag a missing value.
   Higher specificity (.source-badge.source-X) overrides the per-source colors above in both light and dark mode. */
.source-badge.source-po, .source-badge.source-gp, .source-badge.source-both,
.source-badge.source-lookup, .source-badge.source-derived, .source-badge.source-override,
.source-badge.source-default {
    background: rgba(68, 84, 106, 0.10); color: var(--ab-text-muted);
}
[data-theme="dark"] .source-badge.source-po, [data-theme="dark"] .source-badge.source-gp,
[data-theme="dark"] .source-badge.source-both, [data-theme="dark"] .source-badge.source-lookup,
[data-theme="dark"] .source-badge.source-derived, [data-theme="dark"] .source-badge.source-override,
[data-theme="dark"] .source-badge.source-default {
    background: rgba(159, 176, 196, 0.14); color: #9fb0c4;
}

/* On-demand pickers: D365 active-quote picker (D365 Quote field) + GP item "Find part #" search (a part-less line).
   Outlined-teal trigger button (brand secondary) + a scrollable dropdown of clickable options. */
.quote-pick { margin-top: 6px; position: relative; }   /* position:relative anchors the floating buyer-pick dropdown */
.li-find-part-wrap { margin-top: 6px; }
.quote-pick-btn, .buyer-pick-btn, .li-find-part {
    display: inline-flex; align-items: center; gap: 4px;
    font-size: 12px; font-weight: 600; padding: 3px 10px;
    border: 1px solid var(--ab-teal); border-radius: 6px;
    color: var(--ab-teal); background: transparent; cursor: pointer;
}
.quote-pick-btn:hover, .buyer-pick-btn:hover, .li-find-part:hover { background: var(--ab-teal); color: #fff; }
.quote-pick-results, .buyer-pick-results, .li-find-results {
    margin-top: 6px; border: 1px solid var(--ab-border); border-radius: 6px;
    background: var(--ab-surface); max-height: 240px; overflow-y: auto; max-width: 480px;
}
/* The buyer-contact picker FLOATS as a dropdown below its button (position:absolute) instead of expanding the Buyer
   field row. Anchored to the .quote-pick wrapper (position:relative above). */
.buyer-pick-results {
    position: absolute; top: 100%; left: 0; z-index: 40;
    margin-top: 4px; min-width: 260px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
}
.pick-opt {
    display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
    padding: 6px 10px; cursor: pointer; font-size: 13px;
    border-bottom: 1px solid var(--ab-border);
}
.pick-opt:last-child { border-bottom: none; }
.pick-opt:hover, .pick-opt:focus { background: var(--ab-surface-hover); outline: none; }
.pick-pn { font-weight: 600; color: var(--ab-heading); }
.pick-desc { color: var(--ab-text-muted); flex: 1 1 200px; }
.pick-meta { color: var(--ab-teal); font-weight: 600; font-size: 12px; }
.pick-msg { padding: 8px 10px; font-size: 12px; color: var(--ab-text-muted); }

/* Create-a-D365-contact panel (inside the buyer picker dropdown). The one place Order Handler writes to D365, so it
   reads as a form the reviewer commits — not a one-click pick. Gold accents flag the look-alike warning; the sync
   note is deliberately plain text, not a warning colour, because it's information rather than a problem. */
/* The create-contact form lives in a CENTERED MODAL (#createContactOverlay), not the picker dropdown: six fields, a
   duplicate disclosure and an irreversible-write warning don't fit a 260px dropdown, and the write reaches GP. The
   dialog is wider than the page's confirmation dialogs and scrolls internally on a short viewport. */
/* One BELOW the other confirm overlays (which are z-index 1000). The unsaved-line-item guard fires from this dialog's
   Create button — while this dialog is still open — so its confirmation has to paint ON TOP of this one. Without this the
   guard would open behind the create form and read as a frozen page. */
#createContactOverlay { z-index: 999; }
.cc-dialog { max-width: 560px; max-height: calc(100vh - 40px); overflow-y: auto; }
.cc-dialog .confirm-title { margin-bottom: 4px; }
/* First/last name pair up on one line — they're one thought, and it keeps the form short enough to see whole. */
.cc-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 520px) { .cc-grid-2 { grid-template-columns: 1fr; } }
.contact-create { padding: 8px 0 0; }
.cc-lbl {
    display: block; margin: 0 0 8px;
    font-size: 12px; font-weight: 600; color: var(--ab-text-muted);
}
.cc-lbl .value-input { display: block; width: 100%; margin-top: 3px; box-sizing: border-box; font-weight: 400; }
.cc-lbl .value-input[disabled] { opacity: 0.7; cursor: not-allowed; }
/* Every field on a created contact is required by D365 and NOT enforced by its Web API, so the panel has to carry the
   requirement itself — stated once at the top, marked per field, and outlined on the ones actually left blank. */
.cc-allreq { font-size: 12px; color: var(--ab-text-muted); padding: 0 0 8px; }
.cc-lbl .cc-req { color: var(--ab-red-light); font-weight: 700; margin-left: 2px; }
.cc-lbl .value-input.cc-missing { border-color: var(--ab-red-light); }
/* Optional details, collapsed by default — neither field is extracted from the PO, so open-by-default would just be
   empty boxes between the reviewer and the Create button. */
.cc-optional { margin: 0 0 8px; }
.cc-optional > summary {
    cursor: pointer; font-size: 12px; font-weight: 600; color: var(--ab-teal);
    margin-bottom: 6px; list-style-position: inside;
}
.cc-dupes {
    margin: 0 0 8px; padding: 7px 9px;
    border: 1px solid var(--ab-gold); border-radius: 6px;
    background: color-mix(in srgb, var(--ab-gold) 12%, transparent);
}
.cc-dupe-hd { font-size: 12px; font-weight: 600; color: var(--ab-heading); margin-bottom: 4px; }
.cc-dupe { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; font-size: 12px; }
.cc-dupe a { color: var(--ab-teal); font-weight: 600; }
.cc-note { padding: 0 0 8px; }
.cc-status { padding: 0 0 8px; font-size: 12px; color: var(--ab-text-muted); }
.cc-status.cc-err { color: var(--ab-red-light); font-weight: 600; }
.cc-actions { display: flex; gap: 8px; justify-content: flex-end; }
.cc-actions button {
    padding: 5px 12px; font-size: 13px; font-weight: 600;
    border-radius: 6px; border: 1px solid var(--ab-border); cursor: pointer;
    background: var(--ab-surface); color: var(--ab-heading);
}
.cc-actions .cc-submit { background: var(--ab-teal); border-color: var(--ab-teal); color: #fff; }
.cc-actions .cc-submit:disabled { opacity: 0.6; cursor: default; }
.cc-actions button:hover:not(:disabled) { filter: brightness(1.06); }
.pick-opt.cc-open .pick-pn { color: var(--ab-teal); }

/* In-row GP item search (line-item editor part# cell): the input + a compact search button, with an inline results
   dropdown below (reuses .part-search-* / .pick-* like the part-less "Find part #" picker, so it isn't clipped by the
   table's overflow). Lets a reviewer search for an item while ADDING or editing a line. */
.li-pn-edit { display: flex; align-items: center; gap: 4px; }
.li-pn-edit .li-i-pn { flex: 1 1 auto; min-width: 0; }
.li-pn-search-btn {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width: 24px; height: 24px; padding: 0; border: 1px solid var(--ab-teal); border-radius: 4px;
    color: var(--ab-teal); background: transparent; cursor: pointer;
}
.li-pn-search-btn:hover { background: var(--ab-teal); color: #fff; }
/* Inline part-search results: a FLOATING dropdown below the Part # field (position: fixed + JS-set top/left so the
   line-items table's overflow can't clip it), rather than expanding the row vertically. */
.li-pn-search-results {
    position: fixed;
    z-index: 1000;
    max-height: 260px;
    overflow-y: auto;
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-radius: 7px;
    box-shadow: 0 8px 22px rgba(0,0,0,0.18);
}

/* Required-field marker (red *) + a subtle red accent on a row whose required value isn't filled yet. */
.required-star { color: var(--ab-red-light); font-weight: 700; margin-left: 2px; }
.resolve-table tbody tr.resolve-row-required .resolve-label { color: var(--ab-red-light); }
/* When a required field has no value, the value text ("Not found") is red too — not just the label. */
.resolve-table tbody tr.resolve-row-required td.resolve-value,
.resolve-table tbody tr.resolve-row-required td.resolve-value .rv-text { color: var(--ab-red-light); }
.resolve-table tbody tr.resolve-row-required td.resolve-value .field-edit-btn { color: var(--ab-text-muted); }

/* Ship To Address ID — click-to-view of the GP address the code resolves to. */
.addr-id-row { cursor: pointer; }
.addr-id-code { font-weight: 600; }
.addr-id-detail-cell { padding: 8px 10px; background: rgba(127, 127, 127, 0.08); font-size: 12px; }
.addr-id-detail-addr { font-weight: 600; }
.addr-id-detail-why { color: var(--ab-text-muted); margin-top: 3px; }
/* Pencil edit affordance — mirrors .field-edit-btn so the Address-ID override reads the same as the field edits. */
.addr-id-change { margin-left: 4px; padding: 6px; cursor: pointer; border-radius: 6px; border: 1px solid transparent;
    background: transparent; color: var(--ab-text); opacity: 0.6; vertical-align: middle;
    display: inline-flex; align-items: center; }
.addr-id-change:hover { opacity: 1; background: var(--ab-surface-hover); border-color: var(--ab-border); }
.addr-id-change .ab-icon { width: 18px; height: 18px; }
/* Match the Customer ID field's styled-input look (.site-id-input) so the Ship To / Bill To Address ID pickers
   read as the same control family as the Customer ID search rather than a bare native dropdown. */
.addr-id-select {
    margin-left: 8px;
    max-width: 340px;
    vertical-align: middle;
    padding: 5px 9px;
    font-family: inherit;
    font-size: 13px;
    color: var(--ab-text);
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-radius: 4px;
}
.addr-id-select:focus {
    outline: none;
    border-color: var(--ab-teal);
    box-shadow: 0 0 0 2px rgba(69, 143, 156, 0.20);
}

/* ── Cross-reference notes ── */
.xref-notes {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    margin-top: 14px;
    padding: 10px 14px;
    background: #fffbf0;
    border: 1px solid #f7dfa8;
    border-left: 3px solid var(--ab-gold);
    border-radius: 4px;
    font-size: 13px;
}

.xref-notes-label {
    font-weight: 600;
    color: #7a5200;
    white-space: nowrap;
    flex-shrink: 0;
}

.xref-notes-text {
    color: #5a3c00;
    line-height: 1.5;
}

/* ── Note count badge ── */
.note-count-badge {
    font-size: 12px;
    font-weight: 400;
    color: rgba(255, 255, 255, 0.7);
}

/* ── Numeric cells in line items table ── */
.col-num {
    text-align: right;
    white-space: nowrap;
}

/* Line Items, Additional Line Items, and Assemblies tables: left-align the numeric
   columns (Qty, Unit Price, /N, Line Total, Design Qty, Scrap %) so each value sits
   directly under its left-aligned header. The .po-totals summary block keeps its
   right alignment (it's not a .results-table). */
.results-table .col-num {
    text-align: left;
}

/* Header column with an explanatory tooltip (e.g. /N) — signal hoverability. */
.results-table th.col-help {
    cursor: help;
    text-decoration: underline dotted;
    text-underline-offset: 3px;
}

/* Editable Site ID field (overridable by the user). */
.resolve-value-editable { padding-top: 6px; padding-bottom: 6px; }

.site-id-input {
    width: 100%;
    max-width: 240px;
    padding: 5px 9px;
    font-family: inherit;
    font-size: 13px;
    color: var(--ab-text);
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-radius: 4px;
}

.site-id-input:focus {
    outline: none;
    border-color: var(--ab-teal);
    box-shadow: 0 0 0 2px rgba(69, 143, 156, 0.20);
}

/* Special Shipping Instructions — a full-width textarea that starts at one line and auto-grows (height set in JS).
   Overrides the site-id-input max-width + adds textarea behavior (no manual resize handle, no scrollbar). */
.ssi-input {
    max-width: 100%;
    min-height: 32px;
    line-height: 1.4;
    resize: none;
    overflow: hidden;
    white-space: pre-wrap;
    display: block;
}

/* Top-of-review identifiers strip: ConnectWise ticket / GP order # / owner. */
.review-meta-strip {
    display: flex;
    flex-wrap: wrap;
    gap: 2rem;
    padding: 10px 16px;
    margin: 0 0 6px;
    background: var(--ab-surface-2);
    border: 1px solid var(--ab-border);
    border-radius: 8px;
}
.review-meta-item { display: flex; flex-direction: column; gap: 2px; }
.review-meta-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ab-text-muted); }
.review-meta-value { font-size: 14px; color: var(--ab-text); font-family: var(--ab-mono, monospace); }
.review-meta-empty { color: var(--ab-text-muted); font-family: inherit; }

/* The free-text Order Notes box at the end of the Order Notes section (Initiative 1). */
.order-notes-input {
    width: 100%;
    margin-top: 10px;
    font-size: 13px;
}
.order-note-list:empty {
    display: none;
}

/* Initiative 7 — Approve button gets a clean green glow when the order is clean enough to auto-process
   (ABEINT-PROCESS): a soft, constant halo plus a slow, gentle "ping" ring. Subtle and professional — no scale,
   brightness, or color changes to the button itself. */
.btn-approve-glow {
    box-shadow: 0 0 8px 0 rgba(56, 189, 160, 0.35), 0 0 0 0 rgba(56, 189, 160, 0.5);
    animation: approve-glow 2s ease-in-out infinite;
}
@keyframes approve-glow {
    0%   { box-shadow: 0 0 8px 0 rgba(56, 189, 160, 0.35), 0 0 0 0 rgba(56, 189, 160, 0.5); }
    70%  { box-shadow: 0 0 8px 0 rgba(56, 189, 160, 0.35), 0 0 0 7px rgba(56, 189, 160, 0); }
    100% { box-shadow: 0 0 8px 0 rgba(56, 189, 160, 0.35), 0 0 0 0 rgba(56, 189, 160, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .btn-approve-glow { animation: none; box-shadow: 0 0 10px 1px rgba(56, 189, 160, 0.45); }
}

/* Initiative 4 — line-item status pills shimmer while parts are being re-validated (Site ID change, re-check, etc.). */
.li-revalidating .li-c-status > * { visibility: hidden; }
.li-revalidating .li-c-status { position: relative; min-height: 18px; }
.li-revalidating .li-c-status::after {
    content: ""; position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%);
    height: 12px; border-radius: 6px;
    /* Light mode: a clearly-visible gray base (darker than the row + alt-row surfaces) with a lighter sweep — the old
       surface-2/surface-hover pair was near-white on a light row, so the shimmer was almost invisible (reported). */
    background: linear-gradient(90deg, #d3d9e2 25%, #eef2f8 50%, #d3d9e2 75%);
    background-size: 200% 100%; animation: li-shimmer 1.1s linear infinite;
}
/* Dark mode: a visibly lighter-than-the-row base with a brighter sweep. The old surface-2 -> surface-hover pair used a
   ~12%-alpha teal tint as the highlight, so the sweep barely read on the dark row (reported). */
[data-theme="dark"] .li-revalidating .li-c-status::after {
    background: linear-gradient(90deg, #333b4d 25%, #4a556b 50%, #333b4d 75%);
    background-size: 200% 100%;
}
@keyframes li-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* Initiative 3 — full-screen overlay while an Approve/Reject is submitting (until the redirect to /Automation). */
.review-submit-overlay {
    position: fixed; inset: 0; z-index: 10000;
    display: none; align-items: center; justify-content: center;
    background: rgba(15, 23, 32, 0.55); backdrop-filter: blur(2px);
}
.review-submit-box {
    display: flex; flex-direction: column; align-items: center; gap: 14px;
    padding: 28px 36px; border-radius: 12px;
    background: var(--ab-surface); border: 1px solid var(--ab-border);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}
.review-submit-msg { font-size: 15px; font-weight: 600; color: var(--ab-text); }
.review-submit-spinner {
    width: 34px; height: 34px; border-radius: 50%;
    border: 3px solid var(--ab-border); border-top-color: var(--ab-teal);
    animation: review-submit-spin 0.8s linear infinite;
}
@keyframes review-submit-spin { to { transform: rotate(360deg); } }

/* Initiative 8 — the "Search part #" picker's type-to-search box + results. */
.part-search-input {
    width: 100%; box-sizing: border-box; padding: 6px 8px; margin-bottom: 6px;
    border: 1px solid var(--ab-border); border-radius: 6px; font-size: 13px;
    background: var(--ab-surface); color: var(--ab-text);
}
.part-search-input:focus { outline: none; border-color: var(--ab-teal); }
.part-search-results { max-height: 280px; overflow-y: auto; }
.pick-mfg { font-size: 11px; color: var(--ab-text-muted); margin-left: 8px; }

/* Reviewer GP customer search (#41) — in-cell search bar + dropdown overlay under the Customer ID field. */
/* Customer ID value cell: the search field and the "View in D365" button on one row (button to the right). */
.customer-id-cell {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.customer-id-cell .customer-d365-link { margin-left: 0; } /* the flex gap handles spacing */
.customer-search-inputwrap {
    position: relative;
    display: flex;
    align-items: center;
    max-width: 200px;
}

/* Override .site-id-input's 240px cap so the search bar fills the wrapper; pad right for the clear button. */
.customer-search-input {
    max-width: none;
    width: 100%;
    padding-right: 30px;
}

.customer-search-clear {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: none;
    background: transparent;
    color: var(--ab-text);
    opacity: 0.55;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    border-radius: 4px;
}

.customer-search-clear:hover { opacity: 1; background: var(--ab-surface-hover); }

.customer-search-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 60;
    margin-top: 4px;
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-radius: 6px;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
    max-height: 260px;
    overflow-y: auto;
}

/* Dark mode: lift the dropdown off the same-coloured card with a brighter surface, border, and stronger shadow. */
[data-theme="dark"] .customer-search-dropdown {
    background: #2a3346;
    border-color: #46516b;
    box-shadow: 0 8px 26px rgba(0, 0, 0, 0.6);
}

/* Review field edit (#45): pencil next to an editable field; the value stays click-to-evidence. */
.resolve-value .rv-text { margin-right: 8px; }
.resolve-value .rv-text.rv-edited { color: var(--ab-teal); font-weight: 600; } /* unsaved correction */
.resolve-value .rv-text.rv-multiline { white-space: pre-line; }                /* preserve address line breaks */

.field-edit-multiline {
    width: 100%;
    max-width: 320px;
    min-height: 64px;
    resize: vertical;
    white-space: pre-wrap;
    font-family: inherit;
}

.field-edit-btn {
    background: transparent;
    border: 1px solid transparent;
    padding: 6px;
    cursor: pointer;
    color: var(--ab-text);
    opacity: 0.6;
    vertical-align: middle;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
}

.field-edit-btn:hover { opacity: 1; background: var(--ab-surface-hover); border-color: var(--ab-border); }
.field-edit-btn .ab-icon { width: 18px; height: 18px; }

.customer-search-option {
    padding: 8px 12px;
    cursor: pointer;
    color: var(--ab-text);
    font-size: 13px;
    border-bottom: 1px solid var(--ab-border);
}

.customer-search-option:last-child { border-bottom: none; }

.customer-search-option:hover,
.customer-search-option:focus {
    background: var(--ab-surface-hover);
    outline: none;
}

.customer-search-message {
    padding: 8px 12px;
    color: var(--ab-text);
    font-size: 13px;
    opacity: 0.75;
}

.source-badge.source-override {
    background: rgba(69, 143, 156, 0.15);
    color: var(--ab-teal);
    border: 1px solid rgba(69, 143, 156, 0.4);
}

/* ── Model name label (next to port selector) ── */
.model-name-label {
    font-size: 12px;
    color: var(--ab-text-muted);
    font-style: italic;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 240px;
}

.model-name-ok {
    color: #1c8a73;
    font-style: normal;
    font-weight: 500;
}

.model-name-warn {
    color: #7a5200;
    font-style: normal;
}

.model-name-error {
    color: var(--ab-red-light);
    font-style: normal;
}

/* ── Timer display (sits inside .llm-thinking pill) ── */
.timer-display {
    font-family: 'Courier New', Courier, monospace;
    font-size: 12px;
    color: var(--ab-teal);
    font-weight: 700;
    min-width: 52px;
    text-align: center;
    padding: 3px 10px;
    background: rgba(69, 143, 156, 0.14);
    border-radius: 999px;
    letter-spacing: 0.04em;
    font-variant-numeric: tabular-nums;
}

[data-theme="dark"] .timer-display {
    background: rgba(69, 143, 156, 0.22);
    color: #99e2eb;
}

/* ── Customer disambiguation panel ── */
.disambig-panel {
    margin-top: 10px;
    padding: 12px 14px;
    background: #fffbf0;
    border: 1px solid #f7dfa8;
    border-left: 4px solid var(--ab-gold);
    border-radius: 4px;
}

.disambig-title {
    font-size: 13px;
    font-weight: 600;
    color: #7a5200;
    margin-bottom: 8px;
}

.disambig-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.disambig-option {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 12px;
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
    user-select: none;
}

.disambig-option:hover {
    background: var(--ab-surface-hover);
    border-color: var(--ab-primary);
}

.disambig-custnum {
    font-size: 12px;
    font-weight: 600;
    color: var(--ab-heading);
    background: var(--ab-chip-bg);
    padding: 2px 10px;
    border-radius: 10px;
    white-space: nowrap;
    flex-shrink: 0;
    min-width: 100px;
    text-align: center;
}

.disambig-custname {
    font-size: 13px;
    font-weight: 500;
    color: var(--ab-text);
    flex: 1;
}

.disambig-notecount {
    font-size: 12px;
    color: var(--ab-text-muted);
    white-space: nowrap;
    flex-shrink: 0;
}

.disambig-col-headers {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 2px 12px 5px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #7a5200;
}

.dch-gpid {
    min-width: 100px;
    flex-shrink: 0;
}

.dch-name {
    flex: 1;
}

/* ── Order Notes block (gold = attention, not success) ── */
.additional-notes {
    margin-top: 14px;
    padding: 12px 16px;
    background: var(--ab-surface-2);
    border: 1px solid var(--ab-border);
    border-radius: 4px;
}

.additional-notes-label {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ab-heading);
    margin-bottom: 6px;
}

.additional-notes-text {
    font-size: 13px;
    color: var(--ab-text);
    line-height: 1.7;
    white-space: pre-wrap;
    word-break: break-word;
}

.order-note-list {
    display: flex;
    flex-direction: column;
    gap: 0;   /* spacing comes from .order-note-row + .order-note-row below, so it can be matched exactly */
}

.order-note-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    font-size: 13px;
    color: var(--ab-text);
    line-height: 1.5;
    padding: 5px 8px;
    border-radius: 4px;
}

/* The gap BETWEEN notes has to equal a blank line INSIDE a note, or the two kinds of break don't line up — a blank line
   rendered by pre-line is one line box (1.5em = 19.5px at this font size), while the old flex gap + paddings came to 14px.
   Subtract the row's own 5px top and bottom padding so the visual result is identical either way. */
.order-note-row + .order-note-row {
    margin-top: calc(1.5em - 10px);
}

.order-note-row-clickable {
    cursor: pointer;
    transition: background-color 0.12s ease;
}

.order-note-row-clickable:hover {
    background: rgba(0, 0, 0, 0.05);
}

.order-note-row-clickable:focus-visible {
    background: rgba(0, 0, 0, 0.05);
    outline: 2px solid var(--ab-teal);
    outline-offset: 1px;
}

/* .order-note-bullet is gone: each note has its own row, so the glyph added nothing but colour, and the notes now reach
   GP bullet-free too. */

.order-note-text {
    flex: 1;
    word-break: break-word;
    /* Notes can be genuinely multi-line — the batch-reason note lists one reason per line, and the reviewer's own note is
       typed in a textarea. pre-line honours those breaks while still collapsing incidental whitespace and wrapping long
       lines normally. Without it the whole thing renders as one paragraph, which is what it looked like before. */
    white-space: pre-line;
}

.order-note-why {
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ab-teal);
    opacity: 0;
    transition: opacity 0.12s ease;
}

.order-note-row-clickable:hover .order-note-why,
.order-note-row-clickable:focus-visible .order-note-why {
    opacity: 1;
}

/* The duplicate-of label while the document is actually HELD in DuplicateHold. Amber, matching .assembly-warn —
   the same "you can proceed, but know what you're proceeding past" signal. Neutral once the hold is cleared, so the
   colour tracks the state rather than the mere existence of a duplicate link. */
.review-dup-held {
    color: #9a6700;
    background: rgba(154, 103, 0, 0.14);
    border-radius: 10px;
    padding: 1px 8px;
    font-weight: 600;
}
.review-dup-held a { color: inherit; }
[data-theme="dark"] .review-dup-held { color: #e3b341; background: rgba(214, 158, 46, 0.16); }

/* ── Assemblies section (expandable BOM rows) ── */
/* ONE bordered list with dividers, not a stack of individually-bordered gold cards.
   The rows used to carry FOUR gold elements each — item border, background tint, left accent and a solid gold pill —
   which at two assemblies read as a wall of yellow. The attention signal now lives ONCE in the section header
   (.assembly-warn) and the rows are ordinary data: this section cannot render unless something needs building, so
   repeating "this is a problem" on every line was decoration, not information. */
.assembly-list {
    display: flex;
    flex-direction: column;
    gap: 0;
    border: 1px solid var(--ab-border);
    border-radius: 6px;
    overflow: hidden;
    background: var(--ab-surface);
}

.assembly-item + .assembly-item { border-top: 1px solid var(--ab-border); }

.assembly-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 12px;
    cursor: pointer;
    transition: background-color 0.12s ease;
}

.assembly-row:hover { background: var(--ab-surface-hover); }

/* Stated once, in the header: what routing consequence these assemblies carry. Reuses the gp-term-diff amber. */
.assembly-warn {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 11px;
    font-weight: 600;
    color: #9a6700;
    background: rgba(154, 103, 0, 0.14);
    border-radius: 10px;
    padding: 1px 8px;
    white-space: nowrap;
}
[data-theme="dark"] .assembly-warn { color: #e3b341; background: rgba(214, 158, 46, 0.16); }

/* The actionable sentence the gold pill never carried: what the reviewer has to DO about these. */
.assembly-note {
    font-size: 12px;
    color: var(--ab-text-muted);
    line-height: 1.5;
    margin: -2px 0 10px;
}

.assembly-chevron {
    display: inline-flex;
    flex-shrink: 0;
    color: var(--ab-text-muted);
    transform: rotate(-90deg);
    transition: transform 0.15s ease;
}

.assembly-chevron .ab-icon {
    width: 16px;
    height: 16px;
}

.assembly-row.expanded .assembly-chevron { transform: rotate(0deg); }

.assembly-pn {
    font-family: 'Courier New', Courier, monospace;
    font-weight: 700;
    color: var(--ab-heading);
    flex-shrink: 0;
}

.assembly-desc {
    flex: 1;
    color: var(--ab-text);
    word-break: break-word;
}

/* .assembly-badge ("ASSEMBLY REQUIRED") is gone: the section heading says it, and the section only renders when it's
   true, so it repeated itself on every row while being the loudest thing on screen. */

.assembly-qty {
    flex-shrink: 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--ab-text);
}

.assembly-count {
    flex-shrink: 0;
    font-size: 12px;
    color: var(--ab-text-muted);
}

/* Slightly recessed against the row above, now that the rows themselves sit on the plain surface. */
.assembly-children {
    padding: 2px 12px 12px;
    background: var(--ab-surface-3);
}

.assembly-children[hidden] { display: none; }

.assembly-sub-badge {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--ab-teal);
    border: 1px solid var(--ab-teal);
    border-radius: 4px;
    padding: 0 4px;
    margin-left: 6px;
    white-space: nowrap;
}

/* ── Parse timing badge (PO summary header) ── */
.parse-timing-badge {
    margin-left: auto;
    font-size: 12px;
    color: var(--ab-text-muted);
}

/* ── Timing bar (step 3) ── */
.timing-bar {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-top: 10px;
    padding: 6px 12px;
    background: var(--ab-surface-2);
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    font-size: 12px;
    color: var(--ab-text-muted);
}

.timing-label {
    font-weight: 600;
    color: var(--ab-heading);
    margin-right: 2px;
}

.timing-label::after {
    content: ':';
}

.timing-sep {
    color: #c8cdd6;
}

/* ── Login page ── */
.login-body {
    background: var(--ab-surface-2);
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
}

.login-container {
    width: 100%;
    max-width: 420px;
    padding: 24px;
}

.login-card {
    background: var(--ab-surface);
    border-radius: 8px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.12);
    overflow: hidden;
}

.login-header {
    background: var(--ab-primary);
    color: #fff;
    padding: 32px 32px 28px;
    text-align: center;
}

.login-title {
    font-size: 28px;
    font-weight: 700;
    letter-spacing: 0.01em;
    margin-bottom: 6px;
}

.login-subtitle {
    font-size: 13px;
    opacity: 0.7;
}

.login-body-content {
    padding: 32px;
    text-align: center;
}

.login-description {
    font-size: 14px;
    color: var(--ab-text-muted);
    line-height: 1.6;
    margin-bottom: 28px;
}

.btn-microsoft {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 12px 24px;
    background: var(--ab-surface);
    color: var(--ab-text);
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    font-size: 15px;
    font-family: inherit;
    font-weight: 500;
    text-decoration: none;
    transition: background 0.15s, box-shadow 0.15s;
    box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

.btn-microsoft:hover {
    background: var(--ab-surface-2);
    box-shadow: 0 2px 6px rgba(0,0,0,0.12);
}

.ms-logo {
    width: 21px;
    height: 21px;
    flex-shrink: 0;
}

.login-footer {
    padding: 14px 32px;
    text-align: center;
    font-size: 12px;
    color: var(--ab-text-muted);
    border-top: 1px solid var(--ab-border);
}

/* ── Resolve table clickable rows ── */
.resolve-table tbody tr.resolve-row-clickable {
    cursor: pointer;
    transition: background 0.12s;
}

.resolve-table tbody tr.resolve-row-clickable:hover td {
    background: var(--ab-surface-hover);   /* visible teal-tint hover (surface-2 was ~identical to the row bg in light mode) */
}

.resolve-table tbody tr.resolve-row-clickable .resolve-value::after {
    content: '\203A';
    margin-left: 8px;
    color: var(--ab-text-muted);
    opacity: 0;
    transition: opacity 0.12s;
    font-weight: 700;
}

.resolve-table tbody tr.resolve-row-clickable:hover .resolve-value::after {
    opacity: 1;
}

/* ── Line items inside the Order Entry panel ── */
.oe-line-items {
    margin-top: 18px;
}

/* Give the line-items / additional-items tables a panel surface distinct from the Order Entry card behind them, so
   the table reads as its own block instead of blending into the card (was hard to see in dark mode). The .table-wrap
   border already frames it; this just lifts the fill one step. */
.oe-line-items .table-wrap { background: var(--ab-surface-2); }
.oe-line-items .results-table tbody tr:hover td,
.oe-line-items .results-table tbody tr.line-item-row-clickable:hover td { background: var(--ab-surface-hover); }
/* Slim rows: tighter cell padding than the default results-table so line items read compact, not chunky. */
.oe-line-items .results-table th,
.oe-line-items .results-table td { padding: 5px 10px; }
/* Description is the flexible column — let it wrap and absorb width so the table fits without horizontal scroll. */
.oe-line-items .results-table .li-c-desc { white-space: normal; }

.oe-line-items-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}

.oe-line-items-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--ab-heading);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.results-table tbody tr.line-item-row-clickable {
    cursor: pointer;
}

.results-table tbody tr.line-item-row-clickable:hover td {
    background: var(--ab-surface-2);
}

/* Keyboard focus for line-item rows (#16 follow-up). Outline on the row + a cell-background fallback, since a
   <tr> outline can be clipped by table rendering — guarantees a visible focus state either way. */
.line-item-row-clickable:focus-visible {
    outline: 2px solid var(--ab-teal);
    outline-offset: -2px;
}

.line-item-row-clickable:focus-visible td {
    background: var(--ab-surface-2);
}

[data-theme="dark"] .line-item-row-clickable:focus-visible td {
    background: rgba(69, 143, 156, 0.12);
}

/* ── Page-with-panel layout: po-card shrinks, source panel docks on the right ── */
.po-page-with-panel {
    display: flex;
    align-items: flex-start;
    min-width: 0;
}

.po-page-with-panel > .po-card {
    flex: 1 1 0;
    min-width: 0;
    margin-right: 16px;
}

body.has-source-panel .po-page-with-panel > .po-card {
    margin-right: 0;
}

/* Drag handle that lets the user resize the panel by dragging its left edge */
.panel-resize-handle {
    display: none;
    flex: 0 0 12px;
    align-self: stretch;
    cursor: ew-resize;
    position: relative;
    background: transparent;
    user-select: none;
}

body.has-source-panel .panel-resize-handle {
    display: block;
    position: sticky;
    top: 0;
    height: 100vh;
}

.panel-resize-handle::before {
    content: '';
    position: absolute;
    left: 5px;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--ab-border);
    transition: background 0.12s, left 0.12s, width 0.12s;
}

.panel-resize-handle:hover::before,
.panel-resize-handle.dragging::before {
    background: var(--ab-teal);
    left: 4px;
    width: 4px;
}

/* ── Source panel (in-page inspector — docks flush against viewport right edge) ── */
.source-panel {
    display: none;
    flex: 0 0 50vw;   /* default to half the viewport width; the drag handle still adjusts it */
    min-width: 0;
    max-width: 85vw;
    max-height: calc(100vh - 96px);
    position: sticky;
    top: 16px;
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-radius: 6px;
    box-shadow: 0 2px 12px rgba(36, 48, 68, 0.10);
    flex-direction: column;
    overflow: hidden;
}

.source-panel.source-panel-open {
    display: flex;
}

/* When the panel is open, let .app-main span the full viewport so the panel docks
   to the right edge of the window (no leftover blank space from the centered max-width).
   .app-main's top/bottom margins are intentionally preserved — the panel is sticky
   100vh and covers the full viewport on its own. Removing those margins used to
   cause a visible page jump when toggling the panel at scrollY=0. */
body.has-source-panel .app-main {
    max-width: none;
    padding-right: 0;
}

body.has-source-panel .source-panel {
    /* Sticky at viewport top:0 with full 100vh height. Natural document position is at y=56
       (below the header), so the browser slides the panel up as you scroll, then pins it at
       the top once the header has scrolled out — all on the compositor, no main-thread work. */
    top: 0;
    height: 100vh;
    max-height: 100vh;
    border-top: none;
    border-right: none;
    border-bottom: none;
    border-radius: 0;
}

@media (max-width: 1100px) {
    .po-page-with-panel { flex-direction: column; }
    .source-panel { flex: 1 1 auto; width: 100%; position: static; max-height: 80vh; }
}

.source-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 20px;
    background: var(--ab-primary);
    color: #fff;
    flex-shrink: 0;
}

.source-panel-title-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.source-panel-label {
    font-family: 'aktiv-grotesk', Arial, sans-serif;
    font-size: 16px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.source-panel-close {
    background: none;
    border: none;
    color: #fff;
    font-size: 28px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
    opacity: 0.8;
    flex-shrink: 0;
}

.source-panel-close:hover {
    opacity: 1;
}

.source-panel-value-row {
    padding: 14px 20px;
    border-bottom: 1px solid var(--ab-border);
    background: var(--ab-surface-2);
    flex-shrink: 0;
}

.source-panel-section-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ab-text-muted);
    margin-bottom: 4px;
}

.source-panel-value {
    font-size: 14px;
    color: var(--ab-text);
    white-space: pre-wrap;
    word-break: break-word;
    font-weight: 500;
}

.source-panel-body {
    padding: 14px 20px;
    flex: 1;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    min-height: 0;
}

.source-panel-body-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 6px;
}

.source-panel-zoom {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.source-panel-zoom .zoom-btn {
    width: 24px;
    height: 24px;
    border: 1px solid var(--ab-border);
    background: var(--ab-surface);
    color: var(--ab-heading);
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0;
}

.source-panel-zoom .zoom-btn:hover {
    background: var(--ab-surface-2);
    border-color: var(--ab-primary);
}

#sourcePanelZoomLabel {
    font-size: 11px;
    color: var(--ab-text-muted);
    min-width: 38px;
    text-align: center;
}

.source-panel-pdf {
    flex: 1;
    overflow-y: scroll;
    overflow-x: hidden;
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    background: #4a4a4a;
    padding: 12px;
}

.pdf-page-wrap {
    position: relative;
    display: block;
    margin: 0 auto 12px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.3);
    background: var(--ab-surface);
}

.pdf-page-wrap canvas {
    display: block;
}

.pdf-highlight {
    position: absolute;
    background: rgba(238, 185, 89, 0.45);
    border: 1px solid rgba(112, 24, 26, 0.4);
    border-radius: 2px;
    pointer-events: none;   /* selection passes through to the text layer underneath */
    z-index: 3;             /* above the selectable text layer so the box stays visible */
    animation: pdf-highlight-pulse 1.2s ease-in-out 1;
}

/* PDF.js v4 selectable text layer (transparent text over the canvas) — enables click-drag highlight + Ctrl+F.
   Standard pdf.js text-layer styles, scoped to the source-panel viewer; spans are positioned via --scale-factor
   set on .pdf-page-wrap. */
.pdf-page-wrap .textLayer {
    position: absolute;
    inset: 0;
    text-align: initial;
    overflow: clip;
    opacity: 1;
    line-height: 1;
    text-size-adjust: none;
    forced-color-adjust: none;
    transform-origin: 0 0;
    z-index: 2;
    caret-color: CanvasText;
}
.pdf-page-wrap .textLayer span,
.pdf-page-wrap .textLayer br {
    color: transparent;
    position: absolute;
    white-space: pre;
    cursor: text;
    transform-origin: 0% 0%;
}
.pdf-page-wrap .textLayer span.markedContent {
    top: 0;
    height: 0;
}
.pdf-page-wrap .textLayer .endOfContent {
    display: block;
    position: absolute;
    inset: 100% 0 0;
    z-index: -1;
    cursor: default;
    user-select: none;
}
.pdf-page-wrap .textLayer.selecting .endOfContent { top: 0; }
.pdf-page-wrap .textLayer ::selection { background: rgba(69, 143, 156, 0.35); }

@keyframes pdf-highlight-pulse {
    0%   { background: rgba(238, 185, 89, 0.8); }
    100% { background: rgba(238, 185, 89, 0.45); }
}

.source-panel-text {
    margin-top: 8px;
    padding: 16px 18px;
    background: #fbf7ed;
    border: 1px solid #e6dcc0;
    border-radius: 6px;
    box-shadow: inset 0 1px 2px rgba(36, 48, 68, 0.06);
    font-family: 'Courier New', Courier, monospace;
    font-size: 13px;
    line-height: 1.75;
    color: #2a2620;
    white-space: pre-wrap;
    word-break: break-word;
    overflow-y: auto;
    flex: 1;
}

.source-panel-text .derived-explain-intro {
    font-family: 'proxima-nova', Arial, sans-serif;
    font-size: 14px;
    line-height: 1.55;
    color: var(--ab-text);
    margin-bottom: 14px;
}

.source-panel-text .derived-explain-list-label {
    font-family: 'proxima-nova', Arial, sans-serif;
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ab-heading);
    margin-bottom: 6px;
}

.source-panel-text .derived-explain-list {
    font-family: 'proxima-nova', Arial, sans-serif;
    list-style: none;
    padding: 0;
    margin: 0;
}

.source-panel-text .derived-explain-list li {
    padding: 8px 10px;
    margin-bottom: 6px;
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-left: 3px solid #f97316;
    border-radius: 4px;
    font-size: 13px;
    line-height: 1.5;
}

.source-panel-text .derived-explain-pn {
    font-family: 'Courier New', Courier, monospace;
    font-weight: 700;
    color: var(--ab-heading);
}

.source-panel-text .derived-explain-ds {
    color: var(--ab-text);
}

.source-panel-text .derived-explain-reason {
    color: var(--ab-teal);
    font-size: 12px;
    font-weight: 600;
    font-style: italic;
}

.source-panel-text .derived-explain-match {
    color: var(--ab-text-muted);
    font-size: 11px;
    font-style: italic;
}

.source-panel-text .derived-explain-empty {
    font-family: 'proxima-nova', Arial, sans-serif;
    font-size: 13px;
    color: var(--ab-text-muted);
    font-style: italic;
}

.source-panel-text .derived-explain-rules {
    font-family: 'proxima-nova', Arial, sans-serif;
    list-style: disc;
    padding-left: 22px;
    margin: 0 0 8px 0;
    font-size: 13px;
    line-height: 1.55;
    color: var(--ab-text);
}

.source-panel-text .derived-explain-rules li {
    margin-bottom: 4px;
}

.source-panel-text .derived-explain-rules em {
    font-style: italic;
    color: var(--ab-text-muted);
}

.source-panel-text .derived-explain-detail {
    font-family: 'proxima-nova', Arial, sans-serif;
    font-size: 13px;
    color: var(--ab-text);
    background: var(--ab-surface-2);
    border: 1px solid var(--ab-border);
    border-radius: 6px;
    padding: 10px 12px;
}

.source-panel-text .derived-explain-detail > div {
    padding: 4px 0;
}

.source-panel-text .derived-explain-detail > div + div {
    border-top: 1px solid var(--ab-border);
}

.source-panel-text .derived-explain-key {
    font-weight: 600;
    color: var(--ab-heading);
    margin-right: 6px;
}

.source-panel-text .derived-explain-val {
    color: var(--ab-text);
}

/* Derived (CONFIGDETAILS) rows in the Additional Line Items section sit on the same panel surface as the other rows —
   no background fill and no left accent of their own (the old yellow "derived" bar was removed). */
.results-table tr.line-item-row-derived td {
    background: transparent;
    color: var(--ab-text);
}

[data-theme="dark"] .results-table tr.line-item-row-derived td {
    background: transparent;
    color: var(--ab-text);
}

/* A line item (primary OR additional) gets a RED left bar when something BLOCKS the GP push — the item isn't in GP, or
   isn't set up at the order's Site ID (the hard gates; same condition as lineStatusMeter's "Blocked" state)... */
.results-table tr[data-blocked="1"] td:first-child {
    box-shadow: inset 4px 0 0 0 var(--ab-red-light);
}
/* Order-total mismatch: a gold warning button beside the Total whose click opens the plain-language
   explainer panel (computed vs the PO's printed total + the most likely cause). */
.po-total-warn {
    background: none; border: none; cursor: pointer; padding: 0 6px 0 0;
    color: var(--ab-gold, #d9a521); vertical-align: middle;
}
.po-total-warn .ab-icon { width: 16px; height: 16px; }
/* Frozen-record banner on decided documents — the values are as captured, never re-validated. */
.historical-banner {
    margin: 8px 0; padding: 8px 12px; font-size: 12.5px; line-height: 1.4;
    border: 1px solid var(--ab-gold, #d9a521); border-left-width: 4px; border-radius: 6px;
    background: color-mix(in srgb, var(--ab-gold, #d9a521) 8%, transparent);
}

/* The meta strip's "History (n)" button — opens the activity-history panel (replaced its standalone strip).
   Teal outline + icon so it clearly reads as CLICKABLE against the strip's own surface in BOTH themes (a
   surface-2-on-surface-2 pill was invisible in dark mode). */
.review-meta-activity-btn {
    display: inline-flex; align-items: center; gap: 5px;
    font: inherit; font-size: 12.5px; font-weight: 600; line-height: 1.3;
    padding: 3px 12px; border-radius: 999px; cursor: pointer;
    color: var(--ab-teal, #1a9c96);
    border: 1.5px solid var(--ab-teal, #1a9c96);
    background: color-mix(in srgb, var(--ab-teal, #1a9c96) 10%, transparent);
}
.review-meta-activity-btn:hover {
    background: color-mix(in srgb, var(--ab-teal, #1a9c96) 24%, transparent);
}
.review-meta-activity-btn .ab-icon { width: 13px; height: 13px; flex: 0 0 auto; }

/* The over-credit-limit acknowledgment dialog: a compact limit/balance/with-this-order figures block, and a GREEN
   approve button (btn-green overrides btn-primary's color only — size/shape unchanged). */
.credit-ack-figures { margin: 10px 0 12px; font-size: 13.5px; }
.credit-ack-row { display: flex; justify-content: space-between; gap: 24px; padding: 2px 0; }
.credit-ack-row span:first-child { color: var(--ab-text-muted); }
.credit-ack-row span:last-child { font-family: var(--ab-mono, monospace); }
.credit-ack-over { border-top: 1px solid var(--ab-border); margin-top: 2px; padding-top: 5px; }
.credit-ack-over span { color: #c0392b; font-weight: 700; }
.btn-green { background: #219a7f; border-color: #219a7f; color: #fff; }
.btn-green:hover:not(:disabled) { background: #1c8770; border-color: #1c8770; }

/* Red banner: GP rejected this staged order (OrderStatus='Error') — shows GP's IntegrationError on the review screen. */
.gp-error-banner {
    margin: 8px 0; padding: 8px 12px; font-size: 12.5px; line-height: 1.4; font-weight: 600;
    color: var(--ab-red-light, #e03a3e);
    border: 1px solid var(--ab-red-light, #e03a3e); border-left-width: 4px; border-radius: 6px;
    background: color-mix(in srgb, var(--ab-red-light, #e03a3e) 8%, transparent);
    white-space: pre-wrap; word-break: break-word;
}

/* The row whose value the source pop-out is currently showing — a subtle teal tint linking panel ↔ row. */
.resolve-row-clickable.source-active,
.order-note-row-clickable.source-active {
    background: color-mix(in srgb, var(--ab-teal) 12%, transparent);
}
.results-table tr.source-active td {
    background: color-mix(in srgb, var(--ab-teal) 12%, transparent);
}

/* Download-original icon in the source pop-out header — the ONE place to download the uploaded file.
   Hover = clearly clickable: teal icon on a tinted pill, not just a subtle color shift. */
.source-panel-download {
    display: inline-flex; align-items: center; margin-left: auto; margin-right: 6px;
    padding: 4px; border-radius: 6px;
    color: var(--ab-text-muted); cursor: pointer;
    transition: color .12s ease, background-color .12s ease;
}
.source-panel-download:hover, .source-panel-download:focus-visible {
    color: var(--ab-teal);
    background: color-mix(in srgb, var(--ab-teal) 14%, transparent);
}
.source-panel-download .ab-icon { width: 16px; height: 16px; }

/* Green "Matches PO" chip beside the Computed Total when it equals the total printed on the document. */
.po-total-match {
    display: inline-flex; align-items: center; gap: 3px; margin-right: 8px;
    font-size: 11px; font-weight: 600; color: #1f7a64; vertical-align: middle;
}
.po-total-match .ab-icon { width: 13px; height: 13px; }
[data-theme="dark"] .po-total-match { color: #6fd6bd; }
.po-total-mismatch {
    margin-top: 6px; padding: 10px 12px; font-size: 12.5px; line-height: 1.45;
    border: 1px solid var(--ab-gold, #d9a521); border-left-width: 4px; border-radius: 6px;
    background: color-mix(in srgb, var(--ab-gold, #d9a521) 8%, transparent);
}
.po-total-mismatch-list { margin: 6px 0 0 0; padding-left: 18px; }
.po-total-mismatch-list li { margin-top: 4px; }

/* ...a GOLD left bar when review-severity issues exist (price not validated / qty differs / ambiguous match —
   lineStatusMeter's "Review" state; routes to ABEINT-REVIEW but doesn't block the push)... */
.results-table tr[data-review="1"] td:first-child {
    box-shadow: inset 4px 0 0 0 var(--ab-gold, #d9a521);
}
/* ...and a GREEN left bar when the line is fully validated and ready to push (lineStatusMeter's "Ready" state). */
.results-table tr[data-ready="1"] td:first-child {
    box-shadow: inset 4px 0 0 0 var(--ab-mint, #38bda0);
}

.li-pn-derived {
    color: var(--ab-text);
}

[data-theme="dark"] .li-pn-derived {
    color: var(--ab-text);
}

/* ── Line-item validation status (Option D): ONE slim line — a small labelled 3-segment meter (GP · SITE · PRICE) +
   a one-word severity. Segment fills use the brand semantics: mint = passed, gold = warning/review, red =
   failed/blocked, neutral = n/a. The labelled, colored segments (and their tooltips) show WHICH check failed; the
   word gives overall severity. Kept on one line + content-width so rows stay slim and the table never scrolls
   sideways. GP & Site failures are HARD push-gates (red); price/qty/ambiguous issues are warnings (gold → review). */
.li-status-col { width: 1%; white-space: nowrap; }
.li-c-status { white-space: nowrap; }
.li-status { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.li-meter { display: inline-flex; border: 1px solid var(--ab-border); border-radius: 6px; overflow: hidden; }
.li-seg {
    font-size: 9.5px; font-weight: 700; letter-spacing: 0.02em; padding: 2px 6px; line-height: 1.4;
    border-right: 1px solid rgba(255, 255, 255, 0.35); cursor: help; user-select: none;
}
.li-seg:last-child { border-right: none; }
.li-seg-ok   { background: #38BDA0; color: #0c2b24; }
.li-seg-warn { background: #EEB959; color: #4a3500; }
.li-seg-bad  { background: #E03A3E; color: #ffffff; }
.li-seg-na   { background: var(--ab-surface-3); color: var(--ab-text-muted); border-right-color: var(--ab-border); }
.li-status-word { font-size: 12px; font-weight: 600; }
/* Always-visible reason caption under the status word — the status column is nowrap/1%, so the caption
   must wrap within a bounded width instead of stretching the column. */
.li-status-issues { font-size: 11px; font-weight: 400; white-space: normal; max-width: 220px; line-height: 1.3; }
.li-status-ready  { color: #1f7a64; }
.li-status-review { color: #8a6112; }
.li-status-block  { color: var(--ab-red-light); }
.li-status-na     { color: var(--ab-text-muted); }
[data-theme="dark"] .li-status-ready  { color: #6fd6bd; }
[data-theme="dark"] .li-status-review { color: #f0cb83; }

/* Part-resolution provenance — a quiet, MUTED sub-label under the part #. Informational only (the validation STATE
   lives in the status meter), so it never competes with the status colors. Replaces .li-orig-part + the old pills. */
.li-prov { margin-top: 2px; font-size: 10.5px; color: var(--ab-text-muted); }

/* Inline per-row line-item editing (review screen): a pencil + a red trashcan on every row, with the row's
   cells flipping to inputs (+ a check/cancel) on edit. */
.li-actions { white-space: nowrap; text-align: right; }
.li-actions-col { width: 1%; }

/* Pin the Actions column (edit / save / delete) to the right edge so it stays visible when the line-items table
   scrolls horizontally under a popped-out source panel — the reviewer never has to scroll right to reach the buttons.
   Opaque bg so the scrolling cells pass cleanly underneath; a soft left shadow separates it; hover/dirty rows match. */
#primaryLineItems td.li-actions, #additionalLineItems td.li-actions,
#primaryLineItems th.li-actions-col, #additionalLineItems th.li-actions-col {
    position: sticky; right: 0; z-index: 2;
    /* A step different from the table-wrap surface (surface-2) so the pinned column reads as its own column and isn't
       confused with whatever scrolls underneath it. Opaque + a left divider line + soft shadow. */
    background: var(--ab-surface-3);
    border-left: 1px solid var(--ab-border);
    box-shadow: -6px 0 6px -6px rgba(0, 0, 0, 0.18);
}
#primaryLineItems th.li-actions-col, #additionalLineItems th.li-actions-col { z-index: 3; }
.oe-line-items .results-table tbody tr:hover td.li-actions { background: var(--ab-surface-hover); }
tr.li-row-dirty > td.li-actions { background: var(--ab-surface-3); }
.li-icon-btn {
    background: none;
    border: 1px solid transparent;
    cursor: pointer;
    padding: 5px;
    border-radius: 6px;
    color: var(--ab-text);
    opacity: 0.65;
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
}
.li-icon-btn:hover { opacity: 1; background: var(--ab-surface-hover); border-color: var(--ab-border); }
.li-icon-btn:disabled { opacity: 0.25; cursor: default; background: none; border-color: transparent; }
.li-icon-btn .ab-icon { width: 16px; height: 16px; }
.li-row-del .ab-icon  { color: var(--ab-red-light); }
.li-row-done .ab-icon { color: var(--ab-mint); }

/* Lock the line-items tables (primary AND additional — they share the same column structure) so swapping a cell
   to an input never reflows the columns (fixed layout). The Assemblies table has a different structure and is
   intentionally NOT included here.
   Column order — cols 1-8 are identical in view & edit mode; Actions is the edit-only LAST column:
     1 Part #  ·  2 Description (auto — absorbs the slack + wraps)  ·  3 Qty  ·  4 UoM  ·  5 Stock  ·  6 Unit Price
     ·  7 Line Total  ·  8 Status (the GP·SITE·PRICE meter + severity word, sized to hold it on one line)
     ·  9 Actions (edit only)
   The fixed widths sum to well under 100%, so Description takes the remainder and the table never scrolls
   sideways. NOTE: the Status column was previously clamped to 82px — a stale width meant for Actions back when
   the table had no Status column. The status-meter commit inserted Status at position 6 and pushed Actions to 7,
   so that 82px starved the nowrap meter and it overflowed its cell, forcing a horizontal scrollbar. (The
   additional-items table had the same latent bug via .li-status-col's width:1% under what is now fixed layout.) */
/* min-width floor so the (flex-remainder) Description column can't be squeezed to ~0 when the source
   pop-out narrows the card — at ~0 width, word-break:break-word wrapped the description ONE CHARACTER
   per line into a giant-tall row. Below this width the table holds its size and .table-wrap (overflow-x:auto)
   scrolls horizontally inside its own box instead of collapsing the column; the wide (panel-closed) layout
   is unaffected since the card is far wider than this floor. Part# 18% + Qty/UoM/Stock/Price/Total/Status/Actions
   (720px fixed) leaves Description ~150px at the floor — readable, wraps by word.
   Description is the ONLY flexible column, so every widening below is paid for out of Description (deliberate —
   it is the column with slack to give). The min-width floor is raised in step so the narrow pop-out layout keeps
   that same ~150px Description floor instead of shattering it one character per line. */
#primaryLineItems table, #additionalLineItems table { table-layout: fixed; width: 100%; min-width: 1044px; }
#primaryLineItems th:nth-child(1), #primaryLineItems td:nth-child(1),
#additionalLineItems th:nth-child(1), #additionalLineItems td:nth-child(1) { width: 18%; }    /* Part # */
#primaryLineItems th:nth-child(3), #primaryLineItems td:nth-child(3),
#additionalLineItems th:nth-child(3), #additionalLineItems td:nth-child(3) { width: 84px; }   /* Qty — wide enough that a large quantity (e.g. 12,000) isn't clipped when editing (table-layout is fixed, so this column width is the real constraint, not the input's width) */
#primaryLineItems th:nth-child(4), #primaryLineItems td:nth-child(4),
#additionalLineItems th:nth-child(4), #additionalLineItems td:nth-child(4) { width: 88px; }   /* UoM — 56px starved both the value and the edit-mode <select> (chevron ate most of it); a unit like THOUSAND needs the room */
#primaryLineItems th:nth-child(5), #primaryLineItems td:nth-child(5),
#additionalLineItems th:nth-child(5), #additionalLineItems td:nth-child(5) { width: 76px; }   /* Stock — available at the order's Site ID; read-only in both modes, so it only has to hold a number + a dash */
#primaryLineItems th:nth-child(6), #primaryLineItems td:nth-child(6),
#additionalLineItems th:nth-child(6), #additionalLineItems td:nth-child(6) { width: 88px; }   /* Unit Price */
#primaryLineItems th:nth-child(7), #primaryLineItems td:nth-child(7),
#additionalLineItems th:nth-child(7), #additionalLineItems td:nth-child(7) { width: 88px; }   /* Line Total */
#primaryLineItems th:nth-child(8), #primaryLineItems td:nth-child(8),
#additionalLineItems th:nth-child(8), #additionalLineItems td:nth-child(8) { width: 172px; }  /* Status meter */
#primaryLineItems th:nth-child(9), #primaryLineItems td:nth-child(9),
#additionalLineItems th:nth-child(9), #additionalLineItems td:nth-child(9) { width: 124px; }  /* Actions (edit mode) — fits the labelled Save plus two icons; 68px only ever fitted two icons and overflowed once a staged row gained its save button */

/* Stock cell — GP available (on hand minus allocated) at the order's Site ID. Colour is a READING AID ONLY: unlike
   the GP/site/price states in the status meter, stock never gates the push and never routes a batch, so it must not
   borrow the left-bar severity channel. A negative available (GP permits oversell) renders as-is under .li-stock-none. */
.li-stock { text-align: left; font-variant-numeric: tabular-nums; white-space: nowrap; }
.li-stock-ok   { color: var(--ab-mint); font-weight: 600; }
.li-stock-low  { color: var(--ab-gold); font-weight: 600; }
.li-stock-none { color: var(--ab-red-light); font-weight: 600; }
.li-stock-unknown { color: var(--ab-text-muted); }

/* "Stock by site" strip under the line items — now just the "Find stock by part #" button and its on-demand
   search. The always-visible parts x sites grid that used to sit here was removed: other-site stock is answered by the
   per-line Stock hover, and a second permanent table just restated it. */
.stock-matrix { margin: 14px 0 4px; }
.stock-matrix-head {
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 6px;
    font-weight: 600;
    color: var(--ab-text);
}
.stock-matrix-sub { font-weight: 400; font-size: 12px; color: var(--ab-text-muted); }

/* "Find stock by part #" — the hover only covers parts ON this order, so this covers a part that isn't: a substitute,
   or one about to be added. Results are a table, but only after an explicit click. */
.stock-find-btn { margin-left: auto; padding: 3px 10px; font-size: 12px; }
.stock-find {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
    padding: 8px 10px;
    background: var(--ab-surface-2);
    border: 1px solid var(--ab-border);
    border-radius: 6px;
}
.stock-find-input {
    flex: 0 1 240px;
    padding: 4px 8px;
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    background: var(--ab-surface);
    color: var(--ab-text);
    font-size: 13px;
}
.stock-find-results { flex: 1 0 100%; }
.stock-find-table { table-layout: auto; width: auto; min-width: 0; margin-top: 4px; }
.stock-find-table td, .stock-find-table th { white-space: nowrap; }
.stock-find-empty { padding: 4px 0; font-size: 13px; color: var(--ab-text-muted); }
#primaryLineItems td, #additionalLineItems td { word-break: break-word; }   /* long part #s / descriptions wrap instead of overflowing */

/* Assemblies ("Assemblies Required for:") block — the SAME source-pop-out collapse the line-items floor above fixes,
   but this block was missed: the parent rows are flex (not a table) and the component table is ID-less, so neither
   got the #primaryLineItems floor. When the pop-out is enlarged and the Order Entry card narrows, the flex
   .assembly-desc was squeezed toward 0 and word-break:break-word shattered the description one char per line, and
   the component table collapsed the same way. Fix: floor the list to a usable width and let the block scroll
   horizontally inside its own box (mirrors .table-wrap), and give the component table a fixed layout so its
   Description column wraps by word. The wide (panel-closed) layout is far above the floor, so it's unaffected. */
.oe-assemblies { overflow-x: auto; }
.oe-assemblies .assembly-list { min-width: 560px; }
.oe-assemblies .results-table { table-layout: fixed; width: 100%; }
.oe-assemblies .results-table th:nth-child(1), .oe-assemblies .results-table td:nth-child(1) { width: 32%; }   /* Component # */
.oe-assemblies .results-table th:nth-child(3), .oe-assemblies .results-table td:nth-child(3) { width: 96px; }  /* Design Qty */
.oe-assemblies .results-table td { white-space: normal; overflow-wrap: anywhere; }   /* Description wraps by word, not per char */

/* Whole-order Site-ID suggestion under the Site ID combo: which site(s) stock every in-GP part. Advisory only. */
.site-suggestion-hint {
    margin-top: 5px;
    font-size: 12px;
    line-height: 1.4;
    color: var(--ab-text-muted);
}

/* min-width:0 so an input shrinks to its fixed cell instead of widening the column. */
.li-edit-input { width: 100%; min-width: 0; box-sizing: border-box; }
td.li-c-qty .li-edit-input, td.li-c-price .li-edit-input { text-align: right; }
/* Hide the native number-input spinner arrows on ALL number fields app-wide (line-item qty/price, Admin
   int settings, and any future ones). */
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
input[type=number] { -moz-appearance: textfield; appearance: textfield; }

tr.li-removed .li-c-pn, tr.li-removed .li-c-desc, tr.li-removed .li-c-qty,
tr.li-removed .li-c-price, tr.li-removed .li-c-total { text-decoration: line-through; opacity: 0.5; }

/* UNSAVED row (edited / new / marked-for-removal / open in edit mode). Gold is the brand's pending-attention accent;
   the old 7% teal wash read as "normal, informational" — exactly the wrong signal for outstanding work. */
tr.li-row-unsaved > td { background: rgba(238, 185, 89, 0.10); }
tr.li-row-unsaved > td.li-actions { background: rgba(238, 185, 89, 0.14); }
/* The left-bar channel already encodes GP-push severity (red blocked / gold review / mint ready, ~line 2990 on).
   While a row is unsaved that verdict describes the last SAVED values and may no longer hold, so the bar goes
   neutral rather than asserting a state — and gold there would collide with review-severity gold anyway. Same
   specificity as those rules, declared later, so it wins. */
.results-table tr.li-row-unsaved td:first-child {
    box-shadow: inset 4px 0 0 0 var(--ab-text-muted);
}
/* "Unsaved" chip in the Status cell, replacing the (now stale) validation meter. Matches .batch-pill-review. */
.li-unsaved-chip {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 10px;
    font-size: 12px;
    white-space: nowrap;
    color: #9a6700;
    background: rgba(238, 185, 89, 0.20);
    border: 1px solid rgba(238, 185, 89, 0.55);
}
[data-theme="dark"] .li-unsaved-chip {
    color: #e3b341;
    background: rgba(238, 185, 89, 0.18);
    border-color: rgba(238, 185, 89, 0.45);
}
/* The per-line save. Everything else in this column is a muted outline icon; this one is FILLED and LABELLED,
   because reviewers not realising the save was theirs to make is the entire reason this treatment exists. Same gold
   as the page-level "Save N changes" button so the two read as one action at two scopes. */
.li-icon-btn.li-row-done {
    opacity: 1;
    gap: 5px;
    padding: 5px 10px;
    font-size: 12px;
    font-weight: 700;
    color: #4a3410;
    background: var(--ab-gold);
    border-color: var(--ab-gold);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 0 0 3px rgba(238, 185, 89, 0.22);
}
.li-icon-btn.li-row-done .ab-icon { width: 14px; height: 14px; color: #4a3410; }
.li-icon-btn.li-row-done:hover { background: #e0a83f; border-color: #e0a83f; color: #33230a; }
.li-icon-btn.li-row-done:hover .ab-icon { color: #33230a; }
.li-row-done-label { line-height: 1; }
/* In-flight save: the chip drops the gold "needs attention" read (the reviewer has already acted) and goes muted. */
.li-unsaved-chip.li-saving-chip {
    color: var(--ab-text-muted);
    background: var(--ab-surface-3);
    border-color: var(--ab-border);
}
[data-theme="dark"] .li-unsaved-chip.li-saving-chip {
    color: var(--ab-text-muted);
    background: var(--ab-surface-3);
    border-color: var(--ab-border);
}

/* Transient bottom-of-viewport warning toast (e.g. "nothing to save") — visible regardless of scroll position. */
.bottom-toast {
    position: fixed;
    left: 50%;
    bottom: 24px;
    transform: translateX(-50%) translateY(10px);
    max-width: min(90vw, 520px);
    padding: 11px 18px;
    background: var(--ab-gold);
    color: var(--ab-primary);
    font-size: 14px;
    font-weight: 600;
    border-radius: 6px;
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.22);
    opacity: 0;
    pointer-events: none;
    z-index: 1200;
    transition: opacity 0.2s ease, transform 0.2s ease;
}
.bottom-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
@media (prefers-reduced-motion: reduce) { .bottom-toast { transition: opacity 0.2s ease; } }

.li-edit-footer { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.li-edit-footer-actions { margin-left: auto; display: inline-flex; gap: 8px; }
.li-save-status { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--ab-teal); }
.li-save-spinner {
    width: 14px; height: 14px;
    border: 2px solid rgba(69, 143, 156, 0.30);
    border-top-color: var(--ab-teal);
    border-radius: 50%;
    animation: stage-spin 0.7s linear infinite;
}
[data-theme="dark"] .li-save-status { color: #7fc4d0; }
@media (prefers-reduced-motion: reduce) { .li-save-spinner { animation: none; } }

/* Neutral "Validating…" chip on live-status fields (address IDs, D365 quote, GP payment terms, shipping cross-ref)
   during the progressive review load's phase 1, until the background re-validation fills in their real state. */
.fld-validating { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-style: italic; color: var(--ab-text-muted); }
.fld-spin {
    width: 11px; height: 11px; flex: none;
    border: 2px solid rgba(69, 143, 156, 0.30);
    border-top-color: var(--ab-teal);
    border-radius: 50%;
    animation: stage-spin 0.7s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .fld-spin { animation: none; } }

/* Rendered .docx view (docx-preview): render at the natural Word page width and SCALE the whole page (via JS `zoom`)
   to fit the pop-out width — no text reflow, the page shrinks/grows as one. overflow-y is always reserved so the
   refit-on-resize can't toggle the scrollbar and oscillate the width. */
#sourcePanelText { overflow-y: scroll; overflow-x: auto; }
#sourcePanelText .docx-wrapper { padding: 10px; background: transparent; }
#sourcePanelText .docx-wrapper > section { box-shadow: none; margin: 0 0 12px 0; }
#sourcePanelText mark { background: #ffe58a; color: inherit; }

/* Rendered .xlsx view in the source pop-out (SheetJS sheet_to_html output) — one table per sheet, horizontally
   scrollable so a wide sheet doesn't break the panel layout. */
.xlsx-render { font-size: 12px; color: var(--ab-text); overflow-x: auto; }
.xlsx-render table { border-collapse: collapse; margin: 4px 0 12px 0; }
.xlsx-render td, .xlsx-render th { border: 1px solid var(--ab-border); padding: 3px 6px; white-space: nowrap; }
.xlsx-sheet-name { font-weight: 700; color: var(--ab-heading); margin: 10px 0 4px 0; }

/* Rendered .rtf view in the source pop-out (server-sanitized RtfPipe HTML). Deliberately white in BOTH themes —
   a document facsimile, matching how docx-preview pages render (RTF inline colors assume a white page). */
.rtf-render { background: #fff; color: #1a1a1a; padding: 1rem 1.25rem; border-radius: 4px; overflow-x: auto; font-size: 13px; }
.rtf-render table { border-collapse: collapse; margin: 4px 0 12px 0; }
.rtf-render td, .rtf-render th { border: 1px solid #c9c9c9; padding: 2px 8px; }

.li-derived-chip {
    margin-left: 8px;
    font-size: 10px;
    padding: 1px 6px;
    vertical-align: middle;
}

.source-panel-text mark {
    background: var(--ab-gold);
    color: var(--ab-heading);
    padding: 1px 3px;
    border-radius: 2px;
    font-weight: 600;
}

.source-panel-empty {
    margin-top: 10px;
    padding: 12px 14px;
    background: #fffbf0;
    border: 1px solid #f7dfa8;
    border-left: 3px solid var(--ab-gold);
    border-radius: 4px;
    font-size: 12px;
    color: #5a4318;
    line-height: 1.5;
}

/* ── Settings menu (gear icon in header) ── */
.header-user { position: relative; }

.btn-settings {
    background: rgba(255, 255, 255, 0.10);
    border: 1px solid rgba(255, 255, 255, 0.35);
    color: #fff;
    border-radius: 4px;
    padding: 5px 8px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s;
}

.btn-settings:hover { background: rgba(255, 255, 255, 0.25); }
.btn-settings .ab-icon { display: block; }

.settings-menu {
    display: none;
    position: absolute;
    top: calc(100% + 10px);
    right: 0;
    min-width: 220px;
    background: var(--ab-surface);
    color: var(--ab-text);
    border: 1px solid var(--ab-border);
    border-radius: 6px;
    box-shadow: 0 6px 20px var(--ab-shadow);
    padding: 6px 0;
    z-index: 100;
}

.settings-menu.open { display: block; }

.settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 10px 16px;
    font-size: 14px;
    cursor: pointer;
    user-select: none;
}

.settings-row:hover { background: var(--ab-surface-2); }

.settings-label { color: var(--ab-text); }

.settings-row-link {
    text-decoration: none;
    color: inherit;
    border-top: 1px solid var(--ab-border);
}

.settings-row-link .ab-icon {
    color: var(--ab-text-muted);
}

.toggle-switch {
    position: relative;
    display: inline-block;
    width: 36px;
    height: 20px;
    flex-shrink: 0;
}

.toggle-switch input {
    opacity: 0;
    width: 0;
    height: 0;
    position: absolute;
}

.toggle-slider {
    position: absolute;
    inset: 0;
    background: #c8ccd4;
    border-radius: 20px;
    transition: background 0.18s ease;
}

.toggle-slider::before {
    content: '';
    position: absolute;
    width: 16px;
    height: 16px;
    left: 2px;
    top: 2px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.18s ease;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

.toggle-switch input:checked + .toggle-slider {
    background: var(--ab-teal);
}

.toggle-switch input:checked + .toggle-slider::before {
    transform: translateX(16px);
}

.toggle-switch input:focus-visible + .toggle-slider {
    outline: 2px solid var(--ab-teal);
    outline-offset: 2px;
}

/* ── Dark mode overrides for elements that use literal text/background colors ── */
[data-theme="dark"] body { color: var(--ab-text); }

[data-theme="dark"] .app-footer {
    color: var(--ab-text-muted);
    border-top-color: var(--ab-border);
}

[data-theme="dark"] .resolve-value,
[data-theme="dark"] .resolve-label,
[data-theme="dark"] .po-summary-row-value,
[data-theme="dark"] .po-summary-row-label,
[data-theme="dark"] .file-name,
[data-theme="dark"] .drop-zone-text,
[data-theme="dark"] .timing-label,
[data-theme="dark"] .source-panel-value,
[data-theme="dark"] .li-cell,
[data-theme="dark"] .resolve-table td,
[data-theme="dark"] .line-item-table td {
    color: var(--ab-text);
}

[data-theme="dark"] .timing-sep,
[data-theme="dark"] .drop-zone-hint,
[data-theme="dark"] .user-name {
    color: var(--ab-text-muted);
}

[data-theme="dark"] .drop-zone {
    border-color: var(--ab-border);
    color: var(--ab-text-muted);
}
[data-theme="dark"] .drop-zone:hover { border-color: var(--ab-teal); }
[data-theme="dark"] .drop-zone-active {
    border-color: var(--ab-teal);
    background: rgba(69, 143, 156, 0.10);
}

[data-theme="dark"] .resolve-table th,
[data-theme="dark"] .line-item-table th {
    color: var(--ab-text);
    border-color: var(--ab-border);
}

[data-theme="dark"] .resolve-table td,
[data-theme="dark"] .line-item-table td {
    border-color: var(--ab-border);
}

[data-theme="dark"] .resolve-table tbody tr.resolve-row-clickable:hover td,
[data-theme="dark"] .line-item-row-clickable:hover td {
    background: var(--ab-surface-2);
}

[data-theme="dark"] input[type="text"],
[data-theme="dark"] input[type="search"],
[data-theme="dark"] input[type="number"],
[data-theme="dark"] select,
[data-theme="dark"] textarea {
    background: var(--ab-input-bg);
    color: var(--ab-text);
    border-color: var(--ab-input-border);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
}

[data-theme="dark"] input[type="text"]::placeholder,
[data-theme="dark"] input[type="search"]::placeholder,
[data-theme="dark"] textarea::placeholder {
    color: var(--ab-text-muted);
}

/* Highlight chips: lighten background, keep colored text readable */
[data-theme="dark"] .source-po {
    background: #4a3a14;
    color: #fde68a;
}
[data-theme="dark"] .source-gp {
    background: #1e3a64;
    color: #bfdbfe;
}
[data-theme="dark"] .source-both {
    background: #1d4a52;
    color: #99e2eb;
}
[data-theme="dark"] .source-none {
    background: rgba(224, 58, 62, 0.18);
    color: var(--ab-red-light);
}
[data-theme="dark"] .source-lookup {
    background: rgba(99, 102, 241, 0.22);
    color: #c7d2fe;
}
[data-theme="dark"] .source-derived {
    background: rgba(249, 115, 22, 0.22);
    color: #fdba74;
}
[data-theme="dark"] .source-default {
    background: rgba(154, 103, 0, 0.30);
    color: #e3b341;
}

[data-theme="dark"] .field-conflict,
/* Amber panels — cross-reference notes and empty/warning states. `.additional-notes` (Order Notes) used to be in this
   list; it is styled neutrally further down, so the entry here was already dead and only made the section read as
   amber-by-design. Order notes are order CONTENT, not a caution. */
[data-theme="dark"] .xref-notes,
[data-theme="dark"] .source-panel-empty {
    background: #3a2f1a;
    border-color: #6b5526;
    color: #f3d99c;
}

[data-theme="dark"] .xref-notes-text {
    color: #f3d99c;
}

/* Order notes read as ORDINARY TEXT, not amber. They're the order's content — the reviewer reads them, they aren't a
   warning. The gold LEFT BORDER (and the bullet) already identify the section; tinting the prose as well made a normal
   note look like a caution. */
[data-theme="dark"] .order-note-row { color: var(--ab-text); }
[data-theme="dark"] .order-note-row-clickable:hover,
[data-theme="dark"] .order-note-row-clickable:focus-visible { background: rgba(255, 255, 255, 0.07); }

/* PDF viewer canvas wraps stay white (PDF is white) — but soft border helps in dark mode */
[data-theme="dark"] .pdf-page-wrap {
    box-shadow: 0 0 0 1px var(--ab-border);
}

[data-theme="dark"] .source-panel-pdf {
    background: #11151d;
}

[data-theme="dark"] .source-panel-text {
    background: #0e131c;
    border-color: #3a4561;
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.45);
    color: #e8eaed;
}

[data-theme="dark"] .source-panel-text mark {
    background: #6b5526;
    color: #fde68a;
}

/* Buttons: keep brand primary, but soften disabled state in dark */
[data-theme="dark"] .btn-secondary {
    background: var(--ab-surface-2);
    color: var(--ab-text);
    border-color: var(--ab-border);
}
[data-theme="dark"] .btn-secondary:hover:not(:disabled) {
    background: var(--ab-surface-3);
}

/* Settings menu: thumb stays white, slider track darkens */
[data-theme="dark"] .toggle-slider { background: #3d4659; }

/* ── Dark mode: tinted surfaces (alerts, drop zones, summary cards) ── */

/* Drop zone — was light blue tints */
[data-theme="dark"] .drop-zone {
    background: var(--ab-surface-2);
    border-color: var(--ab-border);
    color: var(--ab-text-muted);
}
[data-theme="dark"] .drop-zone:hover {
    background: rgba(69, 143, 156, 0.10);
    border-color: var(--ab-teal);
}
[data-theme="dark"] .drop-zone-active {
    background: rgba(69, 143, 156, 0.15);
    border-color: var(--ab-teal);
}
[data-theme="dark"] .drop-zone-icon { color: var(--ab-teal); }
[data-theme="dark"] .file-label {
    background: rgba(69, 143, 156, 0.15);
    border-color: rgba(69, 143, 156, 0.45);
    color: var(--ab-text);
}
[data-theme="dark"] .file-name { color: var(--ab-text); }
[data-theme="dark"] .file-meta { color: var(--ab-text-muted); }

/* PO summary card variants (#f8faff, #c5d3e8, #eef2f8, #f6f8fb) */
[data-theme="dark"] .po-summary-card,
[data-theme="dark"] .po-summary-info {
    background: var(--ab-surface);
    border-color: var(--ab-border);
}
[data-theme="dark"] .po-summary-header { background: var(--ab-surface-2); }
[data-theme="dark"] .po-summary-title { color: var(--ab-text); }
[data-theme="dark"] .po-summary-row { border-color: var(--ab-border); }
[data-theme="dark"] .po-summary-row-label { color: var(--ab-text-muted); }
[data-theme="dark"] .po-summary-row-value { color: var(--ab-text); }
[data-theme="dark"] .po-totals { background: var(--ab-surface-2); }
[data-theme="dark"] .po-totals-row { color: var(--ab-text); }

/* Preview buttons (dark mode) */
[data-theme="dark"] .preview-btn { background: var(--ab-surface-2); }
[data-theme="dark"] .preview-btn:hover:not(:disabled) {
    background: var(--ab-surface-3);
    border-color: var(--ab-teal);
}
[data-theme="dark"] .preview-btn-icon {
    background: rgba(69, 143, 156, 0.20);
    color: #99e2eb;
}

/* Buttons — secondary/disabled */
[data-theme="dark"] .btn-secondary {
    background: var(--ab-surface-2);
    color: var(--ab-text);
    border-color: var(--ab-border);
}
[data-theme="dark"] .btn-secondary:hover:not(:disabled) { background: var(--ab-surface-3); }
[data-theme="dark"] .btn-secondary:active:not(:disabled) { background: var(--ab-surface); }
[data-theme="dark"] .btn-primary:disabled,
[data-theme="dark"] .btn-secondary:disabled,
[data-theme="dark"] .btn-microsoft:disabled {
    background: #3a4156;
    color: var(--ab-text-muted);
    border-color: var(--ab-border);
}

/* Microsoft sign-in button — was light grey */
[data-theme="dark"] .btn-microsoft {
    background: var(--ab-surface);
    color: var(--ab-text);
    border-color: var(--ab-border);
}
[data-theme="dark"] .btn-microsoft:hover { background: var(--ab-surface-2); }

/* Resize handle background (#f0f2f5) */
[data-theme="dark"] .panel-resize-handle::before { background: var(--ab-border); }

/* Source panel internals (#f8fafc, #f0f4f9, #eef3fa) */
[data-theme="dark"] .source-panel-body { background: var(--ab-surface-2); }
[data-theme="dark"] .source-panel-value-row { background: var(--ab-surface-2); }
[data-theme="dark"] .source-panel-section-label { color: var(--ab-text-muted); }
[data-theme="dark"] .source-panel-value { color: var(--ab-text); }

/* Alert / warning style blocks (the various #fffbf0 + #f7dfa8 / #fff3cd combos) */
[data-theme="dark"] .field-conflict,
[data-theme="dark"] .xref-notes,
[data-theme="dark"] .source-panel-empty,
[data-theme="dark"] .alert-warning {
    background: rgba(238, 185, 89, 0.10);
    border-color: rgba(238, 185, 89, 0.35);
    color: #f3d99c;
}
[data-theme="dark"] .xref-notes-label,
[data-theme="dark"] .field-conflict { color: #f3d99c; }
[data-theme="dark"] .xref-notes-text { color: #f3d99c; }

/* Order Notes: neutral surface with only a thin gold left accent (minimal yellow) — match the light treatment */
[data-theme="dark"] .additional-notes {
    background: var(--ab-surface-2);
    border-color: var(--ab-border);
    color: var(--ab-text);
}
/* Matches the light theme, where this label is --ab-heading like every other section heading. */
[data-theme="dark"] .additional-notes-label { color: var(--ab-heading); }
[data-theme="dark"] .additional-notes-text { color: var(--ab-text); }

/* Error/red soft block (#fff5f5 + #f5a5a5) */
[data-theme="dark"] .alert-error,
[data-theme="dark"] .error-banner {
    background: rgba(224, 58, 62, 0.12);
    border-color: rgba(224, 58, 62, 0.40);
    color: #f7b6b8;
}

/* Line item table — alternating rows / hover bg (#f0f5fb, #deeaf8) */
[data-theme="dark"] .line-item-table tbody tr:nth-child(even) td {
    background: var(--ab-surface-2);
}
[data-theme="dark"] .line-item-table tbody tr.line-item-row-clickable:hover td {
    background: rgba(69, 143, 156, 0.12);
}

/* Resolve table — same idea */
[data-theme="dark"] .resolve-table tbody tr:nth-child(even) td {
    background: var(--ab-surface-2);
}

/* Search/search input area card backgrounds — covered by --ab-surface refactor, but explicit overrides for input borders */
[data-theme="dark"] input[type="text"]:focus,
[data-theme="dark"] input[type="search"]:focus,
[data-theme="dark"] input[type="number"]:focus,
[data-theme="dark"] select:focus,
[data-theme="dark"] textarea:focus {
    border-color: var(--ab-teal);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35), 0 0 0 2px rgba(69, 143, 156, 0.25);
    outline: none;
}

/* Disabled button gradient sits on lighter grey (#8fa0b5) in light mode — already covered above */

/* Misc text colors */
[data-theme="dark"] .resolve-table td.resolve-empty { color: var(--ab-text-muted); }
[data-theme="dark"] .timing-sep { color: var(--ab-border); }
[data-theme="dark"] .timing-pill,
[data-theme="dark"] .timing-bar { color: var(--ab-text); }

/* Card box-shadows — soften in dark mode */
[data-theme="dark"] .search-card,
[data-theme="dark"] .po-card,
[data-theme="dark"] .po-summary-card,
[data-theme="dark"] .source-panel {
    box-shadow: 0 1px 4px var(--ab-shadow);
}

/* ── Customer disambiguation (warning yellow → soft amber in dark) ── */
[data-theme="dark"] .disambig-panel {
    background: rgba(238, 185, 89, 0.08);
    border-color: rgba(238, 185, 89, 0.28);
    border-left-color: var(--ab-gold);
}
[data-theme="dark"] .disambig-title,
[data-theme="dark"] .disambig-col-headers {
    color: #e8c87a;
}
[data-theme="dark"] .disambig-option {
    background: var(--ab-surface);
    border-color: var(--ab-border);
}
[data-theme="dark"] .disambig-option:hover {
    background: rgba(69, 143, 156, 0.10);
    border-color: var(--ab-teal);
}
[data-theme="dark"] .disambig-custnum {
    background: rgba(69, 143, 156, 0.20);
    color: #bfdbfe;
}
[data-theme="dark"] .disambig-custname { color: var(--ab-text); }
[data-theme="dark"] .disambig-notecount { color: var(--ab-text-muted); }

/* ── Other warning-yellow blocks (PO summary alerts, source panel empty) ── */
[data-theme="dark"] .alert-warning,
[data-theme="dark"] .po-totals-warning,
[data-theme="dark"] .source-panel-empty {
    background: rgba(238, 185, 89, 0.10);
    border-color: rgba(238, 185, 89, 0.32);
    color: #e8c87a;
}

/* Tighten harsh row hover in resolve / line-items tables — translucent teal instead of bright */
[data-theme="dark"] .resolve-table tbody tr.resolve-row-clickable:hover td,
[data-theme="dark"] .line-item-table tbody tr.line-item-row-clickable:hover td,
[data-theme="dark"] .results-table tbody tr.line-item-row-clickable:hover td,
[data-theme="dark"] .results-table tbody tr:hover td {
    background: rgba(69, 143, 156, 0.12);
}

/* Remove the alternating row stripe in dark mode — it looked patchy; let the table be flat */
[data-theme="dark"] .resolve-table tbody tr:nth-child(even) td,
[data-theme="dark"] .line-item-table tbody tr:nth-child(even) td {
    background: transparent;
}

/* Buttons that hover to light grey/blue — keep dark in dark mode */
[data-theme="dark"] #resolveBtn { background: var(--ab-surface-2); color: var(--ab-text); }
[data-theme="dark"] #resolveBtn:hover:not(:disabled) { background: var(--ab-surface-3); }
[data-theme="dark"] #searchBtn:hover:not(:disabled),
[data-theme="dark"] #clearBtn:hover,
[data-theme="dark"] #summarizeBtn:hover:not(:disabled) {
    background: var(--ab-primary-light);
}

/* PO summary alert chip (gold left-border block) */
[data-theme="dark"] .po-summary-row-warn,
[data-theme="dark"] [class*="warn-block"] {
    background: rgba(238, 185, 89, 0.10);
    border-color: rgba(238, 185, 89, 0.32);
    color: #e8c87a;
}

/* The .file-label uses --ab-chip-bg now — already auto-themed */

/* ── Admin dashboard ── */
.admin-page {
    max-width: 1100px;
    margin: 0 auto;
}

.admin-card {
    background: var(--ab-surface);
    border: 1px solid var(--ab-border);
    border-radius: 8px;
    box-shadow: 0 1px 2px var(--ab-shadow);
    padding: 24px;
}

.admin-header {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 6px;
}

.admin-back-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--ab-teal);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    padding: 6px 10px;
    border: 1px solid var(--ab-teal);
    border-radius: 6px;
    background: transparent;
    transition: background 0.15s ease, color 0.15s ease;
}

.admin-back-link:hover {
    background: var(--ab-teal);
    color: #fff;
}

[data-theme="dark"] .admin-back-link {
    color: #93cccd;
    border-color: #93cccd;
}

[data-theme="dark"] .admin-back-link:hover {
    background: rgba(69, 143, 156, 0.20);
    color: #fff;
}

.admin-title {
    font-family: 'aktiv-grotesk', Arial, sans-serif;
    font-size: 24px;
    font-weight: 700;
    color: var(--ab-heading);
    margin: 0;
}

.admin-subtitle {
    color: var(--ab-text-muted);
    font-size: 13px;
    margin: 0 0 20px 0;
}

.admin-profiles {
    margin: 0 0 20px 0;
    padding: 14px 16px;
    background: var(--ab-surface-3);
    border: 1px solid var(--ab-border);
    border-radius: 4px;
}

.admin-section-help {
    margin: 0 0 12px 0;
    font-size: 12.5px;
    color: var(--ab-text-muted);
    line-height: 1.45;
}

.admin-section-help code {
    font-family: var(--ab-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px;
    padding: 1px 5px;
    background: var(--ab-surface-2);
    border-radius: 3px;
}

.admin-profiles-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font-size: 13px;
}

.admin-profiles-table thead th {
    text-align: left;
    font-weight: 700;
    color: var(--ab-heading);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 6px 10px;
    border-bottom: 1px solid var(--ab-border);
}

.admin-profiles-table tbody td {
    padding: 8px 10px;
    border-top: 1px solid var(--ab-border);
    vertical-align: top;
    color: var(--ab-text);
}

.admin-profiles-table .profile-col-name      { width: 24%; font-weight: 600; }
.admin-profiles-table .profile-col-provider  { width: 14%; }
.admin-profiles-table .profile-col-url       { width: 50%; }
.admin-profiles-table .profile-col-actions   { width: 12%; white-space: nowrap; text-align: right; }

.profile-url {
    display: block;
    overflow-wrap: anywhere;
    word-break: break-all;
    font-family: var(--ab-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px;
    line-height: 1.4;
    color: var(--ab-text-muted);
}

.profile-row-active {
    background: rgba(56, 189, 160, 0.07);
}

.profile-active-pill {
    display: inline-block;
    margin-left: 8px;
    padding: 1px 7px;
    border-radius: 10px;
    background: var(--ab-mint, #38bda0);
    color: #0b1b1a;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    vertical-align: middle;
}

.profile-empty-row td {
    text-align: center;
    padding: 14px 10px;
    color: var(--ab-text-muted);
    font-style: italic;
}

.btn-apply-profile,
.btn-delete-profile {
    margin-left: 6px;
}

.btn-delete-profile {
    color: #b91c1c;
}

.profile-save-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--ab-border);
}

.profile-name-input {
    flex: 1;
    max-width: 380px;
    padding: 6px 10px;
    font-size: 13px;
    border: 1px solid var(--ab-border);
    border-radius: 3px;
    background: var(--ab-surface);
    color: var(--ab-text);
}

.profile-save-result {
    font-size: 12.5px;
    color: var(--ab-text-muted);
}

.profile-save-result.profile-save-fail {
    color: #b91c1c;
}

.confirm-overlay {
    position: fixed;
    inset: 0;
    background: rgba(11, 17, 27, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 20px;
}

.confirm-overlay[hidden] {
    display: none;
}

.confirm-dialog {
    background: var(--ab-surface);
    color: var(--ab-text);
    border: 1px solid var(--ab-border);
    border-radius: 6px;
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.25);
    max-width: 440px;
    width: 100%;
    padding: 18px 20px;
}

.confirm-title {
    margin: 0 0 8px 0;
    font-size: 15px;
    font-weight: 700;
    color: var(--ab-heading);
}

.confirm-message {
    margin: 0 0 16px 0;
    font-size: 13px;
    line-height: 1.5;
    color: var(--ab-text);
}

.confirm-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    flex-wrap: wrap;
}

.btn-danger {
    background: #b91c1c;
    color: #fff;
}

.btn-danger:hover:not(:disabled) {
    background: #991b1b;
}

/* Unsaved-changes dialog (the Save / Discard / Keep-editing popup) — scoped restyle so the button colors read at a
   glance: teal "Save & continue" = the recommended action (filled primary), red "Discard & continue" = destructive
   (de-emphasized outline), grey "Keep editing" = dismiss. Cleaner header with an amber caution icon + a left/right
   footer split (dismiss on the left, the two continue actions on the right). Scoped so the shared Approve/Deny
   dialogs are untouched. */
.confirm-dialog-unsaved { max-width: 468px; padding: 20px 22px; }
.confirm-dialog-unsaved .confirm-title { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.confirm-dialog-unsaved .confirm-title .ab-icon { width: 18px; height: 18px; color: #d98a00; flex: none; }
/* All three actions on ONE right-aligned row — never stacking. */
.confirm-dialog-unsaved .confirm-actions { justify-content: flex-end; align-items: center; flex-wrap: nowrap; }
/* Discard Changes = filled red (destructive). */
.btn-discard { background: var(--ab-red-light); color: #fff; border: 1px solid var(--ab-red-light); }
.btn-discard:hover:not(:disabled) { background: var(--ab-red); border-color: var(--ab-red); }
/* Save & Continue = teal (the recommended action) — the base .btn-primary is navy, so override to the teal token. */
.btn-teal { background: var(--ab-teal); }
.btn-teal:hover:not(:disabled) { background: #3a7a85; }
[data-theme="dark"] .confirm-dialog-unsaved .confirm-title .ab-icon { color: #f0b429; }

[data-theme="dark"] .confirm-overlay {
    background: rgba(0, 0, 0, 0.65);
}

[data-theme="dark"] .confirm-dialog {
    background: var(--ab-surface-2);
    border-color: var(--ab-border);
}

[data-theme="dark"] .btn-danger {
    background: #dc2626;
}

[data-theme="dark"] .btn-danger:hover:not(:disabled) {
    background: #b91c1c;
}

.admin-connections {
    margin: 0 0 24px 0;
    padding: 14px 16px;
    background: var(--ab-surface-3);
    border: 1px solid var(--ab-border);
    border-radius: 4px;
}

.admin-section-title {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ab-heading);
    margin: 0 0 10px 0;
}

.admin-connections-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.admin-connections-head .admin-section-title { margin: 0; }

.admin-connections-list {
    margin-top: 12px;
    border: 1px solid var(--ab-border);
    border-radius: 6px;
    overflow: hidden;
    background: var(--ab-surface-2);
}

.admin-connections-list .connection-row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 14px;
    border-top: 1px solid var(--ab-border);
}
.admin-connections-list .connection-row:first-child { border-top: none; }
.admin-connections-list .connection-row:hover { background: var(--ab-surface-hover); }

.admin-connections-list .conn-info {
    flex: 1 1 46%;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.admin-connections-list .conn-label {
    font-weight: 600;
    font-size: 13px;
    color: var(--ab-heading);
}
.admin-connections-list .conn-target {
    color: var(--ab-text-muted);
    font-family: var(--ab-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 12px;
    overflow-wrap: anywhere;
}

/* The result fills the space BETWEEN the info and the button, so the Test button stays pinned to the right and never
   shifts as the result text changes length (the reported "buttons move around" bug). */
.admin-connections-list .test-result {
    flex: 1 1 auto;
    min-width: 0;
    text-align: right;
}
.admin-connections-list .conn-note {
    flex: 0 0 auto;
    color: var(--ab-text-muted);
    font-style: italic;
    font-size: 12px;
}
.admin-connections-list .btn-test { flex: 0 0 auto; }

/* Collapsible per-system settings groups */
.settings-group {
    margin: 0 0 12px 0;
    border: 1px solid var(--ab-border);
    border-radius: 4px;
    overflow: hidden;
}

.settings-group-summary {
    list-style: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    background: var(--ab-surface-3);
    color: var(--ab-heading);
    font-weight: 700;
    font-size: 13px;
    -webkit-user-select: none;
    user-select: none;
}

.settings-group-summary::-webkit-details-marker { display: none; }
.settings-group-summary:hover { filter: brightness(0.97); }

.settings-group-chevron {
    width: 16px;
    height: 16px;
    color: var(--ab-teal, #458F9C);
    transition: transform 0.15s ease;
    flex: 0 0 auto;
}

.settings-group[open] > .settings-group-summary .settings-group-chevron { transform: rotate(90deg); }

.settings-group-name { text-transform: uppercase; letter-spacing: 0.06em; }

.settings-group-count {
    margin-left: auto;
    font-weight: 400;
    font-size: 11.5px;
    color: var(--ab-text-muted);
    text-transform: none;
    letter-spacing: 0;
}

.settings-group .admin-table thead th { border-top: 1px solid var(--ab-border); }

.admin-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
}

.admin-table thead th {
    text-align: left;
    font-weight: 700;
    color: var(--ab-heading);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 8px 12px;
    border-bottom: 1px solid var(--ab-border);
    background: var(--ab-surface-3);
}

.admin-table .col-key       { width: 34%; }
.admin-table .col-value     { width: 28%; }
.admin-table .col-type      { width: 10%; }
.admin-table .col-meta      { width: 20%; }
.admin-table .col-actions   { width: 8%; text-align: right; }

.admin-table tbody td {
    padding: 12px;
    border-bottom: 1px solid var(--ab-border);
    vertical-align: top;
    font-size: 14px;
    color: var(--ab-text);
    word-wrap: break-word;
}

.admin-table .setting-row:hover {
    background: var(--ab-surface-hover);
}

.admin-table .setting-row.row-editing {
    background: var(--ab-surface-2);
}

.setting-key {
    font-family: 'Courier New', Courier, monospace;
    font-weight: 600;
    color: var(--ab-heading);
}

.setting-description {
    color: var(--ab-text-muted);
    font-size: 12px;
    margin-top: 4px;
    line-height: 1.4;
}

.value-display {
    font-family: 'Courier New', Courier, monospace;
    color: var(--ab-text);
    word-break: break-all;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.value-text {
    flex: 0 1 auto;
}

/* Per-row test button = brand secondary (outlined teal); "Test all" = solid teal. Both real, consistently-sized buttons. */
.btn-test,
.btn-test-all {
    flex: 0 0 auto;
    box-sizing: border-box;
    min-height: 34px;
    padding: 7px 18px;
    border-radius: 6px;
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    font-family: 'proxima-nova', Arial, sans-serif;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.btn-test {
    background: transparent;
    border: 1px solid var(--ab-teal);
    color: var(--ab-teal);
}
.btn-test:hover:not(:disabled) {
    background: var(--ab-teal);
    color: #fff;
}

.btn-test-all {
    background: var(--ab-teal);
    border: 1px solid var(--ab-teal);
    color: #fff;
}
.btn-test-all:hover:not(:disabled) {
    background: #3a7b86;
    border-color: #3a7b86;
}

.btn-test:disabled,
.btn-test-all:disabled {
    opacity: 0.6;
    cursor: wait;
}

.test-result {
    font-family: 'proxima-nova', Arial, sans-serif;
    font-size: 12px;
    font-weight: 600;
    display: inline-block;
    max-width: 100%;
    text-align: left;
    vertical-align: middle;
    overflow-wrap: anywhere;
    word-break: break-word;
}

.test-result-ok {
    color: #166534;
}

.test-result-fail {
    color: #b91c1c;
}

[data-theme="dark"] .test-result-ok { color: #6ee7b7; }
[data-theme="dark"] .test-result-fail { color: var(--ab-red-light); }

.value-edit {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.value-input {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--ab-input-border);
    border-radius: 4px;
    background: var(--ab-input-bg);
    color: var(--ab-text);
    font-family: 'Courier New', Courier, monospace;
    font-size: 13px;
}

.value-input:focus {
    outline: none;
    border-color: var(--ab-teal);
    box-shadow: 0 0 0 2px rgba(69, 143, 156, 0.25);
}

.value-textarea {
    resize: vertical;
    min-height: 60px;
}

.bool-toggle {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    user-select: none;
}

.bool-toggle-label {
    font-family: 'Courier New', Courier, monospace;
    font-size: 13px;
    color: var(--ab-text);
    min-width: 36px;
}

.type-pill {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    text-transform: lowercase;
    background: var(--ab-chip-bg);
    color: var(--ab-chip-text);
    font-family: 'Courier New', Courier, monospace;
}

.type-pill.type-string  { background: #dceaee; color: #1f3a4a; }
.type-pill.type-int     { background: #e0e7ff; color: #2d2f78; }
.type-pill.type-bool    { background: #d1fae5; color: #065f46; }
.type-pill.type-json    { background: #fef3c7; color: #78350f; }
.type-pill.type-endpoint { background: #fce7f3; color: #831843; }
.type-pill.type-endpoint-provider { background: #ede9fe; color: #4c1d95; }

[data-theme="dark"] .type-pill.type-string  { background: rgba(69, 143, 156, 0.15); color: #93cccd; }
[data-theme="dark"] .type-pill.type-int     { background: rgba(124, 92, 230, 0.15); color: #c4b5fd; }
[data-theme="dark"] .type-pill.type-bool    { background: rgba(34, 197, 94, 0.15); color: #6ee7b7; }
[data-theme="dark"] .type-pill.type-json    { background: rgba(234, 179, 8, 0.15); color: #fde68a; }
[data-theme="dark"] .type-pill.type-endpoint { background: rgba(236, 72, 153, 0.15); color: #f9a8d4; }
[data-theme="dark"] .type-pill.type-endpoint-provider { background: rgba(139, 92, 246, 0.15); color: #c4b5fd; }

.endpoint-display {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.endpoint-url {
    font-family: 'Courier New', Courier, monospace;
    font-size: 13px;
    color: var(--ab-text);
    word-break: break-all;
}

.endpoint-edit {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.endpoint-field {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.endpoint-field-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--ab-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.endpoint-provider,
.endpoint-url-input {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--ab-input-border);
    border-radius: 4px;
    background: var(--ab-input-bg);
    color: var(--ab-text);
    font-family: 'Courier New', Courier, monospace;
    font-size: 13px;
}

.endpoint-provider:focus,
.endpoint-url-input:focus {
    outline: none;
    border-color: var(--ab-teal);
    box-shadow: 0 0 0 2px rgba(69, 143, 156, 0.25);
}

.meta-by {
    font-size: 13px;
    color: var(--ab-text);
}

.meta-at {
    font-size: 11px;
    color: var(--ab-text-muted);
    margin-top: 2px;
}

.col-actions button {
    background: none;
    border: 1px solid var(--ab-border);
    color: var(--ab-text-muted);
    padding: 4px 8px;
    border-radius: 4px;
    cursor: pointer;
    margin-left: 4px;
    transition: background 0.1s, color 0.1s, border-color 0.1s;
}

.col-actions button:hover {
    background: var(--ab-surface-hover);
    color: var(--ab-text);
    border-color: var(--ab-teal);
}

.col-actions .btn-save {
    background: var(--ab-teal);
    color: #fff;
    border-color: var(--ab-teal);
    padding: 6px 12px;
    font-weight: 600;
}

.col-actions .btn-save:hover {
    background: var(--ab-primary);
    border-color: var(--ab-primary);
    color: #fff;
}

.col-actions .btn-cancel {
    padding: 6px 12px;
}

.history-row td {
    background: var(--ab-surface-2);
    padding: 0;
}

.history-container {
    padding: 12px 24px;
    border-top: 1px solid var(--ab-border);
}

.history-loading,
.history-empty {
    color: var(--ab-text-muted);
    font-size: 12px;
    font-style: italic;
    padding: 4px 0;
}

.history-entry {
    padding: 8px 0;
    border-bottom: 1px dashed var(--ab-border);
}

.history-entry:last-child {
    border-bottom: none;
}

.history-entry-meta {
    display: flex;
    gap: 12px;
    font-size: 11px;
    color: var(--ab-text-muted);
    margin-bottom: 4px;
}

.history-who {
    font-weight: 600;
}

.history-entry-vals {
    display: flex;
    gap: 8px;
    align-items: center;
    font-family: 'Courier New', Courier, monospace;
    font-size: 12px;
    flex-wrap: wrap;
}

.history-old {
    color: var(--ab-text-muted);
    text-decoration: line-through;
}

.history-arrow {
    color: var(--ab-text-muted);
}

.history-new {
    color: var(--ab-text);
    font-weight: 600;
}

.admin-error {
    margin-top: 16px;
    padding: 10px 14px;
    border-radius: 6px;
    background: rgba(254, 226, 226, 1);
    color: #b91c1c;
    border: 1px solid rgba(252, 165, 165, 0.6);
    font-size: 13px;
}

[data-theme="dark"] .admin-error {
    background: rgba(127, 29, 29, 0.25);
    color: var(--ab-red-light);
    border-color: rgba(248, 113, 113, 0.35);
}

/* ── User management page (#42) ── */
.admin-success {
    margin-top: 16px;
    padding: 10px 14px;
    border-radius: 6px;
    background: rgba(220, 252, 231, 1);
    color: #166534;
    border: 1px solid rgba(134, 239, 172, 0.7);
    font-size: 13px;
}

[data-theme="dark"] .admin-success {
    background: rgba(20, 83, 45, 0.25);
    color: #86efac;
    border-color: rgba(74, 222, 128, 0.35);
}

.admin-intro { color: var(--ab-text); opacity: 0.8; font-size: 13px; margin: 4px 0 16px; }
.admin-subtle { color: var(--ab-text); opacity: 0.6; font-size: 12px; }

.user-inline-form { display: inline-flex; align-items: center; gap: 8px; }
.user-inline-form + .user-inline-form { margin-left: 8px; }

.btn-link-danger {
    background: transparent;
    border: none;
    color: var(--ab-red-light, #b91c1c);
    cursor: pointer;
    font-size: 12px;
    text-decoration: underline;
    padding: 0;
    margin-left: 8px;
}

.btn-link-danger:hover { opacity: 0.8; }

/* ── Admin store degraded banner (rendered site-wide when settings can't persist) ── */
.admin-store-banner {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 16px;
    background: #fff5f5;
    border-bottom: 2px solid #e03a3e;
    color: #7a1f22;
    font-size: 13px;
    line-height: 1.45;
}

.admin-store-banner .ab-icon {
    color: #e03a3e;
    flex-shrink: 0;
    margin-top: 1px;
}

.admin-store-banner a {
    color: inherit;
    text-decoration: underline;
}

[data-theme="dark"] .admin-store-banner {
    background: rgba(224, 58, 62, 0.14);
    border-bottom-color: rgba(248, 113, 113, 0.55);
    color: #f7b6b8;
}

[data-theme="dark"] .admin-store-banner .ab-icon {
    color: #f7b6b8;
}

/* In-app broadcast notice (admin-posted, e.g. a maintenance warning). Mirrors .admin-store-banner's
   layout; severity only changes colour. Each severity needs its own dark override for the same reason
   .admin-store-banner does — a pale background with dark text is unreadable once the theme flips. */
.oh-broadcast {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 16px;
    font-size: 13px;
    border-bottom: 2px solid transparent;
}

.oh-broadcast[hidden] { display: none; }

.oh-broadcast .ab-icon {
    color: inherit;
    flex-shrink: 0;
    margin-top: 1px;
}

.oh-broadcast.ob-warning {
    background: #fff8e8;
    border-bottom-color: var(--ab-gold);
    color: #6b4a12;
}

[data-theme="dark"] .oh-broadcast.ob-warning {
    background: rgba(238, 185, 89, 0.14);
    border-bottom-color: rgba(238, 185, 89, 0.55);
    color: #f3d99c;
}

.oh-broadcast.ob-info {
    background: var(--ab-surface-2);
    border-bottom-color: var(--ab-border);
    color: var(--ab-text);
}

.oh-broadcast-text { font-weight: 600; }

.oh-broadcast-countdown {
    color: inherit;
    opacity: 0.75;
    font-weight: 400;
}

/* SVG icons stay teal by default; for icons on dark backgrounds they already use currentColor */
