/**
 * style.css
 * ============================================================================
 * ERP Phase 1 Prototype — Design System & Styles
 * ============================================================================
 * Extracted from index.html's embedded <style> block as part of a v14
 * pure structural reorganization — NO VISUAL OR BEHAVIOR CHANGE. Every
 * rule below is byte-for-byte identical to what was previously embedded
 * directly in index.html's <head>.
 *
 * WHY THIS SPLIT: the vast majority of past prototype iterations were
 * pure visual/CSS changes (status pill sizing, header color, row height,
 * mobile breakpoints, etc.) that never touched the page's actual HTML
 * markup or Alpine logic. Keeping CSS embedded meant every such change
 * required viewing and editing a ~1,300-line HTML file. As a plain,
 * separately-linked stylesheet, a CSS-only change now only touches this
 * file. No build step is introduced — this is a static file, linked via
 * a plain <link rel="stylesheet"> tag in index.html, uploaded via FTP
 * exactly like every other file in this project.
 * ============================================================================
 */

    /* ==========================================================================
       DESIGN TOKENS
       ==========================================================================
       Light-mode-only, modern SaaS-dashboard palette. Deliberately avoids
       the common "AI-generated" defaults (warm cream + terracotta, or
       near-black + acid accent) in favor of a cool, clean workspace feel
       with a confident teal primary and a warm coral reserved strictly for
       attention/urgency — so color itself carries meaning in the UI.
       ========================================================================== */
    :root {
        /* Surfaces */
        --bg: #F5F7F9;
        --surface: #FFFFFF;
        --surface-sunken: #EFF2F5;
        --border: #E2E7EC;
        --border-strong: #CBD3DC;

        /* Text */
        --text-primary: #14181F;
        --text-secondary: #5B6472;
        --text-tertiary: #8A93A1;

        /* Brand */
        --accent: #0E7C86;
        --accent-dark: #0A5F67;
        --accent-tint: #E4F3F3;

        /* Semantic status */
        --status-good: #1D8A5E;
        --status-good-tint: #E4F5EC;
        --status-warning: #B7791F;
        --status-warning-tint: #FBF2E1;
        --status-critical: #C0392B;
        --status-critical-tint: #FBEAE7;
        --status-info: #3D5A80;
        --status-info-tint: #EAF0F7;
        --status-neutral: #667085;
        --status-neutral-tint: #EEF0F2;

        /* Type scale */
        --font-display: 'Sora', sans-serif;
        --font-body: 'Inter', sans-serif;

        /* Spacing */
        --space-1: 4px;
        --space-2: 8px;
        --space-3: 12px;
        --space-4: 16px;
        --space-5: 24px;
        --space-6: 32px;
        --space-7: 48px;

        --radius-sm: 6px;
        --radius-md: 10px;
        --radius-lg: 16px;

        --shadow-card: 0 1px 2px rgba(20, 24, 31, 0.04), 0 4px 16px rgba(20, 24, 31, 0.04);
    }

    * { box-sizing: border-box; }

    body {
        margin: 0;
        background: var(--bg);
        color: var(--text-primary);
        font-family: var(--font-body);
        font-feature-settings: 'tnum' 1; /* tabular numbers for aligned figures */
        -webkit-font-smoothing: antialiased;
    }

    h1, h2, h3, .display {
        font-family: var(--font-display);
        letter-spacing: -0.01em;
        margin: 0;
    }

    a { color: inherit; }

    /* ==========================================================================
       APP SHELL
       ========================================================================== */
    .app-shell {
        display: flex;
        min-height: 100vh;
    }

    .sidebar {
        width: 240px;
        flex-shrink: 0;
        background: var(--surface);
        border-right: 1px solid var(--border);
        padding: var(--space-5) var(--space-4);
        display: flex;
        flex-direction: column;
        gap: var(--space-6);
    }

    .brand {
        display: flex;
        flex-direction: column;
        gap: 2px;
        padding: 0 var(--space-2);
    }
    .brand .mark {
        font-family: var(--font-display);
        font-weight: 700;
        font-size: 20px;
        color: var(--accent-dark);
    }
    .brand .sub {
        font-size: 12px;
        color: var(--text-tertiary);
        font-weight: 500;
    }

    .nav-group { display: flex; flex-direction: column; gap: 2px; }
    .nav-group-label {
        font-size: 11px;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: 0.06em;
        color: var(--text-tertiary);
        padding: 0 var(--space-2);
        margin-bottom: var(--space-1);
    }
    .nav-item {
        display: flex;
        align-items: center;
        gap: var(--space-2);
        padding: 9px var(--space-2);
        border-radius: var(--radius-sm);
        font-size: 14px;
        font-weight: 500;
        color: var(--text-secondary);
        cursor: pointer;
        border: none;
        background: none;
        text-align: left;
        width: 100%;
        transition: background 0.12s ease, color 0.12s ease;
    }
    .nav-item:hover { background: var(--surface-sunken); color: var(--text-primary); }
    .nav-item.active { background: var(--accent-tint); color: var(--accent-dark); font-weight: 600; }

    .main {
        flex: 1;
        min-width: 0;
        padding: var(--space-6) var(--space-7);
    }

    .page-header {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        margin-bottom: var(--space-6);
    }
    .page-header h1 { font-size: 26px; font-weight: 700; }
    .page-header .page-desc { color: var(--text-secondary); font-size: 14px; margin-top: 4px; }

    /* ==========================================================================
       COMPONENTS
       ========================================================================== */
    .card {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius-lg);
        box-shadow: var(--shadow-card);
        padding: var(--space-5);
    }

    .grid-2 { display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--space-5); }
    .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }

    .kpi-card { display: flex; flex-direction: column; gap: var(--space-1); }
    .kpi-label { font-size: 13px; color: var(--text-secondary); font-weight: 500; }
    .kpi-value { font-family: var(--font-display); font-size: 30px; font-weight: 700; }
    .kpi-sub { font-size: 12.5px; color: var(--text-tertiary); }

    .section-title {
        font-size: 15px;
        font-weight: 600;
        margin-bottom: var(--space-4);
    }

    /* Recommendation cards — the signature element of this dashboard.
       Color-coded left border + tinted icon chip carries meaning at a
       glance for a non-technical owner, without relying on reading dense
       numbers first. */
    .recommendation {
        display: flex;
        gap: var(--space-3);
        padding: var(--space-4);
        border-radius: var(--radius-md);
        border-left: 4px solid transparent;
        margin-bottom: var(--space-3);
        font-size: 14px;
        line-height: 1.5;
    }
    .recommendation:last-child { margin-bottom: 0; }
    .recommendation .chip {
        flex-shrink: 0;
        width: 28px; height: 28px;
        border-radius: 50%;
        display: flex; align-items: center; justify-content: center;
        font-size: 14px; font-weight: 700;
    }
    .recommendation.good { background: var(--status-good-tint); border-left-color: var(--status-good); }
    .recommendation.good .chip { background: var(--status-good); color: white; }
    .recommendation.warning { background: var(--status-warning-tint); border-left-color: var(--status-warning); }
    .recommendation.warning .chip { background: var(--status-warning); color: white; }
    .recommendation.critical { background: var(--status-critical-tint); border-left-color: var(--status-critical); }
    .recommendation.critical .chip { background: var(--status-critical); color: white; }
    .recommendation.info { background: var(--status-info-tint); border-left-color: var(--status-info); }
    .recommendation.info .chip { background: var(--status-info); color: white; }

    .remedy-list { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-3); }
    .remedy-item {
        display: flex; gap: var(--space-3); align-items: flex-start;
        padding: var(--space-3); background: var(--surface-sunken); border-radius: var(--radius-sm);
    }
    .remedy-rank {
        flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%;
        background: var(--accent); color: white; font-size: 12px; font-weight: 700;
        display: flex; align-items: center; justify-content: center;
    }
    .remedy-item .remedy-label { font-weight: 600; font-size: 13.5px; }
    .remedy-item .remedy-desc { font-size: 13px; color: var(--text-secondary); margin-top: 2px; }

    .capacity-gauge-wrap { display: flex; align-items: center; gap: var(--space-5); }

    .tabs-row {
        display: flex; gap: var(--space-2); margin-bottom: var(--space-5);
        border-bottom: 1px solid var(--border);
    }
    .tab-btn {
        padding: var(--space-3) var(--space-2);
        border: none; background: none; cursor: pointer;
        font-family: var(--font-body); font-size: 14px; font-weight: 500;
        color: var(--text-secondary);
        border-bottom: 2px solid transparent;
        margin-bottom: -1px;
    }
    .tab-btn.active { color: var(--accent-dark); border-bottom-color: var(--accent); font-weight: 600; }

    .btn {
        display: inline-flex; align-items: center; gap: 6px;
        padding: 8px 14px; border-radius: var(--radius-sm);
        font-family: var(--font-body); font-size: 13.5px; font-weight: 600;
        border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-primary);
        cursor: pointer;
    }
    .btn:hover { background: var(--surface-sunken); }
    .btn.primary { background: var(--accent); border-color: var(--accent); color: white; }
    .btn.primary:hover { background: var(--accent-dark); }
    .btn.danger-ghost { color: var(--status-critical); border-color: var(--status-critical-tint); }
    .btn.danger-ghost:hover { background: var(--status-critical-tint); }

    .rule-card {
        border: 1px solid var(--border);
        border-radius: var(--radius-md);
        padding: var(--space-4);
        margin-bottom: var(--space-3);
        display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-4);
    }
    .rule-card .rule-label { font-weight: 600; font-size: 14px; }
    .rule-card .rule-desc { font-size: 12.5px; color: var(--text-secondary); margin-top: 4px; max-width: 480px; }
    /* Text side shrinks/wraps first when a card is tight on space -- it's
       just paragraph text, which reflows without any visual problem.
       min-width:0 is what actually allows a flex child to shrink below
       its own natural content width; without it, flexbox would refuse to
       compress this side at all. */
    .rule-input-wrap {
        display: flex; align-items: center; gap: var(--space-2); flex-shrink: 0;
    }
    /* The structured multi-input rows (day boundaries, lag-pattern
       percentages) need their wrapper to actually be allowed to shrink
       and wrap -- flex-shrink:0 above is right for the simple single-
       input case, but forced these wider rows to overflow past the
       card's edge into its neighbor instead of wrapping, since the
       wrapper refused to be any narrower than its full unwrapped width. */
    .rule-input-wrap:has(.rule-structured-row) { flex-shrink: 1; min-width: 0; max-width: 100%; }
    /* Opt-in only (via a rule.unit.length check in the template) for the
       rare case of a genuinely long unit string ("Prozentpunkte/Monat").
       A more "general" attempt at this (letting the text side shrink
       first via flex:1 + min-width:0) was tried and confirmed BROKEN by
       direct testing: at certain card widths it squeezed labels into an
       unreadable word-by-word stack, and in the worst case caused input
       boxes to visually overlap the label text entirely. This narrower,
       targeted rule is less "clever" but has been confirmed to actually
       work correctly across the range of card widths this app uses. */
    .rule-input-wrap.wrap-long-unit {
        flex-wrap: wrap; justify-content: flex-end; max-width: 100%; flex-shrink: 1; min-width: 0;
    }
    .rule-input {
        font-family: var(--font-body); font-size: 14px; font-weight: 600;
        padding: 7px 10px; border-radius: var(--radius-sm); border: 1px solid var(--border-strong);
        width: 110px; text-align: right;
    }
    /* Removes the native up/down spinner arrows entirely -- confirmed via
       pixel measurement that simply adding right-padding didn't actually
       reserve safe space for them (the browser overlays the spinner on
       the input regardless of padding), so digits kept rendering behind
       it. Without the spinner rendered at all, the full input width is
       available to the text and this category of bug goes away entirely. */
    .rule-input::-webkit-outer-spin-button,
    .rule-input::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }
    .rule-input[type="number"] {
        -moz-appearance: textfield;
        appearance: textfield;
    }
    .rule-input.json { width: 340px; text-align: left; font-family: monospace; font-size: 12px; }
    .rule-unit { font-size: 13px; color: var(--text-tertiary); }
    .save-flash { font-size: 12px; color: var(--status-good); font-weight: 600; opacity: 0; transition: opacity 0.2s; }
    .save-flash.show { opacity: 1; }

    .empty-state {
        text-align: center; padding: var(--space-7) var(--space-5);
        color: var(--text-tertiary); font-size: 14px;
    }

    .loading-bar {
        height: 2px; background: var(--accent-tint); border-radius: 2px; overflow: hidden; margin-bottom: var(--space-4);
    }
    .loading-bar .fill { height: 100%; width: 40%; background: var(--accent); animation: loading-sweep 1s infinite; }
    @keyframes loading-sweep {
        0% { transform: translateX(-100%); }
        100% { transform: translateX(350%); }
    }

    /* Tabulator theme override — modern SaaS look matching the rest of the
       app's tokens. Deliberately does NOT touch row/cell vertical padding
       anywhere in this block — row height must stay exactly as compact as
       before; only color, weight, and the header get more presence. */
    .tabulator {
        font-family: var(--font-body) !important;
        border: none !important;
        background: var(--surface) !important;
    }
    .tabulator .tabulator-tableholder,
    .tabulator .tabulator-table {
        background: var(--surface) !important;
    }

    /* Header: matches the sidebar's active-nav-item styling exactly (light
       teal tint + dark teal text) for visual consistency across the app.
       Hover turns solid teal with white text -- a clear, familiar
       "this is interactive" signal reusing the same two brand colors. */
    .tabulator-header {
        background: var(--accent-tint) !important;
        border-bottom: 2px solid var(--accent-dark) !important;
    }
    .tabulator-col {
        font-size: 12.5px !important;
        font-weight: 700 !important;
        color: var(--accent-dark) !important;
        background: var(--accent-tint) !important;
        padding-top: 10px !important;
        padding-bottom: 10px !important;
        /* Only slightly darker than the header's own light tint background
           -- a soft separator rather than a bold dark-teal line. Left
           border stays transparent by default (invisible) so it doesn't
           double up visually with the neighboring column's right border;
           it only becomes visible on hover, matching that state's solid
           background so both edges of the hovered column blend in. */
        border-right: 1px solid #CFE8E8 !important;
        border-left: 1px solid transparent !important;
    }
    .tabulator-col .tabulator-col-content { padding: 4px 8px !important; }
    /* The checkbox column's header content needs the same simple centering
       as its row cells (no horizontal padding) -- confirmed via measurement
       that the generic 8px horizontal header padding above was shifting the
       header checkbox ~4px off from the row checkboxes below it. Targeted
       by position (always the first column) since Tabulator doesn't
       reliably carry a column's cssClass onto its own header cell. */
    .tabulator-header .tabulator-col:first-child .tabulator-col-content {
        padding: 4px 0 !important;
        display: flex; justify-content: center;
    }
    .tabulator-col .tabulator-arrow { border-bottom-color: var(--accent-dark) !important; border-top-color: var(--accent-dark) !important; }
    /* The currently-sorted column gets a slightly more present background
       than an unsorted header, so it's clear at a glance which column is
       driving the current sort even without hovering -- but distinctly
       less intense than the hover color, so hovering still reads as a
       clear, uniform "this is interactive" signal on every header alike. */
    .tabulator-col[aria-sort="ascending"],
    .tabulator-col[aria-sort="descending"] {
        background: #C9E6E6 !important;
    }
    .tabulator-col.tabulator-sortable:hover,
    .tabulator-col.tabulator-sortable:hover .tabulator-col-content {
        background: var(--accent) !important;
        color: white !important;
    }
    .tabulator-col.tabulator-sortable:hover {
        border-left-color: var(--accent) !important;
        border-right-color: var(--accent) !important;
    }
    .tabulator-col.tabulator-sortable:hover .tabulator-arrow { border-bottom-color: white !important; border-top-color: white !important; }

    /* Below "fitDataFill" stretches the last real column's row to fill any
       remaining width, but the header's own trailing filler strip needs
       its background set separately to match -- otherwise it's left
       showing Tabulator's own default background instead of the tint
       used across the rest of the header. */
    .tabulator-headers { background: var(--accent-tint) !important; }

    /* Rows: vertical grid lines kept (per feedback — they help scanning)
       but softened to a much lighter hairline than a full-strength border,
       and the zebra/hover/edit-focus colors now use the brand teal instead
       of generic grays/blues. Row height is untouched — no padding changes
       here at all. */
    .tabulator-row { font-size: 13.5px !important; min-height: 32px !important; }
    .tabulator-row.tabulator-row-even { background: #FAFCFC !important; }
    .tabulator-row:hover { background: var(--accent-tint) !important; }
    /* A selected row gets ONE consistent highlight color regardless of
       whether it lands on an even/odd (zebra-striped) position -- without
       this, selecting every row visibly alternated between two different
       blues depending on row parity, which read as a bug rather than a
       deliberate two-tone selection style. */
    .tabulator-row.tabulator-selected,
    .tabulator-row.tabulator-selected.tabulator-row-even {
        background: var(--accent-tint) !important;
    }
    .tabulator-cell {
        border-right: 1px solid #EFF2F4 !important;
        padding-top: 4px !important;
        padding-bottom: 4px !important;
        /* Vertically centers single-line cell content within the row
           without touching display/box-model behavior -- confirmed via
           testing that forcing display:flex here broke Tabulator's own
           internal row-height calculation catastrophically (rows
           ballooned to 700px+). line-height is a much safer way to
           center inline content. Value = 32px row minus 4px+4px padding. */
        line-height: 24px !important;
    }
    .tabulator-cell > * { vertical-align: middle; }
    .tabulator-cell.tabulator-editing {
        border: 1px solid var(--accent) !important;
        box-shadow: 0 0 0 2px var(--accent-tint) !important;
    }

    /* Native row-selection checkboxes, restyled as circles (per the
       reference screenshot) rather than Tabulator's default square. */
    .select-col input[type="checkbox"] {
        appearance: none; -webkit-appearance: none;
        width: 15px; height: 15px; border-radius: 50%;
        border: 1.5px solid var(--border-strong);
        cursor: pointer; margin: 0; position: relative;
    }
    .select-col input[type="checkbox"]:checked {
        background-color: var(--accent);
        border-color: var(--accent);
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: center;
        background-size: 8px 8px;
    }

    /* The pinned "new row" — visually distinct (tinted background,
       dashed top/bottom) so it reads clearly as "not a saved record yet"
       rather than blending in with real data. */
    .tabulator-row.new-row-pinned {
        background: var(--surface-sunken) !important;
        /* Neither border-top nor border-bottom here -- confirmed via
           testing that a border drawn on the row's own box (rather than
           each cell) goes stale after horizontal scroll: the row's own
           bounding box ends up not matching where the actual visible
           cells render, so the border visibly "stops" partway across
           instead of spanning the full row. Same underlying issue as the
           earlier background-color bug, same fix: apply per-cell instead
           of per-row, further below. */
    }
    /* The frozen-rows-holder itself is transparent by default, letting
       the header's own light tint show through in the gap to the right
       of the pinned row's actual cells -- matching this to the pinned
       row's own background instead keeps that trailing gap visually
       consistent with the row it belongs to. */
    .tabulator-frozen-rows-holder {
        background: var(--surface-sunken) !important;
        /* Confirmed via testing at a wide viewport (1920px): this holder
           does NOT stretch to the table's full available width the way
           regular rows do (Tabulator's fitDataFill filler logic doesn't
           apply the same way to frozen rows) -- it stays capped at the
           sum of the actual column widths. Forcing 100% here makes the
           pinned row's background genuinely span the full table width
           regardless of viewport size, instead of only coincidentally
           looking full-width at whatever narrower width was tested before. */
        width: 100% !important;
    }
    .tabulator-row.new-row-pinned {
        width: 100% !important;
    }
    /* The default cell divider (#EFF2F4) is nearly invisible against this
       row's darker --surface-sunken background -- a distinct, slightly
       darker divider color keeps the column separation visible here too. */
    .tabulator-row.new-row-pinned .tabulator-cell {
        /* Setting this directly on every cell rather than relying purely
           on the parent row's background -- confirmed via testing that
           columns scrolled into view after being off-screen on initial
           load rendered with a stale white background instead of this
           row's actual color, even though the row element itself had the
           correct background all along. */
        background: var(--surface-sunken) !important;
        border-top: 1px dashed #DDE3E8 !important;
        border-right-color: #DDE3E8 !important;
        /* This row structurally lives inside Tabulator's own header
           container (confirmed via DOM inspection: frozen rows nest
           inside .tabulator-header for sticky-positioning purposes),
           which bolds text by default as part of Tabulator's base theme.
           Without this reset, real typed values here rendered bold while
           the placeholder text (which had its own explicit weight) didn't
           -- the two looked inconsistent side by side in the same row. */
        font-weight: 400 !important;
    }
    /* Higher specificity than the divider-color rule above (which was
       winning on border-right-color specifically, confirmed via testing:
       an actively-edited cell in this row showed teal on 3 sides but the
       divider gray on the right side instead of teal) -- this makes the
       active-edit border correctly solid teal on all 4 sides here too. */
    .tabulator-row.new-row-pinned .tabulator-cell.tabulator-editing {
        border-right-color: var(--accent) !important;
    }
    /* The pinned row can't be selected or deleted (it isn't a saved
       record yet), so its checkbox is hidden entirely rather than shown
       in a confusing disabled-but-visible state. */
    .tabulator-row.new-row-pinned .tabulator-cell:first-child input[type="checkbox"] {
        display: none;
    }
    /* No divider after the very last real column -- there's nothing to
       its right to divide from, so a trailing line there just looks like
       a stray leftover rather than a meaningful separator. Applies to
       both the header and every row's last column consistently. */
    .tabulator-col:last-of-type,
    .tabulator-cell:last-of-type {
        border-right: none !important;
    }
    .new-row-placeholder { color: var(--text-tertiary); font-style: italic; font-weight: 400 !important; }
    .new-row-btn {
        display: inline-flex; align-items: center; justify-content: center;
        width: 24px; height: 24px; border-radius: 50%;
        margin: 0 3px; user-select: none;
    }

    /* Selection toolbar — appears above the grid only once something is
       checked; replaces the old always-visible per-row delete column. */
    .selection-toolbar {
        display: flex; align-items: center; gap: var(--space-3);
        font-size: 13.5px; color: var(--text-secondary); font-weight: 500;
    }

    /* Wraps the Tabulator grid in the same card language as the rest of
       the app. Height is set directly in JS (calcGridHeight() in app.js)
       so every scenario-data screen is the same size regardless of row
       count. overflow:hidden (not auto) is what actually clips the
       header's corners to the card's own border-radius — confirmed via
       testing that overflow:auto left sharp corners poking past the
       rounded edge. */
    .grid-card {
        background: var(--surface);
        border: 1px solid var(--border);
        border-radius: var(--radius-lg);
        box-shadow: var(--shadow-card);
        padding: 0;
        overflow: hidden;
    }
    .grid-row-count {
        font-size: 12.5px;
        color: var(--text-tertiary);
        font-weight: 500;
        margin-top: 2px;
    }

    /* Status pills — genuine workflow/lifecycle states (quote status,
       invoice status, customer lifecycle stage) get a glanceable colored
       badge instead of plain text. Compact padding/line-height so this
       fits inside the existing row height without growing it. */
    .status-pill {
        display: inline-block;
        padding: 2px 10px;
        border-radius: 999px;
        font-size: 12.5px;
        font-weight: 600;
        line-height: 1.5;
        white-space: nowrap;
    }
    .status-pill-good { background: var(--status-good-tint); color: var(--status-good); }
    .status-pill-warning { background: var(--status-warning-tint); color: var(--status-warning); }
    .status-pill-critical { background: var(--status-critical-tint); color: var(--status-critical); }
    .status-pill-info { background: var(--status-info-tint); color: var(--status-info); }
    .status-pill-neutral { background: var(--status-neutral-tint); color: var(--status-neutral); }

    /* Customer type icon — a small circular Privatperson/Unternehmen
       indicator that follows a customer's name everywhere it appears
       (the Kunden grid itself, plus the "Kunde" column on every other
       grid). Scaled up to match the taller row height. */
    .name-with-icon { display: inline-flex; align-items: center; gap: 6px; line-height: 1; }
    .type-badge {
        display: inline-flex; align-items: center; justify-content: center;
        width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
    }
    .type-badge svg { width: 11px; height: 11px; }
    .type-badge-individual { background: var(--accent-tint); color: var(--accent-dark); }
    .type-badge-company { background: var(--status-info-tint); color: var(--status-info); }

    /* Brief highlight on a grid cell right after it saves successfully —
       gives the same "did that actually save?" confidence the Business
       Rules page's "Gespeichert" flash already provides, applied to the
       scenario-data grids too. */
    .tabulator .tabulator-cell.cell-flash-saved {
        background: var(--status-good-tint) !important;
        transition: background 0.15s ease;
    }

    /* ==========================================================================
       BANNER NOTIFICATIONS & CONFIRMATION MODAL (replace native alert/confirm)
       ========================================================================== */
    .app-banner {
        position: fixed;
        top: var(--space-5);
        left: 50%;
        transform: translateX(-50%);
        z-index: 1000;
        max-width: 520px;
        padding: var(--space-3) var(--space-4);
        border-radius: var(--radius-md);
        box-shadow: 0 8px 24px rgba(20, 24, 31, 0.16);
        font-size: 14px;
        display: flex;
        align-items: center;
        gap: var(--space-3);
    }
    .app-banner.critical { background: var(--status-critical); color: white; }
    .app-banner.good { background: var(--status-good); color: white; }
    .app-banner-close {
        margin-left: auto; cursor: pointer; opacity: 0.8; font-size: 16px; line-height: 1; flex-shrink: 0;
    }
    .app-banner-close:hover { opacity: 1; }

    .modal-overlay {
        position: fixed; inset: 0; background: rgba(20, 24, 31, 0.32);
        display: flex; align-items: center; justify-content: center; z-index: 1001;
    }
    .modal-card {
        background: var(--surface); border-radius: var(--radius-lg);
        box-shadow: 0 16px 48px rgba(20, 24, 31, 0.24);
        padding: var(--space-5); max-width: 380px; width: 90%;
    }
    .modal-card p { font-size: 14.5px; line-height: 1.5; margin: 0 0 var(--space-4); }
    .modal-actions { display: flex; justify-content: flex-end; gap: var(--space-2); }

    /* ==========================================================================
       BUSINESS RULES — two-column layout
       ========================================================================== */
    .rules-grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
        gap: var(--space-4);
        /* No explicit align-items here -- CSS Grid's default (stretch)
           makes every card in the same row match the height of its
           tallest sibling, which is what we want. The card's own internal
           flex layout (align-items: flex-start) keeps its label/description
           anchored to the top rather than awkwardly centering when the
           card stretches taller than its own content needs. */
    }
    /* JSON/structured rules (realization lag pattern, remedy ranking) need
       more horizontal room for their content than a numeric input does —
       let those span the full grid width instead of being squeezed into
       one column. */
    .rules-grid .rule-card.span-full { grid-column: 1 / -1; }

    .toggle-switch {
        width: 44px; height: 24px; border-radius: 12px;
        background: var(--border-strong); border: none; cursor: pointer;
        position: relative; flex-shrink: 0; padding: 0;
        transition: background 0.15s ease;
    }
    .toggle-switch.on { background: var(--accent); }
    .toggle-knob {
        position: absolute; top: 2px; left: 2px;
        width: 20px; height: 20px; border-radius: 50%; background: white;
        box-shadow: 0 1px 3px rgba(0,0,0,0.2);
        transition: transform 0.15s ease;
    }
    .toggle-switch.on .toggle-knob { transform: translateX(20px); }

    /* Compact structured editors for the two simple JSON rules (day
       boundaries, lag-pattern percentages) -- a row of small labeled
       number inputs, each with its own inline unit ("30 Tage", "20 %")
       instead of a raw JSON array the tester would otherwise have to
       hand-edit correctly. */
    .rule-structured-row { display: flex; align-items: flex-start; gap: var(--space-4); flex-wrap: wrap; justify-content: flex-end; max-width: 100%; }
    .rule-mini-field { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
    .rule-mini-input-row { display: flex; align-items: center; gap: 6px; }
    .rule-mini-field .rule-input { text-align: right; }
    .rule-mini-label { font-size: 10.5px; color: var(--text-tertiary); white-space: nowrap; }
    .rule-unit-inline { font-size: 12.5px; color: var(--text-tertiary); white-space: nowrap; }

    /* Editable, reorderable remedy list -- replaces a raw JSON array of
       {rank, label, description} objects with an actual list a tester can
       read, edit, and reprioritize without touching JSON syntax at all. */
    .remedy-edit-row {
        display: flex; gap: var(--space-3); align-items: flex-start;
        background: var(--surface-sunken); padding: var(--space-3); border-radius: var(--radius-sm);
    }
    .remedy-edit-reorder { display: flex; flex-direction: column; align-items: center; gap: 2px; flex-shrink: 0; }
    .remedy-reorder-btn {
        border: none; background: none; cursor: pointer; color: var(--text-tertiary);
        font-size: 11px; padding: 2px 6px; line-height: 1;
    }
    .remedy-reorder-btn:hover:not(:disabled) { color: var(--accent-dark); }
    .remedy-reorder-btn:disabled { opacity: 0.25; cursor: default; }

    /* ==========================================================================
       MOBILE TOP BAR + HAMBURGER (hidden on desktop by default)
       ========================================================================== */
    .mobile-topbar { display: none; }
    .hamburger-btn { display: none; }

    @media (max-width: 900px) {
        .app-shell { flex-direction: column; }

        /* A compact, single-line top bar replaces the old cramped 3-column
           nav strip (which forced horizontal scrolling just to see all
           three nav groups, confirmed via screenshots as genuinely broken
           on real phones). Sticky so it stays reachable while scrolling a
           long page, matching the "modern app" feel that was asked for. */
        .mobile-topbar {
            display: flex; align-items: center; justify-content: space-between;
            background: var(--accent-tint);
            padding: var(--space-3) var(--space-4);
            position: sticky; top: 0; z-index: 50;
            border-bottom: 1px solid var(--border);
        }
        .mobile-brand {
            display: flex; align-items: baseline; gap: var(--space-2);
            white-space: nowrap; overflow: hidden;
        }
        .mobile-brand .mark {
            font-family: var(--font-display); font-weight: 700; font-size: 18px; color: var(--accent-dark);
        }
        .mobile-brand .sub { font-size: 12px; color: var(--text-tertiary); white-space: nowrap; }

        /* Animated hamburger -> X, a small but deliberate touch of polish
           rather than just swapping a "☰"/"✕" character. */
        .hamburger-btn {
            display: block;
            position: relative;
            width: 24px; height: 18px; background: none; border: none; cursor: pointer;
            padding: 0; flex-shrink: 0;
        }
        .hamburger-btn span {
            position: absolute; left: 0; width: 100%; height: 2.5px;
            background: var(--accent-dark); border-radius: 2px;
            transition: top 0.25s ease, transform 0.25s ease, opacity 0.2s ease;
        }
        .hamburger-btn span:nth-child(1) { top: 0; }
        .hamburger-btn span:nth-child(2) { top: 7.5px; }
        .hamburger-btn span:nth-child(3) { top: 15px; }
        .hamburger-btn.open span:nth-child(1) { top: 7.5px; transform: rotate(45deg); }
        .hamburger-btn.open span:nth-child(2) { opacity: 0; }
        .hamburger-btn.open span:nth-child(3) { top: 7.5px; transform: rotate(-45deg); }

        /* The sidebar's own brand block is replaced by the mobile top bar
           above, and the sidebar itself is now a collapsible panel that
           drops down below the top bar only when opened, instead of
           always taking up screen space as a horizontally-scrolling strip. */
        .sidebar .brand { display: none; }
        .sidebar {
            display: none;
            width: 100%; flex-direction: column; overflow-x: visible;
            border-right: none; border-bottom: 1px solid var(--border);
            box-shadow: 0 4px 12px rgba(0,0,0,0.08);
        }
        .sidebar.mobile-open { display: flex; }

        .main { padding: var(--space-4); }
        .grid-2, .grid-3 { grid-template-columns: 1fr; }

        /* The 380px-minimum grid column (fine on desktop) is wider than
           many phone screens' actual available content width, confirmed
           via testing to force horizontal page scroll -- a plain single
           column removes that hard minimum on mobile. */
        .rules-grid { grid-template-columns: 1fr; }
        /* Side-by-side text + inputs works fine on desktop/tablet widths,
           but on narrow phones there genuinely isn't room for both a
           readable label column and a multi-input row at once -- stacking
           them (text on top, full-width inputs below) reads far better
           than squeezing both into a too-narrow row, which was forcing
           long German compound words to overflow their column. */
        .rule-card { flex-direction: column; gap: var(--space-3); }
        .rule-input-wrap { width: 100%; justify-content: flex-end; }
    }
