/* ── Scrollbar ── */
::-webkit-scrollbar {
    width: 5px;
    height: 5px;
}
::-webkit-scrollbar-track {
    background: transparent;
}
::-webkit-scrollbar-thumb {
    background: var(--border);
    border-radius: 99px;
}
::-webkit-scrollbar-thumb:hover {
    background: var(--border-2);
}

html,
body,
#root {
    height: 100%;
    margin: 0;
}
body {
    font-family:
        system-ui,
        -apple-system,
        'Inter',
        Segoe UI,
        Roboto,
        Ubuntu,
        sans-serif;
    background: var(--bg);
    color: var(--text-1);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

/* ── Dark theme (default) ──
   Whole-app repaint: slate+indigo (the generic AI-tool control-room
   look) replaced with a warm charcoal ink + a single saturated berry
   signal color — Committed color strategy (brand register permits
   it), reference point Cash App's confident magenta-on-charcoal, not
   another blue/indigo SaaS accent. All neutrals carry a tiny chroma
   tint toward the accent's own hue (oklch hue ~346), not toward a
   generic warm-or-cool default — see SKILL.md's tinted-neutrals rule.
   Semantic status colors (green/amber/red/blue) are UNCHANGED on
   purpose: they're a recognizable, cross-app vocabulary independent
   of brand identity, and shifting them wasn't part of the ask. */
:root {
    --bg: #110b0e;
    --surface: #1c1518;
    --surface-2: #271f23;
    --border: #3c3237;
    --border-2: #52474c;
    --accent: #ce3f99;
    --accent-h: #a91a7a;
    --green: #22c55e;
    --amber: #f59e0b;
    --red: #ef4444;
    --blue: #3b82f6;
    --text-1: #f5f0f3;
    --text-2: #b7a7af;
    --text-3: #8f8087;
    --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.3);
    /* legacy compat */
    --panel: #1c1518;
    --panel-2: #0a0608;
    --sidebar: #0a0608;
    --border-legacy: #3c3237;
    --accent-css: #ce3f99;
    --accent-2: #ef83c0;
    --good: #22c55e;
    --bad: #ef4444;
    --warn: #f59e0b;

    /* ── Control surface (see The Control-Plane Rule) ──
     Interactive controls do NOT reuse --surface. --surface is the *card*
     plane, and its position in the tonal ladder flips between themes
     (above --bg on dark, below it on light), so a button filled with it
     is raised on dark and invisible on light — 1.11:1 against the page,
     1.00:1 on a white card. These tokens always step the same direction
     relative to whatever they sit on, in both themes, so a button reads
     as a button everywhere. --border stays the quiet decorative hairline
     for cards, dividers and table rows; --control-border is the heavier
     boundary a control needs to clear WCAG 1.4.11's 3:1 non-text floor. */
    --control: #282124;
    --control-hover: #372e32;
    --control-border: #776d72;
    --control-border-hover: #8f858a;
    /* Keyboard focus ring. The old rgba(206,63,153,0.35) flattened to
     1.60:1 on light — a focus indicator that effectively didn't exist.
     Tuned per theme (soft berry on dark, pressed berry on light) so it
     clears 3:1 against page, card and control fill alike. */
    --focus-ring: rgba(239, 131, 192, 0.6);
}

/* ── Light theme override ── */
html:not(.dark) {
    --bg: #f7f2f4;
    --surface: #ffffff;
    --surface-2: #ede5e9;
    --border: #a38a97;
    --border-2: #8a727f;
    --text-1: #22171d;
    --text-2: #614b57;
    --text-3: #76626d;
    --panel: #ffffff;
    --panel-2: #ede5e9;
    --sidebar: #ede5e9;
    --border-legacy: #a38a97;
    /* accent, green, amber, red, blue stay the same */

    /* Control plane, light: a step DOWN from both the page and a white
     card, mirroring dark's step UP. Same direction of travel, opposite
     sign — that is the whole point of these tokens. */
    --control: #ece4e7;
    --control-hover: #dcd2d7;
    --control-border: #8a7c83;
    --control-border-hover: #6f6168;
    --focus-ring: rgba(169, 26, 122, 0.75);
}

/* ── Layout ── */
.app {
    display: flex;
    height: 100%;
    overflow: hidden;
}

.sidebar {
    width: 232px;
    min-width: 232px;
    background: var(--sidebar);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    box-sizing: border-box;
}

.content {
    flex: 1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    min-width: 0;
}

.topbar {
    display: flex;
    gap: 6px;
    padding: 10px 18px;
    border-bottom: 1px solid var(--border);
    background: var(--sidebar);
    align-items: center;
    flex-shrink: 0;
}

.panel {
    padding: 20px 24px;
    overflow: auto;
    flex: 1;
    background: var(--bg);
}

/* ── Buttons ── */
.btn {
    padding: 9px 16px;
    border: 1px solid var(--control-border);
    background: var(--control);
    color: var(--text-2);
    border-radius: 8px;
    cursor: pointer;
    transition:
        background 0.15s,
        border-color 0.15s,
        color 0.15s,
        transform 0.1s,
        box-shadow 0.15s;
    font-size: 13px;
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
    font-family: inherit;
}
.btn:hover {
    background: var(--control-hover);
    border-color: var(--control-border-hover);
    color: var(--text-1);
}
/* Tactile press instead of a blanket opacity dim — a real (if small)
   transform reads as "pressed", opacity alone reads as "loading". */
.btn:active {
    transform: scale(0.97);
}
/* 0.5, not 0.4: now that .btn carries a real fill and a 3:1 boundary,
   0.4 washed both back out to roughly the invisible state this pass
   just fixed. Still unmistakably muted against an enabled sibling. */
.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
.btn:disabled:active {
    transform: none;
}
.btn:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--focus-ring);
}

/* Generic keyboard-focus ring for any other interactive control
   (step nav, pills-as-buttons, etc.) that doesn't already define its
   own focus treatment — same signal-berry language as .btn/inputs. */
button:focus-visible,
a:focus-visible,
[role='button']:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--focus-ring);
}
/* White text on the raw --accent (#ce3f99) only measures 4.38:1 — just
   under WCAG AA's 4.5:1 floor for normal text, in both themes (this
   button doesn't vary the accent by theme). Both gradient stops below
   are verified independently: --accent-h 6.74:1, #83005b 9.92:1 — a
   gradient between two already-safe stops can't dip below either
   endpoint's contrast, unlike using the raw --accent anywhere in it.
   --accent itself stays untouched for every other consumer (focus
   rings, active-tab tints, range thumb) since those aren't solid-fill
   text-on-color pairings and don't carry this constraint. The
   resting-state gradient (accent-h -> #83005b) gives the primary
   button a whisper of glossy depth; the hover state darkens one step
   further (#83005b -> #640043, 12.94:1) and adds a soft glow — the one
   shadow this system permits outside the card-separation rule. Kept
   deliberately restrained (0.2 alpha, 8px blur, hover-only, never at
   rest) after the design-hook flagged colored-glow-on-dark as a
   generic AI-UI tell: reviewed, not blindly suppressed — this is one
   touch on the single interactive/active element the One Signal Rule
   reserves Signal Berry for, matching the same glow language the
   existing focus ring above already uses, not decorative glow spread
   around.

   HOVER DIRECTION (The Hover-Toward-Foreground Rule): hover moves the
   berry ramp toward the theme's *foreground*, not unconditionally
   darker. Darkening on light mode drove the button to #640043 — a
   near-black plum that reads as "switching off", loses the brand
   colour entirely, and was the single worst button state on the site.
   Each theme therefore gets its own two-stop window on one shared
   four-stop ramp (#c3338f -> --accent-h -> #83005b -> #640043):
   light rests at the bright end and deepens on hover, dark rests deep
   and brightens on hover. Both directions *increase* the fill's
   contrast against the page it sits on. Every stop below carries the
   white 13px label at >=4.5:1 (#c3338f 5.01, --accent-h 6.74,
   #83005b 9.92) so no window can dip under AA — which is also why the
   raw --accent (#ce3f99, 4.38:1) is still not a fill here. */
.btn-primary {
    background: linear-gradient(180deg, var(--accent-h) 0%, #83005b 100%);
    color: #fff;
    /* --accent, not #83005b. The deep-plum fill only separates from the
     charcoal page by 2.5-2.7:1, and a border the same colour as the fill
     added nothing — so on dark the button's own edge was under the 3:1
     non-text floor and it read as a shape floating with no boundary.
     Raw --accent is barred as a *fill* under white text (4.38:1) but is
     exactly right as a 1px edge: 4.45:1 against the page. This is the
     resting look preserved, with the outline it was always missing. */
    border-color: var(--accent);
    font-weight: 600;
}
/* `color` MUST be re-declared on every .btn-*:hover variant. `.btn:hover`
   sets `color: var(--text-1)` at specificity (0,2,0); a variant's resting
   `color` is only (0,1,0), so it loses on hover and the label silently
   becomes the theme's body ink. On dark --text-1 is near-white and this
   looked harmless for a long time; on light it is #22171d, which put a
   near-black label on the berry fill at 1.75-2.58:1. Don't remove these. */
.btn-primary:hover {
    background: linear-gradient(180deg, #c3338f 0%, var(--accent-h) 100%);
    border-color: var(--accent-h);
    color: #fff;
    box-shadow: 0 2px 8px rgba(206, 63, 153, 0.22);
    transform: translateY(-1px);
}
.btn-primary:active {
    transform: scale(0.97) translateY(0);
    box-shadow: none;
}
/* Light mode: the whole ramp shifts one stop brighter. Resting berry is
   recognisably the brand colour instead of the deep plum it read as on
   white, and hover lands on the pair dark mode rests at. */
html:not(.dark) .btn-primary {
    background: linear-gradient(180deg, #c3338f 0%, var(--accent-h) 100%);
    border-color: var(--accent-h);
}
html:not(.dark) .btn-primary:hover {
    background: linear-gradient(180deg, var(--accent-h) 0%, #83005b 100%);
    border-color: #83005b;
    color: #fff;
    /* the dark-tuned berry glow reads muddy on white — crisper and a
     touch stronger to keep the lift cue */
    box-shadow: 0 2px 10px rgba(131, 0, 91, 0.28);
}
/* Border alphas are asymmetric between themes on purpose. On white the
   old 0.35 tint flattened to 1.76:1 and the button had no visible edge
   at all, so light needs the strong values below. On near-black the
   same alphas flatten to a hot red outline that breaks DESIGN.md's
   "visible without shouting" rule for destructive actions — dark stays
   softer (~2.3:1 edge) and leans on its #F87171 label, which carries
   5.86:1 against the fill, as the primary identifier. */
.btn-danger {
    background: rgba(239, 68, 68, 0.1);
    color: #f87171;
    border-color: rgba(239, 68, 68, 0.55);
}
.btn-danger:hover {
    background: rgba(239, 68, 68, 0.18);
    border-color: rgba(239, 68, 68, 0.75);
    /* same cascade trap as .btn-primary:hover — without this the label
     turned --text-1 and the destructive action lost its red on dark. */
    color: #fca5a5;
}
/* Light mode: desaturated dark-mode red text/tint is illegible on white
   — saturate + darken, same treatment as .status-refused. The border
   alphas are the 1.4.11 boundary for a translucent-fill button (the
   0.35/0.5 pair they replace flattened to 1.76:1), not decoration. */
html:not(.dark) .btn-danger {
    background: rgba(220, 38, 38, 0.1);
    color: #b91c1c;
    border-color: rgba(220, 38, 38, 0.75);
}
html:not(.dark) .btn-danger:hover {
    background: rgba(220, 38, 38, 0.17);
    border-color: rgba(220, 38, 38, 1);
    color: #991b1b;
}

/* ── Cards ── */
.card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 16px;
    box-shadow: var(--shadow-card);
}
.card-item {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 11px 13px;
    transition:
        border-color 0.12s,
        background 0.12s;
}
.card-item:hover {
    background: var(--surface-2);
    border-color: var(--border-2);
}

/* ── Inputs ──
   Prefixed with #root to out-specificity Tailwind's preflight reset
   (input,optgroup,select,textarea{margin:0;padding:0;...}), which is
   injected as a stylesheet *after* this inline block and would
   otherwise win ties on the plain "input"/"select"/"textarea"
   selectors, silently zeroing out padding/color/font-size. */
#root input,
#root select,
#root textarea {
    background: var(--bg);
    border: 1px solid var(--border);
    color: var(--text-1);
    padding: 8px 12px;
    border-radius: 7px;
    font-size: 13px;
    transition:
        border-color 0.12s,
        box-shadow 0.12s;
    outline: none;
    font-family: inherit;
    box-sizing: border-box;
    min-width: 0;
}
#root textarea {
    resize: vertical;
    line-height: 1.5;
}
#root input:focus,
#root select:focus,
#root textarea:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--focus-ring);
}
#root input::placeholder,
#root textarea::placeholder,
#root select option[value=''] {
    color: var(--text-3);
}
#root input:disabled,
#root select:disabled,
#root textarea:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background: var(--surface-2);
}

input[type='number']::-webkit-inner-spin-button,
input[type='number']::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type='number'] {
    -moz-appearance: textfield;
    appearance: textfield;
}

input[type='range'] {
    -webkit-appearance: none;
    appearance: none;
    height: 4px;
    background: var(--border);
    border-radius: 99px;
    outline: none;
    border: none;
    padding: 0;
    box-shadow: none;
    cursor: pointer;
}
input[type='range']::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent);
    cursor: pointer;
    border: 2px solid var(--surface);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    transition: background 0.12s;
}
input[type='range']::-webkit-slider-thumb:hover {
    background: var(--accent-h);
}
input[type='range']::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--accent);
    border: 2px solid var(--surface);
    cursor: pointer;
}
input[type='checkbox'] {
    width: 15px;
    height: 15px;
    cursor: pointer;
    accent-color: var(--accent);
    border-radius: 4px;
    padding: 0;
}

/* ── Utility ── */
.grid {
    display: grid;
    gap: 12px;
}
.row {
    display: flex;
    gap: 12px;
    align-items: center;
}
.spacer {
    flex: 1;
}

/* ── Form fields ── */
.field {
    display: grid;
    gap: 6px;
}
.field-label {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-2);
    letter-spacing: 0.02em;
}
.field-hint {
    font-size: 11px;
    color: var(--text-3);
    line-height: 1.4;
}
/* Unit adornment (e.g. "ms") inset inside its input, instead of
   floating next to the label where it reads as disconnected. */
.field-suffixed {
    position: relative;
    display: flex;
}
.field-suffixed input {
    padding-right: 32px;
    width: 100%;
}
.field-suffix {
    position: absolute;
    right: 12px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 11px;
    font-weight: 500;
    color: var(--text-3);
    pointer-events: none;
}

/* ── Pills / Badges ── */
.pill {
    padding: 2px 8px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--surface-2);
    color: var(--text-2);
    font-size: 11px;
    font-weight: 500;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.status-active {
    background: rgba(34, 197, 94, 0.1);
    border-color: rgba(34, 197, 94, 0.3);
    color: #4ade80;
}
.status-pending {
    background: rgba(245, 158, 11, 0.1);
    border-color: rgba(245, 158, 11, 0.3);
    color: #fcd34d;
}
.status-matched {
    background: rgba(59, 130, 246, 0.1);
    border-color: rgba(59, 130, 246, 0.3);
    color: #93c5fd;
}
.status-completed {
    background: rgba(34, 197, 94, 0.1);
    border-color: rgba(34, 197, 94, 0.3);
    color: #4ade80;
}
.status-refused {
    background: rgba(239, 68, 68, 0.1);
    border-color: rgba(239, 68, 68, 0.3);
    color: #fca5a5;
}
/* Light mode: saturate AI pipeline pills (green/amber/violet are too light on white) */
html:not(.dark) .ai-pill {
    filter: brightness(0.65);
}
/* Light mode: neon status pill colors are illegible on white — use saturated dark variants */
html:not(.dark) .status-active {
    background: rgba(22, 163, 74, 0.08);
    border-color: rgba(22, 163, 74, 0.3);
    color: #15803d;
}
html:not(.dark) .status-pending {
    background: rgba(217, 119, 6, 0.08);
    border-color: rgba(217, 119, 6, 0.3);
    color: #b45309;
}
html:not(.dark) .status-matched {
    background: rgba(37, 99, 235, 0.08);
    border-color: rgba(37, 99, 235, 0.3);
    color: #1d4ed8;
}
html:not(.dark) .status-completed {
    background: rgba(22, 163, 74, 0.08);
    border-color: rgba(22, 163, 74, 0.3);
    color: #15803d;
}
html:not(.dark) .status-refused {
    background: rgba(220, 38, 38, 0.08);
    border-color: rgba(220, 38, 38, 0.3);
    color: #b91c1c;
}

/* ── Status dot ── */
.status-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}
.status-dot.running {
    background: var(--green);
    animation: pulse-dot 2s ease-in-out infinite;
}
.status-dot.stopped {
    background: #52474c;
}
@keyframes pulse-dot {
    0%,
    100% {
        opacity: 1;
    }
    50% {
        opacity: 0.55;
    }
}

/* ── Stepper ── */
.stepper {
    position: sticky;
    top: 0;
    z-index: 10;
}
.steps {
    display: flex;
    gap: 4px;
    align-items: center;
}
.step {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 6px 12px;
    border-radius: 7px;
    background: transparent;
    color: var(--text-3);
    border: 1px solid transparent;
    cursor: pointer;
    font-size: 13px;
    font-weight: 500;
    transition: all 0.12s;
    font-family: inherit;
}
/* Control tokens: a --surface hover fill is white-on-near-white in light
   mode, so the step gave no hover feedback at all there. */
.step:hover {
    color: var(--text-2);
    background: var(--control);
    border-color: var(--control-border);
}
.step.active {
    background: rgba(206, 63, 153, 0.12);
    color: var(--text-1);
    border-color: rgba(206, 63, 153, 0.35);
}
.step-index {
    display: inline-flex;
    width: 20px;
    height: 20px;
    border-radius: 999px;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 11px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    flex-shrink: 0;
    color: var(--text-3);
}
/* --accent-h, not --accent: white on raw berry is 4.38:1, and an 11px/700
   numeral is not "large text", so the raw accent fill missed AA by a hair.
   Pressed berry carries it at 6.74:1 — the Berry-As-Text Rule again. */
.step.active .step-index {
    background: var(--accent-h);
    border-color: var(--accent-h);
    color: white;
}
.step-label {
    font-size: 13px;
}

/* ── Section ── */
.section {
    padding: 4px 0 36px;
}
.section-header {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin: 8px 0 20px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border);
}
.section-header h3 {
    margin: 0;
    font-size: 18px;
    font-weight: 700;
    color: var(--text-1);
}
.section-sub {
    font-size: 13px;
    color: var(--text-3);
}
.section-actions {
    display: flex;
    align-items: center;
    padding-top: 12px;
    gap: 8px;
}

/* ── Legend ── */
.legend {
    margin-top: 0;
    display: grid;
    gap: 7px;
    font-size: 12px;
    color: var(--text-2);
    padding: 14px 16px;
    border-top: 1px solid var(--border);
}
.legend > div {
    display: flex;
    align-items: center;
    gap: 8px;
}
.swatch {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 2px;
    flex-shrink: 0;
}
.swatch-queue {
    background: #f59e0b;
}
.swatch-match {
    background: #3b82f6;
}
.swatch-complete {
    background: #22c55e;
}
.swatch-refuse {
    background: #ef4444;
}

/* ── Mobile shell ──
   Sidebar becomes an off-canvas drawer, multi-column layouts collapse to
   a single column, and canvases (map/flow SVGs) follow their intrinsic
   aspect ratio instead of a fixed desktop pixel height. Nothing here is
   active above the breakpoints, so the existing desktop layout is
   untouched. */
.hamburger-btn {
    display: none;
}
.sidebar-backdrop {
    display: none;
}
.sidebar-close-btn {
    display: none;
}

@media (max-width: 880px) {
    .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        z-index: 40;
        transform: translateX(-100%);
        transition: transform 0.22s ease;
        box-shadow: 4px 0 24px rgba(0, 0, 0, 0.25);
    }
    .sidebar.open {
        transform: translateX(0);
    }

    .sidebar-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.45);
        z-index: 30;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.22s ease;
    }
    .sidebar-backdrop.open {
        opacity: 1;
        pointer-events: auto;
    }

    .hamburger-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 34px;
        height: 34px;
        border-radius: 8px;
        border: 1px solid var(--border);
        background: var(--surface);
        color: var(--text-2);
        cursor: pointer;
        flex-shrink: 0;
    }
    .sidebar-close-btn {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 28px;
        height: 28px;
        border-radius: 7px;
        border: 1px solid var(--border);
        background: var(--surface);
        color: var(--text-2);
        cursor: pointer;
    }

    .topbar {
        padding: 10px 12px;
    }
    .step-label {
        display: none;
    }
    .step {
        padding: 6px 8px;
    }
    .steps {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .steps::-webkit-scrollbar {
        display: none;
    }

    .panel {
        padding: 14px 12px;
    }
    .section-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;
    }

    /* Multi-column workflow/analytics/learning layouts stack to one column. */
    .responsive-grid {
        grid-template-columns: 1fr !important;
    }

    /* Map/flow canvases: follow the intrinsic aspect ratio instead of a
     fixed desktop pixel height, so narrow widths don't letterbox or crop. */
    .europe-map-svg {
        height: auto !important;
        aspect-ratio: 2 / 1;
    }
}

@media (max-width: 560px) {
    .section-sub {
        display: none;
    }
}
