/* ==========================================================================
   Three dashboard leaderboards (profit / prep speed / volume)
   ========================================================================== */

/* 2x2 so all four fit without shrinking the rows to unreadable. The dividers
   are borders on the boards themselves rather than a grid gap: a gap separates
   by empty space, which at this density reads as "these are unrelated cards",
   while a hairline reads as "one panel, four sections". */
.top-boards {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0;
}
.top-board {
    min-width: 0;
    padding: 12px 14px;
}
/* RTL-aware: the odd children are the RIGHT-hand column, so the seam between
   the columns is their inline-END edge. Using inline-start here puts the rule
   on the outer edge of the panel instead, where it reads as a stray line. */
.top-board:nth-child(odd) { border-inline-end: 1px solid var(--border-color); }
.top-board:nth-child(-n + 2) { border-block-end: 1px solid var(--border-color); }

.top-board h4 {
    font-size: 13.5px;
    margin: 0;
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 6px;
}
.top-board .board-icon { flex-shrink: 0; opacity: 0.75; }
.top-board .board-hint {
    font-size: 10.5px;
    color: var(--text-muted);
    margin: 2px 0 8px;
}
.top-board .top-list { margin: 0; gap: 6px; }
.top-board .top-list li { padding: 6px 9px; font-size: 12.5px; gap: 8px; }
.top-board .top-list .name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.top-board .top-list .profit {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1.25;
}
.top-board .top-list .board-main { font-weight: 800; }
.top-board .top-list .board-sub {
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text-muted);
}

@media (max-width: 900px) {
    .top-boards { grid-template-columns: 1fr; }
    /* One column: every seam is now horizontal, so reset the column rule and
       give every board but the last a bottom rule. */
    .top-board:nth-child(odd) { border-inline-end: none; }
    .top-board { border-block-end: 1px solid var(--border-color); }
    .top-board:last-child { border-block-end: none; }
}

/* ==========================================================================
   Add-dish call to action + draft card
   ========================================================================== */

.add-dish-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    padding: 16px;
    margin-bottom: 16px;
    font-family: inherit;
    font-size: 16px;
    font-weight: 800;
    color: var(--primary-color);
    background: rgba(37, 99, 235, 0.08);
    border: 2px dashed rgba(37, 99, 235, 0.4);
    border-radius: 14px;
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s;
}
.add-dish-cta:hover {
    background: rgba(37, 99, 235, 0.14);
    border-color: var(--primary-color);
}

.dish-draft {
    padding: 16px 18px;
    margin-bottom: 16px;
    border: 2px solid var(--primary-color);
    border-radius: 14px;
    background: var(--bg-solid);
}
.dish-draft-head { margin-bottom: 12px; }
.dish-draft-head strong { display: block; font-size: 16px; margin-bottom: 2px; }
.dish-draft-head span { font-size: 12px; color: var(--text-muted); line-height: 1.6; }
.dish-draft-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
    margin-bottom: 14px;
}
.dish-draft-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.dish-draft .supplier-btn-save:disabled { opacity: 0.45; cursor: not-allowed; }

/* ==========================================================================
   Ingredient picker (search + category groups)
   ========================================================================== */

.ing-picker-card {
    /* Not width:100% - on a phone that puts the card flush against both bezels. */
    width: min(560px, calc(100vw - 24px));
    display: flex;
    flex-direction: column;
    max-height: 82vh;
}

.ing-picker-search-wrap {
    position: relative;
    display: flex;
    align-items: center;
    margin: 4px 0 12px;
}
.ing-picker-search-wrap svg {
    position: absolute;
    inset-inline-start: 12px;
    color: var(--text-muted);
    pointer-events: none;
}
.ing-picker-search-wrap input {
    width: 100%;
    padding: 11px 14px;
    padding-inline-start: 36px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-color);
    background: var(--bg-main);
    color: var(--text-primary);
    font-size: 14px;
    font-family: inherit;
}
.ing-picker-search-wrap input:focus {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}

.ing-picker-body {
    overflow-y: auto;
    flex: 1;
    min-height: 180px;
    padding-inline-end: 4px;
}

.ing-group { margin-bottom: 14px; }
.ing-group-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.4px;
    color: var(--text-muted);
    text-transform: uppercase;
    padding: 6px 4px;
    position: sticky;
    top: 0;
    background: var(--bg-solid);
    z-index: 1;
    border-block-end: 1px solid var(--border-color);
}
.ing-group-count {
    background: var(--bg-main);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    padding: 1px 7px;
    font-size: 10px;
}
.ing-group-body {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 6px;
    padding-top: 6px;
}

.ing-opt {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    text-align: start;
    padding: 8px 11px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-color);
    background: var(--bg-main);
    color: var(--text-primary);
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, border-color 0.15s;
}
.ing-opt:hover,
.ing-opt.is-active {
    background: var(--bg-solid);
    border-color: var(--primary-color);
}
.ing-opt.is-current {
    border-color: var(--primary-color);
    box-shadow: inset 0 0 0 1px var(--primary-color);
}
.ing-opt-name {
    font-weight: 700;
    font-size: 13px;
    line-height: 1.3;
}
.ing-opt-meta {
    font-size: 11px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.ing-opt-missing { color: var(--warning); font-weight: 700; }

/* Pinned above the search box. Three states, so the button always says what it
   will actually do rather than sitting there looking uniformly clickable. */
.ing-create {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    margin: 4px 0 10px;
    padding: 11px 14px;
    border-radius: var(--radius-md);
    border: 1px dashed var(--border-color);
    background: transparent;
    color: var(--text-muted);
    font-weight: 700;
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    text-align: start;
    transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.ing-create:hover { background: var(--bg-main); }
/* A name has been typed that does not exist yet: this is the live action. */
.ing-create.is-armed {
    border-color: var(--primary-color);
    color: var(--primary-color);
}
.ing-create.is-armed:hover { background: rgba(59, 130, 246, 0.08); }
/* The typed name already exists. Still clickable, but it selects the existing
   ingredient rather than creating a duplicate. */
.ing-create.is-blocked {
    border-style: solid;
    border-color: var(--warning);
    color: var(--warning);
}

.ing-picker-empty {
    padding: 24px 8px;
    text-align: center;
    color: var(--text-muted);
    font-size: 13px;
}

/* ==========================================================================
   Recipes page: shared search bar (cards + table)
   ========================================================================== */

.recipes-search-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    margin-bottom: 12px;
}
.recipes-search-bar > svg { color: var(--text-muted); flex-shrink: 0; }
.recipes-search-bar input {
    flex: 1;
    min-width: 0;
    border: none;
    background: transparent;
    color: var(--text-primary);
    font-size: 14.5px;
    font-family: inherit;
    padding: 4px 0;
}
.recipes-search-bar input:focus { outline: none; }
.recipes-search-count {
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
    white-space: nowrap;
}
.recipes-search-clear {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 1px solid var(--border-color);
    background: var(--bg-main);
    color: var(--text-muted);
    cursor: pointer;
    flex-shrink: 0;
}
.recipes-search-clear:hover { color: var(--text-primary); border-color: var(--text-muted); }

/* ==========================================================================
   Procurement tab (price comparison + supplier search)
   ========================================================================== */

.proc-body { min-height: 240px; }

.proc-soon {
    padding: 42px 28px;
    text-align: center;
    color: var(--text-muted);
}
.proc-soon svg { color: var(--text-muted); opacity: 0.6; }
.proc-soon h3 {
    margin: 12px 0 8px;
    font-size: 17px;
    color: var(--text-primary);
}
.proc-soon p { max-width: 520px; margin: 0 auto; font-size: 13.5px; line-height: 1.6; }
.proc-soon-note {
    margin-top: 12px !important;
    font-size: 12px !important;
    opacity: 0.8;
}

/* ==========================================================================
   SVG icon system (replaces the emoji that used to sit in titles and buttons)

   Emoji rendered differently on every machine, could not take the surrounding
   text colour, and had no dark-mode behaviour. These inherit currentColor and
   sit on the text baseline.
   ========================================================================== */

/* Sized in em, NOT in px.
 *
 * The emoji-to-SVG migration wrote width="16" height="16" onto every icon
 * regardless of where it landed. A 16px glyph is invisible next to a 40px page
 * title and bursts out of a 10px badge. CSS beats presentation attributes, so
 * this one rule re-sizes every icon already in the markup to match whatever
 * text it sits in. */
.ui-icon {
    width: 1.1em;
    height: 1.1em;
    vertical-align: -0.16em;
    flex-shrink: 0;
}
/* Large display type does not want a full-height icon beside it: at 1.1em a
   page title's icon out-weighs the words. */
h1 > .ui-icon,
h2 > .ui-icon { width: 0.78em; height: 0.78em; }

/* Titles and buttons that are flex containers already space their children, so
   the icon should not also carry a margin there. */
h2 > .ui-icon,
h3 > .ui-icon,
h4 > .ui-icon { margin-inline-end: 7px; }

/* Small pills and badges: the icon is a marker beside a short word, so it
   tracks the text rather than dominating it. */
.par-badge > .ui-icon,
.supplier-chip > .ui-icon,
.activity-flag > .ui-icon,
.dup-col-tag > .ui-icon,
.cat-chip > .ui-icon,
.raw-pill-x > .ui-icon { width: 1em; height: 1em; }

/* A placeholder cannot contain markup, so the magnifier that used to be typed
   into the placeholder text becomes a background image on the field itself. */
#inventory-search,
#history-search,
#activity-search,
#receipts-search,
#map-search,
#raw-list-search,
#overhead-search {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 15px 15px;
    padding-inline-start: 36px;
}

/* ==========================================================================
   Page head (option ב): the stats row IS the header

   The 40px title plus 16px subtitle plus 48px margin cost ~140px on every page
   and said the same thing every time. The page name shrinks to an eyebrow and
   the numbers underneath carry the weight.
   ========================================================================== */

.page-head {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

/* A coloured tile carries the page identity so the title does not have to do it
   with size alone. That is what lets this sit at 32px instead of the 40px it
   replaced while still reading as the loudest thing on the page. */
.page-head-icon {
    width: 52px;
    height: 52px;
    border-radius: 14px;
    background: rgba(37, 99, 235, 0.12);
    color: var(--primary-color);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.page-head-icon .ui-icon,
.page-head-icon svg { width: 26px; height: 26px; }

.page-head-text { display: flex; flex-direction: column; min-width: 0; }
.page-head-title {
    font-size: 32px;
    font-weight: 800;
    letter-spacing: -1px;
    line-height: 1.12;
    color: var(--text-primary);
}
.page-head-sub {
    font-size: 13px;
    color: var(--text-secondary);
    margin-top: 3px;
}
.page-head-actions {
    margin-inline-start: auto;
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
}
.page-stats { margin-bottom: 22px; }

@media (max-width: 700px) {
    .page-head-actions { margin-inline-start: 0; width: 100%; }
    .page-head-title { font-size: 25px; letter-spacing: -0.6px; }
    .page-head-icon { width: 44px; height: 44px; border-radius: 12px; }
    .page-head-icon .ui-icon,
    .page-head-icon svg { width: 22px; height: 22px; }
}

/* The light-mode primary is too dark to read against a dark tile. */
body.dark-theme .page-head-icon {
    background: rgba(59, 130, 246, 0.18);
    color: #60a5fa;
}

/* ==========================================================================
   Leaderboard cost bar
   ========================================================================== */

.top-list li.has-bar { align-items: flex-start; }
.top-list li .body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}
.top-list li.has-bar .rank,
.top-list li.has-bar .profit { padding-top: 1px; }

.cost-bar {
    display: flex;
    width: 100%;
    min-height: 22px;
    border-radius: 6px;
    overflow: hidden;
    background: var(--border-color);
}
.cost-bar .seg {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    min-width: 0;
    overflow: hidden;
}
.seg-text {
    font-size: 11px;
    font-weight: 700;
    color: #fff;
    white-space: nowrap;
    /* The four fills are mid-tone, so white text on the lighter ones needs a
       little help rather than a lighter weight. */
    text-shadow: 0 1px 1px rgba(0, 0, 0, 0.35);
    direction: ltr;
    unicode-bidi: isolate;
}
/* Deliberately far apart in hue AND in lightness, so the boundaries survive
   both a small bar and a colour-blind reader. The previous slate overhead sat
   almost on top of the empty-track colour. */
.seg-food { background: #ea580c; }
.seg-labor { background: #4f46e5; }
.seg-overhead { background: #475569; }
.seg-profit { background: #059669; }
/* Hairline between neighbours: two mid-tones of similar lightness still blur
   into each other at this height without one. */
.cost-bar .seg + .seg { box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.28); }
.seg-loss { background: var(--danger); }

.cost-bar.is-loss { position: relative; height: auto; background: none; }
.cost-bar.is-loss .seg-loss { height: 7px; border-radius: 4px; }
.cost-bar-loss-label {
    display: block;
    font-size: 10.5px;
    font-weight: 800;
    color: var(--danger);
    margin-top: 3px;
    white-space: nowrap;
}
.cost-bar-na {
    font-size: 10.5px;
    color: var(--text-muted);
    font-weight: 600;
}

.cost-bar-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
    padding: 12px 14px 2px;
    font-size: 10.5px;
    color: var(--text-muted);
    font-weight: 600;
}
.cost-bar-legend span { display: inline-flex; align-items: center; gap: 5px; }
.cost-bar-legend .swatch {
    width: 9px;
    height: 9px;
    border-radius: 2px;
    display: inline-block;
}

/* ==========================================================================
   AI usage
   ========================================================================== */

/* Currency figures are LTR runs sitting in an RTL page. Without an explicit
   direction the bidi algorithm reorders "≈ ₪0.06" into "₪0.06 ≈" and drags the
   decimal point with it, which reads as a different number. */
/* A currency amount is a left-to-right run sitting in an RTL page. Without an
   explicit direction the bidi algorithm reorders it and drags the decimal point
   with it, so "₪0.21" came out as "₪021" - a different number, not just ugly
   spacing. Each half is isolated separately. */
.money-main,
.money-sub {
    display: block;
    direction: ltr;
    unicode-bidi: isolate;
    /* direction:ltr also flips the default alignment to left, which would leave
       these numbers hanging away from every other stat card on the page. */
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.ai-stat-value .money-main { font-size: 26px; font-weight: 800; }
/* The dollar line is reference, not the headline. It was previously bold at
   11px, which at this size turns the digits into a smudge. */
.money-sub {
    font-size: 12px;
    font-weight: 400;
    color: var(--text-muted);
    margin-top: 3px;
    letter-spacing: 0.2px;
}
.ai-stat-value { font-size: 26px; }
.stat-card .stat-sub {
    display: block;
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 4px;
}
.ai-empty-card { grid-column: 1 / -1; }
.ai-empty-card p {
    font-size: 13px;
    color: var(--text-muted);
    margin-top: 6px;
    line-height: 1.6;
}

.ai-log-summary { margin-bottom: 4px; }
/* Same bidi reason as the stat cards: the log's cost column is an LTR run. */
.health-table .rl-num,
.dup-pill { direction: ltr; unicode-bidi: isolate; }
.ai-log-detail {
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 2px;
}
.health-empty {
    padding: 28px 8px 4px;
    text-align: center;
    font-size: 14px;
    font-weight: 700;
    color: var(--text-primary);
}
.health-empty-sub {
    padding: 0 8px 24px;
    text-align: center;
    font-size: 12px;
    color: var(--text-muted);
    line-height: 1.6;
}

/* ==========================================================================
   Duplicate receipt warning

   Warns, never blocks: a supplier can legitimately issue two documents with the
   same total on the same day, and the manager is the one who can tell.
   ========================================================================== */

.receipt-dup {
    border-radius: var(--radius-md);
    padding: 12px 14px;
    margin-bottom: 14px;
    border: 1px solid var(--warning);
    background: var(--warning-bg);
}
/* A total-based match is near-certain; a line-count-only match is a maybe, and
   should not shout as loudly. */
.receipt-dup.is-weak {
    border-color: var(--border-color);
    background: var(--bg-main);
}
.receipt-dup-head {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13.5px;
    color: var(--warning);
    margin-bottom: 8px;
}
.receipt-dup.is-weak .receipt-dup-head { color: var(--text-secondary); }

.receipt-dup-row {
    font-size: 12.5px;
    color: var(--text-primary);
    padding: 5px 0;
    border-block-start: 1px solid var(--border-color);
    line-height: 1.6;
}
.receipt-dup-when {
    display: block;
    font-size: 11px;
    color: var(--text-muted);
}
.receipt-dup-diff { color: var(--text-muted); font-size: 11px; }
.receipt-dup-scope,
.receipt-dup-note {
    font-size: 11.5px;
    color: var(--text-muted);
    margin-top: 8px;
    line-height: 1.5;
}
.receipt-dup-actions {
    display: flex;
    gap: 8px;
    margin-top: 10px;
    flex-wrap: wrap;
}

/* ==========================================================================
   Receipts: filed on scan, applied later

   A scanned receipt is a record straight away. It carries a status so the list
   distinguishes "read but not confirmed" from "counted", and rows are clickable
   because finishing one later is now a normal part of the flow.
   ========================================================================== */

.receipt-row { cursor: pointer; transition: border-color 0.15s, background 0.15s; }
.receipt-row:hover { border-color: var(--primary-color); }
/* An unconfirmed receipt has changed nothing yet, so it reads as outstanding
   work rather than as history. */
.receipt-row.is-pending { border-inline-start: 3px solid var(--warning); }

.receipt-status {
    font-size: 10.5px;
    font-weight: 800;
    padding: 2px 9px;
    border-radius: 999px;
    white-space: nowrap;
}
.rs-pending { background: var(--warning-bg); color: var(--warning); }
.rs-applied { background: var(--success-bg); color: var(--success); }

.receipt-bulk {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 10px;
}
.receipt-bulk-count {
    font-size: 11.5px;
    color: var(--text-muted);
    font-weight: 600;
}
.receipt-bulk .chip-btn:disabled { opacity: 0.45; cursor: not-allowed; }

.receipt-pending-note,
.receipt-applied-note {
    font-size: 11.5px;
    line-height: 1.55;
    margin-top: 6px;
    padding: 8px 11px;
    border-radius: var(--radius-md);
}
.receipt-pending-note { color: var(--text-secondary); background: var(--bg-main); }
.receipt-applied-note { color: var(--warning); background: var(--warning-bg); }

.supplier-btn-danger {
    background: transparent;
    border: 1px solid var(--danger);
    color: var(--danger);
}
.supplier-btn-danger:hover { background: var(--danger-bg); }
.supplier-btn:disabled { opacity: 0.45; cursor: not-allowed; }

/* Health tab shows the org-wide totals, so it needs more columns than the
   4-up scoped rows on the individual pages. */
.ai-row-health { grid-template-columns: repeat(4, 1fr); margin-bottom: 10px; }
@media (max-width: 900px) { .ai-row-health { grid-template-columns: repeat(2, 1fr); } }

/* Page stat tiles: a number plus the share of the whole it represents. */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 10px;
    margin-bottom: 16px;
}
/* ======================================================================
   Unified Stat Tiles - Option A: Icon-Tile Cards + Progress Bars
   Used across ALL page headers for consistent KPI presentation.
   ====================================================================== */
.stat-tile {
    /* The KPI figure sizes itself against this tile, not against the viewport.
       The tile is what actually constrains it: the same phone shows these two
       across, one across, or three on a wide screen, and a vw-based size is
       wrong in at least two of those. `cqi` is the only unit that tracks the
       box the number has to fit inside. */
    container-type: inline-size;
    padding: 14px 16px;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: var(--bg-solid);
    display: flex;
    flex-direction: column;
    gap: 6px;
    height: 100%;
    width: 100%;
    transition: box-shadow 0.2s ease, transform 0.2s ease;
    position: relative;
    overflow: hidden;
}
.stat-tile.st-tone-primary { border-top: 3px solid #3b82f6; }
.stat-tile.st-tone-ok      { border-top: 3px solid #10b981; }
.stat-tile.st-tone-warn    { border-top: 3px solid #f59e0b; }
.stat-tile.st-tone-danger  { border-top: 3px solid #ef4444; }
.stat-tile.st-tone-accent  { border-top: 3px solid #8b5cf6; }

/* UI-UX Pro Max: Interactive Affordances & Active Selected Feedback */
.stat-tile.clickable { 
    cursor: pointer;
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.stat-tile.clickable:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1), 0 0 0 1px var(--primary-color);
    border-color: var(--primary-color);
}
body.dark-theme .stat-tile.clickable:hover {
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.4), 0 0 0 1px #6366f1;
    border-color: #6366f1;
}
.stat-tile.clickable:active {
    transform: translateY(-1px) scale(0.99);
}

/* Unmistakable Active / Current View State */
.stat-tile.active {
    border: 2px solid var(--primary-color) !important;
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary-color) 18%, transparent), 0 8px 24px rgba(0, 0, 0, 0.12) !important;
    background: color-mix(in srgb, var(--primary-color) 10%, var(--bg-solid)) !important;
    transform: translateY(-2px);
    z-index: 10;
}
body.dark-theme .stat-tile.active {
    border: 2px solid #6366f1 !important;
    box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.25), 0 8px 28px rgba(0, 0, 0, 0.45) !important;
    background: rgba(99, 102, 241, 0.16) !important;
}

.stat-tile:hover {
    box-shadow: 0 6px 20px rgba(0,0,0,0.07);
    transform: translateY(-2px);
}

/* Head row: icon tile + label + status badge */
.st-head {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
}
.st-head-left {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    flex: 1;
}

/* Interactive Action & Active Badges */
.st-status-badge {
    margin-inline-start: auto;
    font-size: 11px;
    font-weight: 700;
    padding: 3px 8px;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: all 0.2s ease;
    white-space: nowrap;
    flex-shrink: 0;
}
.st-status-badge.clickable-badge {
    background: var(--bg-input, #f1f5f9);
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
}
body.dark-theme .st-status-badge.clickable-badge {
    background: #334155;
    color: #cbd5e1;
    border-color: rgba(255, 255, 255, 0.15);
}
.stat-tile.clickable:hover .st-status-badge.clickable-badge {
    background: var(--primary-color, #6366f1);
    color: #ffffff;
    border-color: var(--primary-color, #6366f1);
    box-shadow: 0 2px 6px color-mix(in srgb, var(--primary-color) 35%, transparent);
}
.st-status-badge.active-badge {
    background: var(--primary-color, #6366f1);
    color: #ffffff;
    border: 1px solid var(--primary-color, #6366f1);
    box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4);
}
body.dark-theme .st-status-badge.active-badge {
    background: #6366f1;
    color: #ffffff;
    box-shadow: 0 2px 10px rgba(99, 102, 241, 0.6);
}
.st-icon-tile {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 10px;
    flex-shrink: 0;
}
.st-icon-tile svg {
    width: 18px;
    height: 18px;
}
/* Tone-based icon tile backgrounds */
.st-icon-primary { background: rgba(59, 130, 246, 0.12); color: #3b82f6; }
.st-icon-accent  { background: rgba(139, 92, 246, 0.12); color: #8b5cf6; }
.st-icon-ok      { background: rgba(16, 185, 129, 0.12); color: #10b981; }
.st-icon-warn    { background: rgba(245, 158, 11, 0.12); color: #f59e0b; }
.st-icon-danger  { background: rgba(239, 68, 68, 0.12);  color: #ef4444; }
.st-icon-        { background: rgba(107, 114, 128, 0.10); color: #6b7280; }

.st-label {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary, #4b5563);
    min-width: 0;
    letter-spacing: 0.1px;
    /* Wrap to a second line before giving up.
       `white-space: nowrap` with an ellipsis turned "פריטים בחוסר" into "פ..."
       and "ללא ספק" into "לל..." once the tiles narrowed, which tells the
       reader nothing at all: a label clipped to one glyph is worse than a
       label on two lines. Two lines is the cap, so a long label still cannot
       push the number out of the tile. */
    /* Two lines, then stop. Not `-webkit-line-clamp`: this is a flex item, and
       a flex item blockifies, so `display: -webkit-box` computes to flow-root
       and the clamp silently does nothing. A max-height in line units gets the
       same two lines without depending on a display value that cannot survive
       here. */
    line-height: 1.35;
    max-height: 2.7em;
    overflow: hidden;
    overflow-wrap: break-word;
    /* Claim the space the icon leaves.
       `nowrap` used to give this a wide min-content, so it held its ground and
       then ellipsised. Allowing it to wrap dropped min-content to the longest
       word, and with nothing telling it to grow it collapsed to 12px. */
    flex: 1 1 auto;
}

/* The label was never the thief. The header row is 163px in a 199px tile and
   the "תצוגה פעילה" badge is a fixed 95px of it, so the icon and the label were
   dividing the 58px left over: hence a 12px label and "פ...".

   The badge drops to its own line when the row cannot hold both. A flex-basis
   of 120px is what decides "cannot hold both", so on a wide tile they stay
   side by side exactly as before and only a squeezed tile pays the extra line. */
.st-head { flex-wrap: wrap; }
.st-head-left {
    flex: 1 1 120px;
    min-width: 0;
}

/* Main KPI value */
.st-value {
    font-size: clamp(20px, 1.8vw, 26px);
    font-weight: 800;
    line-height: 1.1;
    margin: 2px 0 0 0;
    padding: 0;
    color: var(--text-primary);
    unicode-bidi: isolate;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.st-val-ok      { color: var(--success, #10b981); }
.st-val-warn    { color: var(--warning, #f59e0b); }
.st-val-danger  { color: var(--danger, #ef4444); }
.st-val-accent  { color: #8b5cf6; }
.st-val-primary { color: var(--text-primary); }

.st-value .money-main,
.st-value .money-sub {
    display: inline-block;
    vertical-align: baseline;
    margin-top: 0;
}
.st-value .money-sub {
    font-size: 14px; /* Slightly larger so it's readable inline */
    margin-right: 6px;
}

/* Progress bar track and fill */
.st-bar-container {
    margin-top: 4px;
}
.st-bar-track {
    height: 5px;
    border-radius: 3px;
    background: var(--border-color);
    overflow: hidden;
}
.st-bar-fill {
    height: 100%;
    border-radius: 3px;
    transition: width 0.6s cubic-bezier(0.25, 1, 0.5, 1);
}
.st-fill-ok      { background: var(--success, #10b981); }
.st-fill-warn    { background: var(--warning, #f59e0b); }
.st-fill-danger  { background: var(--danger, #ef4444); }
.st-fill-accent  { background: #8b5cf6; }
.st-fill-primary { background: #3b82f6; }

/* PAR coverage list.
 *
 * Reuses .st-bar-track / .st-bar-fill above rather than defining a second bar,
 * so a change to the tile bars carries here. Only the row that holds one is
 * new. */
.inv-par-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-height: 300px;
    overflow-y: auto;
}
/* The bar takes the flexible column, not the name. The bar is the thing being
 * compared down the list, so it is the one that has to line up and the one
 * that earns the width. */
.inv-par-row {
    display: grid;
    grid-template-columns: minmax(0, 140px) minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    font-size: 13px;
}
.inv-par-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-primary);
    font-weight: 600;
}
.inv-par-nums {
    color: var(--text-muted);
    font-size: 12px;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
/* An empty shelf must not render as an empty bar.
 *
 * A line at zero stock computes to 0% width and draws nothing. On a real
 * inventory most of the lane sits at exactly zero, so the most urgent rows
 * were the least visible thing on the screen, and an empty track reads as
 * "no data" rather than "none left". A minimum width keeps the colour on
 * screen at zero; the numbers beside it still carry the exact value. */
.inv-par-row .st-bar-fill { min-width: 4px; }

/* Barcode scanner sheet. The viewport is a fixed box with animated viewfinder */
.barcode-card { max-width: 500px; width: 94vw; }
.barcode-viewport {
    position: relative;
    width: 100%;
    aspect-ratio: 4 / 3;
    background: #090d16;
    border-radius: 16px;
    overflow: hidden;
    border: 1.5px solid var(--border-color);
    box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.4), 0 4px 20px rgba(0, 0, 0, 0.08);
}
.barcode-viewport video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.barcode-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
.scanner-reticle {
    position: relative;
    width: 78%;
    height: 62%;
    border-radius: 12px;
}
.reticle-corner {
    position: absolute;
    width: 24px;
    height: 24px;
    border-color: #10b981;
    border-style: solid;
    pointer-events: none;
}
.reticle-corner.top-left {
    top: 0;
    left: 0;
    border-width: 3px 0 0 3px;
    border-top-left-radius: 8px;
}
.reticle-corner.top-right {
    top: 0;
    right: 0;
    border-width: 3px 3px 0 0;
    border-top-right-radius: 8px;
}
.reticle-corner.bottom-left {
    bottom: 0;
    left: 0;
    border-width: 0 0 3px 3px;
    border-bottom-left-radius: 8px;
}
.reticle-corner.bottom-right {
    bottom: 0;
    right: 0;
    border-width: 0 3px 3px 0;
    border-bottom-right-radius: 8px;
}
.scanner-laser {
    position: absolute;
    left: 4px;
    right: 4px;
    height: 2px;
    background: linear-gradient(90deg, transparent 0%, #10b981 50%, transparent 100%);
    box-shadow: 0 0 12px #10b981, 0 0 4px #34d399;
    animation: scanLaser 2.2s ease-in-out infinite alternate;
}
@keyframes scanLaser {
    0% { top: 8%; opacity: 0.4; }
    50% { opacity: 1; }
    100% { top: 90%; opacity: 0.4; }
}

/* Camera Blocked State */
.barcode-camera-blocked {
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.95);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 24px 20px;
    text-align: center;
    z-index: 10;
}
.bcb-icon-wrap {
    width: 56px;
    height: 56px;
    border-radius: 16px;
    background: rgba(239, 68, 68, 0.15);
    color: #f87171;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 12px;
}
.bcb-title {
    font-size: 15px;
    font-weight: 800;
    color: #ffffff;
    margin: 0 0 6px 0;
}
.bcb-desc {
    font-size: 12.5px;
    color: #94a3b8;
    line-height: 1.5;
    margin: 0 0 16px 0;
    max-width: 320px;
}
.bcb-retry-btn {
    font-size: 12.5px;
    padding: 6px 14px;
    color: #ffffff;
    border-color: rgba(255, 255, 255, 0.2);
}

/* Barcode Status Box */
.barcode-status-box {
    margin-top: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border-radius: 10px;
    background: var(--bg-input);
    border: 1px solid var(--border-color);
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
}
.barcode-status-box.is-warn {
    background: rgba(245, 158, 11, 0.08);
    border-color: rgba(245, 158, 11, 0.28);
    color: #b45309;
}
.dark-theme .barcode-status-box.is-warn {
    background: rgba(245, 158, 11, 0.14);
    border-color: rgba(245, 158, 11, 0.35);
    color: #fbbf24;
}
.barcode-status-box.is-ok {
    background: rgba(16, 185, 129, 0.08);
    border-color: rgba(16, 185, 129, 0.28);
    color: #047857;
}
.barcode-status {
    margin: 0;
    line-height: 1.4;
}

/* Card View Quick Intake CTA Button */
.inv-card-intake-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 10px 14px;
    border-radius: 12px;
    background: linear-gradient(135deg, rgba(16, 185, 129, 0.08) 0%, rgba(5, 150, 105, 0.14) 100%);
    border: 1.5px solid rgba(16, 185, 129, 0.38);
    color: #065f46;
    cursor: pointer;
    font-family: var(--font-sans);
    transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: 0 2px 6px rgba(16, 185, 129, 0.08);
    text-align: right;
}
.dark-theme .inv-card-intake-btn {
    background: linear-gradient(135deg, rgba(16, 185, 129, 0.16) 0%, rgba(5, 150, 105, 0.24) 100%);
    border-color: rgba(52, 211, 153, 0.45);
    color: #a7f3d0;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
}
.inv-card-intake-btn:hover {
    background: linear-gradient(135deg, #059669 0%, #047857 100%);
    color: #ffffff;
    border-color: #047857;
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(5, 150, 105, 0.28);
}
.dark-theme .inv-card-intake-btn:hover {
    background: linear-gradient(135deg, #10b981 0%, #059669 100%);
    color: #ffffff;
    border-color: #10b981;
    box-shadow: 0 8px 22px rgba(16, 185, 129, 0.35);
}
.inv-card-intake-btn:active {
    transform: scale(0.98);
}
.ici-icon-box {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: rgba(16, 185, 129, 0.2);
    color: currentColor;
    flex-shrink: 0;
    transition: background 0.2s ease;
}
.inv-card-intake-btn:hover .ici-icon-box {
    background: rgba(255, 255, 255, 0.25);
}
.ici-text {
    font-size: 13.5px;
    font-weight: 800;
    letter-spacing: -0.1px;
    flex: 1;
}
.ici-badge {
    font-size: 11px;
    font-weight: 800;
    padding: 3px 8px;
    border-radius: 6px;
    background: rgba(16, 185, 129, 0.2);
    color: currentColor;
    transition: background 0.2s ease;
}
.inv-card-intake-btn:hover .ici-badge {
    background: rgba(255, 255, 255, 0.25);
}
/* An item with no PAR gets a full-width bar in a neutral colour, never a green
 * one. A green bar would assert the shelf is fine for something nobody set a
 * target for. */
.inv-par-unset { background: var(--border-color); }
.inv-par-row.is-unset .inv-par-name { color: var(--text-muted); font-weight: 500; }
.inv-par-more {
    align-self: flex-start;
    background: none;
    border: none;
    padding: 4px 0;
    color: var(--primary);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
}
.inv-par-note,
.inv-par-empty {
    color: var(--text-muted);
    font-size: 12px;
    line-height: 1.5;
}
.inv-cat-note {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 12px;
}
.inv-cat-chip {
    background: rgba(245, 158, 11, 0.15);
    color: var(--warning, #f59e0b);
    border: 1px solid rgba(245, 158, 11, 0.3);
    border-radius: 999px;
    padding: 3px 10px;
    font-size: 11px;
    font-weight: 600;
}
/* The inventory pair sits above a full-width controls bar, so it wraps to one
 * column earlier than the dashboard grid does. */
@media (max-width: 900px) {
    .inventory-charts-grid { grid-template-columns: 1fr; }
}

/* Footer: status pill */
.st-footer {
    margin-top: auto;
}
.st-sub-pill {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 20px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.st-pill-ok      { background: rgba(16, 185, 129, 0.10); color: #059669; }
.st-pill-warn    { background: rgba(245, 158, 11, 0.10); color: #d97706; }
.st-pill-danger  { background: rgba(239, 68, 68, 0.10);  color: #dc2626; }
.st-pill-accent  { background: rgba(139, 92, 246, 0.10); color: #7c3aed; }
.st-pill-primary { background: rgba(59, 130, 246, 0.08);  color: #2563eb; }
.st-pill-        { background: rgba(107, 114, 128, 0.08); color: #6b7280; }

/* Dark mode overrides */
[data-theme="dark"] .st-icon-primary { background: rgba(96, 165, 250, 0.15); color: #60a5fa; }
[data-theme="dark"] .st-icon-ok      { background: rgba(52, 211, 153, 0.15); color: #34d399; }
[data-theme="dark"] .st-icon-warn    { background: rgba(251, 191, 36, 0.15); color: #fbbf24; }
[data-theme="dark"] .st-icon-danger  { background: rgba(248, 113, 113, 0.15); color: #f87171; }
[data-theme="dark"] .st-pill-ok      { background: rgba(52, 211, 153, 0.12); color: #34d399; }
[data-theme="dark"] .st-pill-warn    { background: rgba(251, 191, 36, 0.12); color: #fbbf24; }
[data-theme="dark"] .st-pill-danger  { background: rgba(248, 113, 113, 0.12); color: #f87171; }
[data-theme="dark"] .st-pill-primary { background: rgba(96, 165, 250, 0.12); color: #60a5fa; }

/* Responsive */
@media (max-width: 640px) {
    .stat-tile { padding: 12px 14px; }
    .st-value { font-size: clamp(18px, 5vw, 22px); }
    .st-icon-tile { width: 30px; height: 30px; }
    .st-icon-tile svg { width: 14px; height: 14px; }
}

