/* RestaurantPOS Web Console — premium dark theme that echoes the WPF host's
   palette: pure black surface + vivid gold accent. Kept minimal on purpose;
   Phase W.5 ships the architecture, polish lands on top. */

:root {
    /* Refined dark-luxury (WEB-31): warmer-than-black surfaces that step in
       elevation, calmer hairlines, gold reserved as an accent. */
    --bg:       #0e0e11;
    --panel:    #17171c;   /* base card */
    --panel-hi: #1c1c22;   /* top of card gradient */
    --panel2:   #1f1f26;   /* raised chrome (th, chips, inputs) */
    --line:     #272730;   /* hairline, low-contrast */
    --line-soft:#20202a;
    --text:     #f1efe7;
    --muted:    #9a9386;
    --gold:     #d4af37;
    --gold-hi:  #e6c452;
    --ok:       #2ecc71;
    --warn:     #f39c12;
    --off:      #555555;
    --err:      #e74c3c;
    --radius:   12px;
    --radius-lg:16px;
    --focus:    0 0 0 3px rgba(212, 175, 55, .26);
    --speed:    160ms;
    /* Layered elevation — soft, never a hard drop. */
    --elev-1: 0 1px 2px rgba(0,0,0,.4), 0 4px 14px rgba(0,0,0,.30);
    --elev-2: 0 2px 6px rgba(0,0,0,.45), 0 14px 40px rgba(0,0,0,.45);
    --card-grad: linear-gradient(180deg, var(--panel-hi), var(--panel));
    color-scheme: dark;
}

/* ============ Light theme (WEB-16) ============
   The whole portal is CSS-variable driven, so this single palette re-skins
   every surface built on the tokens. `data-theme` is stamped pre-paint (see
   _Host.cshtml) from the cookie or the OS preference, and flipped live by the
   ☀/🌙 toggle. Component styles that hardcode a dark surface get a light
   override in the block near the bottom of this file. Gold stays the brand
   accent, deepened slightly so it stays legible as text on light panels. */
:root[data-theme="light"] {
    --bg:       #f4f2ec;
    --panel:    #ffffff;
    --panel-hi: #ffffff;
    --panel2:   #f1ece1;
    --line:     #e7e1d3;
    --line-soft:#efeade;
    --text:     #1b1913;
    --muted:    #6f6858;
    --gold:     #a97f16;
    --gold-hi:  #c99a2a;
    --ok:       #1e9e5a;
    --warn:     #c07c0c;
    --err:      #d13b2c;
    --focus:    0 0 0 3px rgba(169, 127, 22, .22);
    --elev-1: 0 1px 2px rgba(60,50,20,.05), 0 4px 14px rgba(60,50,20,.06);
    --elev-2: 0 2px 8px rgba(60,50,20,.07), 0 16px 40px rgba(60,50,20,.10);
    --card-grad: linear-gradient(180deg, #ffffff, #fdfbf6);
    color-scheme: light;
}

* { box-sizing: border-box; }
/* Belt-and-braces: the PAGE itself can never grow a horizontal scrollbar, no
   matter what a future component gets wrong. Anything that legitimately needs
   to scroll sideways (a wide table, an off-canvas drawer, a filter-chip rail)
   owns its own overflow-x — this only stops that overflow from leaking up and
   dragging the whole page with it. */
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text);
             overflow-x: hidden;
             font-family: 'Segoe UI', system-ui, -apple-system, sans-serif; }
/* …but `overflow-x: hidden` costs more than it looks. Per spec, hiding ONE axis
   computes the other from `visible` to `auto`, which makes <body> a scroll
   CONTAINER. `position: sticky` resolves against its nearest scroll container, so
   the sidebar was sticking to a body that never scrolls while the real scrolling
   happened on <html> — it slid off the top like a static element. `clip` does the
   same clipping WITHOUT creating a scroll container, so sticky works again.
   Kept as a @supports upgrade: a browser without `clip` falls back to today's
   behaviour rather than growing the horizontal scrollbar this rule exists to kill. */
@supports (overflow-x: clip) {
    html, body { overflow-x: clip; }
}
code { background: var(--panel2); padding: 1px 6px; border-radius: 4px; color: var(--gold); font-size: 0.9em; }

/* ============ Unified button system (W1) ============
   One base for EVERY button in the console: comfortable touch target,
   consistent radius, calm transitions, real focus/active/disabled states.
   Page-level classes (.primary/.warn/.tab/.chip/…) only recolour. */
button {
    font-family: inherit; font-size: .95em; font-weight: 600;
    min-height: 40px; padding: 8px 18px;
    border-radius: var(--radius); border: 1px solid var(--line);
    background: var(--panel2); color: var(--text);
    cursor: pointer; user-select: none;
    transition: border-color var(--speed), background var(--speed),
                color var(--speed), transform var(--speed), box-shadow var(--speed);
}
button:hover:not(:disabled) { border-color: var(--gold); }
button:active:not(:disabled) { transform: translateY(1px); }
button:focus-visible { outline: none; box-shadow: var(--focus); }
button:disabled { opacity: .45; cursor: not-allowed; }
button.primary {
    background: linear-gradient(180deg, var(--gold-hi), var(--gold));
    color: #141414; border: 0; font-weight: 700;
    box-shadow: 0 2px 10px rgba(212, 175, 55, .22);
}
button.primary:hover:not(:disabled) {
    background: linear-gradient(180deg, #f0d066, var(--gold-hi));
    box-shadow: 0 4px 16px rgba(212, 175, 55, .32);
}
button.warn { color: var(--warn); border-color: rgba(245, 158, 11, .5); background: transparent; }
button.warn:hover:not(:disabled) { border-color: var(--warn); background: rgba(245, 158, 11, .08); }

.shell { min-height: 100vh; }
.shell.anon .content { display: grid; place-items: center; min-height: 100vh; }

header.top {
    display: flex; align-items: center; gap: 24px;
    padding: 12px 24px; background: var(--panel); border-bottom: 1px solid var(--line);
}
header.top .brand { font-weight: 700; letter-spacing: 0.2px; }
header.top .brand .dot {
    display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    background: var(--gold); margin-right: 8px; box-shadow: 0 0 8px var(--gold);
}
header.top nav.nav { display: flex; gap: 4px; margin-left: auto; }
header.top nav.nav a {
    color: var(--muted); text-decoration: none; padding: 8px 14px;
    border-radius: 6px; transition: 120ms;
}
header.top nav.nav a:hover { color: var(--text); background: var(--panel2); }
header.top nav.nav a.active { color: var(--gold); background: var(--panel2); }
header.top .who { display: flex; align-items: center; gap: 12px; }
header.top .user { font-weight: 600; }
header.top .muted, .muted { color: var(--muted); font-size: 0.85em; }
header.top button.logout {
    background: transparent; color: var(--text); border: 1px solid var(--line);
    padding: 6px 12px; border-radius: 6px; cursor: pointer;
}
header.top button.logout:hover { border-color: var(--gold); color: var(--gold); }

/* width:100% is LOAD-BEARING: .content sits in a column flex with auto side margins,
   which sizes it fit-content — floored by the widest child's MIN-content. One nowrap
   rail (the WEB-13 swipeable filter row) then silently inflated the whole page to
   ~630px on a 375px phone. An explicit width opts out of intrinsic sizing entirely;
   max-width still caps it and the auto margins still center it. */
.content { padding: 32px 32px 64px; width: 100%; max-width: 1280px; margin: 0 auto; }
h1 { margin: 0 0 4px; }
h2 { margin: 28px 0 12px; color: var(--muted); font-weight: 500; font-size: 1em;
     text-transform: uppercase; letter-spacing: 0.1em; }
.sub { color: var(--muted); margin: 0 0 24px; max-width: 720px; line-height: 1.5; }

/* Login card */
.login { width: 100%; display: grid; place-items: center; }
.login .card {
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
    padding: 32px; width: 380px; max-width: 90vw;
}
.login .card label { display: block; margin: 16px 0; }
.login .card label span { display: block; color: var(--muted); margin-bottom: 6px; font-size: 0.9em; }
.login .card label input {
    width: 100%; background: var(--bg); color: var(--text);
    border: 1px solid var(--line); border-radius: 6px; padding: 10px 12px; font-size: 1em;
}
.login .card label input:focus { outline: none; border-color: var(--gold); }
.login .card button {
    margin-top: 12px; width: 100%; background: var(--gold); color: #000;
    border: 0; padding: 12px; border-radius: 8px; font-weight: 700; font-size: 1em; cursor: pointer;
}
.login .card button:disabled { opacity: 0.5; cursor: wait; }

/* Glowing-blue database badge on the tenant sign-in card */
.db-badge {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    margin: 4px 0 18px; padding: 9px 12px;
    background: rgba(59, 130, 246, 0.08);
    border: 1px solid rgba(59, 130, 246, 0.45); border-radius: 8px;
    color: #60a5fa; font-family: Consolas, monospace; font-size: 0.92em;
    text-shadow: 0 0 8px rgba(96, 165, 250, 0.85);
    box-shadow: 0 0 12px rgba(59, 130, 246, 0.25), inset 0 0 18px rgba(59, 130, 246, 0.06);
    animation: dbGlow 2.4s ease-in-out infinite;
}
.db-badge .db-ico {
    color: #60a5fa; -webkit-text-fill-color: #60a5fa;
    text-shadow: 0 0 8px rgba(96, 165, 250, 0.85);
    filter: drop-shadow(0 0 6px rgba(96, 165, 250, 0.9));
}
.db-badge .db-label { color: var(--muted); font-family: inherit; text-shadow: none; font-size: 0.9em; }
@keyframes dbGlow {
    0%, 100% { box-shadow: 0 0 10px rgba(59, 130, 246, 0.22), inset 0 0 18px rgba(59, 130, 246, 0.06); }
    50%      { box-shadow: 0 0 22px rgba(59, 130, 246, 0.55), inset 0 0 22px rgba(59, 130, 246, 0.10); }
}

.error {
    background: rgba(231, 76, 60, 0.12); border: 1px solid var(--err); color: #ffb3aa;
    border-radius: 6px; padding: 10px 12px; margin-top: 12px;
}
.empty { color: var(--muted); padding: 32px; text-align: center;
         background: var(--panel); border: 1px dashed var(--line); border-radius: 8px; }

/* KPI tiles */
.kpis { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.kpi { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 16px 20px; }
.kpi .label { color: var(--muted); font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.1em; }
.kpi .value { font-size: 1.6em; font-weight: 700; margin-top: 6px; display: flex; align-items: center; gap: 10px; }
.kpi .dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; }
.kpi .dot.ok   { background: var(--ok);   box-shadow: 0 0 6px var(--ok); }
.kpi .dot.warn { background: var(--warn); box-shadow: 0 0 6px var(--warn); }
.kpi .dot.off  { background: var(--off); }

/* Recent activity feed */
.activity { list-style: none; padding: 0; margin: 0; }
.activity li { padding: 10px 14px; border-bottom: 1px solid var(--line); display: flex; gap: 12px; }
.activity li .type { color: var(--gold); font-weight: 600; min-width: 180px; }
.activity li .when { color: var(--muted); min-width: 80px; }
.activity li .raw  { color: var(--text); opacity: 0.9; font-family: ui-monospace, Consolas, monospace; font-size: 0.9em; }

/* Grid table */
.grid { width: 100%; border-collapse: collapse; background: var(--panel); border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.grid th, .grid td { padding: 12px 14px; text-align: left; border-bottom: 1px solid var(--line); }
.grid th { color: var(--muted); font-weight: 500; font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.08em; background: var(--panel2); }
.grid th.num, .grid td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* CRED-ON6 — sign-in history. The cloud-arrival row is the case that used to be
   invisible and generates the support call, so it is the one that is tinted. */
.ch-note {
    margin: 0 0 14px; padding: 10px 14px; border-radius: 8px;
    background: var(--panel2); border: 1px solid var(--line);
    color: var(--muted); font-size: .85rem;
}
.grid tr.ch-cloud td { background: rgba(245, 158, 11, .10); }
.ch-tag {
    margin-inline-start: 8px; padding: 1px 7px; border-radius: 999px;
    background: rgba(245, 158, 11, .18); color: #d97706;
    font-size: .72rem; font-weight: 700; white-space: nowrap;
}
.grid tr:last-child td { border-bottom: 0; }

.pill { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 0.8em; font-weight: 600; margin-right: 4px; }
.pill.ok   { background: rgba(46, 204, 113, 0.15); color: var(--ok); }
.pill.off  { background: rgba(85,  85,  85, 0.25); color: var(--muted); }
.pill.gold { background: rgba(212, 175, 55, 0.15); color: var(--gold); }

/* ---- Live pill (next to page H1) ---- */
.live-pill {
    display: inline-block; vertical-align: middle; margin-left: 12px;
    font-size: 0.55em; padding: 3px 10px; border-radius: 999px; font-weight: 600;
    letter-spacing: 0.05em; text-transform: uppercase;
}
.live-pill.ok   { background: rgba(46,  204, 113, 0.18); color: var(--ok); }
.live-pill.warn { background: rgba(243, 156, 18,  0.18); color: var(--warn); }
.live-pill.off  { background: rgba(85,  85,  85,  0.30); color: var(--muted); }

/* ---- Orders filter chip row ---- */
.filter-row { display: flex; align-items: center; gap: 8px; margin: 8px 0 18px; flex-wrap: wrap; }
.filter-row .spacer { flex: 1; }
.chip {
    background: var(--panel); color: var(--text); border: 1px solid var(--line);
    padding: 6px 14px; border-radius: 999px; cursor: pointer; font-size: 0.9em; transition: 120ms;
}
.chip:hover { border-color: var(--gold); }
.chip.active { background: var(--gold); color: #000; border-color: var(--gold); font-weight: 700; }

/* ---- Kitchen Display grid ---- */
.kds-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.ticket {
    background: var(--panel); border: 1px solid var(--line); border-left: 4px solid var(--line);
    border-radius: 10px; padding: 14px 16px; display: flex; flex-direction: column; gap: 10px;
}
.ticket.new      { border-left-color: var(--gold);   box-shadow: 0 0 0 1px rgba(212, 175, 55, 0.15); }
.ticket.wip      { border-left-color: var(--warn); }
.ticket.done     { border-left-color: var(--ok); }
.ticket.bumped   { opacity: 0.55; }

.ticket header { display: flex; justify-content: space-between; align-items: center; }
.ticket .head-left { display: flex; gap: 10px; align-items: center; }
.ticket .num { font-weight: 700; font-size: 1.1em; }
.ticket .station {
    display: inline-block; padding: 2px 10px; border-radius: 6px; font-size: 0.8em;
    font-weight: 700; background: var(--panel2); color: var(--muted);
}
.ticket .elapsed {
    font-family: ui-monospace, Consolas, monospace; color: var(--muted); font-size: 0.95em;
}

.ticket .meta { display: flex; gap: 12px; color: var(--muted); font-size: 0.85em; flex-wrap: wrap; }
.ticket .meta .order { color: var(--gold); }

.ticket ul.lines { list-style: none; padding: 0; margin: 0; }
.ticket ul.lines li { padding: 6px 0; border-bottom: 1px dashed var(--line); }
.ticket ul.lines li:last-child { border-bottom: 0; }
.ticket ul.lines li .qty { color: var(--gold); font-weight: 700; margin-right: 6px; }
.ticket ul.lines li .name { font-weight: 500; }
/* K5 — a line the POS cancelled after firing. Struck through and badged so nobody keeps
   cooking it; this screen used to render voids as ordinary lines. */
.ticket ul.lines li.voidline .name { text-decoration: line-through; color: var(--err); }
.ticket ul.lines li.voidline .qty { color: var(--err); }
.ticket ul.lines li.voidline .mods,
.ticket ul.lines li.voidline .variant { text-decoration: line-through; opacity: .6; }
.ticket ul.lines li .void-badge {
    background: var(--err); color: #fff; font-weight: 800; font-size: .68rem;
    letter-spacing: .06em; padding: 2px 8px; border-radius: 6px; margin-inline-start: 8px;
}
.ticket ul.lines li .variant { color: var(--muted); }
.ticket ul.lines li .mods,
.ticket ul.lines li .note,
.ticket .ticket-note {
    color: var(--muted); font-size: 0.85em; margin-top: 4px; padding-left: 22px;
}

.ticket footer { display: flex; gap: 8px; margin-top: auto; }
.ticket footer button {
    flex: 1; padding: 10px; border-radius: 6px; border: 0; cursor: pointer; font-weight: 700;
    background: var(--panel2); color: var(--text);
}
.ticket footer button.primary { background: var(--gold); color: #000; }
.ticket footer button.primary.success { background: var(--ok); }

#blazor-error-ui {
    background: var(--err); color: white; bottom: 0; left: 0; right: 0;
    position: fixed; padding: 12px 24px; display: none; z-index: 1000;
}
#blazor-error-ui.show { display: block; }

/* ---- Vendor console: Tenants page ---------------------------------------- */
.notice {
    background: rgba(34, 197, 94, .12); border: 1px solid rgba(34, 197, 94, .5);
    color: var(--ok, #22c55e); border-radius: 8px; padding: 10px 14px; margin: 10px 0;
}
.toolbar { display: flex; gap: 10px; align-items: center; margin: 14px 0; }
.toolbar input[type="text"], .toolbar input:not([type]) {
    flex: 0 1 320px; padding: 8px 12px; border-radius: 8px;
    border: 1px solid var(--line, #333); background: var(--panel2, #1b1b1b); color: var(--text, #eee);
}
.toolbar button { padding: 8px 16px; border-radius: 8px; border: 0; cursor: pointer;
    background: var(--panel2, #222); color: var(--text, #eee); }
.toolbar button.primary { background: var(--gold, #d4af37); color: #000; font-weight: 700; }

.editor {
    border: 1px solid var(--line, #333); border-radius: 12px;
    padding: 16px 18px; margin: 12px 0; background: var(--panel, #161616);
}
.editor h3 { margin: 0 0 12px; }
.form-grid { display: grid; grid-template-columns: repeat(3, minmax(180px, 1fr)); gap: 10px 14px; }
.form-grid label { display: flex; flex-direction: column; gap: 4px; font-size: .85em; color: var(--muted, #999); }
.form-grid input, .form-grid select {
    padding: 8px 10px; border-radius: 8px; border: 1px solid var(--line, #333);
    background: var(--panel2, #1b1b1b); color: var(--text, #eee);
}
.editor .actions { display: flex; gap: 8px; margin-top: 14px; }
.editor .actions button { padding: 8px 20px; border-radius: 8px; border: 0; cursor: pointer;
    background: var(--panel2, #222); color: var(--text, #eee); }
.editor .actions button.primary { background: var(--gold, #d4af37); color: #000; font-weight: 700; }

.pill.info { background: rgba(59, 130, 246, .15); color: #3b82f6; }
.row-actions { display: flex; flex-wrap: wrap; gap: 5px; }
.row-actions button {
    padding: 5px 10px; border-radius: 7px; border: 1px solid var(--line, #333);
    background: var(--panel2, #1c1c1c); color: var(--text, #eee); cursor: pointer; font-size: .82em;
}
.row-actions button.primary { background: var(--gold, #d4af37); color: #000; border: 0; font-weight: 700; }
.row-actions button.warn { color: #f59e0b; border-color: rgba(245, 158, 11, .5); }
.row-actions button:disabled { opacity: .45; cursor: default; }
/* ---- CUS-ACT — per-row actions menu (customer list) ----------------------------
   A kebab that opens a small anchored menu. The cell is the positioning context, so
   the menu hangs off the row it belongs to; a transparent scrim below it closes on
   the next click anywhere. Actions are NAMED, not left as bare emoji. */
.cus-act { position: relative; width: 1%; white-space: nowrap; text-align: end; }
.cus-act .kebab {
    font-size: 1.25rem; line-height: 1; font-weight: 700; letter-spacing: 1px;
    padding: 2px 10px; border-radius: 8px; background: var(--panel2);
    color: var(--text); border: 1px solid var(--line); cursor: pointer;
}
.cus-act .kebab:hover { border-color: var(--gold); color: var(--gold); }

.act-scrim { position: fixed; inset: 0; background: transparent; z-index: 30; }

.act-menu {
    position: absolute; z-index: 31; inset-inline-end: 0; top: calc(100% + 4px);
    min-width: 210px; padding: 6px; text-align: start;
    background: var(--panel2, #1c1c1c); border: 1px solid var(--line, #333);
    border-radius: 10px; box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
    display: flex; flex-direction: column; gap: 2px;
}
.act-menu > button, .act-menu > a {
    display: flex; align-items: center; gap: 10px; width: 100%;
    padding: 9px 10px; border: 0; border-radius: 7px;
    background: transparent; color: var(--text, #eee);
    font: inherit; font-size: .88em; text-align: start; text-decoration: none;
    cursor: pointer;
}
.act-menu > button:hover, .act-menu > a:hover { background: rgba(212, 175, 55, .12); color: var(--gold); }

/* ---- Tenants: expandable branches panel ---- */
.branches-row td { background: var(--panel, #141414); }
.branches-panel { padding: 10px 6px 14px; }
.branches-head { margin-bottom: 8px; display: flex; gap: 10px; align-items: baseline; }
table.grid.inner { margin: 0 0 10px; font-size: .92em; }
.branch-create { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.branch-create input {
    padding: 7px 10px; border-radius: 8px; border: 1px solid var(--line, #333);
    background: var(--panel2, #1b1b1b); color: var(--text, #eee);
}
.branch-create button { padding: 7px 16px; border-radius: 8px; border: 0; cursor: pointer;
    background: var(--panel2, #222); color: var(--text, #eee); }
.branch-create button.primary { background: var(--gold, #d4af37); color: #000; font-weight: 700; }
.branches-panel button.warn { color: #f59e0b; border: 1px solid rgba(245,158,11,.5); background: transparent; }

/* ================= Vendor console — professional dashboard ================= */
.nav-group { color: var(--gold); font-size: .7em; font-weight: 700; text-transform: uppercase;
    letter-spacing: 1px; padding: 0 6px; opacity: .8; }

/* WEB-33 — collapsible sidebar categories. The header is a <button> (not the old inert
   <span>) so it is focusable and announces aria-expanded.
   MOB-3 made it a bordered, gold-tinted pill because bare uppercase text at 80% opacity
   said nothing about being pressable — right diagnosis, heavy cure: with six categories
   that put six gold boxes down the rail, each shouting as loud as the ACTIVE page, which
   is the one question the rail exists to answer.
   NAV-2 keeps the affordance and drops the boxes. The header is now a section RULE:
   micro-caps title, a hairline running across to a chevron disclosure at the row's end.
   What makes it read as a control is the chevron, the full-row press surface and the
   40px target — not a border. Gold is spent on ONE thing in this rail: where you are. */
.nav-cat {
    display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px;
    background: transparent; border: 0; border-radius: 9px;
    cursor: pointer; text-align: start; font-family: inherit;
    color: var(--muted); font-size: .66rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .14em;
    padding: 8px 10px; margin: 14px 0 4px;
    transition: color var(--speed), background var(--speed);
}
.nav-cat:first-child { margin-top: 0; }
.nav-cat:hover { color: var(--text); background: color-mix(in srgb, var(--text) 6%, transparent); }
.nav-cat:hover .nav-cat-chev { color: var(--text); }
/* The global button rule lifts on :active — wrong for a nav row, which should feel
   pinned to the rail, not springy. */
.nav-cat:active { transform: none; }
.nav-cat.open { color: var(--text); }
.nav-cat:focus-visible { outline: none; box-shadow: var(--focus); }
.nav-cat-title { flex: 0 0 auto; }
/* The rule IS the device: it ties a title to its disclosure and gives the rail a
   horizontal beat between the vertical run of links. */
.nav-cat-rule { flex: 1 1 auto; min-width: 10px; height: 1px; background: var(--line); }
.nav-cat.open .nav-cat-rule { background: color-mix(in srgb, var(--gold) 28%, var(--line)); }
/* ONE glyph, rotated. The old ▸/▾ pair pointed INTO the text and needed a per-direction
   flip to survive Arabic; ▾ is symmetric, so rotation alone carries the state. */
.nav-cat-chev {
    flex: 0 0 auto; width: 18px; height: 18px; display: grid; place-items: center;
    font-size: .8rem; line-height: 1; color: var(--muted);
    transition: transform .2s cubic-bezier(.3,.8,.3,1), color var(--speed);
}
.nav-cat:not(.open) .nav-cat-chev { transform: rotate(-90deg); }
[dir="rtl"] .nav-cat:not(.open) .nav-cat-chev { transform: rotate(90deg); }
/* A shut category still has to say "your page is in here" — see the holdsActive note
   in MainLayout. This is the one place gold leaves the active pill. */
.nav-cat.holds-active { color: var(--gold-hi); }
.nav-cat.holds-active .nav-cat-rule { background: color-mix(in srgb, var(--gold) 45%, transparent); }
.nav-cat.holds-active .nav-cat-chev { color: var(--gold-hi); }
@media (prefers-reduced-motion: reduce) { .nav-cat-chev { transition: none; } }
.nav-sep { display: inline-block; width: 1px; height: 18px; background: var(--line); margin: 0 8px; vertical-align: middle; }

.page-head { display: flex; align-items: flex-end; justify-content: space-between; margin: 8px 0 18px; }
.page-head h1 { margin: 0; }
.page-head .sub { margin: 4px 0 0; color: var(--muted); }
.page-head button, .page-head select {
    padding: 8px 16px; border-radius: 8px; border: 1px solid var(--line);
    background: var(--panel2); color: var(--text); cursor: pointer;
}
.page-head .range { display: flex; align-items: center; gap: 12px; }
.page-head .range label { display: flex; gap: 8px; align-items: center; color: var(--muted); font-size: .9em; }
/* Date pickers — themed dark to match the console (native inputs default to white) */
.page-head input[type="date"], .range input[type="date"] {
    background: var(--panel2); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px;
    padding: 7px 10px; font-size: .9em; font-family: inherit;
    color-scheme: dark;   /* dark native calendar popup + light glyphs */
}
.page-head input[type="date"]:hover, .range input[type="date"]:hover { border-color: var(--gold); }

/* WEB-RSEL — the period combo that replaced the Today/7d/30d chip rows.
   Same chrome as the date inputs beside it, plus the calendar glyph inside
   the pill so the control names itself at a glance. */
.range-select {
    display: inline-flex; align-items: center; gap: 8px;
    background: var(--panel2); border: 1px solid var(--line); border-radius: 8px;
    padding: 0 4px 0 10px;
}
.range-select:hover, .range-select:focus-within { border-color: var(--gold); }
.range-select .rs-ico { font-size: .95em; opacity: .8; }
.range-select select {
    background: transparent; color: var(--text);
    border: none; outline: none;
    padding: 7px 6px; font-size: .9em; font-family: inherit;
    cursor: pointer; min-width: 110px;
}
.range-select select option { background: var(--panel2); color: var(--text); }
.page-head input[type="date"]:focus, .range input[type="date"]:focus {
    outline: none; border-color: var(--gold); box-shadow: 0 0 0 2px rgba(212,175,55,.2);
}
.page-head input[type="date"]::-webkit-calendar-picker-indicator {
    filter: invert(.7) sepia(1) saturate(4) hue-rotate(5deg);   /* gold-tinted icon */
    cursor: pointer;
}

.kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; margin-bottom: 20px; }
.kpi-card {
    background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
    padding: 16px 18px; position: relative; overflow: hidden;
}
.kpi-card::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--line); }
.kpi-card.accent-gold::before   { background: var(--gold); }
.kpi-card.accent-danger::before { background: var(--err); }
.kpi-card.accent-warn::before   { background: #f59e0b; }
.kpi-label { color: var(--muted); font-size: .72em; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; }
.kpi-value { font-size: 30px; font-weight: 800; margin: 6px 0 2px; }
.kpi-value .unit { font-size: .45em; color: var(--muted); font-weight: 600; }
.kpi-sub { color: var(--muted); font-size: .82em; }

.dash-cols { display: grid; grid-template-columns: 1.4fr 1fr; gap: 16px; }
@media (max-width: 900px) { .dash-cols { grid-template-columns: 1fr; } }
.panel { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 16px 18px; }
.panel-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.panel-head h2 { margin: 0; font-size: 1.05em; }
.link { color: var(--gold); text-decoration: none; font-size: .85em; }
.link:hover { text-decoration: underline; }
.empty.ok { color: var(--ok); }

/* One-time API-key reveal box (vendor console) */
.apikey-box {
    background: rgba(212,175,55,.06); border: 1px solid rgba(212,175,55,.5);
    border-radius: 10px; padding: 12px 14px; margin: 0 0 14px;
}
.apikey-box .apikey-head { color: var(--gold); font-size: .9em; margin-bottom: 8px; }
.apikey-box .apikey-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.apikey-value {
    flex: 1 1 auto; min-width: 240px; background: var(--bg); color: var(--text);
    border: 1px solid var(--line); border-radius: 6px; padding: 8px 10px;
    font-size: .9em; word-break: break-all; user-select: all;
}

/* Reports — tab bar + panel stacking + scrollable detail grids */
.reports .panel { margin-bottom: 16px; }
.tabs { display: flex; gap: 6px; border-bottom: 1px solid var(--line); margin: 4px 0 18px; flex-wrap: wrap; }
/* Report tabs — quiet pills that light up gold when active; 38px touch target. */
.tabs .tab, .tabgroup .tab {
    background: transparent; border: 1px solid transparent;
    color: var(--muted); min-height: 38px; padding: 7px 16px;
    font-size: .92em; font-weight: 600; cursor: pointer; border-radius: 999px;
    box-shadow: none;
}
.tabs .tab:hover:not(:disabled), .tabgroup .tab:hover:not(:disabled) {
    color: var(--text); background: rgba(255,255,255,.05); border-color: var(--line);
}
.tabs .tab.active, .tabgroup .tab.active {
    color: #141414; font-weight: 700;
    background: linear-gradient(180deg, var(--gold-hi), var(--gold));
    border-color: transparent; box-shadow: 0 2px 10px rgba(212,175,55,.25);
}
.tabs .tab:disabled, .tabgroup .tab:disabled { opacity: .4; cursor: not-allowed; }
.scroll-y { max-height: 460px; overflow-y: auto; }
.scroll-y table { margin: 0; }

/* horizontal status bars */
.bars { display: flex; flex-direction: column; gap: 9px; }
.bar-row { display: grid; grid-template-columns: 90px 1fr 36px; align-items: center; gap: 10px; }
.bar-lbl { color: var(--muted); font-size: .85em; }
.bar-track { height: 9px; background: var(--panel2); border-radius: 5px; overflow: hidden; }
.bar-fill { display: block; height: 100%; border-radius: 5px; }
.bar-fill.ok { background: var(--ok); } .bar-fill.info { background: #3b82f6; }
.bar-fill.warn { background: #f59e0b; } .bar-fill.off { background: #6b7280; }
.bar-num { text-align: right; font-weight: 700; font-size: .9em; }

/* sparkline / mini bar chart */
.spark { display: flex; align-items: flex-end; gap: 6px; height: 110px; padding: 4px 0; }
.spark.tall { height: 190px; }
.spark-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap: 4px; }
.spark-bar { width: 70%; min-height: 4px; background: linear-gradient(180deg, var(--gold), #9a7d1e); border-radius: 4px 4px 0 0; }
.spark-lbl { color: var(--muted); font-size: .68em; }

/* ---- Tenant row kebab + management drawer ---- */
.row-actions .kebab {
    font-size: 1.25rem; line-height: 1; font-weight: 700; letter-spacing: 1px;
    padding: 2px 10px; border-radius: 8px; background: var(--panel2);
    color: var(--text); border: 1px solid var(--line); cursor: pointer;
}
.row-actions .kebab:hover { border-color: var(--gold); color: var(--gold); }

.drawer-scrim { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 40; animation: fade .15s ease; }
.drawer {
    position: fixed; top: 0; right: 0; height: 100vh; width: 420px; max-width: 92vw;
    background: var(--panel); border-left: 1px solid var(--line); z-index: 41;
    display: flex; flex-direction: column; box-shadow: -18px 0 48px rgba(0,0,0,.5);
    animation: slideIn .18s ease;
}
@keyframes slideIn { from { transform: translateX(24px); opacity: .4; } to { transform: none; opacity: 1; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.drawer-head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
    padding: 18px 20px; border-bottom: 1px solid var(--line);
    background: linear-gradient(180deg, #1a1a1a, var(--panel));
}
.drawer-code { display: flex; align-items: center; gap: 8px; font-size: 1.05rem; }
.drawer-code code { color: var(--gold); font-size: 1.05rem; }
.drawer-name { color: var(--muted); margin-top: 4px; font-size: .92rem; }
/* MOB-6 — was a bare glyph with 2px of padding, i.e. a ~20px target. Even with a
   mouse that is a small thing to hit; the mobile block at the foot of this file takes
   it to 40px. min-height:0 is needed because the global button rule sets 40px and
   would otherwise stretch this square into a rectangle. */
.drawer-close {
    flex: none; width: 32px; height: 32px; min-height: 0; padding: 0;
    display: grid; place-items: center; border-radius: 8px;
    background: transparent; border: 0; color: var(--muted); font-size: 1.05rem;
    cursor: pointer;
}
.drawer-close:hover { color: var(--text); background: var(--panel2); }
.drawer-body { padding: 16px 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; }

.drawer-card { background: var(--panel2); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px; }
.dc-title { font-weight: 700; font-size: .82rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-bottom: 10px; }
.drawer-card p.muted { margin: 6px 0; font-size: .86rem; }
.dc-field { display: flex; flex-direction: column; gap: 4px; margin: 8px 0; font-size: .85rem; color: var(--muted); }
.dc-field input {
    background: var(--bg); color: var(--text); border: 1px solid var(--line);
    border-radius: 8px; padding: 9px 11px; font-size: 1rem;
}
.dc-field input:focus { outline: none; border-color: #3b82f6; box-shadow: 0 0 0 2px rgba(59,130,246,.25); }
.drawer-card button {
    margin-top: 8px; padding: 10px 14px; border-radius: 9px; cursor: pointer; font-weight: 700;
    background: var(--panel); color: var(--text); border: 1px solid var(--line); font-size: .92rem;
}
.drawer-card button.primary { background: var(--gold); color: #000; border: 0; }
.drawer-card button.warn { background: rgba(231,76,60,.14); color: #ff6b5c; border-color: rgba(231,76,60,.5); }
.drawer-card button:disabled { opacity: .5; cursor: wait; }
.dc-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.dc-actions button { margin-top: 0; }

.kv { display: flex; justify-content: space-between; padding: 5px 0; border-top: 1px dashed var(--line); font-size: .9rem; }
.kv:first-of-type { border-top: 0; }
.kv span { color: var(--muted); }

.sub-hero { display: flex; justify-content: center; padding: 6px 0 14px; }
.sub-days { display: flex; flex-direction: column; align-items: center; line-height: 1; }
.sub-days .n { font-size: 3rem; font-weight: 800; }
.sub-days .u { font-size: .8rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-top: 4px; }
.sub-days.ok   .n { color: var(--ok); }
.sub-days.warn .n { color: var(--warn); }
.sub-days.over .n { color: var(--err); }

/* ---- Reports hub: grouped tabs, share bars, deltas, P&L statement, mini charts ---- */
.tabgroups { display: flex; flex-wrap: wrap; gap: 10px 26px; margin: 6px 0 18px; }
.tabgroup { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.tabgroup-label {
    font-size: .72rem; text-transform: uppercase; letter-spacing: .12em;
    color: var(--muted); margin-right: 4px; font-weight: 700;
}

.bar-track {
    display: inline-block; vertical-align: middle; width: calc(100% - 52px);
    height: 8px; background: var(--panel2); border-radius: 999px; overflow: hidden; margin-right: 8px;
}
.bar-fill { height: 100%; background: var(--gold); border-radius: 999px; }

.delta-up   { color: var(--ok);  font-weight: 700; white-space: nowrap; }
.delta-down { color: var(--err); font-weight: 700; white-space: nowrap; }

.kpi-card.accent-ok::before { background: var(--ok); }

/* P&L statement rows.
   WEB-32: the statement is a 2-column ledger — it must NEVER inherit the
   mobile `.grid { display:block; white-space:nowrap }` scroll treatment, which
   collapses it to content width and leaves the card half empty. It stays a real
   table at every size: label column takes the slack, amounts hug the end. */
.grid.pnl { display: table !important; width: 100%; white-space: normal !important; table-layout: auto; }
.grid.pnl td { padding: 9px 14px; white-space: normal; }
.grid.pnl td.num { width: 1%; white-space: nowrap; text-align: end; font-variant-numeric: tabular-nums; }
.grid.pnl .sec td {
    background: var(--panel2); color: var(--muted); font-size: .74rem;
    letter-spacing: .12em; font-weight: 700; padding: 7px 14px;
}
.grid.pnl .ind { padding-inline-start: 28px; padding-left: unset; }   /* RTL-correct indent */
.grid.pnl .neg { color: var(--err); }
.grid.pnl .tot td { font-weight: 700; border-top: 1px solid var(--line); }
.grid.pnl .net td {
    font-weight: 800; font-size: 1.05rem; border-top: 2px solid var(--gold);
    background: rgba(212, 175, 55, .06);
}
.grid.pnl .net.loss td { border-top-color: var(--err); background: rgba(231, 76, 60, .08); }

/* Mini bar chart (sales by hour / cost by day) */
.hours { display: flex; align-items: flex-end; gap: 4px; min-height: 128px; padding: 8px 2px 0; }
.hourcol { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: 1; min-width: 0; }
.hourcol span { font-size: .62rem; color: var(--muted); }
.hourbar { width: 100%; max-width: 26px; background: var(--gold); border-radius: 3px 3px 0 0; opacity: .85; }
.hourcol:hover .hourbar { opacity: 1; }

/* ============ W1 — compact-control reconciliation ============
   The unified button base above sets a 40px touch target; these controls are
   deliberately smaller (dense table rows / icon buttons) and opt back down. */
.login .card button {
    background: linear-gradient(180deg, var(--gold-hi), var(--gold));
    color: #141414; border: 0; box-shadow: 0 2px 10px rgba(212, 175, 55, .22);
}
.login .card button:hover:not(:disabled) {
    background: linear-gradient(180deg, #f0d066, var(--gold-hi));
    box-shadow: 0 4px 16px rgba(212, 175, 55, .32);
}
.row-actions button { min-height: 32px; padding: 4px 12px; font-size: .82em; }
.row-actions .kebab { min-height: 32px; padding: 2px 10px; }
header.top button.logout { min-height: 34px; padding: 5px 12px; }
.drawer-close { min-height: 32px; padding: 2px 10px; border: 0; background: transparent; }
.chip { min-height: 34px; }
.spark, .hours { min-width: 0; }

/* ============ W1 — responsive: the console fits every screen ============ */

/* Tables never break the page — they scroll inside their own lane. */
.table-wrap, .scroll-y { max-width: 100%; }
@media (max-width: 980px) {
    .content { padding: 20px 16px 48px; }

    /* Header: hamburger + brand on the left, who-actions on the right; the nav
       moves OFF-CANVAS into a slide-in sidebar toggled by the hamburger. */
    header.top { gap: 12px; padding: 10px 14px; }
    .nav-toggle { display: inline-flex; }
    header.top .brand { font-size: .96rem; }
    header.top .who { margin-inline-start: auto; gap: 8px; }

    /* The off-canvas sidebar itself. */
    header.top nav.nav {
        position: fixed; z-index: 60; top: 0; bottom: 0; inset-inline-start: 0;
        width: 272px; max-width: 82vw; margin: 0;
        flex-direction: column; align-items: stretch; gap: 4px;
        padding: 66px 14px 20px;
        background: var(--panel); border-inline-end: 1px solid var(--line);
        box-shadow: 0 0 60px rgba(0,0,0,.5);
        overflow-y: auto; -webkit-overflow-scrolling: touch;
        /* MOB-3 — without this, the moment the drawer's scroll hits its end the
           gesture CHAINS to the page behind it, so the background visibly moves
           while the user thinks they're scrolling the menu. Contain stops the
           hand-off at the drawer's edge. */
        overscroll-behavior-y: contain;
        transform: translateX(-100%);
        transition: transform .28s cubic-bezier(.3,.8,.3,1);
    }
    [dir="rtl"] header.top nav.nav { transform: translateX(100%); }
    header.top.nav-open nav.nav { transform: translateX(0); }

    header.top nav.nav a { white-space: nowrap; padding: 12px 14px; border-radius: 10px; }
    header.top nav.nav .nav-group { padding: 6px 14px 2px; }

    /* Backdrop appears only when the sidebar is open. */
    header.top.nav-open .nav-backdrop {
        position: fixed; inset: 0; z-index: 55; display: block;
        background: rgba(0,0,0,.5); backdrop-filter: blur(2px);
        animation: navFade .2s ease both;
    }

    /* Page heads stack; the action row keeps its buttons reachable. */
    .page-head { flex-direction: column; align-items: stretch; gap: 12px; }
    .page-head .range { flex-wrap: wrap; }

    /* Data tables scroll horizontally instead of squeezing columns — !important
       because a LATER unconditional `.grid { overflow: hidden }` (the "real card"
       redesign, below) has equal specificity and silently won this exact property
       once already (found live: every non-Reports table was clipping columns with
       no way to reach them, not just scrolling badly). This is the one property
       this codebase has already had to re-fight for once; don't let it drift back. */
    .grid { display: block !important; overflow-x: auto !important; -webkit-overflow-scrolling: touch; white-space: nowrap !important; }
    .grid th, .grid td { white-space: nowrap; }

    .form-grid { grid-template-columns: repeat(2, minmax(140px, 1fr)); }
    /* `.drawer { width: 100vw }` used to live here and never applied — an
       unconditional `.drawer` rule further down the file won on source order. The
       full-bleed sheet now lives in the MOB-6 block at the foot of this file, and at
       a deliberately narrower breakpoint (640px): a 700px tablet wants a side panel,
       not a sheet that swallows the page it was opened from. */
    .kpi-value { font-size: 24px; }
}

@media (max-width: 560px) {
    .content { padding: 16px 12px 40px; }
    h1 { font-size: 1.45em; }
    .form-grid { grid-template-columns: 1fr; }
    .kpi-grid { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
    .kpi-card { padding: 12px 14px; }
    .toolbar { flex-wrap: wrap; }
    .toolbar input[type="text"], .toolbar input:not([type]) { flex: 1 1 100%; }
    .editor .actions { flex-wrap: wrap; }
    .editor .actions button { flex: 1 1 auto; }
    .tabgroups { gap: 8px 16px; }
    .kds-grid { grid-template-columns: 1fr; }
    .activity li { flex-wrap: wrap; }
    .activity li .type { min-width: 0; }
    .bar-row { grid-template-columns: 72px 1fr 34px; }
    .login .card { padding: 24px 18px; }
}

/* ================= Owner dashboard (WEB-1 Phase 1) ================= */
.own-dash .dash-head { display: flex; justify-content: space-between; align-items: flex-end;
    gap: 12px; flex-wrap: wrap; margin-bottom: 18px; }
.own-dash .dash-head h1 { margin: 0; }
.own-dash .live-meta { display: flex; align-items: center; gap: 6px; color: var(--text);
    font-size: 0.9em; }
.own-dash .live-meta .muted { color: var(--muted); }

.pill.err  { background: rgba(231, 76, 60, 0.15);  color: var(--err); }
.pill.warn { background: rgba(243, 156, 18, 0.15); color: var(--warn); }

.dash-skeleton { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.dash-skeleton div { height: 110px; border-radius: var(--radius); background: var(--panel);
    animation: dash-pulse 1.2s ease-in-out infinite alternate; }
@keyframes dash-pulse { from { opacity: .55; } to { opacity: 1; } }

.hero-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.kcard { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 16px 18px; }
.kcard.gold { border-color: rgba(212, 175, 55, .45);
    background: linear-gradient(180deg, rgba(212,175,55,.10), var(--panel) 55%); }
.kcard .klabel { color: var(--muted); font-size: .78em; font-weight: 700;
    letter-spacing: .08em; text-transform: uppercase; }
.kcard .kvalue { font-size: 1.9em; font-weight: 800; margin-top: 4px; color: var(--text); }
.kcard.gold .kvalue { color: var(--gold-hi); }
.kcard .kvalue .unit { font-size: .5em; font-weight: 600; color: var(--muted); }
.kcard .ksub { margin-top: 6px; font-size: .85em; color: var(--text); }
.kcard .ksub .muted { color: var(--muted); }
.delta { font-weight: 800; padding: 1px 8px; border-radius: 999px; font-size: .9em; }
.delta.up   { color: var(--ok);  background: rgba(46, 204, 113, .12); }
.delta.down { color: var(--err); background: rgba(231, 76, 60, .12); }

.alert-strip { margin-top: 14px; display: flex; gap: 8px; flex-wrap: wrap; }
.alert-strip .pill { font-size: .88em; padding: 5px 12px; }

.dash-grid { display: grid; grid-template-columns: 3fr 2fr; gap: 14px; margin-top: 14px; }
.dash-grid .panel { background: var(--panel); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 16px 18px; min-width: 0; }
.dash-grid .panel h2 { margin: 0 0 12px; font-size: 1.02em; color: var(--muted);
    font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }

.hour-chart { width: 100%; height: 170px; display: block; }
.hour-chart .bar { fill: var(--gold); opacity: .9; }
.hour-chart .bar:hover { fill: var(--gold-hi); opacity: 1; }
.hour-chart .bar.zero { fill: var(--line); }
.hour-chart .tick { fill: var(--muted); font-size: 10px; }

.top-products { list-style: none; margin: 0; padding: 0; counter-reset: rank; }
.top-products li { padding: 8px 0; }
.top-products li + li { border-top: 1px solid var(--line); }
.top-products .row { display: flex; gap: 10px; align-items: baseline; }
.top-products .row::before { counter-increment: rank; content: counter(rank);
    color: var(--gold); font-weight: 800; min-width: 18px; }
.top-products .name { flex: 1; font-weight: 600; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; }
.top-products .qty { color: var(--muted); font-size: .85em; }
.top-products .amt { font-weight: 700; color: var(--gold-hi); }
.top-products .meter { height: 4px; border-radius: 999px; background: var(--panel2);
    margin-top: 6px; overflow: hidden; }
.top-products .meter .fill { height: 100%; border-radius: 999px;
    background: linear-gradient(90deg, var(--gold), var(--gold-hi)); }

@media (max-width: 900px) {
    .hero-kpis, .dash-skeleton { grid-template-columns: repeat(2, 1fr); }
    .dash-grid { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
    .hero-kpis, .dash-skeleton { grid-template-columns: 1fr; }
}

/* Reports — quick range presets */
.range .presets { display: inline-flex; gap: 6px; margin-right: 10px; flex-wrap: wrap; }
.range .chip { padding: 6px 12px; border-radius: 999px; font-size: .85em;
    background: var(--panel2); border: 1px solid var(--line); color: var(--muted); }
.range .chip:hover:not(:disabled) { border-color: var(--gold); color: var(--text); }
.range .chip.active { background: rgba(212, 175, 55, .14); border-color: var(--gold);
    color: var(--gold-hi); font-weight: 700; }

/* ================= Orders — filters, summary, detail drawer (WEB-2) ============ */
.filter-row .vr { width: 1px; height: 22px; background: var(--line); margin: 0 4px; align-self: center; }
.filter-row select { background: var(--panel2); color: var(--text); border: 1px solid var(--line);
    border-radius: 8px; padding: 7px 10px; }
.filter-row .search { background: var(--panel2); color: var(--text); border: 1px solid var(--line);
    border-radius: 8px; padding: 7px 12px; min-width: 190px; }
.filter-row .search:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }

.orders-summary { display: flex; gap: 8px; align-items: center; margin: 10px 0;
    padding: 10px 14px; background: var(--panel); border: 1px solid var(--line);
    border-radius: var(--radius); font-size: .92em; }
.orders-summary .spacer { flex: 1; }
.gold-text { color: var(--gold-hi); }

table.grid.clickable tbody tr { cursor: pointer; }
table.grid.clickable tbody tr:hover td { background: var(--panel2); }

.drawer-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 40; }
.drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(440px, 94vw); z-index: 41;
    background: var(--panel); border-left: 1px solid var(--line);
    box-shadow: -18px 0 48px rgba(0,0,0,.5); display: flex; flex-direction: column;
    animation: drawer-in .18s ease-out; }
@keyframes drawer-in { from { transform: translateX(30px); opacity: 0; } to { transform: none; opacity: 1; } }
.drawer-head { display: flex; justify-content: space-between; align-items: flex-start;
    padding: 20px 22px 14px; border-bottom: 1px solid var(--line); }
.drawer-head h2 { margin: 0; color: var(--gold-hi); }
.drawer-head .sub { margin: 4px 0 0; font-size: .88em; color: var(--text); }
.drawer-head .sub.muted { color: var(--muted); }
.drawer-body { padding: 16px 22px; overflow-y: auto; }
.drawer-body h3 { margin: 18px 0 8px; font-size: .82em; color: var(--muted);
    text-transform: uppercase; letter-spacing: .06em; }
.drawer .lines td.qty { color: var(--gold); font-weight: 700; white-space: nowrap; width: 1%; }
.drawer .lines .mod { color: var(--muted); font-size: .86em; padding-left: 2px; }
.drawer .lines .mod.note { color: var(--warn); }

.drawer .totals { margin-top: 14px; border-top: 1px dashed var(--line); padding-top: 10px; }
.drawer .totals > div { display: flex; justify-content: space-between; padding: 3px 0; }
.drawer .totals .neg span:last-child { color: var(--err); }
.drawer .totals .grand { border-top: 2px solid var(--gold); margin-top: 6px; padding-top: 8px;
    font-weight: 800; font-size: 1.15em; }
.drawer .totals .grand span:last-child { color: var(--gold-hi); }
.drawer .totals .muted-row { color: var(--muted); font-size: .9em; }

/* ================= Kitchen — counts strip + station filter + aging (WEB-3) ====== */
.kds-toolbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap;
    margin: 4px 0 14px; padding: 10px 14px; background: var(--panel);
    border: 1px solid var(--line); border-radius: var(--radius); }
.kds-count { font-weight: 700; font-size: .92em; }
.kds-count.new  { color: var(--text); }
.kds-count.wip  { color: var(--warn); }
.kds-count.done { color: var(--ok); }
.kds-toolbar .vr { width: 1px; height: 22px; background: var(--line); margin: 0 4px; }
.kds-toolbar .chip { padding: 6px 12px; border-radius: 999px; font-size: .85em;
    background: var(--panel2); border: 1px solid var(--line); color: var(--muted); }
.kds-toolbar .chip:hover { border-color: var(--gold); color: var(--text); }
.kds-toolbar .chip.active { background: rgba(212,175,55,.14); border-color: var(--gold);
    color: var(--gold-hi); font-weight: 700; }

/* Aging borders — a ticket owed to a customer turns amber at 10m, red at 20m. */
.ticket.aging { border-color: var(--warn); box-shadow: 0 0 0 1px var(--warn); }
.ticket.aging .elapsed { color: var(--warn); font-weight: 800; }
.ticket.late { border-color: var(--err); box-shadow: 0 0 0 1px var(--err); animation: late-pulse 1.6s ease-in-out infinite; }
.ticket.late .elapsed { color: var(--err); font-weight: 800; }
@keyframes late-pulse { 0%, 100% { box-shadow: 0 0 0 1px var(--err); } 50% { box-shadow: 0 0 10px 1px rgba(231,76,60,.65); } }

/* ================= EN/AR — language toggle + RTL overrides (WEB-4) ============ */
button.lang { background: var(--panel2); border: 1px solid var(--line); color: var(--gold-hi);
    border-radius: 999px; padding: 6px 12px; font-weight: 700; }
button.lang:hover { border-color: var(--gold); }
/* Anonymous-page utility cluster (theme + language) — ONE fixed flex row.
   The old per-button `.floating` pinned both to the same corner (they stacked
   and clipped each other on phones). */
.float-tools { position: fixed; top: 14px; inset-inline-end: 16px; z-index: 60;
    display: flex; gap: 8px; }

/* Flexbox flips itself under dir=rtl; these are the few physical-side leftovers. */
[dir="rtl"] .pill { margin-right: 0; margin-left: 4px; }
[dir="rtl"] .drawer { right: auto; left: 0; border-left: none; border-right: 1px solid var(--line);
    box-shadow: 18px 0 48px rgba(0,0,0,.5); animation: drawer-in-rtl .18s ease-out; }
@keyframes drawer-in-rtl { from { transform: translateX(-30px); opacity: 0; } to { transform: none; opacity: 1; } }
[dir="rtl"] .dot { margin-right: 0; margin-left: 8px; }
/* Numbers stay LTR inside RTL text so "1,234.56 QAR" never reorders. */
[dir="rtl"] .num, [dir="rtl"] .kvalue, [dir="rtl"] .amt, [dir="rtl"] code { direction: ltr; unicode-bidi: embed; }

/* ================= Menu manager (WEB-5) ================= */
.menu-mgr .inactive-row td { opacity: .5; }
.menu-mgr .price-edit { display: inline-flex; gap: 6px; align-items: center; justify-content: flex-end; }
.menu-mgr .price-edit input { width: 92px; background: var(--panel2); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px; text-align: right;
    direction: ltr; }
.menu-mgr .price-edit input:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }
.menu-mgr .price-edit .save { padding: 5px 10px; border-radius: 8px; }
.menu-mgr .pill-btn { border-radius: 999px; padding: 4px 14px; font-weight: 700; font-size: .85em;
    border: 1px solid var(--line); background: var(--panel2); color: var(--muted); }
.menu-mgr .pill-btn.on  { background: rgba(46, 204, 113, .15); color: var(--ok);  border-color: rgba(46,204,113,.4); }
.menu-mgr .pill-btn.off { background: rgba(85, 85, 85, .25);  color: var(--muted); }
.menu-mgr .pill-btn:hover { border-color: var(--gold); }
.menu-notice { margin: 10px 0; padding: 10px 14px; border-radius: var(--radius);
    background: rgba(46, 204, 113, .12); color: var(--ok); border: 1px solid rgba(46,204,113,.35); }
.pager { display: flex; gap: 12px; align-items: center; justify-content: center; margin-top: 14px; }
.pager button { min-width: 40px; }
/* WEB-45 — the Rows box rides inside every server-paged list's pager; it must sit
   with the buttons, not fly to the end (the global .tbl-size auto-margin is for the
   tools row above a table, where it right-aligns). */
.pager .tbl-size { margin-inline-start: 0; }

/* ---- WEB-35: PagedTable tools (search + row count + page size) ----
   Sits directly above its table, quiet by default — the table is the content, this is
   the handle. It only renders when the table is long enough to need it. */
.tbl-tools {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin: 0 0 10px;
}
.tbl-search {
    flex: 1 1 200px; min-width: 0; max-width: 320px;
    background: var(--panel2); color: var(--text);
    border: 1px solid var(--line); border-radius: 999px;
    padding: 8px 14px; font-size: .9rem; font-family: inherit;
}
.tbl-search:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }
.tbl-search::placeholder { color: var(--muted); }
.tbl-count { font-size: .8rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tbl-size { display: flex; align-items: center; gap: 7px; margin-inline-start: auto; }
.tbl-size span { font-size: .78rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 700; }
.tbl-size select {
    background: var(--panel2); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px;
    padding: 6px 9px; font-size: .88rem; font-family: inherit;
}
.tbl-size select:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }

@media (max-width: 560px) {
    /* The size box keeps its own line rather than squeezing the search to nothing. */
    .tbl-size { margin-inline-start: 0; }
    .tbl-search { max-width: none; }
}

/* ---- WEB-35: audit trail — one CARD per change, not a table row ----
   A change is one record but MANY fields, and a table can't nest a list without becoming
   a rowspan puzzle that dies on a phone. So the row is a card and the fields are lines
   inside it: "Price  44.00 → 40.00". Reads identically at 375px and 1440px. */
.aud-trunc { display: inline-block; margin-bottom: 12px; }

.aud-list { display: flex; flex-direction: column; gap: 8px; }
.aud-row {
    border: 1px solid var(--line); border-radius: 12px;
    background: var(--panel); padding: 11px 13px;
}
.aud-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.aud-what { flex: 1; min-width: 0; }
.aud-when { white-space: nowrap; font-size: .8rem; font-variant-numeric: tabular-nums; }
.aud-who { font-size: .78rem; margin-top: 3px; }

.aud-fields {
    margin-top: 9px; padding-top: 8px;
    border-top: 1px solid var(--line-soft);
    display: flex; flex-direction: column; gap: 5px;
}
/* The label column is fixed so the before→after pairs line up down the card and the eye
   can scan them; the values wrap rather than truncate — a hidden value is a useless audit. */
.aud-field {
    display: grid; grid-template-columns: minmax(90px, 22%) 1fr auto 1fr;
    align-items: baseline; gap: 4px 10px;
    font-size: .88rem; font-variant-numeric: tabular-nums;
}
.aud-fname {
    color: var(--muted); font-size: .7rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .06em;
}
.aud-before { color: var(--muted); text-decoration: line-through; word-break: break-word; }
.aud-arrow { color: var(--gold); font-weight: 700; }
.aud-after { font-weight: 600; word-break: break-word; }

@media (max-width: 560px) {
    /* Stack: label on its own line, then before → after — a 4-column grid at 375px would
       give each value ~60px and turn every name into an ellipsis. */
    .aud-field { grid-template-columns: 1fr auto 1fr; }
    .aud-fname { grid-column: 1 / -1; }
}

/* ================= Staff manager (WEB-6) ================= */
.menu-mgr .row-click { cursor: pointer; }
.menu-mgr .row-click:hover td { background: rgba(212, 175, 55, .06); }
.dc-field select {
    background: var(--bg); color: var(--text); border: 1px solid var(--line);
    border-radius: 8px; padding: 9px 11px; font-size: 1rem;
}
.dc-field select:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }
.check-row { display: flex; align-items: center; gap: 9px; padding: 6px 2px;
    font-size: .92rem; cursor: pointer; color: var(--text); }
.check-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--gold); cursor: pointer; }

/* ================= Menu product/category editors (WEB-7) ================= */

/* ---- head-actions (WEB-37): the page's action bar, shared by Inventory / Menu /
   Purchases / Suppliers / Recipes / Notifications. One visual family: the gold
   .primary is THE action, everything else is a quiet outlined sibling of the same
   height — mixed heights and jammed emoji were what made the old row look homemade. */
.page-head .head-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

.page-head .head-actions button,
.page-head .head-actions .ghost-link {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    min-height: 40px; padding: 8px 15px;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--panel2); color: var(--text);
    font-size: .88rem; font-weight: 600; font-family: inherit;
    text-decoration: none; white-space: nowrap; cursor: pointer;
    transition: border-color .14s ease, background .14s ease, transform .08s ease;
    -webkit-tap-highlight-color: transparent;
}
.page-head .head-actions button:hover,
.page-head .head-actions .ghost-link:hover {
    border-color: var(--gold); color: var(--gold-hi, var(--gold));
}
.page-head .head-actions button:active { transform: scale(.97); }
.page-head .head-actions button.primary {
    background: var(--gold); border-color: var(--gold); color: #141414;
}
.page-head .head-actions button.primary:hover {
    background: var(--gold-hi, var(--gold)); color: #141414;
    filter: brightness(1.06);
}
.page-head .head-actions button.active {
    background: rgba(212,175,55,.14); border-color: var(--gold); color: var(--gold-hi, var(--gold));
}

@media (max-width: 760px) {
    /* Phone: a 2-up grid of equal tiles, not a wrapping row — wrapped buttons of
       ragged widths read as clutter, a grid reads as a menu. Order does the layout:
       Inventory's two primaries land side by side on row one. 44px touch target. */
    .page-head .head-actions {
        display: grid; grid-template-columns: 1fr 1fr; gap: 8px; width: 100%;
    }
    .page-head .head-actions button,
    .page-head .head-actions .ghost-link {
        width: 100%; min-height: 46px; padding: 10px 8px; font-size: .86rem;
    }
    /* An odd last action stretches full width instead of leaving a hole. */
    .page-head .head-actions > :last-child:nth-child(odd) { grid-column: 1 / -1; }
}
/* INV-5: the Import control is a <label> wrapping a hidden <InputFile>, so it must
   carry the head-action button look itself (the shared rule only targets button/.ghost-link). */
.page-head .head-actions .file-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    min-height: 40px; padding: 8px 15px;
    border: 1px solid var(--line); border-radius: 10px;
    background: var(--panel2); color: var(--text);
    font-size: .88rem; font-weight: 600; white-space: nowrap; cursor: pointer;
    transition: border-color .14s ease, background .14s ease, transform .08s ease;
    -webkit-tap-highlight-color: transparent;
}
.page-head .head-actions .file-btn:hover { border-color: var(--gold); color: var(--gold-hi, var(--gold)); }
.page-head .head-actions .file-btn input { display: none; }
@media (max-width: 760px) {
    .page-head .head-actions .file-btn { width: 100%; min-height: 46px; padding: 10px 8px; font-size: .86rem; }
}

/* Menu-insights ranking header: title on the left, rows-per-page box on the right. */
.rank-head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
    flex-wrap: wrap; margin: 18px 0 4px; }
.rank-head h2 { margin: 0; }

.menu-mgr .link-btn {
    background: transparent; border: 0; padding: 0; min-height: 0;
    color: var(--text); font-size: inherit; font-weight: 600;
    cursor: pointer; text-decoration: underline dotted var(--muted);
    text-underline-offset: 3px;
}
.menu-mgr .link-btn:hover { color: var(--gold); text-decoration-color: var(--gold); }
.color-field { display: flex; gap: 8px; align-items: center; }
.color-field input { flex: 1; }
.swatch { width: 22px; height: 22px; border-radius: 6px; border: 1px solid var(--line); flex: none; }
.cat-row {
    display: flex; align-items: center; gap: 10px; width: 100%;
    background: transparent; border: 0; border-top: 1px dashed var(--line);
    border-radius: 0; padding: 9px 2px; min-height: 0; text-align: start;
    font-size: .92rem; cursor: pointer;
}
.cat-row:first-of-type { border-top: 0; }
.cat-row:hover { color: var(--gold); }
.cat-row .cat-name { flex: 1; }
.cat-row.cat-off .cat-name { opacity: .55; }

/* ================= Inventory (WEB-8) ================= */
/* I5 — ledger-drift banner. Only rendered when the levels and the movements actually
   disagree, so it reads as an alarm rather than furniture. */
.ledger-drift {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    margin: 4px 0 14px; padding: 14px 16px; border-radius: 12px;
    background: color-mix(in srgb, var(--err) 10%, transparent);
    border: 1px solid var(--err);
}
.ledger-drift .small { font-size: .8rem; opacity: .75; margin-top: 4px; }

/* INV-A2 — clickable product chips inside the recipe-coverage warning. Each opens
   the product's recipe editor directly, so the fix is one tap from the diagnosis. */
.cov-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.cov-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: 999px; font-size: .8rem; cursor: pointer;
    background: color-mix(in srgb, var(--err) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--err) 45%, transparent);
    color: inherit;
}
.cov-chip:hover { background: color-mix(in srgb, var(--err) 24%, transparent); }
.cov-chip span { opacity: .7; font-size: .72rem; }

/* I4 — short-delivery entry inside the PO detail drawer. */
.rcv-partial { margin-top: 12px; padding: 12px; border-radius: 12px; border: 1px dashed var(--line); }
.rcv-partial .rcv-row {
    display: grid; grid-template-columns: 1fr auto 110px; gap: 10px;
    align-items: center; padding: 6px 0; border-bottom: 1px dashed var(--line);
}
.rcv-partial .rcv-row:last-of-type { border-bottom: 0; }

.inv-kpis { display: flex; gap: 12px; margin: 4px 0 14px; flex-wrap: wrap; }
.inv-kpi {
    display: flex; align-items: baseline; gap: 8px;
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
    padding: 10px 18px;
}
.inv-kpi-n { font-size: 1.5rem; font-weight: 800; }
.inv-kpi-l { color: var(--muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .06em; }
.inv-kpi.warn { border-color: rgba(243,156,18,.5); }
.inv-kpi.warn .inv-kpi-n { color: var(--warn); }
.inv-kpi.err { border-color: rgba(231,76,60,.5); }
.inv-kpi.err .inv-kpi-n { color: var(--err); }
.menu-mgr .pill-btn.adj { font-size: 1rem; padding: 2px 12px; }

/* ---- Product-editor variant rows (mirrors the desktop dialog) ---- */
.drawer.wide { width: 560px; }
.var-hint { margin: -4px 0 10px; font-size: .82rem; }
.var-row {
    display: grid; grid-template-columns: 1fr 1fr 84px 68px 26px 30px;
    gap: 6px; align-items: center; padding: 4px 0;
}
.var-row input {
    background: var(--bg); color: var(--text); border: 1px solid var(--line);
    border-radius: 7px; padding: 7px 8px; font-size: .9rem; min-width: 0;
}
.var-row input:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }
.var-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--gold);
    justify-self: center; padding: 0; }
.var-row input.num, .var-head .num { text-align: right; }
.var-head { color: var(--muted); font-size: .68rem; text-transform: uppercase;
    letter-spacing: .05em; border-bottom: 1px solid var(--line); padding-bottom: 6px; }
.var-head span:nth-child(5) { text-align: center; }
.add-variant { margin-top: 10px; }

/* ================= Reports charts (WEB-12) ================= */
.trend-wrap { padding: 4px 2px 0; }
.trend { width: 100%; height: 150px; display: block; }
.trend-x { display: flex; justify-content: space-between; color: var(--muted);
    font-size: .72rem; margin-top: 4px; direction: ltr; }
.hours.dow .hourcol span { font-size: .68rem; }
.hourbar.dowbar { background: linear-gradient(180deg, #6366F1, rgba(99,102,241,.35)); }
.ch-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%;
    margin-inline-end: 5px; vertical-align: baseline; }
.flow { display: flex; flex-direction: column; gap: 10px; padding: 6px 0 2px; }
.flow-row { display: grid; grid-template-columns: 200px 1fr 190px; gap: 12px; align-items: center; }
@media (max-width: 760px) { .flow-row { grid-template-columns: 120px 1fr 130px; } }
.flow-lbl { color: var(--muted); font-size: .82rem; }
.flow-row.net .flow-lbl { color: var(--text); font-weight: 700; }
.flow-row b { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
.flow-row b.neg { color: var(--err); }
.flow-row b.flow-pos { color: var(--ok); }
.flow-track { background: var(--bg); border: 1px solid var(--line); border-radius: 7px;
    height: 18px; overflow: hidden; }
.flow-bar { height: 100%; border-radius: 6px; transition: width .4s ease; }
.flow-bar.gold { background: linear-gradient(90deg, #D4AF37, #E8C55F); }
.flow-bar.green { background: linear-gradient(90deg, #10B981, #34D399); }
.flow-bar.red { background: linear-gradient(90deg, #EF4444, #F87171); }
.flow-row.net .flow-track { height: 24px; }

/* ================= POS workspace (WEB-9/10/11) ================= */
/* The POS breaks out of the reading-width shell: it is a WORKSTATION, not a page. */
.content:has(.wpos) { max-width: none; padding: 18px 22px 28px; }
.wpos { --pos-radius: 14px; }
.wpos .page-head { margin-bottom: 12px; }
.wpos .page-head h1 { letter-spacing: .01em; }

.wpos .hall { margin: 18px 0 6px; }
.wpos .hall-name {
    color: var(--muted); font-weight: 700; font-size: .74rem;
    text-transform: uppercase; letter-spacing: .12em; margin-bottom: 10px;
    display: flex; align-items: center; gap: 10px;
}
.wpos .hall-name::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* ---- table tiles: status told by a top accent + tinted field, not tiny text ---- */
.table-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(138px, 1fr)); gap: 12px; }
.table-tile {
    --tclr: var(--ok);
    position: relative; overflow: hidden;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
    padding: 18px 10px 12px; min-height: 112px; border-radius: var(--pos-radius);
    background: var(--panel); border: 1px solid var(--line);
    transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.table-tile::before {
    content: ""; position: absolute; inset: 0 0 auto 0; height: 4px;
    background: var(--tclr); opacity: .9;
}
.table-tile:hover:not(:disabled) { transform: translateY(-2px); border-color: var(--tclr);
    box-shadow: 0 8px 22px rgba(0,0,0,.28); }
.table-tile .t-num { font-size: 1.45rem; font-weight: 800; letter-spacing: .02em; }
.table-tile .t-cap { color: var(--muted); font-size: .76rem; }
.table-tile .t-state { font-size: .7rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: .07em; color: var(--tclr); }
.table-tile .t-amt { color: var(--gold); font-weight: 800; font-size: .95rem; }
.table-tile.st-0 { --tclr: var(--ok); }
.table-tile.st-1 { --tclr: var(--gold); background: rgba(212,175,55,.08); border-color: rgba(212,175,55,.4); }
.table-tile.st-2 { --tclr: #3b82f6; }
.table-tile.st-3 { --tclr: var(--warn); background: rgba(243,156,18,.07); }
.table-tile.st-4 { --tclr: var(--muted); opacity: .4; }

/* ---- order view chrome ---- */
.wpos-top { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; }
.wpos-title { display: flex; align-items: center; gap: 10px; font-size: 1.05rem; flex-wrap: wrap; }
.wpos-title code { font-size: 1rem; }
.wpos-body { display: grid; grid-template-columns: minmax(0, 1fr) 390px; gap: 18px; align-items: start; }
@media (max-width: 980px) { .wpos-body { grid-template-columns: 1fr; } }

.pos-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.pos-actions button {
    min-height: 40px; padding: 7px 14px; border-radius: 10px; font-size: .87rem; font-weight: 600;
    transition: border-color .12s ease, background .12s ease;
}
.pos-actions button:hover { border-color: var(--gold); }
.pos-actions button.warn:hover { border-color: var(--err); }

/* ---- product cards: category colour accent + confident price ---- */
.prod-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin-top: 10px; }
.prod-card {
    position: relative; overflow: hidden;
    display: flex; flex-direction: column; justify-content: space-between; gap: 8px; align-items: flex-start;
    padding: 12px 14px 10px; padding-inline-start: 18px; min-height: 86px;
    border-radius: 12px; text-align: start;
    background: var(--panel); border: 1px solid var(--line);
    transition: transform .12s ease, border-color .12s ease, box-shadow .12s ease;
}
.prod-card .p-accent { position: absolute; inset-block: 0; inset-inline-start: 0; width: 4px; }
.prod-card:hover:not(:disabled) { transform: translateY(-2px); border-color: var(--gold);
    box-shadow: 0 8px 20px rgba(0,0,0,.26); }
.prod-card:disabled { opacity: .55; }
.prod-card .p-name {
    font-weight: 600; font-size: .92rem; line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.prod-card .p-price { color: var(--gold); font-weight: 800; font-size: .92rem; align-self: flex-end; }

/* ---- cart: dark header band (desktop dialog chrome), pinned workspace column ---- */
.wpos-cart {
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--pos-radius);
    position: sticky; top: 10px; display: flex; flex-direction: column;
    max-height: calc(100vh - 96px); overflow: hidden;
}
.cart-band {
    background: linear-gradient(135deg, #111827, #1F2937);
    padding: 12px 16px; display: flex; flex-direction: column; gap: 2px;
}
.cart-band .cb-num { color: #E8C55F; font-weight: 800; font-size: 1.02rem; letter-spacing: .02em; }
.cart-band .cb-meta { color: rgba(255,255,255,.66); font-size: .8rem; }
.cart-lines { flex: 1; overflow-y: auto; padding: 6px 14px; min-height: 60px; }
.cart-line { border-top: 1px dashed var(--line); padding: 9px 0; }
.cart-line:first-child { border-top: 0; }
.cart-line.locked { opacity: .78; }
.cl-main { display: flex; justify-content: space-between; gap: 10px; font-size: .93rem; }
.cl-name { font-weight: 600; }
.cl-total { font-weight: 800; white-space: nowrap; font-variant-numeric: tabular-nums; }
.cl-note { color: var(--muted); font-size: .8rem; margin-top: 2px; }
.cl-actions { display: flex; align-items: center; gap: 6px; margin-top: 7px; }
.cl-qty { min-width: 36px; text-align: center; font-weight: 800; font-variant-numeric: tabular-nums; }
.qbtn { min-height: 34px; min-width: 38px; padding: 2px 8px; border-radius: 9px; font-size: 1rem; }
.qbtn:hover { border-color: var(--gold); }
.qbtn.danger { color: #ff6b5c; border-color: rgba(231,76,60,.5); }
.qbtn.danger:hover { border-color: var(--err); }
.cl-note-edit { display: flex; gap: 6px; margin-top: 6px; }
.cl-note-edit input { flex: 1; background: var(--bg); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; min-width: 0; }
.cart-totals { border-top: 1px solid var(--line); padding: 10px 16px 4px; }
.cart-totals .kv { padding: 3px 0; font-variant-numeric: tabular-nums; }
.cart-totals .kv.grand { border-top: 1px dashed var(--line); margin-top: 6px; padding-top: 9px; }
.cart-totals .kv.grand b { color: var(--gold); font-size: 1.3rem; }
.cart-btns { display: flex; gap: 10px; padding: 10px 14px 14px; }
.send-btn { width: 100%; min-height: 54px; font-size: 1rem; font-weight: 700; border-radius: 12px; }

/* ---- modals: one confident dialog system ---- */
.variant-modal {
    position: fixed; inset: auto 0 0 0; margin: 0 auto; max-width: 430px; z-index: 42;
    background: var(--panel); border: 1px solid var(--line); border-radius: 18px 18px 0 0;
    padding: 18px; display: flex; flex-direction: column; gap: 10px;
    box-shadow: 0 -18px 50px rgba(0,0,0,.55);
    max-height: 92vh; overflow-y: auto;
}
@media (min-width: 700px) {
    .variant-modal { inset: 50% auto auto 50%; transform: translate(-50%, -50%);
        border-radius: 18px; width: 400px; }
}
.variant-modal .dc-field input, .variant-modal .dc-field select { min-height: 44px; }
.variant-modal > button { min-height: 46px; border-radius: 11px; font-weight: 600; }
.variant-opt { display: flex; justify-content: space-between; align-items: center;
    gap: 12px; min-height: 52px; border-radius: 11px; }
.variant-opt:hover { border-color: var(--gold); }
.variant-opt.def { border-color: var(--gold); background: rgba(212,175,55,.06); }
.variant-opt b { color: var(--gold); font-variant-numeric: tabular-nums; }

/* ================= Full POS chrome (WEB-10/11) ================= */
.shift-bar {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    background: var(--panel); border: 1px solid var(--line); border-radius: var(--pos-radius, 14px);
    padding: 12px 16px; margin-bottom: 16px;
    border-inline-start: 4px solid var(--gold);
}
.shift-bar.closed { border-inline-start-color: var(--err); }
.sb-state { display: flex; align-items: center; gap: 8px; font-size: .92rem; }
.sb-stat { display: flex; flex-direction: column; line-height: 1.15;
    padding-inline-start: 14px; border-inline-start: 1px solid var(--line); }
.sb-stat span { color: var(--muted); font-size: .68rem; text-transform: uppercase; letter-spacing: .07em; }
.sb-stat b { font-size: .98rem; font-variant-numeric: tabular-nums; }
.sb-stat.gold b { color: var(--gold); font-size: 1.05rem; }
.sb-spacer { flex: 1; }
.shift-bar button { min-height: 38px; border-radius: 10px; font-weight: 600; }
.held-chip { border-color: rgba(212,175,55,.55); color: var(--gold); }
button.warn { color: #ff8a7a; border-color: rgba(231,76,60,.5); }

.send-btn.half { flex: 1; min-height: 54px; font-size: .98rem; }
.send-btn.pay { background: linear-gradient(135deg, #10B981, #059669); border-color: transparent;
    color: #fff; box-shadow: 0 6px 18px rgba(16,185,129,.25); }
.send-btn.pay:hover:not(:disabled) { filter: brightness(1.06); }
.send-btn.pay:disabled { opacity: .45; box-shadow: none; }

.cl-note.disc { color: var(--gold); }
.kv.disc span { color: var(--gold); }
.qbtn.sm { min-height: 22px; min-width: 24px; padding: 0 6px; font-size: .75rem; margin-inline-start: 6px; }
.var-bad { color: var(--err); }
.chg { color: var(--ok); font-size: 1.25rem; font-variant-numeric: tabular-nums; }

.seg-row { display: flex; gap: 6px; flex-wrap: wrap; }
.seg-row .chip { min-height: 42px; padding: 6px 14px; font-weight: 600; }
.pin-row { border-top: 1px dashed var(--gold); padding-top: 10px; }
.pay-modal { max-height: 92vh; overflow-y: auto; }
@media (min-width: 700px) { .variant-modal.pay-modal { width: 440px; } }
.wide-modal { width: 470px; max-width: 94vw; }
.pay-extras { border-top: 1px dashed var(--line); padding-top: 10px; display: flex; flex-direction: column; gap: 6px; }
.pay-done { color: var(--ok); font-size: 1.25rem; text-align: center; }

/* payment header band + method cards */
.pay-band {
    background: linear-gradient(135deg, #111827, #1F2937);
    margin: -18px -18px 4px; padding: 14px 18px 16px; border-radius: 18px 18px 0 0;
    display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.pay-band .pb-title { color: rgba(255,255,255,.75); font-size: .85rem; align-self: flex-start; }
.pay-band .pb-title code { color: #E8C55F; }
.pay-band .pb-due { color: #E8C55F; font-size: 2.1rem; font-weight: 800;
    font-variant-numeric: tabular-nums; line-height: 1.1; }
.pay-band .pb-due small { font-size: .9rem; font-weight: 600; color: rgba(255,255,255,.6); }
.pay-band .pb-sub { color: rgba(255,255,255,.55); font-size: .72rem;
    text-transform: uppercase; letter-spacing: .1em; }
.pm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
.pm-card {
    display: flex; align-items: center; gap: 8px; min-height: 50px;
    padding: 8px 12px; border-radius: 11px; font-weight: 600; font-size: .88rem;
    border: 1px solid var(--line); background: var(--bg);
    border-inline-start: 4px solid var(--mclr, var(--gold));
    transition: border-color .12s ease, background .12s ease;
}
.pm-card .pm-ic { font-size: 1.15rem; }
.pm-card:hover { border-color: var(--mclr, var(--gold)); }
.pm-card.active { border-color: var(--gold); background: rgba(212,175,55,.1);
    box-shadow: 0 0 0 1px var(--gold) inset; }

/* receipt + browser print */
.rcpt { background: var(--bg); border: 1px dashed var(--line); border-radius: 10px; padding: 14px; font-size: .9rem; }
.rcpt-head { display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; }
.rcpt hr { border: 0; border-top: 1px dashed var(--line); margin: 8px 0; }
/* ============ PRINT ISOLATION — one rule for every printable document ============
   A print job must contain the DOCUMENT and nothing else. `visibility: hidden` does not
   achieve that on its own: a hidden element still occupies layout, so the app shell went
   on generating pages behind the sheet — a customer statement came out of the printer as
   four pages, three of them blank (owner report). Worse, the shell was RELEASED for print
   (height:auto, overflow:visible) so its full, normally-clipped length counted: the longer
   the screen behind the document, the more blank pages.

   So the shell is REMOVED from the print flow, not merely made invisible. The `:has()`
   chain drops, at every level, each child of a document ancestor that is neither the
   document nor on the path down to it — the page collapses to exactly the document,
   wherever it sits in the tree (`.a4-doc` is a direct child of `main.content` on
   Customers and several panels deep on Reports). The surviving ancestors are stripped of
   layout so the sheet starts at the paper margin, and each document prints in NORMAL
   FLOW — an absolutely-positioned one paginates unreliably once it outgrows a page.
   The visibility pair stays as a backstop for anything the chain cannot reach. */
@media print {
    /* Level 1: body's own children that have nothing to do with the document. */
    body:has(.rcpt-print, .trf-print, .a4-doc) > *:not(:has(.rcpt-print, .trf-print, .a4-doc)) {
        display: none !important;
    }
    /* Levels 2..n: inside each ancestor, keep only the branch leading to the document. */
    body:has(.rcpt-print, .trf-print, .a4-doc) :has(.rcpt-print, .trf-print, .a4-doc) > *:not(.rcpt-print):not(.trf-print):not(.a4-doc):not(:has(.rcpt-print, .trf-print, .a4-doc)) {
        display: none !important;
    }
    /* The ancestors themselves: pure pass-through, no chrome, no scroll box, no width cap. */
    body:has(.rcpt-print, .trf-print, .a4-doc) :has(.rcpt-print, .trf-print, .a4-doc) {
        display: block !important; position: static !important;
        width: auto !important; max-width: none !important;
        height: auto !important; max-height: none !important;
        margin: 0 !important; padding: 0 !important; overflow: visible !important;
        border: 0 !important; box-shadow: none !important; background: #fff !important;
        transform: none !important;
    }

    body * { visibility: hidden; }
    .rcpt-print, .rcpt-print * { visibility: visible; }
    .rcpt-print { position: static; width: 80mm; max-width: 80mm;
        transform: none; border: 0; box-shadow: none; background: #fff; color: #000; }
    .rcpt { border: 0; background: #fff; color: #000; }
    .no-print { display: none !important; }
}

/* ================= Mobile polish (WEB-13): filters + tables ================= */
@media (max-width: 760px) {
    /* Chip rows become a SWIPEABLE rail instead of wrapping into a button wall. */
    .filter-row {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        padding-bottom: 2px;
    }
    .filter-row::-webkit-scrollbar { display: none; }
    .filter-row .chip { flex: 0 0 auto; min-height: 38px; }
    .filter-row .vr { flex: 0 0 auto; }
    /* Tools line: select stays compact, search takes the rest. */
    .filter-row.tools { flex-wrap: nowrap; }
    .filter-row.tools select { flex: 0 1 auto; max-width: 40%; min-height: 40px; }
    .filter-row.tools .search { flex: 1 1 120px; min-width: 100px; min-height: 40px; }
    .filter-row.tools button { flex: 0 0 auto; min-height: 40px; }
    /* Secondary table columns give way — the row stays a single glance. */
    .grid .hide-sm { display: none; }
    .orders-summary { flex-wrap: wrap; row-gap: 2px; font-size: .82rem; }
    .page-head { flex-wrap: wrap; gap: 8px; }
}

/* WEB-13 addendum — make five columns genuinely fit a 375px phone. */
@media (max-width: 760px) {
    .grid th, .grid td { padding: 9px 7px; font-size: .8rem; }
    /* Long order numbers keep only their DISTINCT tail — direction:rtl inside
       the ellipsis box trims from the start ("…-1036"). Full number stays in
       the detail drawer. */
    .grid td code {
        display: inline-block; max-width: 72px; overflow: hidden;
        text-overflow: ellipsis; white-space: nowrap;
        direction: rtl; unicode-bidi: plaintext; font-size: .74rem;
    }
    .scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}
@media (max-width: 760px) {
    .grid .pill { padding: 2px 7px; font-size: .66rem; letter-spacing: .02em; }
    .grid td:nth-child(2) { font-size: .74rem; }
    .grid td:last-child, .grid th:last-child { padding-inline-end: 4px; }
}
@media (max-width: 760px) {
    .grid th { font-size: .64rem; letter-spacing: 0; }
    .grid td .num, .grid td.num { font-size: .78rem; }
}

/* ================= WEB-14: bell + account ================= */
.bell-wrap { position: relative; }
.bell { position: relative; min-height: 36px; padding: 4px 10px; font-size: 1rem; }
.bell-badge {
    position: absolute; top: -5px; inset-inline-end: -5px;
    background: var(--err); color: #fff; border-radius: 9px;
    font-size: .62rem; font-weight: 800; padding: 1px 5px; line-height: 1.3;
}
.bell-panel {
    position: absolute; top: 44px; inset-inline-end: 0; width: 330px; max-width: 88vw;
    background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
    box-shadow: 0 16px 44px rgba(0,0,0,.5); z-index: 60; padding: 10px 12px;
    max-height: 60vh; overflow-y: auto;
}
.bp-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.bp-clear { min-height: 26px; padding: 2px 10px; font-size: .72rem; }
.bp-empty { font-size: .8rem; }
.bp-item { display: flex; gap: 8px; align-items: baseline; padding: 7px 0;
    border-top: 1px dashed var(--line); font-size: .84rem; }
.bp-item:first-of-type { border-top: 0; }
.bp-item .bp-txt { flex: 1; }
.bp-item .bp-time { color: var(--muted); font-size: .7rem; white-space: nowrap; }
.bp-item.danger .bp-txt { color: #ff8a7a; }
.bp-item.warn .bp-txt { color: var(--warn); }
.user-link { text-decoration: none; color: var(--text); }
.user-link:hover { color: var(--gold); }
.account .dc-field input { min-height: 42px; }
.totp-secret { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.totp-key { font-size: 1.05rem; letter-spacing: .12em; padding: 8px 12px; word-break: break-all; }

/* ==================== WEB-15: premium sign-in gate ====================
   New lgx-* namespace — the old .login card styles stay untouched for the
   deep-link Login.razor and the vendor gate. Everything here is transform/
   opacity animation only (GPU-cheap) and fully RTL-safe via logical props. */

.lgx { position: relative; width: 100%; display: grid; place-items: center; }

/* --- ambient scene: drifting glow orbs + rising gold sparks + faint grid --- */
.lgx-bg { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none;
          background:
            radial-gradient(1100px 520px at 50% -10%, rgba(212,175,55,.07), transparent 60%),
            radial-gradient(900px 600px at 100% 110%, rgba(59,130,246,.05), transparent 55%);
}
.lgx-bg::after { content: ""; position: absolute; inset: 0;
    background-image: radial-gradient(rgba(212,175,55,.05) 1px, transparent 1.6px);
    background-size: 34px 34px;
    mask-image: radial-gradient(720px 520px at 50% 42%, #000 20%, transparent 75%);
    -webkit-mask-image: radial-gradient(720px 520px at 50% 42%, #000 20%, transparent 75%);
}
.lgx-orb { position: absolute; border-radius: 50%; filter: blur(90px); opacity: .5;
           will-change: transform; animation: lgxDrift 26s ease-in-out infinite alternate; }
.lgx-orb.o1 { width: 480px; height: 480px; left: -140px; top: -160px;
              background: radial-gradient(circle, rgba(212,175,55,.30), transparent 70%); }
.lgx-orb.o2 { width: 420px; height: 420px; right: -120px; bottom: -140px;
              background: radial-gradient(circle, rgba(59,130,246,.20), transparent 70%);
              animation-duration: 32s; animation-delay: -8s; }
.lgx-orb.o3 { width: 300px; height: 300px; left: 55%; top: 62%;
              background: radial-gradient(circle, rgba(230,196,82,.14), transparent 70%);
              animation-duration: 22s; animation-delay: -14s; }
@keyframes lgxDrift {
    0%   { transform: translate(0, 0) scale(1); }
    50%  { transform: translate(60px, -40px) scale(1.12); }
    100% { transform: translate(-50px, 45px) scale(.94); }
}
.lgx-spark { position: absolute; bottom: -10px; width: 4px; height: 4px; border-radius: 50%;
             background: var(--gold-hi); opacity: 0;
             box-shadow: 0 0 8px 2px rgba(212,175,55,.55);
             will-change: transform, opacity; animation: lgxRise 11s linear infinite; }
.lgx-spark.k1 { left: 12%; animation-delay: 0s;   animation-duration: 12s; }
.lgx-spark.k2 { left: 26%; animation-delay: -4s;  animation-duration: 15s; transform: scale(.7); }
.lgx-spark.k3 { left: 41%; animation-delay: -8s;  animation-duration: 10s; }
.lgx-spark.k4 { left: 58%; animation-delay: -2s;  animation-duration: 14s; transform: scale(.6); }
.lgx-spark.k5 { left: 72%; animation-delay: -6s;  animation-duration: 11s; }
.lgx-spark.k6 { left: 86%; animation-delay: -9s;  animation-duration: 16s; transform: scale(.8); }
.lgx-spark.k7 { left: 94%; animation-delay: -1s;  animation-duration: 13s; transform: scale(.5); }
@keyframes lgxRise {
    0%   { transform: translateY(0);      opacity: 0; }
    8%   { opacity: .9; }
    70%  { opacity: .45; }
    100% { transform: translateY(-105vh); opacity: 0; }
}

/* --- the glass card --- */
/* max-width is 100% — NOT a vw figure. A vw cap is measured against the viewport,
   so it ignores the pane's side padding and the card grows until it touches both
   edges: the animated brain the gate is built around ends up hidden behind it.
   Bounded by the padded track instead, the backdrop always breathes. */
/* Width is bounded DIRECTLY against the viewport minus the formpane's own responsive
   side padding (clamp(22px,6vw,120px) each side = clamp(44px,12vw,240px) total). A plain
   `width:384px; max-width:100%` let the fixed 384 drive the grid track wider than a phone,
   so the card's right edge (the password-reveal eye) was clipped off-screen. min() caps it
   to whatever the padded track allows, so it never overflows on any width and the brain
   always breathes at the sides. */
.lgx-card { position: relative; z-index: 1;
    width: min(384px, calc(100vw - clamp(44px, 12vw, 240px)));
    padding: 32px 32px 24px; border-radius: 18px;
    background: linear-gradient(180deg, rgba(26,26,26,.88), rgba(14,14,14,.92));
    border: 1px solid rgba(212,175,55,.16);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    box-shadow: 0 30px 80px rgba(0,0,0,.6), 0 0 0 1px rgba(0,0,0,.4),
                0 0 60px rgba(212,175,55,.05);
    animation: lgxCardIn .65s cubic-bezier(.18,.9,.28,1.08) both;
}
.lgx-card::before { /* shimmering gold hairline across the top edge */
    content: ""; position: absolute; top: 0; left: 10%; right: 10%; height: 1px;
    background: linear-gradient(90deg, transparent, rgba(230,196,82,.85), transparent);
    background-size: 200% 100%;
    animation: lgxSheen 4.5s ease-in-out infinite;
}
@keyframes lgxCardIn {
    from { opacity: 0; transform: translateY(26px) scale(.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes lgxSheen {
    0%, 100% { background-position: 180% 0; opacity: .35; }
    50%      { background-position: -80% 0; opacity: 1; }
}

/* staggered entrance for the card's children */
.rise { opacity: 0; animation: lgxUp .55s cubic-bezier(.2,.8,.3,1) forwards; }
.rise.d0 { animation-delay: .10s; }
.rise.d1 { animation-delay: .22s; }
.rise.d2 { animation-delay: .30s; }
.rise.d3 { animation-delay: .38s; }
.rise.d4 { animation-delay: .48s; }
.rise.d5 { animation-delay: .60s; }
@keyframes lgxUp { from { opacity: 0; transform: translateY(14px); }
                   to   { opacity: 1; transform: translateY(0); } }

/* --- brand block --- */
.lgx-brand { text-align: center; margin-bottom: 22px; }
.lgx-logo { position: relative; width: 74px; height: 74px; margin: 0 auto 14px; }
.lgx-logo img { position: relative; z-index: 1; width: 100%; height: 100%;
                border-radius: 20px; display: block;
                box-shadow: 0 6px 24px rgba(0,0,0,.55); }
.lgx-halo { position: absolute; inset: -12px; border-radius: 50%; z-index: 0;
    background: conic-gradient(from 0deg, transparent 0 60%,
                rgba(212,175,55,.0) 62%, rgba(230,196,82,.9) 78%, transparent 92%);
    filter: blur(9px); opacity: .85;
    animation: lgxSpin 7s linear infinite; will-change: transform; }
@keyframes lgxSpin { to { transform: rotate(360deg); } }
.lgx-name { margin: 0; font-size: 1.7rem; letter-spacing: .18em; font-weight: 800;
    background: linear-gradient(90deg, #d4af37 0%, #f4e2a0 45%, #d4af37 90%);
    background-size: 220% 100%;
    -webkit-background-clip: text; background-clip: text;
    color: transparent; -webkit-text-fill-color: transparent;
    animation: lgxGoldSheen 6s linear infinite; }
.lgx-name span { font-weight: 300; letter-spacing: .3em; }
@keyframes lgxGoldSheen { to { background-position: -220% 0; } }
.lgx-tag { margin: 8px 0 2px; font-weight: 600; font-size: 1.02rem; }
.lgx-sub { margin: 0; color: var(--muted); font-size: .86rem; }

/* --- floating-label fields --- */
.lgx-ff { position: relative; margin: 0 0 16px; }
.lgx-ff .ff-ico { position: absolute; inset-inline-start: 14px; top: 50%;
    transform: translateY(-50%); width: 19px; height: 19px;
    color: var(--muted); pointer-events: none; transition: color var(--speed); }
.lgx-ff:focus-within .ff-ico { color: var(--gold); }
.lgx-ff .ff-in { width: 100%; min-height: 52px;
    padding: 20px 44px 6px; padding-inline-start: 44px; padding-inline-end: 44px;
    background: rgba(10,10,10,.65); color: var(--text);
    border: 1px solid var(--line); border-radius: 12px; font-size: 1rem;
    transition: border-color var(--speed), box-shadow var(--speed), background var(--speed); }
.lgx-ff .ff-in:hover { border-color: #3a3a3a; }
.lgx-ff .ff-in:focus { outline: none; border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(212,175,55,.16), 0 0 24px rgba(212,175,55,.07);
    background: rgba(10,10,10,.85); }
.lgx-ff .ff-lb { position: absolute; inset-inline-start: 44px; top: 50%;
    transform: translateY(-50%); color: var(--muted); font-size: .98rem;
    pointer-events: none; transform-origin: 0 50%;
    transition: transform .18s ease, color .18s ease, font-size .18s ease, top .18s ease; }
[dir="rtl"] .lgx-ff .ff-lb { transform-origin: 100% 50%; }
.lgx-ff .ff-in:focus ~ .ff-lb,
.lgx-ff .ff-in:not(:placeholder-shown) ~ .ff-lb,
.lgx-ff .ff-in:-webkit-autofill ~ .ff-lb {
    top: 15px; transform: translateY(-50%) scale(.74); color: var(--gold); }
/* Chrome autofill: keep the dark chrome + readable text */
.lgx-ff .ff-in:-webkit-autofill {
    -webkit-box-shadow: 0 0 0 60px #121212 inset;
    -webkit-text-fill-color: var(--text);
    caret-color: var(--text); transition: background-color 99999s ease-in-out 0s; }
.lgx-ff .ff-eye { position: absolute; inset-inline-end: 6px; top: 50%;
    transform: translateY(-50%); min-height: 0; width: 36px; height: 36px;
    display: grid; place-items: center; padding: 0; border: 0; border-radius: 10px;
    background: transparent; color: var(--muted); cursor: pointer; }
.lgx-ff .ff-eye:hover { color: var(--gold); background: rgba(212,175,55,.08); border: 0; }
.lgx-ff .ff-eye svg { width: 19px; height: 19px; }

/* --- remembered-account chip --- */
.lgx-acct { display: flex; align-items: center; gap: 10px; margin: 0 0 16px;
    padding: 12px 14px; border-radius: 12px;
    background: rgba(212,175,55,.06); border: 1px solid rgba(212,175,55,.28); }
.lgx-acct .a-ico { width: 20px; height: 20px; color: var(--gold); flex: none; }
.lgx-acct .a-lb { color: var(--muted); font-size: .82rem; }
.lgx-acct .a-no { font-family: Consolas, monospace; font-size: 1.02rem;
    letter-spacing: .06em; color: var(--gold-hi); }
.lgx-acct .a-switch { margin-inline-start: auto; min-height: 0; padding: 5px 10px;
    font-size: .78rem; font-weight: 600; border-radius: 8px;
    background: transparent; border: 1px solid var(--line); color: var(--muted); }
.lgx-acct .a-switch:hover { color: var(--gold); border-color: var(--gold); }

/* --- error + button --- */
.lgx-error { display: flex; align-items: center; gap: 9px; margin: 0 0 14px;
    padding: 11px 13px; border-radius: 10px; font-size: .88rem;
    color: #ff9b8d; background: rgba(231,76,60,.09);
    border: 1px solid rgba(231,76,60,.4);
    animation: lgxShake .45s cubic-bezier(.36,.07,.19,.97) both; }
.lgx-error svg { width: 17px; height: 17px; flex: none; }
@keyframes lgxShake {
    10%, 90% { transform: translateX(-1px); }
    20%, 80% { transform: translateX(2px); }
    30%, 50%, 70% { transform: translateX(-4px); }
    40%, 60% { transform: translateX(4px); }
}
.lgx-btn { position: relative; overflow: hidden; width: 100%; min-height: 52px;
    display: inline-flex; align-items: center; justify-content: center; gap: 10px;
    border: 0; border-radius: 12px; font-size: 1.02rem; font-weight: 700;
    letter-spacing: .02em; cursor: pointer;
    color: #141414; background: linear-gradient(180deg, var(--gold-hi), var(--gold));
    /* The inset top highlight is what reads as "raised metal" rather than a flat
       gold rectangle — a lit edge plus the drop shadow gives the button a form. */
    box-shadow: inset 0 1px 0 rgba(255,255,255,.45),
                inset 0 -1px 0 rgba(0,0,0,.12),
                0 6px 20px rgba(212,175,55,.25);
    transition: box-shadow var(--speed), transform var(--speed), filter var(--speed); }
.lgx-btn::after { /* shine sweep */
    content: ""; position: absolute; top: 0; bottom: 0; width: 40%;
    inset-inline-start: -60%; transform: skewX(-20deg);
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.45), transparent);
    transition: inset-inline-start .55s ease; }
.lgx-btn:hover:not(:disabled) { filter: brightness(1.07);
    transform: translateY(-1px);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.5),
                inset 0 -1px 0 rgba(0,0,0,.12),
                0 10px 30px rgba(212,175,55,.4); border: 0; }
.lgx-btn:hover:not(:disabled)::after { inset-inline-start: 120%; }
/* Press feedback. Without it the button is the only control on the page that
   gives nothing back on touch — on a phone that reads as "the tap missed". */
.lgx-btn:active:not(:disabled) { transform: translateY(1px) scale(.995);
    box-shadow: inset 0 2px 5px rgba(0,0,0,.2),
                0 3px 10px rgba(212,175,55,.28); filter: brightness(.98); }
.lgx-btn:disabled { cursor: wait; filter: saturate(.55) brightness(.9); opacity: .8;
    box-shadow: none; transform: none; }
.lgx-btn:disabled::after { display: none; }   /* the shine must not keep sweeping */
.lgx-spin { width: 17px; height: 17px; border-radius: 50%; flex: none;
    border: 2.5px solid rgba(20,20,20,.25); border-top-color: #141414;
    animation: lgxSpin .7s linear infinite; }

/* --- footer --- */
.lgx-foot { display: flex; align-items: center; justify-content: center; gap: 7px;
    margin-top: 20px; padding-top: 16px; border-top: 1px solid rgba(42,42,42,.6);
    color: var(--muted); font-size: .78rem; }
.lgx-foot svg { width: 14px; height: 14px; color: var(--ok); }

@media (max-width: 480px) {
    .lgx-card { padding: 28px 20px 20px; border-radius: 16px; }
    .lgx-logo { width: 64px; height: 64px; }
    .lgx-name { font-size: 1.45rem; }
}
@media (prefers-reduced-motion: reduce) {
    .lgx-orb, .lgx-spark, .lgx-halo, .lgx-name, .lgx-card::before { animation: none; }
    .lgx-card, .rise { animation-duration: .01s; animation-delay: 0s; }
}

/* ==================== WEB-16: light-theme component overrides ====================
   Surfaces that hardcode a dark background need an explicit light counterpart
   (the token swap alone can't reach them). Everything else re-skins via vars. */

/* Sun/moon toggle — the icon reflects the CURRENT theme via data-theme, so no Blazor
   state is needed and a flip costs no re-render. Dark shows the sun (go light), light
   shows the moon.

   MOB-5 — `block`, never `inline`. These are SVGs now (see Shared/ThemeIcon.razor for
   why the emoji had to go); an inline SVG sits on the TEXT BASELINE, which leaves a
   descender's worth of space under it and pushes the glyph visibly above the button's
   centre. A block SVG has no baseline to sit on, so the parent's centring finally
   means what it says. */
.theme-toggle .i-sun,
.theme-toggle .i-moon { width: 19px; height: 19px; display: block; }
.theme-toggle .i-moon { display: none; }
:root[data-theme="light"] .theme-toggle .i-sun  { display: none; }
:root[data-theme="light"] .theme-toggle .i-moon { display: block; }
/* The top-bar toggle borrows .lang, a TEXT pill whose 6px/12px padding made a lopsided
   box around a square icon. Give it equal sides so the icon sits in a real centred box. */
button.lang.theme-toggle {
    display: inline-grid; place-items: center;
    width: 34px; height: 34px; padding: 0; flex: none;
}
.theme-toggle.floating { position: fixed; top: 14px; inset-inline-end: 64px; z-index: 50; }

/* Drawer header gradient (hardcoded #1a1a1a) */
:root[data-theme="light"] .drawer-head { background: linear-gradient(180deg, #faf7ef, var(--panel)); }

/* --- premium sign-in gate in light --- */
:root[data-theme="light"] .lgx-bg {
    background:
        radial-gradient(1100px 520px at 50% -10%, rgba(212,175,55,.14), transparent 60%),
        radial-gradient(900px 600px at 100% 110%, rgba(59,130,246,.07), transparent 55%),
        linear-gradient(180deg, #f7f4ec, #ece5d6);
}
:root[data-theme="light"] .lgx-bg::after {
    background-image: radial-gradient(rgba(169,127,22,.10) 1px, transparent 1.6px);
}
:root[data-theme="light"] .lgx-orb { opacity: .42; }
:root[data-theme="light"] .lgx-orb.o1 { background: radial-gradient(circle, rgba(212,175,55,.40), transparent 70%); }
:root[data-theme="light"] .lgx-orb.o2 { background: radial-gradient(circle, rgba(59,130,246,.16), transparent 70%); }
:root[data-theme="light"] .lgx-orb.o3 { background: radial-gradient(circle, rgba(230,196,82,.24), transparent 70%); }
:root[data-theme="light"] .lgx-spark { background: #c99a2a; box-shadow: 0 0 8px 2px rgba(169,127,22,.5); }
:root[data-theme="light"] .lgx-card {
    background: linear-gradient(180deg, rgba(255,255,255,.94), rgba(250,247,239,.97));
    border-color: rgba(169,127,22,.24);
    box-shadow: 0 26px 64px rgba(60,50,20,.18), 0 0 0 1px rgba(255,255,255,.6),
                0 0 48px rgba(212,175,55,.05);
}
:root[data-theme="light"] .lgx-name {
    background: linear-gradient(90deg, #9a7212 0%, #d4af37 45%, #9a7212 90%);
    background-size: 220% 100%;
    -webkit-background-clip: text; background-clip: text;
}
:root[data-theme="light"] .lgx-ff .ff-in {
    background: rgba(255,255,255,.9); border-color: var(--line);
}
:root[data-theme="light"] .lgx-ff .ff-in:hover { border-color: #d8cfb8; }
:root[data-theme="light"] .lgx-ff .ff-in:focus {
    background: #fff; box-shadow: 0 0 0 3px rgba(169,127,22,.16), 0 0 24px rgba(212,175,55,.08);
}
:root[data-theme="light"] .lgx-ff .ff-in:-webkit-autofill {
    -webkit-box-shadow: 0 0 0 60px #fff inset; -webkit-text-fill-color: var(--text);
}
:root[data-theme="light"] .lgx-error {
    color: #b23a2b; background: rgba(209,59,44,.08); border-color: rgba(209,59,44,.35);
}
:root[data-theme="light"] .lgx-foot { border-top-color: var(--line); }

/* Active nav gold reads a touch low on the light panel tint — deepen to clear AA. */
:root[data-theme="light"] header.top nav.nav a.active { color: #8a6410; }

/* ==================== WEB-17: restaurant & coffee-shop sign-in identity ====================
   Vector COREX "X" mark (gold chevron + gold top arm + silver bottom arm) and a
   warm ambient scene of slowly drifting café/restaurant line icons. */

/* Warm the ambient orbs from the generic blue toward espresso + gold. */
.lgx-orb.o2 { background: radial-gradient(circle, rgba(120,72,38,.32), transparent 70%); }
.lgx-orb.o3 { background: radial-gradient(circle, rgba(230,196,82,.16), transparent 70%); }

/* Vector logo mark */
.lgx-logo .lgx-x { position: relative; z-index: 1; width: 100%; height: 100%; display: block;
    filter: drop-shadow(0 4px 14px rgba(0,0,0,.5)); }

/* "POS & ERP" badge under the wordmark */
.lgx-name { margin-bottom: 4px; }
.lgx-badge { display: inline-block; margin: 2px 0 4px; padding: 3px 12px;
    font-size: .6rem; font-weight: 700; letter-spacing: .34em; text-indent: .34em;
    color: var(--gold-hi); border: 1px solid rgba(212,175,55,.35); border-radius: 999px;
    background: rgba(212,175,55,.06); }

/* Drifting café / restaurant icons */
.lgx-food { position: absolute; bottom: -10%; color: #e6c452; opacity: 0;
    will-change: transform, opacity; animation: lgxFloatUp linear infinite; }
.lgx-food svg { width: 100%; height: 100%; display: block; }
.lgx-food.f1 { left: 8%;  width: 42px; height: 42px; animation-duration: 24s; animation-delay: -2s; }
.lgx-food.f2 { left: 20%; width: 30px; height: 30px; animation-duration: 19s; animation-delay: -11s; }
.lgx-food.f3 { left: 34%; width: 46px; height: 46px; animation-duration: 27s; animation-delay: -6s; }
.lgx-food.f4 { left: 52%; width: 28px; height: 28px; animation-duration: 17s; animation-delay: -14s; }
.lgx-food.f5 { left: 66%; width: 40px; height: 40px; animation-duration: 22s; animation-delay: -9s; }
.lgx-food.f6 { left: 80%; width: 34px; height: 34px; animation-duration: 25s; animation-delay: -4s; }
.lgx-food.f7 { left: 91%; width: 26px; height: 26px; animation-duration: 20s; animation-delay: -16s; }
@keyframes lgxFloatUp {
    0%   { transform: translateY(0) rotate(-8deg);  opacity: 0; }
    12%  { opacity: .17; }
    88%  { opacity: .10; }
    100% { transform: translateY(-116vh) rotate(14deg); opacity: 0; }
}

/* Light-theme tuning */
:root[data-theme="light"] .lgx-food { color: #b5892a; }
:root[data-theme="light"] .lgx-orb.o2 { background: radial-gradient(circle, rgba(150,95,50,.22), transparent 70%); }
:root[data-theme="light"] .lgx-badge { color: #8a6410; border-color: rgba(169,127,22,.4); background: rgba(169,127,22,.07); }
:root[data-theme="light"] .lgx-logo .lgx-x { filter: drop-shadow(0 4px 14px rgba(120,90,20,.24)); }

@media (prefers-reduced-motion: reduce) { .lgx-food { animation: none; opacity: .12; } }

/* ==================== WEB-18: full horizontal wordmark on the sign-in gate ====================
   Drop wwwroot/corex-wordmark.png (the COREX POS & ERP lockup) and it replaces the
   icon+text automatically. Sat on a subtle light plate so a white-background PNG
   still reads as an intentional brand card on the dark gate — and stays crisp on light. */
.lgx-wordmark { width: 88%; max-width: 300px; height: auto; display: block;
    margin: 0 auto 8px; padding: 10px 12px; border-radius: 14px;
    background: linear-gradient(180deg, #ffffff, #f5f2ea);
    box-shadow: 0 10px 26px rgba(0,0,0,.4), inset 0 0 0 1px rgba(212,175,55,.28); }
:root[data-theme="light"] .lgx-wordmark {
    box-shadow: 0 8px 22px rgba(120,90,20,.16), inset 0 0 0 1px rgba(169,127,22,.28); }
.lgx-fallback { text-align: center; }

/* Blazor's <FocusOnNavigate Selector="h1"> moves focus to the page heading after
   every navigation so screen readers announce it. That programmatic focus must not
   paint a visible box for sighted users — the heading isn't a keyboard tab-stop, and
   the screen-reader announcement comes from the focus move, not the outline. Real
   keyboard focus rings on actual controls are preserved via :focus-visible. */
h1:focus { outline: none; }
:focus:not(:focus-visible) { outline: none; }

/* ==================== WEB-19: interactive 3D parallax sign-in ====================
   The scene gets perspective; a pointer-driven script (see _Host.cshtml) sets --rx/
   --ry on .lgx-tilt so the whole card leans toward the cursor, and --mx/--my for a
   glossy highlight that tracks it. The logo floats forward on its own Z-plane for
   real depth. Degrades to flat on touch / reduced-motion. */
.lgx { perspective: 1200px; }
.lgx-tilt { transform-style: preserve-3d;
    transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
    transition: transform .3s cubic-bezier(.2,.7,.3,1); will-change: transform; }
.lgx-card { transform-style: preserve-3d; }
.lgx-brand { transform-style: preserve-3d; }
.lgx-fallback, .lgx-wordmark { transform: translateZ(30px); }
.lgx-foot { transform: translateZ(12px); }

/* glossy specular highlight that follows the pointer */
.lgx-card::after { content: ""; position: absolute; inset: 0; border-radius: inherit;
    pointer-events: none; z-index: 3; opacity: .6;
    background: radial-gradient(320px 320px at var(--mx, 50%) var(--my, 0%),
                rgba(255,255,255,.16), transparent 62%); }
:root[data-theme="light"] .lgx-card::after {
    background: radial-gradient(320px 320px at var(--mx, 50%) var(--my, 0%),
                rgba(255,255,255,.5), transparent 62%); opacity: .5; }

@media (hover: none) {
    .lgx-tilt { transform: none !important; }
    .lgx-card::after { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    .lgx-tilt { transition: none; transform: none !important; }
    .lgx-fallback, .lgx-wordmark, .lgx-foot { transform: none; }
}

/* Inventory read-only notice (SYNC-2 — quantities are branch-owned) */
.inv-ro { margin: 6px 0 0; font-size: .82rem; color: var(--muted);
    padding: 5px 10px; border-radius: 8px; display: inline-block;
    background: rgba(212,175,55,.07); border: 1px solid rgba(212,175,55,.22); }

/* ==================== WEB-20 Tier 1: Cash & Shifts reconciliation ==================== */
.grid tr.short-row td { background: rgba(231,76,60,.07); }
.grid tr.short-row td:first-child { box-shadow: inset 3px 0 0 var(--err); }
.v-short { color: #ff8a7a; }
.v-over  { color: var(--warn); }
.v-ok    { color: var(--muted); }
:root[data-theme="light"] .v-short { color: #c0392b; }
.grid .tag { display: inline-block; margin-inline-start: 6px; padding: 1px 7px; border-radius: 999px;
    font-size: .68rem; font-weight: 700; vertical-align: middle; }
.grid .tag.warn { color: var(--warn); background: rgba(243,156,18,.12); border: 1px solid rgba(243,156,18,.35); }
.grid .tag.ok   { color: var(--ok);   background: rgba(46,204,113,.12); border: 1px solid rgba(46,204,113,.35); }
.shift-hint { margin-top: 12px; font-size: .82rem; }

/* ==================== WEB-20 Tier 2: Menu engineering ==================== */
.cmp-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
    margin: 0 0 18px; padding: 10px 16px; border-radius: 12px;
    background: var(--panel); border: 1px solid var(--line); font-size: .9rem; }
.cmp-title { color: var(--muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .08em; }
.cmp-cell { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); }
.cmp-cell b { color: var(--text); }
.cmp-pill { font-size: .68rem; padding: 2px 8px; }

.quad-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 14px; margin: 18px 0 10px; }
.quad { border-radius: 14px; padding: 14px 16px; background: var(--panel);
    border: 1px solid var(--line); border-top: 3px solid var(--line); }
.quad.q-star   { border-top-color: var(--gold); }
.quad.q-plow   { border-top-color: #6366F1; }
.quad.q-puzzle { border-top-color: var(--warn); }
.quad.q-dog    { border-top-color: var(--err); }
.quad-head { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
.quad-ico { font-size: 1.1rem; }
.quad-hint { margin: 2px 0 10px; color: var(--muted); font-size: .78rem; line-height: 1.4; }
.quad-row { display: flex; align-items: baseline; gap: 8px; padding: 3px 0; font-size: .88rem; }
.qr-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qr-m { font-weight: 700; color: var(--ok); }
.qr-m.neg { color: var(--err); }
.qr-qty { font-size: .78rem; }
.quad-more { font-size: .78rem; margin-top: 4px; }

.quad-tag { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: .72rem;
    font-weight: 600; background: var(--panel2); border: 1px solid var(--line); white-space: nowrap; }
.quad-tag.q-star   { color: var(--gold-hi); border-color: rgba(212,175,55,.4); }
.quad-tag.q-plow   { color: #8b8df2; border-color: rgba(99,102,241,.4); }
.quad-tag.q-puzzle { color: var(--warn); border-color: rgba(243,156,18,.4); }
.quad-tag.q-dog    { color: #ff8a7a; border-color: rgba(231,76,60,.4); }
:root[data-theme="light"] .quad-tag.q-star { color: #8a6410; }
:root[data-theme="light"] .quad-tag.q-plow { color: #4f52c9; }
:root[data-theme="light"] .quad-tag.q-dog  { color: #c0392b; }

.m-bar { display: inline-block; width: 54px; height: 6px; border-radius: 4px;
    background: var(--panel2); vertical-align: middle; margin-inline-end: 6px; overflow: hidden; }
.m-fill { display: block; height: 100%; border-radius: 4px;
    background: linear-gradient(90deg, var(--gold), var(--gold-hi)); }
.m-fill.low { background: linear-gradient(90deg, #e74c3c, #f39c12); }

/* ==================== WEB-21: CRM Lite ==================== */
tr.clickable { cursor: pointer; transition: background var(--speed); }
tr.clickable:hover td { background: var(--panel2); }
.tag.gold { background: rgba(212,175,55,.12); color: var(--gold-hi);
    border: 1px solid rgba(212,175,55,.4); padding: 1px 8px; border-radius: 999px; font-size: .72rem; font-weight: 600; }
:root[data-theme="light"] .tag.gold { color: #8a6410; }
.st-dates { display: flex; gap: 18px; margin: 6px 0 4px; font-size: .88rem; color: var(--muted); }
.st-dates b { color: var(--text); }
.fav-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.fav-row { display: flex; align-items: baseline; gap: 8px; padding: 4px 0; border-bottom: 1px solid var(--line); font-size: .9rem; }
.fav-name { flex: 1; }
.fav-tot { font-weight: 700; }

/* ==================== WEB-22: Guardian (threshold alerts) ==================== */
.bell.has-alerts { animation: guardPulse 1.6s ease-in-out infinite; }
@keyframes guardPulse { 0%,100% { transform: scale(1); } 50% { transform: scale(1.12); } }
.bell-badge.alert { background: var(--err); color: #fff; box-shadow: 0 0 0 2px rgba(231,76,60,.35); }

.bp-actions { display: inline-flex; align-items: center; gap: 6px; }
.bp-gear { background: transparent; border: 1px solid var(--line); color: var(--muted);
    min-height: 0; padding: 3px 8px; border-radius: 8px; font-size: .9rem; line-height: 1; }
.bp-gear:hover, .bp-gear.on { color: var(--gold); border-color: var(--gold); }

.guard-panel { padding: 12px 14px; border-bottom: 1px solid var(--line);
    background: rgba(212,175,55,.05); display: flex; flex-direction: column; gap: 10px; }
.guard-hint { margin: 0; font-size: .82rem; color: var(--muted); }
.guard-field { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: .84rem; }
.guard-field span { color: var(--text); }
.guard-field input { width: 90px; background: var(--bg); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px; font-size: .9rem; text-align: end; }
.guard-field input:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }
.guard-check { display: flex; align-items: center; gap: 8px; font-size: .82rem; color: var(--muted); cursor: pointer; }
.guard-check input { width: 16px; height: 16px; accent-color: var(--gold); }
.guard-save { align-self: flex-end; min-height: 0; padding: 6px 16px; font-size: .84rem; }

.bp-item.alert { background: rgba(231,76,60,.1); border-inline-start: 3px solid var(--err); }
.bp-flag { font-size: .58rem; font-weight: 800; letter-spacing: .06em; color: #fff;
    background: var(--err); padding: 1px 6px; border-radius: 999px; white-space: nowrap; }

/* ==================== WEB-23: public QR menu (anonymous, mobile-first) ==================== */
.bare { min-height: 100vh; background: var(--bg); }
.pm { max-width: 660px; margin: 0 auto; padding: 0 16px 72px; color: var(--text); position: relative; }
.pm-lang { position: fixed; top: 12px; inset-inline-end: 12px; z-index: 20; min-height: 0;
    padding: 6px 12px; border-radius: 999px; background: var(--panel); border: 1px solid var(--line);
    color: var(--text); font-size: .82rem; }
.pm-center { min-height: 60vh; display: grid; place-items: center; text-align: center; padding: 24px; }
.pm-missing .pm-mark { font-size: 3rem; margin-bottom: 8px; }
.pm-missing h1 { margin: 0 0 6px; }
.pm-missing p { color: var(--muted); max-width: 340px; }
.pm .lgx-spin { width: 26px; height: 26px; border-width: 3px;
    border-color: rgba(212,175,55,.25); border-top-color: var(--gold); }

/* hero */
.pm-hero { text-align: center; padding: 40px 12px 20px; }
.pm-logo { width: 68px; height: 68px; margin: 0 auto 12px; border-radius: 20px;
    display: grid; place-items: center; font-size: 2rem;
    background: linear-gradient(180deg, rgba(212,175,55,.16), rgba(212,175,55,.04));
    border: 1px solid rgba(212,175,55,.3); }
.pm-hero h1 { margin: 0; font-size: 1.7rem; letter-spacing: .01em; }
.pm-tag { margin: 6px 0 0; color: var(--muted); text-transform: uppercase; letter-spacing: .22em; font-size: .72rem; }

/* sticky category rail */
.pm-catrail { position: sticky; top: 0; z-index: 10; display: flex; gap: 8px; overflow-x: auto;
    padding: 12px 2px; margin: 4px -2px 8px; background: var(--bg);
    border-bottom: 1px solid var(--line); scrollbar-width: none; }
.pm-catrail::-webkit-scrollbar { display: none; }
.pm-chip { flex: none; padding: 7px 14px; border-radius: 999px; text-decoration: none;
    background: var(--panel); border: 1px solid var(--line); color: var(--muted);
    font-size: .85rem; white-space: nowrap; transition: 120ms; }
.pm-chip:hover { color: var(--gold); border-color: var(--gold); }

/* category + items */
.pm-cat { scroll-margin-top: 64px; padding-top: 18px; }
.pm-cat h2 { display: inline-block; margin: 0 0 10px; font-size: 1.15rem; color: var(--text);
    text-transform: none; letter-spacing: 0; font-weight: 700; padding-bottom: 4px;
    border-bottom: 2px solid var(--gold); }
.pm-items { display: flex; flex-direction: column; }
.pm-item { padding: 14px 0; border-bottom: 1px solid var(--line); }
.pm-item-main { display: flex; align-items: flex-start; gap: 14px; }
.pm-item-txt { flex: 1; min-width: 0; }
.pm-item h3 { margin: 0; font-size: 1.02rem; font-weight: 600; }
.pm-desc { margin: 4px 0 0; color: var(--muted); font-size: .86rem; line-height: 1.5; }
.pm-price { font-weight: 800; color: var(--gold-hi); white-space: nowrap; font-size: 1.02rem; }
:root[data-theme="light"] .pm-price { color: #8a6410; }
.pm-variants { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.pm-var { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 8px;
    background: var(--panel); border: 1px solid var(--line); font-size: .82rem; color: var(--muted); }
.pm-var b { color: var(--gold-hi); font-weight: 700; }
:root[data-theme="light"] .pm-var b { color: #8a6410; }

.pm-foot { text-align: center; margin-top: 32px; padding-top: 18px; border-top: 1px solid var(--line);
    display: flex; flex-direction: column; gap: 4px; font-size: .8rem; }

/* ==================== WEB-24: public-menu QR share card ==================== */
.qr-share { display: flex; gap: 20px; align-items: center; flex-wrap: wrap;
    margin: 4px 0 20px; padding: 18px 20px; border-radius: 14px;
    background: var(--panel); border: 1px solid rgba(212,175,55,.28); }
.qr-code { width: 132px; height: 132px; flex: none; background: #fff; border-radius: 10px;
    padding: 8px; box-shadow: 0 4px 14px rgba(0,0,0,.25); }
.qr-code svg { width: 100%; height: 100%; display: block; }
.qr-info { flex: 1; min-width: 220px; }
.qr-info h2 { margin: 0 0 4px; color: var(--text); text-transform: none; letter-spacing: 0; font-size: 1.1rem; }
.qr-info .sub { margin: 0 0 12px; }
.qr-url { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.qr-url input { flex: 1; min-width: 180px; background: var(--bg); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px; padding: 9px 12px; font-size: .9rem; direction: ltr; }
.qr-url input:focus { outline: none; border-color: var(--gold); }
.qr-open { display: inline-flex; align-items: center; padding: 9px 14px; border-radius: 8px;
    text-decoration: none; color: var(--muted); border: 1px solid var(--line); font-size: .9rem; font-weight: 600; }
.qr-open:hover { color: var(--gold); border-color: var(--gold); }

/* ---- WEB-24b: printable QR table tent (hidden on screen, isolated on paper) ---- */
.qr-print { display: none; }
@media print {
    /* Isolate the tent: hide the whole app, show only the poster. */
    body { visibility: hidden; background: #fff; }
    .qr-print, .qr-print * { visibility: visible; }
    .qr-print { display: block; position: fixed; inset: 0; z-index: 9999; background: #fff; }
    .qp-inner { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
        text-align: center; width: 100%; max-width: 480px; padding: 24px; color: #111; }
    .qp-code { width: 320px; height: 320px; margin: 0 auto 24px; }
    .qp-code svg { width: 100%; height: 100%; display: block; }
    .qp-title { margin: 0; font-size: 30px; font-weight: 800; color: #111; }
    .qp-ar { margin: 6px 0 0; font-size: 24px; font-weight: 700; color: #111; }
    .qp-url { margin: 20px 0 0; font-size: 15px; color: #555; font-family: Consolas, monospace; word-break: break-all; }
    @page { margin: 1.4cm; }
}

/* ==================== WEB-25: professional split-screen sign-in ====================
   Wide screens get a two-column layout — a brand/marketing pane beside the card —
   the hallmark of a senior SaaS sign-in. Below 900px it collapses to the single
   centred card (the card keeps its own compact brand block for that case). */
.lgx-split { width: 100%; }
.lgx-formpane { position: relative; z-index: 1; display: grid; place-items: center; width: 100%; }
.lgx-show { display: none; }

@media (min-width: 900px) {
    .lgx.lgx-split { display: grid; grid-template-columns: 1.05fr 0.95fr;
        align-items: center; gap: 48px; max-width: 1120px; margin: 0 auto; padding: 0 32px; }
    .lgx-show { display: flex; flex-direction: column; gap: 22px; position: relative; z-index: 1;
        padding-inline-end: 12px; animation: lgxUp .6s cubic-bezier(.2,.8,.3,1) both; }
    .lgx-formpane { justify-items: stretch; }
    .lgx-formpane .lgx-card { margin: 0; }
}

.lgx-show-mark { width: 76px; height: 76px; }
.lgx-show-mark img { width: 100%; height: 100%; border-radius: 20px; display: block;
    box-shadow: 0 10px 30px rgba(0,0,0,.5); }
.lgx-show-name { margin: 4px 0 0; font-size: 2.4rem; letter-spacing: .16em; font-weight: 800;
    background: linear-gradient(90deg, #d4af37 0%, #f4e2a0 45%, #d4af37 90%);
    background-size: 220% 100%; -webkit-background-clip: text; background-clip: text;
    color: transparent; -webkit-text-fill-color: transparent; animation: lgxGoldSheen 6s linear infinite; }
.lgx-show-name span { font-weight: 300; letter-spacing: .3em; }
.lgx-show-tag { margin: 0; color: var(--muted); font-size: 1.02rem; max-width: 30ch; line-height: 1.5; }
.lgx-feats { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.lgx-feats li { display: flex; align-items: center; gap: 12px; font-size: .98rem; color: var(--text); }
.lgx-feats .lf-ic { flex: none; width: 40px; height: 40px; display: grid; place-items: center;
    font-size: 1.15rem; border-radius: 12px;
    background: linear-gradient(180deg, rgba(212,175,55,.14), rgba(212,175,55,.04));
    border: 1px solid rgba(212,175,55,.28); }
:root[data-theme="light"] .lgx-show-mark img { box-shadow: 0 10px 30px rgba(120,90,20,.2); }

/* ==================== WEB-27: deeper 3D on the sign-in (premium feel) ==================== */
/* Gentle continuous float on the whole card column — reads as a card hovering in 3D
   space, layered under the pointer-driven tilt (the tilt lives on .lgx-tilt inside). */
.lgx-formpane { animation: lgxFloatY 6.5s ease-in-out infinite; }
@keyframes lgxFloatY { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }

/* Brand pane gets real depth: mark furthest forward, then name, then features —
   with the scene perspective already set, they sit on distinct Z-planes and lean
   with the ambient tilt. */
.lgx-show { transform-style: preserve-3d; }
.lgx-show-mark { transform: translateZ(55px); }
.lgx-show-name { transform: translateZ(34px); }
.lgx-show-tag  { transform: translateZ(22px); }
.lgx-feats     { transform: translateZ(14px); }
.lgx-feats li  { transition: transform .25s ease; }
.lgx-feats li:hover { transform: translateZ(10px) translateX(4px); }

/* A touch more depth on the card shadow so the float has somewhere to cast. */
.lgx-card { box-shadow: 0 40px 90px rgba(0,0,0,.62), 0 0 0 1px rgba(0,0,0,.4),
            0 0 70px rgba(212,175,55,.06); }
:root[data-theme="light"] .lgx-card {
    box-shadow: 0 40px 90px rgba(60,50,20,.22), 0 0 0 1px rgba(255,255,255,.6); }

@media (prefers-reduced-motion: reduce) { .lgx-formpane { animation: none; } }
@media (max-width: 899px) {
    /* Single-column mobile: the brand pane is hidden, so drop its Z lifts + float. */
    .lgx-formpane { animation: none; }
}

/* ==================== WEB-28: readable tenant rows (vendor console) ==================== */
.tenants-grid { border-collapse: separate; border-spacing: 0; }
.tenants-grid thead th {
    position: sticky; top: 0; z-index: 5;
    background: var(--panel); box-shadow: inset 0 -1px 0 var(--line);
    white-space: nowrap; padding: 11px 12px; font-size: .74rem;
    text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.tenants-grid tbody td { padding: 12px; vertical-align: middle; border: 0;
    box-shadow: inset 0 -1px 0 var(--line); }
/* Zebra + hover so the eye tracks one tenant across all 12 columns. */
.tenants-grid tbody tr:nth-child(odd) td { background: rgba(255,255,255,.015); }
.tenants-grid tbody tr:hover td { background: rgba(212,175,55,.07); }
:root[data-theme="light"] .tenants-grid tbody tr:nth-child(odd) td { background: rgba(0,0,0,.02); }
:root[data-theme="light"] .tenants-grid tbody tr:hover td { background: rgba(212,175,55,.10); }
/* Account ID as a prominent chip — the primary key you scan by. */
.tenants-grid tbody td code {
    background: rgba(212,175,55,.10); color: var(--gold-hi);
    border: 1px solid rgba(212,175,55,.28); border-radius: 7px;
    padding: 3px 9px; font-size: .92rem; font-weight: 700; letter-spacing: .04em; }
:root[data-theme="light"] .tenants-grid tbody td code { color: #8a6410; }
.tenants-grid tbody td:nth-child(2) { font-weight: 600; }   /* Name stands out */
.tenants-grid .row-actions { display: flex; align-items: center; gap: 8px; justify-content: flex-end; }
/* Don't stripe/hover the inline provisioning sub-row. */
.tenants-grid tbody tr.branches-row td { background: var(--panel2) !important; box-shadow: none; }

/* ==================== WEB-29: soft hero-panel sign-in (calmer, less "sharp") ====================
   Feedback: the dark gold gate read as too harsh. Two moves:
   (1) the brand column becomes a SOLID rounded HERO PANEL with a warm espresso→
       gold gradient and a large latte illustration + rising steam — the polished
       split-screen look (calm colour block on the left, form on the right);
   (2) the form card and ambient scene are softened — gentler border, rounder
       corners, dimmer grid, so nothing has a hard high-contrast edge.
   Appended last so it wins by source order. Fully RTL-safe / reduced-motion aware. */

/* --- calmer ambient scene --- */
.lgx-bg::after { opacity: .5; }                 /* dial back the dotted grid */
.lgx-orb { opacity: .38; filter: blur(110px); } /* softer, more diffuse glow */

/* --- the hero panel (wide screens only; mobile keeps the single card) --- */
@media (min-width: 900px) {
    .lgx-show {
        position: relative; overflow: hidden;
        min-height: 552px; justify-content: center;
        padding: 52px 46px; border-radius: 30px;
        background:
            radial-gradient(120% 90% at 18% 12%, rgba(255,220,150,.18), transparent 55%),
            linear-gradient(158deg, #241610 0%, #3a2415 42%, #6c4526 78%, #8a5a2e 100%);
        border: 1px solid rgba(212,175,55,.22);
        box-shadow: 0 34px 80px rgba(30,18,6,.5), inset 0 1px 0 rgba(255,255,255,.06);
    }
    /* soft warm vignette so the illustration melts into the panel */
    .lgx-show::after { content: ""; position: absolute; inset: 0; pointer-events: none;
        background: radial-gradient(90% 70% at 80% 90%, rgba(0,0,0,.28), transparent 60%);
        border-radius: inherit; }
    .lgx-show > * { position: relative; z-index: 1; }
    /* on the warm panel the muted tag needs to lift to a warm cream */
    .lgx-show-tag { color: rgba(245,232,210,.82); }
    .lgx-feats li { color: rgba(248,240,226,.94); }
    .lgx-feats .lf-ic {
        background: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.05));
        border-color: rgba(255,255,255,.22); }
}
:root[data-theme="light"] .lgx-show {
    background:
        radial-gradient(120% 90% at 18% 12%, rgba(255,236,190,.55), transparent 55%),
        linear-gradient(158deg, #f4ecdd 0%, #ecdcc2 45%, #e6c98f 80%, #d9ad63 100%);
    border-color: rgba(169,127,22,.28);
    box-shadow: 0 30px 70px rgba(120,90,20,.2), inset 0 1px 0 rgba(255,255,255,.5);
}
:root[data-theme="light"] .lgx-show::after {
    background: radial-gradient(90% 70% at 80% 90%, rgba(120,80,20,.14), transparent 60%); }
:root[data-theme="light"] .lgx-show-name {
    background: linear-gradient(90deg, #7a4d12 0%, #b5822a 45%, #7a4d12 90%);
    background-size: 220% 100%; -webkit-background-clip: text; background-clip: text; }
:root[data-theme="light"] .lgx-show-tag { color: #6b5024; }
:root[data-theme="light"] .lgx-show .lgx-feats li { color: #4a3a1c; }

/* --- large latte illustration + steam, low in the panel behind the text --- */
.lgx-hero-art { display: none; }
@media (min-width: 900px) {
    .lgx-hero-art { display: block; position: absolute; z-index: 0;
        inset-inline-end: -22px; bottom: -30px; width: 300px; height: 276px;
        opacity: .9; filter: drop-shadow(0 20px 34px rgba(0,0,0,.32));
        animation: lgxCupFloat 6s ease-in-out infinite; }
    .lgx-hero-art .lgx-cup { width: 100%; height: auto; display: block; }
    .lgx-steam { position: absolute; top: 6px; width: 12px; height: 46px; border-radius: 50%;
        background: radial-gradient(ellipse at center, rgba(255,255,255,.85), transparent 70%);
        filter: blur(6px); opacity: 0; will-change: transform, opacity;
        animation: lgxSteam 4.2s ease-in infinite; }
    .lgx-steam.s1 { inset-inline-end: 176px; animation-delay: 0s; }
    .lgx-steam.s2 { inset-inline-end: 152px; animation-delay: 1.1s; height: 54px; }
    .lgx-steam.s3 { inset-inline-end: 128px; animation-delay: 2.2s; }
}
@keyframes lgxCupFloat { 0%,100% { transform: translateY(0) rotate(-1deg); }
                         50% { transform: translateY(-10px) rotate(1deg); } }
@keyframes lgxSteam {
    0%   { transform: translateY(0) scaleY(.7);   opacity: 0; }
    20%  { opacity: .6; }
    60%  { transform: translateY(-34px) scaleY(1.1); opacity: .35; }
    100% { transform: translateY(-64px) scaleY(1.3); opacity: 0; }
}
:root[data-theme="light"] .lgx-steam {
    background: radial-gradient(ellipse at center, rgba(120,80,30,.4), transparent 70%); }

/* --- soften the form card so no edge is harsh --- */
.lgx-card { border-radius: 22px; border-color: rgba(212,175,55,.12);
    box-shadow: 0 34px 80px rgba(0,0,0,.5), 0 0 0 1px rgba(0,0,0,.28); }
.lgx-card::before { opacity: .55; }             /* calmer top hairline */
:root[data-theme="light"] .lgx-card {
    border-color: rgba(169,127,22,.18);
    box-shadow: 0 30px 70px rgba(60,50,20,.16), 0 0 0 1px rgba(255,255,255,.6); }
.lgx-ff .ff-in { border-radius: 14px; }         /* rounder inputs */
.lgx-btn { border-radius: 14px; }

@media (prefers-reduced-motion: reduce) {
    .lgx-hero-art, .lgx-steam { animation: none; }
    .lgx-steam { opacity: .3; }
}

/* ==================== WEB-30: professional header + mobile off-canvas nav ====================
   Desktop: the top nav reads as a tidy pill row with a clear active state.
   Mobile (≤980px, see the W1 block): the nav slides in as a sidebar behind a
   hamburger; base state below keeps the toggle + backdrop hidden on desktop. */

/* Hamburger — three animated bars; shown on mobile (max-width:980 block),
   hidden ONLY on desktop below. NB: the hide MUST be desktop-scoped, not a bare
   `.nav-toggle{display:none}` — appended after the mobile block it would win by
   source order (media queries add no specificity) and hide it on mobile too. */
.nav-toggle { flex: none; width: 40px; height: 40px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    flex-direction: column; gap: 5px;
    background: transparent; border: 1px solid var(--line); border-radius: 10px;
    cursor: pointer; transition: border-color var(--speed), background var(--speed); }
@media (min-width: 981px) { .nav-toggle { display: none; } }
.nav-toggle:hover { border-color: var(--gold); }
.nav-toggle span { display: block; width: 18px; height: 2px; border-radius: 2px;
    background: var(--text); transition: transform .25s ease, opacity .2s ease; }
/* Bars morph into an ✕ when the sidebar is open. */
header.top.nav-open .nav-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
header.top.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
header.top.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Backdrop lives in the DOM always; only painted when .nav-open on mobile. */
.nav-backdrop { display: none; }
@keyframes navFade { from { opacity: 0; } to { opacity: 1; } }

/* --- desktop nav polish: pill row + underline-style active accent --- */
@media (min-width: 981px) {
    header.top nav.nav { gap: 2px; padding: 4px; border-radius: 12px;
        background: var(--panel2); border: 1px solid var(--line); }
    header.top nav.nav a { position: relative; padding: 7px 13px; border-radius: 8px;
        font-size: .92rem; font-weight: 600; }
    header.top nav.nav a.active { color: var(--gold); background: var(--panel);
        box-shadow: inset 0 0 0 1px rgba(212,175,55,.28); }
    header.top nav.nav a.active::after { content: ""; position: absolute;
        left: 13px; right: 13px; bottom: 3px; height: 2px; border-radius: 2px;
        background: linear-gradient(90deg, var(--gold), var(--gold-hi)); }
    /* keep the group label from stretching the pill row */
    header.top nav.nav .nav-group { align-self: center; padding-inline: 8px; }
}

/* ==================== WEB-31: refined dark-luxury design system ====================
   Portal-wide senior polish. Token-driven, so every page lifts at once:
   soft elevation instead of flat borders, subtle card gradients, calmer
   hairlines, gold reserved as accent, tighter typographic rhythm.
   Appended last → wins by source order; light theme covered via the tokens. */

/* --- typography rhythm --- */
h1 { font-weight: 700; letter-spacing: -.01em; font-size: 1.55rem; }
h2 { color: var(--muted); font-weight: 600; font-size: .72rem; letter-spacing: .12em;
     margin: 30px 0 14px; }
.content { padding: 30px 30px 72px; }

/* --- header: quiet, elevated, sticky --- */
header.top {
    position: sticky; top: 0; z-index: 40;
    gap: 22px; padding: 12px 24px;
    background: color-mix(in srgb, var(--panel) 88%, transparent);
    -webkit-backdrop-filter: saturate(140%) blur(10px);
            backdrop-filter: saturate(140%) blur(10px);
    border-bottom: 1px solid var(--line-soft);
    box-shadow: 0 1px 0 rgba(255,255,255,.02), 0 6px 22px rgba(0,0,0,.28);
}
header.top .brand { font-weight: 700; letter-spacing: .2px; font-size: .98rem; }
header.top .brand .dot { box-shadow: 0 0 10px var(--gold), 0 0 3px var(--gold); }

/* --- KPI tiles: gradient card + soft lift on hover + gold cap --- */
.kpi {
    position: relative; overflow: hidden;
    background: var(--card-grad); border: 1px solid var(--line);
    border-radius: var(--radius-lg); padding: 18px 20px;
    box-shadow: var(--elev-1);
    transition: transform var(--speed), box-shadow var(--speed), border-color var(--speed);
}
.kpi::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px;
    background: linear-gradient(90deg, transparent, rgba(212,175,55,.5), transparent);
    opacity: .0; transition: opacity var(--speed); }
.kpi:hover { transform: translateY(-2px); box-shadow: var(--elev-2); border-color: rgba(212,175,55,.28); }
.kpi:hover::before { opacity: 1; }
.kpi .label { font-size: .72rem; letter-spacing: .12em; }
.kpi .value { font-size: 1.7rem; letter-spacing: -.01em; }
.kpis { gap: 18px; }

/* --- tables: real card, hairline rows, calm header, row hover --- */
.grid {
    border-radius: var(--radius); overflow: hidden;
    background: var(--panel); border: 1px solid var(--line);
    box-shadow: var(--elev-1); border-collapse: separate; border-spacing: 0;
}
.grid th { background: var(--panel2); font-weight: 600; font-size: .72rem;
    letter-spacing: .08em; color: var(--muted); padding: 13px 16px;
    border-bottom: 1px solid var(--line); }
.grid td { padding: 13px 16px; border-bottom: 1px solid var(--line-soft); }
.grid tbody tr { transition: background var(--speed); }
.grid tbody tr:hover td { background: color-mix(in srgb, var(--gold) 6%, transparent); }
.grid tr:last-child td { border-bottom: 0; }

/* --- chips / pills: softer, pill-perfect --- */
.chip { background: var(--panel2); border-radius: 999px; padding: 7px 15px;
    transition: border-color var(--speed), background var(--speed), color var(--speed); }
.chip:hover { background: color-mix(in srgb, var(--gold) 8%, var(--panel2)); border-color: rgba(212,175,55,.4); }
.chip.active { background: linear-gradient(180deg, var(--gold-hi), var(--gold)); color: #141414;
    border-color: transparent; box-shadow: 0 2px 10px rgba(212,175,55,.25); }
.pill { padding: 3px 11px; font-weight: 600; }

/* --- generic card-ish surfaces get the same treatment --- */
.editor, .empty, .cmp-strip, .quad, .bell-panel {
    border-radius: var(--radius-lg); box-shadow: var(--elev-1);
}
.editor { background: var(--card-grad); border-color: var(--line); padding: 18px 20px; }
.ticket { background: var(--card-grad); border-radius: var(--radius-lg);
    box-shadow: var(--elev-1); border-color: var(--line); }
.ticket.new { box-shadow: var(--elev-1), 0 0 0 1px rgba(212,175,55,.18); }

/* --- inputs / selects: consistent, refined focus glow --- */
.toolbar input, .form-grid input, .form-grid select,
.branch-create input, .page-head select, .page-head input,
input[type="text"], input[type="number"], input[type="search"], select, textarea {
    background: var(--panel2); border: 1px solid var(--line); border-radius: 10px;
    color: var(--text); transition: border-color var(--speed), box-shadow var(--speed), background var(--speed);
}
.toolbar input:focus, .form-grid input:focus, .form-grid select:focus,
.branch-create input:focus, .page-head select:focus,
input:focus, select:focus, textarea:focus {
    outline: none; border-color: var(--gold); box-shadow: var(--focus); }

/* --- buttons: default gets a subtle fill on hover (not just a gold ring) --- */
button:hover:not(:disabled) { background: color-mix(in srgb, var(--gold) 8%, var(--panel2)); }
button.primary { box-shadow: 0 2px 12px rgba(212,175,55,.26); }
button.primary:hover:not(:disabled) { box-shadow: 0 6px 20px rgba(212,175,55,.36); }

/* --- page-head divider for a cleaner report header --- */
.page-head { padding-bottom: 14px; border-bottom: 1px solid var(--line-soft); }

/* --- softer scrollbars to match the premium feel --- */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--line); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--panel2); }

/* --- WEB-31b: vendor-console cards (kpi-card / panel) get the same lift --- */
.kpi-card, .panel {
    background: var(--card-grad); border: 1px solid var(--line);
    border-radius: var(--radius-lg); box-shadow: var(--elev-1);
}
.kpi-card { transition: transform var(--speed), box-shadow var(--speed), border-color var(--speed); }
.kpi-card:hover { transform: translateY(-2px); box-shadow: var(--elev-2); border-color: rgba(212,175,55,.24); }
.kpi-card::before { width: 3px; }                 /* keep the accent rail crisp */
.kpi-value { letter-spacing: -.02em; }
.panel-head h2 { color: var(--text); font-size: .95rem; letter-spacing: 0; text-transform: none; font-weight: 700; }
.bar-track { background: var(--panel2); border-radius: 999px; }
.bar-fill { border-radius: 999px; }
.apikey-box { border-radius: var(--radius-lg); }

/* ==================== WEB-32: persistent sidebar shell (all sizes) ====================
   The nav moved from the top bar into a left sidebar that shows on EVERY size.
   Desktop/tablet: sidebar pinned, content beside it. Small phones (≤860px):
   sidebar slides off-canvas behind the hamburger. `nav-open` now lives on
   `.shell` (not the header). The old WEB-30 `header.top nav.nav …` rules are
   inert here because the nav is no longer inside the header. */

/* APP SHELL. The shell is exactly one viewport tall and never scrolls; the content
   column is the only scrolling region. That makes the sidebar fixed BY CONSTRUCTION
   on every page, instead of depending on `position: sticky` surviving whatever
   overflow a page's own markup introduces — sticky already failed once here (see the
   overflow-x note near the top) and it fails silently, which is the worst kind.
   dvh over vh so a mobile browser's collapsing URL bar can't crop the last row. */
.shell.auth { display: flex; align-items: stretch; height: 100vh; height: 100dvh; overflow: hidden; }

/* --- the sidebar --- */
.sidebar {
    flex: 0 0 250px; width: 250px;
    height: 100%;
    display: flex; flex-direction: column; z-index: 60;
    background: linear-gradient(180deg, var(--panel-hi), var(--panel));
    border-inline-end: 1px solid var(--line);
    box-shadow: 1px 0 0 rgba(0,0,0,.15);
}
/* NAV-2 — the rail needs a head. The old 9px glowing dot read as a status light
   (there is already a real one in the top bar) and gave the brand row nothing to
   sit against; a monogram tile does, and it is the only saturated gold on screen
   until the active pill appears below it. */
.side-brand {
    display: flex; align-items: center; gap: 11px;
    padding: 16px 14px 15px; color: var(--text);
    border-bottom: 1px solid var(--line-soft);
}
.side-mark {
    flex: none; width: 30px; height: 30px; border-radius: 9px;
    display: grid; place-items: center;
    background: linear-gradient(160deg, var(--gold-hi), var(--gold));
    color: #17140a; font-weight: 900; font-size: .95rem; line-height: 1;
    box-shadow: 0 2px 10px color-mix(in srgb, var(--gold) 30%, transparent);
}
.side-brand-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-weight: 700; font-size: .95rem; letter-spacing: .01em; }

.sidebar nav.nav {
    display: flex; flex-direction: column; align-items: stretch; gap: 2px;
    margin: 0; padding: 14px 12px 24px; flex: 1; overflow-y: auto;
    background: transparent; border: 0; border-radius: 0;   /* undo WEB-30 pill box */
    transform: none;                                         /* undo WEB-30 off-canvas */
    /* MOB-3 — scroll CHAINING is the default: the instant the nav list hits its top
       or bottom, the browser hands the rest of the gesture to the page behind it, so
       flicking the menu visibly scrolls the report underneath. `contain` ends the
       gesture at this box's edge. */
    overscroll-behavior-y: contain;
    -webkit-overflow-scrolling: touch;
}
/* WEB-32 — sidebar palette, rebuilt for the owner who lives in this rail all day:
   • NO underline / no rail — the active row is a solid gold-tinted pill, so the
     eye finds "where am I" in one saccade instead of hunting a 3px line.
   • Idle rows read at ~70% of body text: present, never shouting.
   • Hover = a whisper (raised chrome + full-strength text). Active = commitment. */
.sidebar nav.nav a {
    position: relative; display: flex; align-items: center; gap: 11px;
    width: 100%; padding: 10px 13px; border-radius: 10px;
    color: var(--muted); font-weight: 600; font-size: .92rem; white-space: nowrap;
    text-decoration: none;
    transition: color var(--speed), background var(--speed);
}
.sidebar nav.nav a:hover { color: var(--text); background: var(--panel2); }
.sidebar nav.nav a:hover .nav-ico { opacity: 1; }

.sidebar nav.nav a.active {
    color: var(--gold-hi);
    background: linear-gradient(90deg,
        color-mix(in srgb, var(--gold) 20%, transparent),
        color-mix(in srgb, var(--gold) 9%, transparent));
    font-weight: 700;
    /* A hairline of the same gold closes the pill's edge, so it reads as a chip that
       was placed there rather than a wash that bled across the row. */
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--gold) 20%, transparent);
}
[dir="rtl"] .sidebar nav.nav a.active { background: linear-gradient(270deg,
        color-mix(in srgb, var(--gold) 20%, transparent),
        color-mix(in srgb, var(--gold) 9%, transparent)); }
.sidebar nav.nav a.active .nav-ico { opacity: 1; }
/* The decoration from the old top-nav era is dead here (owner asked): no underline,
   no gold rail marker — the pill IS the state. ::before is NOT reset with it any
   more; NAV-2 uses it for the group guide below, which must run past the active row
   or the tree line breaks exactly where the eye is looking. */
.sidebar nav.nav a.active::after { content: none; }

/* NAV-2 — the tree guide, and the indent that never worked.
   `.nav-sub { padding-inline-start: 18px }` sat up in the generic nav block and has
   never once applied: `.sidebar nav.nav a` (0,2,1) outranks `.nav-sub` (0,1,0), so
   every child sat flush with its category and the rail asserted hierarchy purely by
   colour. The indent belongs here, at the winning specificity, with a hairline drawn
   OUTSIDE the pill so the active row's rounded corner stays clean.
   The guide lands at exactly the x of the category titles above it (nav padding 12 +
   pill margin 20 − 10 = 22px; .nav-cat padding 10 + 12 = 22px), so it reads as the
   group's own stem rather than a stray rule. inset-block overshoots the 2px row gap
   at both ends, which is what makes the segments join into one continuous line. */
/* width:auto, not the inherited width:100% — 100% plus a start margin overflows the
   rail by exactly the indent, and the overflow lands under the scrollbar edge where
   it reads as a clipped label rather than a layout bug. The nav is a stretch column,
   so auto still fills. */
.sidebar nav.nav a.nav-sub { margin-inline-start: 20px; width: auto; }
.sidebar nav.nav a.nav-sub::before {
    content: ""; position: absolute; inset-block: -3px;
    inset-inline-start: -10px; width: 1px; background: var(--line-soft);
}

/* Icons sit a touch back so labels lead the scan; they come forward on hover/active. */
.sidebar .nav-ico { opacity: .75; transition: opacity var(--speed); }

:root[data-theme="light"] .sidebar nav.nav a.active { color: #7a5606; }
/* The VENDOR rail's group header (the tenant rail uses the collapsible .nav-cat).
   Same metrics as .nav-cat on purpose — one product, one rail language, whichever
   session is signed in. */
.sidebar .nav-group {
    /* 13px inline, not .nav-cat's 10 — it lines up with the vendor links below it,
       which are plain <a>s carrying the link padding rather than .nav-sub's indent. */
    padding: 8px 13px 5px; margin-top: 14px; align-self: stretch;
    font-size: .66rem; color: var(--muted); font-weight: 800; letter-spacing: .14em;
}
.sidebar .nav-group:first-child { margin-top: 0; }

/* WEB-31 — icons align the sidebar with the reports index's visual language.
   Fixed width so every label starts on the same x, emoji or not. */
.nav-ico { width: 20px; flex: none; text-align: center; font-size: 1rem; line-height: 1; }

/* --- main column: slim topbar + content --- */
/* The one scrolling region. min-height:0 is load-bearing: a flex CHILD defaults to
   min-height:auto, which refuses to shrink below its content, so without it the column
   grows past the shell and the page scrolls again instead of this pane. */
.main-col { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; flex-direction: column;
            overflow-y: auto; overflow-x: hidden; }
/* The top bar rides with the sidebar rather than scrolling away under it. */
.main-col > header.top { position: sticky; top: 0; z-index: 40; }
.main-col > header.top { gap: 14px; padding: 11px 22px; }
.top-spacer { flex: 1; }

/* --- desktop/tablet: hamburger hidden, sidebar always in flow --- */
@media (min-width: 861px) { .nav-toggle { display: none !important; } }

/* --- small phones: sidebar off-canvas behind the hamburger --- */
@media (max-width: 860px) {
    /* Undo the app shell: on a phone the sidebar is an off-canvas overlay (position:
       fixed, below), so the PAGE goes back to being the scroller. Leaving the shell
       clipped to one viewport here would strand the bottom of every page. */
    .shell.auth { display: block; height: auto; overflow: visible; }
    .main-col { overflow: visible; min-height: 0; }
    .main-col > header.top { position: static; }
    .sidebar {
        position: fixed; top: 0; bottom: 0; inset-inline-start: 0; height: 100%;
        width: 264px; max-width: 84vw; transform: translateX(-100%);
        transition: transform .28s cubic-bezier(.3,.8,.3,1); }
    [dir="rtl"] .sidebar { transform: translateX(100%); }
    .shell.auth.nav-open .sidebar { transform: translateX(0); }
    .nav-toggle { display: inline-flex; }
    .shell.auth.nav-open .nav-backdrop {
        position: fixed; inset: 0; z-index: 55; display: block;
        background: rgba(0,0,0,.5); backdrop-filter: blur(2px);
        animation: navFade .2s ease both; }
    /* MOB-3 — on a phone the PAGE is the scroller (see the shell reset above), and a
       fixed backdrop does NOT stop a touch-drag from scrolling the document beneath
       it. Freeze the document while the drawer is open so the only thing that moves
       is the menu. :has() on <html> is the no-JS way to react to a class the layout
       puts on a descendant; browsers without it simply keep today's behaviour. */
    html:has(.shell.nav-open) { overflow: hidden; }
    html:has(.shell.nav-open) body { overflow: hidden; }
}

/* --- hamburger ✕-morph now keys off `.shell.nav-open` (moved off the header) --- */
.shell.nav-open .nav-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.shell.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
.shell.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ==================== WEB-33: enterprise login refinement (clean & minimal) ====================
   Aligns the sign-in gate to the enterprise brief: a true 60/40 split, a calm
   ambient scene (busy drifting food icons removed in Index.razor), larger touch
   targets, enterprise branding, and quieter motion (the perpetual card float is
   dropped — entrance + hover parallax stay). Appended last → wins by source order. */

/* --- 60/40 split on wide screens --- */
@media (min-width: 900px) {
    .lgx.lgx-split { grid-template-columns: 1.5fr 1fr; max-width: 1240px; gap: 56px; }
}

/* --- calmer motion: no perpetual bob (reads as distracting on an enterprise gate) --- */
.lgx-formpane { animation: none; }

/* --- enterprise branding block under the wordmark --- */
.lgx-show-badges { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 12px 0 4px; }
.lgx-ent-badge {
    display: inline-block; padding: 5px 13px; border-radius: 999px;
    font-size: .68rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
    color: #141414; background: linear-gradient(180deg, var(--gold-hi), var(--gold));
    box-shadow: 0 4px 14px rgba(212,175,55,.28);
}
.lgx-ent-sub { font-size: .82rem; font-weight: 600; letter-spacing: .01em; color: var(--muted); }
@media (min-width: 900px) {
    :root[data-theme="dark"] .lgx-ent-sub { color: rgba(245,232,210,.78); }
}

/* --- larger, premium inputs (58px) + button (56px), rounder card --- */
.lgx-card { border-radius: 24px; padding: 40px 36px 28px; }
.lgx-ff .ff-in { min-height: 58px; border-radius: 14px; padding-top: 22px; }
.lgx-ff .ff-eye { height: 40px; width: 40px; }
.lgx-btn { min-height: 56px; border-radius: 14px; font-size: 1.05rem; }
.lgx-acct { min-height: 56px; border-radius: 14px; }

/* Floating-label resting position tracks the taller field. */
.lgx-ff .ff-in:focus ~ .ff-lb,
.lgx-ff .ff-in:not(:placeholder-shown) ~ .ff-lb,
.lgx-ff .ff-in:-webkit-autofill ~ .ff-lb { top: 17px; }

/* ==================== WEB-34: animated barista hero (premium coffee scene) ====================
   Replaces the flat SVG latte that collided with the feature text. A clean,
   centred composition: brand block on top, an animated CSS ceramic coffee cup
   (crema + curved handle + rising steam + floating beans + warm spotlight) as the
   centrepiece, feature highlights at the bottom — no overlap. Wide screens only
   (the hero pane is hidden < 900px). Honours prefers-reduced-motion. */

@media (min-width: 900px) {
    .lgx-show {
        align-items: center; text-align: center; justify-content: space-between;
        padding: 44px 40px 40px; overflow: hidden;
        background:
            radial-gradient(80% 42% at 50% 6%,  rgba(255,196,120,.26), transparent 60%),
            radial-gradient(55% 40% at 50% 58%, rgba(255,168,84,.20),  transparent 60%),
            linear-gradient(168deg, #1a0f08 0%, #2a1810 46%, #3a2413 100%);
        box-shadow: inset 0 0 140px rgba(0,0,0,.55), 0 34px 90px rgba(18,9,3,.55);
    }
    .lgx-show::after {
        background: radial-gradient(130% 100% at 50% 42%, transparent 52%, rgba(0,0,0,.5));
    }
    .lgx-hero-top { display: flex; flex-direction: column; align-items: center; }
    .lgx-show-badges { justify-content: center; margin: 12px 0 8px; }
    .lgx-show-tag { color: rgba(245,232,210,.82); margin: 0; }
}

/* ---- the coffee scene ---- */
.barista { position: relative; width: 260px; height: 240px; align-self: center;
    display: flex; align-items: center; justify-content: center;
    animation: baristaBob 5s ease-in-out infinite; }
.barista::before {                       /* warm spotlight behind the cup */
    content: ""; position: absolute; width: 320px; height: 320px; border-radius: 50%;
    background: radial-gradient(circle, rgba(255,190,110,.30), transparent 62%);
    filter: blur(4px); pointer-events: none; }
@keyframes baristaBob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }

.cup-scene { position: relative; width: 240px; height: 220px; }

/* saucer */
.saucer { position: absolute; bottom: 0; left: 50%; width: 214px; height: 36px; margin-left: -107px;
    border-radius: 50%;
    background: linear-gradient(180deg, #fbf7f0, #d7ccbc);
    box-shadow: 0 16px 26px rgba(0,0,0,.5), inset 0 3px 6px rgba(255,255,255,.7); }
.saucer::after { content: ""; position: absolute; left: 50%; top: 6px; width: 150px; height: 20px;
    margin-left: -75px; border-radius: 50%; background: rgba(120,80,45,.18); }

/* cup */
.cup { position: absolute; bottom: 18px; left: 50%; width: 152px; height: 134px; margin-left: -76px; }
.cup-body { position: absolute; inset: 0; overflow: hidden;
    border-radius: 20px 20px 66px 66px / 16px 16px 52px 52px;
    background: linear-gradient(102deg, #ffffff 0%, #f4efe8 42%, #ded3c4 82%, #cabeae 100%);
    box-shadow: inset -12px -8px 26px rgba(120,86,52,.28),
                inset 14px 8px 20px rgba(255,255,255,.65),
                0 20px 30px rgba(0,0,0,.42); }
.coffee { position: absolute; top: 11px; left: 13px; right: 13px; height: 28px; border-radius: 50%;
    background: radial-gradient(ellipse at 50% 38%, #7a4a24 0%, #4a2a14 62%, #341d0e 100%);
    box-shadow: inset 0 3px 7px rgba(0,0,0,.55); }
.coffee::after { content: ""; position: absolute; inset: 3px; border-radius: 50%;
    border: 2px solid rgba(206,158,96,.55); }
.cup-handle { position: absolute; top: 36px; right: -30px; width: 42px; height: 52px;
    border: 13px solid #efe7db; border-left: none; border-radius: 0 30px 30px 0;
    box-shadow: 7px 0 12px rgba(0,0,0,.22); }
[dir="rtl"] .cup-handle { right: auto; left: -30px; border: 13px solid #efe7db; border-right: none;
    border-radius: 30px 0 0 30px; box-shadow: -7px 0 12px rgba(0,0,0,.22); }

/* steam — soft wisps rising from the coffee surface */
.steam { position: absolute; bottom: 150px; left: 50%; width: 84px; height: 80px; margin-left: -42px; }
.steam span { position: absolute; bottom: 0; width: 11px; height: 42px; border-radius: 50%;
    background: linear-gradient(to top, rgba(255,255,255,0), rgba(255,255,255,.6));
    filter: blur(5px); opacity: 0; will-change: transform, opacity;
    animation: baristaSteam 3.8s ease-in infinite; }
.steam span:nth-child(1) { left: 12px; animation-delay: 0s;   }
.steam span:nth-child(2) { left: 34px; animation-delay: .95s; height: 52px; }
.steam span:nth-child(3) { left: 56px; animation-delay: 1.9s; }
.steam span:nth-child(4) { left: 44px; animation-delay: 2.7s; height: 34px; }
@keyframes baristaSteam {
    0%   { transform: translateY(0)    translateX(0)   scaleX(1);   opacity: 0; }
    25%  { opacity: .72; }
    60%  { transform: translateY(-36px) translateX(7px) scaleX(1.5); opacity: .4; }
    100% { transform: translateY(-70px) translateX(-5px) scaleX(1.9); opacity: 0; }
}

/* floating coffee beans */
.barista-bean { position: absolute; width: 17px; height: 23px; border-radius: 50%;
    background: radial-gradient(circle at 38% 32%, #7c4a28, #3a2110);
    box-shadow: inset 0 0 0 1px rgba(0,0,0,.35); opacity: .55; }
.barista-bean::after { content: ""; position: absolute; inset: 0; border-radius: 50%;
    background: linear-gradient(92deg, transparent 44%, rgba(0,0,0,.45) 47%, transparent 53%); }
.barista-bean.b1 { left: 8%;  top: 30%; animation: beanFloat 7s ease-in-out infinite; }
.barista-bean.b2 { right: 9%; top: 20%; animation: beanFloat 9s ease-in-out infinite reverse; }
@keyframes beanFloat { 0%,100% { transform: translateY(0) rotate(-10deg); } 50% { transform: translateY(-16px) rotate(12deg); } }

@media (prefers-reduced-motion: reduce) {
    .barista, .barista-bean { animation: none; }
    .steam span { animation: none; opacity: .3; }
}

/* ==================== WEB-35: cinematic café hero (photo + 3D animation) ====================
   Matches the reference espresso-bar gate: a photographic hero with a slow
   Ken-Burns zoom + cursor parallax, a pulsing pendant-light bloom, rising steam,
   brand top-left and a glassy feature card bottom-left. Drop a photo at
   wwwroot/hero-cafe.jpg; without it the warm espresso gradient shows as fallback.
   Wide screens only (hero hidden < 900px). Honours prefers-reduced-motion. */

@media (min-width: 900px) {
    .lgx-show {
        position: relative; overflow: hidden; padding: 0; border-radius: 30px;
        align-items: stretch; text-align: start; justify-content: stretch;
        /* espresso fallback shown if no photo is present */
        background: linear-gradient(168deg, #1a0f08 0%, #2a1810 46%, #3a2413 100%);
    }
    /* legibility gradient over the photo */
    .lgx-show::after {
        z-index: 2;
        background:
            linear-gradient(180deg, rgba(8,5,3,.55) 0%, rgba(8,5,3,.12) 42%, rgba(8,5,3,.78) 100%),
            radial-gradient(80% 70% at 28% 34%, rgba(0,0,0,0) 40%, rgba(0,0,0,.5));
    }
}

/* photo layer — Ken-Burns on ::before, pointer parallax on the wrapper */
.lgx-hero-photo { position: absolute; inset: 0; z-index: 0;
    transition: transform .35s cubic-bezier(.2,.7,.3,1); will-change: transform; }
.lgx-hero-photo::before {
    content: ""; position: absolute; inset: -5%;
    /* jpg (if the owner drops a real photo) layers ON TOP of the authored SVG
       scene, so a real hero-cafe.jpg auto-upgrades this with zero code change. */
    background-image: url('hero-cafe.jpg'), url('hero-cafe.svg');
    background-size: cover, cover; background-position: center, center;
    background-repeat: no-repeat, no-repeat;
    animation: heroKen 28s ease-in-out infinite alternate; will-change: transform; }
@keyframes heroKen {
    0%   { transform: scale(1.05) translate(0, 0); }
    100% { transform: scale(1.14) translate(-2.2%, -1.6%); }
}

/* pendant-light bloom (top, warm, gently pulsing) */
.lgx-hero-glow { position: absolute; z-index: 1; top: -8%; left: 50%; width: 360px; height: 360px;
    margin-left: -180px; border-radius: 50%; pointer-events: none; filter: blur(8px);
    background: radial-gradient(circle, rgba(255,201,120,.45), rgba(255,176,88,.12) 45%, transparent 70%);
    animation: heroGlow 5s ease-in-out infinite; }
@keyframes heroGlow { 0%,100% { opacity: .7; transform: scale(1); } 50% { opacity: 1; transform: scale(1.06); } }

/* rising steam over the counter */
.lgx-hero-steam { position: absolute; z-index: 3; bottom: 150px; left: 44%; width: 74px; height: 84px;
    pointer-events: none; }
.lgx-hero-steam span { position: absolute; bottom: 0; width: 11px; height: 44px; border-radius: 50%;
    background: linear-gradient(to top, rgba(255,255,255,0), rgba(255,255,255,.5));
    filter: blur(5px); opacity: 0; will-change: transform, opacity;
    animation: baristaSteam 4s ease-in infinite; }
.lgx-hero-steam span:nth-child(1) { left: 8px;  animation-delay: 0s; }
.lgx-hero-steam span:nth-child(2) { left: 28px; animation-delay: 1s;   height: 54px; }
.lgx-hero-steam span:nth-child(3) { left: 48px; animation-delay: 2s; }
.lgx-hero-steam span:nth-child(4) { left: 38px; animation-delay: 2.8s; height: 34px; }

/* content over the photo — brand top-left, features bottom-left */
.lgx-hero-content { position: relative; z-index: 4; height: 100%;
    display: flex; flex-direction: column; justify-content: space-between;
    align-items: flex-start; text-align: start; padding: 46px 46px; }
.lgx-hero-content .lgx-hero-top { align-items: flex-start; }
.lgx-hero-content .lgx-show-name { text-shadow: 0 2px 20px rgba(0,0,0,.6); }
.lgx-hero-content .lgx-show-tag { color: rgba(245,232,210,.9); text-shadow: 0 1px 10px rgba(0,0,0,.6); }
.lgx-hero-content .lgx-show-badges { justify-content: flex-start; }

/* feature highlights become a glassy card bottom-left (like the reference) */
.lgx-hero-content .lgx-feats {
    margin: 0; padding: 16px 20px; gap: 12px; border-radius: 20px;
    background: rgba(18,12,8,.52); border: 1px solid rgba(255,255,255,.09);
    -webkit-backdrop-filter: blur(12px) saturate(130%); backdrop-filter: blur(12px) saturate(130%);
    box-shadow: 0 24px 60px rgba(0,0,0,.55); }
.lgx-hero-content .lgx-feats li { color: #f4ece0; }
.lgx-hero-content .lgx-feats .lf-ic {
    background: linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,.05));
    border-color: rgba(255,255,255,.2); }

:root[data-theme="light"] .lgx-show::after {
    background:
        linear-gradient(180deg, rgba(8,5,3,.35) 0%, rgba(8,5,3,.06) 42%, rgba(8,5,3,.6) 100%),
        radial-gradient(80% 70% at 28% 34%, rgba(0,0,0,0) 40%, rgba(0,0,0,.35)); }

@media (prefers-reduced-motion: reduce) {
    .lgx-hero-photo::before, .lgx-hero-glow { animation: none; }
    .lgx-hero-steam span { animation: none; opacity: .3; }
}

/* ==================== WEB-36: full-page café bar (photo fills the whole page) ====================
   The espresso-bar scene now spans the ENTIRE viewport; brand, features and the
   sign-in card all float over it. Professional steam plume rises from the machine.
   The café also shows on mobile (behind the card). Reduced-motion aware. */

/* café layers now live in the full-page fixed .lgx-bg */
.lgx-fullbar .lgx-bg { z-index: 0; }
.lgx-fullbar .lgx-orb { display: none; }              /* orbs replaced by the photo */
.lgx-fullbar .lgx-bg::after { display: none; }        /* drop the dotted grid */
.lgx-fullbar .lgx-hero-photo { position: absolute; inset: 0; }
.lgx-fullbar .lgx-hero-photo::after {                 /* full-page legibility wash */
    content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
    background:
        linear-gradient(90deg, rgba(6,4,2,.52) 0%, rgba(6,4,2,.10) 34%, rgba(6,4,2,.30) 60%, rgba(6,4,2,.76) 100%),
        linear-gradient(180deg, rgba(6,4,2,.34) 0%, transparent 32%, rgba(6,4,2,.55) 100%); }
[dir="rtl"] .lgx-fullbar .lgx-hero-photo::after {
    background:
        linear-gradient(270deg, rgba(6,4,2,.52) 0%, rgba(6,4,2,.10) 34%, rgba(6,4,2,.30) 60%, rgba(6,4,2,.76) 100%),
        linear-gradient(180deg, rgba(6,4,2,.34) 0%, transparent 32%, rgba(6,4,2,.55) 100%); }

/* pendant bloom, larger, over the ceiling */
.lgx-fullbar .lgx-hero-glow { left: 42%; top: -8%; width: 560px; height: 560px; margin-left: -280px; }

/* the brand/features aside becomes a transparent overlay (no panel chrome) */
@media (min-width: 900px) {
    .lgx-fullbar .lgx-show {
        background: none; box-shadow: none; border-radius: 0; overflow: visible; padding: 0;
        z-index: 2;
    }
    .lgx-fullbar .lgx-show::after { display: none; }
}

/* professional steam PLUME rising from the espresso machine (centre-left of the bar) */
.lgx-fullbar .lgx-hero-steam {
    position: absolute; z-index: 2; left: 20%; bottom: 30%; top: auto; margin: 0;
    width: 150px; height: 200px; pointer-events: none; }
.lgx-fullbar .lgx-hero-steam span {
    position: absolute; bottom: 0; width: 15px; height: 80px; border-radius: 50%;
    background: linear-gradient(to top, rgba(255,255,255,0), rgba(255,250,244,.62));
    filter: blur(7px); opacity: 0; will-change: transform, opacity;
    animation: barSteam 5s ease-in infinite; }
.lgx-fullbar .lgx-hero-steam span:nth-child(1) { left: 8px;   animation-delay: 0s;   }
.lgx-fullbar .lgx-hero-steam span:nth-child(2) { left: 34px;  animation-delay: .8s;  height: 100px; }
.lgx-fullbar .lgx-hero-steam span:nth-child(3) { left: 60px;  animation-delay: 1.7s; }
.lgx-fullbar .lgx-hero-steam span:nth-child(4) { left: 86px;  animation-delay: 2.5s; height: 96px; }
.lgx-fullbar .lgx-hero-steam span:nth-child(5) { left: 112px; animation-delay: 3.3s; }
.lgx-fullbar .lgx-hero-steam span:nth-child(6) { left: 46px;  animation-delay: 4s;   height: 70px; }
@keyframes barSteam {
    0%   { transform: translateY(0)     translateX(0)   scaleX(.8); opacity: 0; }
    18%  { opacity: .6; }
    55%  { transform: translateY(-84px)  translateX(12px) scaleX(1.35); opacity: .38; }
    100% { transform: translateY(-172px) translateX(-10px) scaleX(1.8);  opacity: 0; }
}

/* keep the sign-in card clearly floating above the bar */
.lgx-fullbar .lgx-formpane { z-index: 3; }

@media (prefers-reduced-motion: reduce) {
    .lgx-fullbar .lgx-hero-steam span { animation: none; opacity: .28; }
}

/* WEB-36b: let the full-bar gate truly fill the viewport.
   The anon .content wrapper (max-width:1280 + padding) and the .lgx max-width were
   boxing the fixed background in; drop both so the café spans edge to edge. The
   .lgx perspective makes the fixed .lgx-bg fill .lgx, so .lgx must be full-size. */
.shell.anon .content { padding: 0; max-width: none; }
.lgx.lgx-fullbar { width: 100%; max-width: none; min-height: 100vh; margin: 0; padding: 0; }
@media (min-width: 900px) {
    .lgx.lgx-split.lgx-fullbar {
        grid-template-columns: 1fr 500px; gap: 0; max-width: none; padding: 0; min-height: 100vh;
    }
    .lgx-fullbar .lgx-formpane { padding-inline: 28px; }
    .lgx-fullbar .lgx-show { padding: 8px 8px 8px 8px; }   /* content has its own 46px */
}

/* ==================== WEB-37: 3D animated café stage (not a photo) ====================
   Turns the flat café into a layered 3D scene: a perspective stage whose layers
   (photo → god-rays → glow → beans → steam) sit at different translateZ, so the
   cursor-driven stage tilt (JS in _Host.cshtml) parts them in real depth. The photo
   plane also does a continuous 3D Ken-Burns swing. Reduced-motion aware. */

.lgx-fullbar .lgx-bg { perspective: 1500px; }
.lgx-fullbar .lgx-stage {
    position: absolute; inset: 0; transform-style: preserve-3d;
    transition: transform .4s cubic-bezier(.2,.7,.3,1); will-change: transform; }
.lgx-fullbar .lgx-stage > * { position: absolute; }

/* --- back plane: the café itself, pushed back + continuous 3D swing --- */
.lgx-fullbar .lgx-hero-photo { inset: 0; transform: translateZ(-55px) scale(1.09); }
.lgx-fullbar .lgx-hero-photo::before { inset: -9%; }
@keyframes heroKen {
    0%   { transform: perspective(1300px) rotateY(-3deg) rotateX(1deg)  scale(1.06) translate(0, 0); }
    100% { transform: perspective(1300px) rotateY(3deg)  rotateX(-1deg) scale(1.12) translate(-2.2%, -1.4%); }
}

/* --- god-rays from the pendant (mid plane), soft pulse --- */
.lgx-fullbar .lgx-hero-rays {
    inset: 0; z-index: 1; pointer-events: none; transform: translateZ(12px);
    background: linear-gradient(116deg, transparent 38%, rgba(255,201,120,.12) 47%,
                rgba(255,214,140,.05) 52%, transparent 60%);
    mix-blend-mode: screen; animation: rayPulse 7s ease-in-out infinite; }
@keyframes rayPulse { 0%,100% { opacity: .3; } 50% { opacity: .85; } }

/* --- pendant bloom on a forward plane; opacity-only pulse so translateZ survives --- */
.lgx-fullbar .lgx-hero-glow { z-index: 2; transform: translateZ(28px); animation-name: heroGlow3d; }
@keyframes heroGlow3d { 0%,100% { opacity: .7; } 50% { opacity: 1; } }

/* --- steam on the front plane --- */
.lgx-fullbar .lgx-hero-steam { z-index: 3; transform: translateZ(58px); }

/* --- coffee beans floating on the very front plane (translateZ baked in) --- */
.lgx-fullbar .lgx-hero-bean {
    z-index: 3; width: 18px; height: 24px; border-radius: 50%;
    background: radial-gradient(circle at 38% 32%, #7c4a28, #3a2110);
    box-shadow: inset 0 0 0 1px rgba(0,0,0,.35), 0 6px 14px rgba(0,0,0,.45); opacity: .7; }
.lgx-fullbar .lgx-hero-bean::after { content: ""; position: absolute; inset: 0; border-radius: 50%;
    background: linear-gradient(92deg, transparent 44%, rgba(0,0,0,.45) 47%, transparent 53%); }
.lgx-fullbar .lgx-hero-bean.bn1 { left: 30%; top: 60%; animation: bean3d 7s ease-in-out infinite; }
.lgx-fullbar .lgx-hero-bean.bn2 { left: 39%; top: 53%; animation: bean3d 9s ease-in-out infinite reverse; }
.lgx-fullbar .lgx-hero-bean.bn3 { left: 24%; top: 66%; animation: bean3d 8s ease-in-out infinite; }
@keyframes bean3d {
    0%,100% { transform: translateZ(78px) translateY(0)    rotate(-10deg); }
    50%     { transform: translateZ(78px) translateY(-18px) rotate(12deg); }
}

@media (prefers-reduced-motion: reduce) {
    .lgx-fullbar .lgx-stage { transition: none; }
    .lgx-fullbar .lgx-hero-rays, .lgx-fullbar .lgx-hero-bean { animation: none; }
}

/* ==================== WEB-42: single centred sign-in over a 3D "thinking brain" ====
   The gate is now ONE card, centred in the viewport, floating over an animated
   neural-network canvas (a rotating brain of gold neurons firing thought-pulses;
   engine in _Host.cshtml). No side panel, no café scene. Full-bleed, theme-aware. */
/* 100dvh, not 100vh: on mobile the address bar shrinks the visual viewport, and a
   fixed 100vh pushed the card partly under the browser chrome. `safe center` keeps a
   card taller than a short laptop screen from being clipped at the top — it falls back
   to start-alignment and the page scrolls instead. */
.lgx.lgx-solo { width: 100%; max-width: none; min-height: 100dvh; margin: 0; padding: 0;
    display: grid; place-items: safe center; }
.lgx-solo .lgx-bg {
    background:
        /* faint gold circuit grid */
        linear-gradient(rgba(212,175,55,.045) 1px, transparent 1px) 0 0 / 46px 46px,
        linear-gradient(90deg, rgba(212,175,55,.045) 1px, transparent 1px) 0 0 / 46px 46px,
        radial-gradient(1200px 700px at 50% 42%, rgba(212,175,55,.10), transparent 62%),
        radial-gradient(900px 640px at 82% 108%, rgba(59,130,246,.06), transparent 58%),
        linear-gradient(180deg, #0b0b0d 0%, #08080a 100%);
}
.lgx-solo .lgx-bg::after { display: none; }         /* no dotted grid — the brain is the scene */
.lgx-brain-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.lgx-brain-vignette { position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(150% 110% at 50% 48%, transparent 58%, rgba(0,0,0,.58) 100%); }
/* Breathing room scales with the viewport so the rotating brain reads as the SCENE,
   not something peeking from behind the card. The vertical padding is deliberately
   generous — the brain is most visible above the logo and below the "secure sign-in"
   footer, so that band is where the animation gets to show. */
.lgx-solo .lgx-formpane { z-index: 2;
    padding-inline: clamp(22px, 6vw, 120px);
    padding-block: clamp(40px, 9vh, 96px);
    justify-items: center; place-items: center; }

/* Login utility cluster — theme + language + one WhatsApp contact. The ONLY
   utility cluster on the root gate (MainLayout suppresses its own .float-tools
   here — see MainLayout.IsRootGate); the END corner matches where every other
   screen in the app (the authenticated top bar) puts theme/language. */
.lgx-tools { position: fixed; top: 18px; inset-inline-end: 20px; z-index: 5;
    display: flex; gap: 10px; }
@media (max-width: 560px) {
    .lgx-tools { top: 12px; inset-inline-end: 12px; gap: 6px; }
    .lgx-tool { width: 38px; height: 38px; font-size: 16px; }
}
.lgx-lang-lb { font-size: 13px; font-weight: 700; letter-spacing: .02em; }

/* Forced credential change — shown INSIDE the gate card when the account is still on a
   password somebody else set (admin reset / vendor reset-by-email). Reuses .lgx-ff fields
   and .lgx-btn so it can't drift from the sign-in form it replaces. */
.lgx-force-msg { margin: 0 0 6px; font-weight: 700; font-size: 1rem; text-align: center; }
.lgx-force-hint { margin: 0 0 18px; color: var(--muted); font-size: .84rem;
    text-align: center; line-height: 1.5; }
.lgx-force-cancel { display: block; width: 100%; margin-top: 10px; padding: 9px 0;
    background: none; border: 0; color: var(--muted); font-size: .86rem; cursor: pointer;
    border-radius: 10px; transition: color .14s ease, background .14s ease; }
.lgx-force-cancel:hover { color: var(--gold); background: rgba(212,175,55,.07); }
.lgx-tool { width: 42px; height: 42px; display: grid; place-items: center; cursor: pointer;
    border-radius: 12px; border: 1px solid rgba(212,175,55,.28);
    background: rgba(20,20,22,.55); color: var(--gold-hi, #e6c452);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    font-size: 18px; line-height: 1; text-decoration: none;
    transition: transform .12s ease, border-color .14s ease, background .14s ease, box-shadow .14s ease; }
.lgx-tool:hover { transform: translateY(-2px); border-color: var(--gold);
    background: rgba(30,30,34,.7); box-shadow: 0 6px 18px rgba(212,175,55,.18); }
.lgx-tool:active { transform: scale(.95); }
.lgx-tool.wa { color: #25D366; border-color: rgba(37,211,102,.4); }
.lgx-tool.wa:hover { border-color: #25D366; box-shadow: 0 6px 18px rgba(37,211,102,.22); }
/* Two support lines → a small corner numeral tells them apart. ABSOLUTE on purpose:
   .lgx-tool is a centring grid, so a second in-flow child would open a second row and
   shove the WhatsApp glyph off centre — the exact bug just fixed on the theme toggle. */
.lgx-tool.wa { position: relative; }
.lgx-tool.wa .wa-n {
    position: absolute; inset-block-end: 1px; inset-inline-end: 4px;
    width: auto; height: auto; display: block;
    font-size: 9px; font-weight: 800; line-height: 1;
    opacity: .9; pointer-events: none;
}
/* (MOB-6 — the gate's theme toggle no longer wears .lgx-tool or .theme-toggle at all;
   it is self-contained under `.cxtheme` at the end of this file. The overrides that
   used to sit here are deleted on purpose: they were one side of the cascade fight
   that kept knocking the icon off centre.) */
:root[data-theme="light"] .lgx-tool { background: rgba(255,255,255,.7); color: #8a6410;
    border-color: rgba(169,127,22,.35); }
:root[data-theme="light"] .lgx-tool.wa { color: #128C7E; border-color: rgba(18,140,126,.4); }

:root[data-theme="light"] .lgx-solo .lgx-bg {
    background:
        linear-gradient(rgba(169,127,22,.06) 1px, transparent 1px) 0 0 / 46px 46px,
        linear-gradient(90deg, rgba(169,127,22,.06) 1px, transparent 1px) 0 0 / 46px 46px,
        radial-gradient(1200px 700px at 50% 42%, rgba(212,175,55,.16), transparent 62%),
        radial-gradient(900px 640px at 82% 108%, rgba(59,130,246,.08), transparent 58%),
        linear-gradient(180deg, #f7f4ec, #ece5d6);
}
:root[data-theme="light"] .lgx-brain-vignette {
    background: radial-gradient(150% 110% at 50% 48%, transparent 60%, rgba(120,100,50,.18) 100%); }

/* ---- keyboard focus on the sign-in gate ----
   Every control here had `outline:none` or no focus rule at all, so a keyboard or
   screen-reader user tabbing through the form could not see where they were — on
   the one page every user must pass through, and the one page where a password is
   typed. :focus-visible keeps the ring off mouse clicks, so nothing changes for
   pointer users while the keyboard path becomes followable. */
.lgx-btn:focus-visible,
.lgx-tool:focus-visible,
.lgx-acct .a-switch:focus-visible,
.lgx-ff .ff-eye:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--bg, #0b0b0d), 0 0 0 4px var(--gold, #d4af37);
}
.lgx-ff .ff-in:focus-visible { outline: none; }   /* the field draws its own gold border */

/* The password reveal and "switch account" are secondary actions: they should
   answer a press without competing with the primary button for attention. */
.lgx-ff .ff-eye:active { transform: translateY(-50%) scale(.9); }
.lgx-acct .a-switch:active { transform: scale(.96); }
.lgx-acct .a-switch { transition: color .14s ease, border-color .14s ease, transform .1s ease; }

@media (prefers-reduced-motion: reduce) {
    .lgx-btn, .lgx-tool, .lgx-acct .a-switch, .lgx-ff .ff-eye { transition: none; }
    .lgx-btn:hover:not(:disabled), .lgx-btn:active:not(:disabled) { transform: none; }
}

/* ==================== WEB-38: Tenants page — senior control-plane layout ====================
   KPI pulse strip on top, the 12-column wall consolidated into 8 scannable columns
   with stacked two-line cells, colour-coded subscription-days chips, whole row
   clickable into the management drawer. Queues keep their accent borders. */

.tn-kpis { margin: 4px 0 18px; }

/* --- stacked cells --- */
.tenants-grid .tn-acct { display: flex; align-items: center; gap: 8px; }
.tenants-grid .tn-name { margin-top: 3px; font-weight: 600; font-size: .92rem; }
.tenants-grid .tn-owner { font-size: .9rem; }
.tenants-grid .tn-mail { display: inline-block; margin-top: 2px; font-size: .8rem;
    color: var(--muted); text-decoration: none; }
.tenants-grid .tn-mail:hover { color: var(--gold); text-decoration: underline; }
.tenants-grid .tn-caps { margin-top: 3px; font-size: .74rem; color: var(--muted); white-space: nowrap; }
.tenants-grid .tn-ends { font-variant-numeric: tabular-nums; white-space: nowrap; }
.tenants-grid .tn-seen { font-size: .8rem; color: var(--muted); white-space: nowrap; }

/* DB provisioning dot beside the account code */
.tn-db { width: 9px; height: 9px; border-radius: 50%; flex: none; display: inline-block; }
.tn-db.ok  { background: var(--ok); box-shadow: 0 0 6px rgba(46,204,113,.6); }
.tn-db.off { background: var(--off); }

/* subscription-days chip */
.tn-days { display: inline-block; margin-inline-start: 8px; padding: 1px 8px;
    border-radius: 999px; font-size: .7rem; font-weight: 700; }
.tn-days.ok     { color: var(--muted); background: var(--panel2); }
.tn-days.warn   { color: var(--warn); background: rgba(243,156,18,.12); border: 1px solid rgba(243,156,18,.35); }
.tn-days.danger { color: #ff8a7a;    background: rgba(231,76,60,.12);  border: 1px solid rgba(231,76,60,.4); }
:root[data-theme="light"] .tn-days.danger { color: #c0392b; }

/* whole row opens the drawer */
.tenants-grid tr.tn-row { cursor: pointer; }
.tenants-grid tr.tn-row:hover .tn-name { color: var(--gold-hi); }
:root[data-theme="light"] .tenants-grid tr.tn-row:hover .tn-name { color: #8a6410; }
.tenants-grid .kebab { white-space: nowrap; font-size: .8rem; font-weight: 600; }

/* vertical rhythm for the queue cards */
.tenants .editor { margin: 14px 0; }
.tenants .toolbar { margin: 4px 0 16px; }

/* ==================== WEB-39: tenant drawer — customer-360 layout ====================
   The Manage drawer becomes a full account file: overview grid (mode/DB/caps/
   owner/machine/last-seen), money snapshot (current fee + yearly value), and a
   BILLING HISTORY card fed by /tenants/{id}/renewals — every payment with the
   fee in force at that renewal. Wider drawer to breathe. */

.tenants .drawer { width: 520px; }

/* two-column key-value grid */
.kv2 { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 18px; }
.kv2 .kv { min-width: 0; }
.kv2 .kv b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
.kv b a { color: var(--gold); text-decoration: none; }
.kv b a:hover { text-decoration: underline; }
.kv .mono { font-family: Consolas, monospace; font-size: .82rem; letter-spacing: .02em; }
.v-good { color: var(--ok); }
.v-bad  { color: var(--warn); }

/* money snapshot beside the days dial */
.sub-hero { display: flex; align-items: center; gap: 18px; }
.sub-money { flex: 1; display: flex; flex-direction: column; gap: 8px; }
.sub-money .sm-row { display: flex; align-items: baseline; justify-content: space-between;
    padding: 7px 12px; border-radius: 10px; background: var(--panel2);
    border: 1px solid var(--line-soft); }
.sub-money .sm-row span { color: var(--muted); font-size: .78rem; }
.sub-money .sm-row b { font-size: 1.02rem; font-variant-numeric: tabular-nums; }

/* billing totals strip */
.bill-totals { display: flex; gap: 10px; margin: 2px 0 12px; }
.bill-totals .bt { flex: 1; text-align: center; padding: 10px 6px; border-radius: 12px;
    background: var(--panel2); border: 1px solid var(--line-soft); }
.bill-totals .bt .n { display: block; font-size: 1.25rem; font-weight: 800;
    font-variant-numeric: tabular-nums; }
.bill-totals .bt .u { display: block; margin-top: 2px; font-size: .68rem; color: var(--muted);
    text-transform: uppercase; letter-spacing: .06em; }
.bill-totals .bt.gold { border-color: rgba(212,175,55,.35);
    background: color-mix(in srgb, var(--gold) 8%, var(--panel2)); }
.bill-totals .bt.gold .n { color: var(--gold-hi); }
:root[data-theme="light"] .bill-totals .bt.gold .n { color: #8a6410; }

/* compact billing table */
.bill-table { font-size: .82rem; }
.bill-table th, .bill-table td { padding: 8px 10px; white-space: nowrap; }
.bill-table td b { font-variant-numeric: tabular-nums; }

/* WEB-39b: pricing card — Monthly/Yearly segmented control */
.cycle-seg { display: inline-flex; gap: 0; margin: 2px 0 12px; padding: 4px;
    border-radius: 12px; background: var(--panel2); border: 1px solid var(--line); }
.cycle-seg button { min-height: 34px; padding: 5px 18px; border: 0; border-radius: 8px;
    background: transparent; color: var(--muted); font-size: .85rem; font-weight: 600; }
.cycle-seg button:hover:not(:disabled) { color: var(--text); background: transparent; }
.cycle-seg button.on { background: linear-gradient(180deg, var(--gold-hi), var(--gold));
    color: #141414; font-weight: 700; box-shadow: 0 2px 8px rgba(212,175,55,.25); }

/* WEB-38b: row click expands the tenant's branches inline — chevron shows state */
.tn-chev { display: inline-block; font-size: .8rem; color: var(--muted);
    transition: transform .15s ease, color .15s ease; }
.tn-chev.open { transform: rotate(90deg); color: var(--gold); }

/* ================= INV-1b: inventory writes + recipes ================= */
.ghost-link {
    display: inline-flex; align-items: center; gap: 6px; padding: 8px 14px;
    border: 1px solid var(--line); border-radius: 9px; color: var(--text);
    text-decoration: none; font-size: .9rem; white-space: nowrap;
}
.ghost-link:hover { border-color: var(--gold); color: var(--gold); }

.grid td.row-actions { white-space: nowrap; text-align: end; }
button.mini {
    background: transparent; color: var(--muted); border: 1px solid var(--line);
    border-radius: 7px; padding: 3px 9px; font-size: .85rem; cursor: pointer;
    margin-inline-start: 4px;
}
button.mini:hover { color: var(--gold); border-color: var(--gold); }

.menu-mgr button.danger {
    background: transparent; color: #ff8a7a; border: 1px solid rgba(231,76,60,.5);
}
.menu-mgr button.danger:hover { border-color: var(--err); color: var(--err); }
:root[data-theme="light"] .menu-mgr button.danger { color: #c0392b; }

/* Receive drawer line rows: item · qty · cost · total · ✕ */
.var-row.rcv-row { grid-template-columns: 1fr 76px 90px 80px 30px; }
.var-row select {
    background: var(--bg); color: var(--text); border: 1px solid var(--line);
    border-radius: 7px; padding: 7px 8px; font-size: .9rem; min-width: 0;
}
.var-row select:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }
.var-row.sup-add { grid-template-columns: 90px 1fr 120px 34px 34px; }
.rcv-total { margin-top: 8px; text-align: end; color: var(--muted); }
.rcv-total b { color: var(--gold); font-variant-numeric: tabular-nums; }

/* ================= Smart inventory =================
   Four independent panels, each a complete answer on its own — the page is read by
   glancing at one card, not by scrolling a report. */
.si-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 16px; }
.si-card {
    background: var(--panel2); border: 1px solid var(--line); border-radius: 14px;
    padding: 14px 16px; min-width: 0; overflow-x: auto;
}
.si-title {
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
    font-weight: 600; margin-bottom: 10px;
}
.si-sub { color: var(--gold); font-variant-numeric: tabular-nums; font-size: .9rem; }
.si-foot { margin-top: 10px; display: flex; justify-content: flex-end; }
.si-bar { background: var(--panel); border-radius: 6px; height: 8px; min-width: 70px; overflow: hidden; }
.si-bar > span { display: block; height: 100%; background: var(--gold); }
@media (max-width: 900px) {
    .si-grid { grid-template-columns: 1fr; }
}

/* R7 — the Z-report drawer: a printed document on screen, so label/value rows
   line up like a slip rather than a form. */
.z-drawer { width: min(520px, 96vw); }
.z-row { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: .92rem; }
.z-row > span { color: var(--muted); }
.z-row > b { font-variant-numeric: tabular-nums; }

/* I6 — the write-off countersignature card. Amber, not red: nothing has gone wrong,
   the operator is being asked for a second signature. */
.drawer-card.wo-approve {
    border-color: rgba(245, 158, 11, .55);
    background: linear-gradient(180deg, rgba(245,158,11,.10), transparent);
}
.drawer-card.wo-approve .dc-title { color: #f0a92b; }

/* ================= Prep / sub-recipes (I7) =================
   A prep sheet reads top-down: what it makes and how much, then the ingredient
   table, then what the batch costs. The totals sit next to the Save button
   because the cost per unit is the number the owner is actually deciding on. */
.prep-editor { display: flex; flex-direction: column; gap: 14px; }
.prep-head {
    display: flex; flex-wrap: wrap; gap: 18px; align-items: flex-end;
    background: var(--panel2); border: 1px solid var(--line); border-radius: 12px; padding: 14px 16px;
}
.prep-head label { display: flex; flex-direction: column; gap: 6px; min-width: 160px; }
.prep-head label > span { color: var(--muted); font-size: .82rem; }
.prep-head input, .prep-head select {
    background: var(--panel); color: var(--text); border: 1px solid var(--line);
    border-radius: 8px; padding: 8px 10px; min-height: 38px;
}
.prep-head input:focus, .prep-head select:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }
.prep-head .unit { color: var(--muted); font-size: .82rem; }
.prep-editor .grid input, .prep-editor .grid select {
    background: var(--panel); color: var(--text); border: 1px solid var(--line);
    border-radius: 8px; padding: 6px 8px; width: 100%; min-height: 34px;
}
.prep-editor .grid .num input { text-align: end; font-variant-numeric: tabular-nums; }
.prep-foot { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; justify-content: space-between; }
.prep-totals { display: flex; gap: 22px; }
.prep-totals b { color: var(--gold); font-variant-numeric: tabular-nums; margin-inline-start: 6px; }
.prep-save { display: flex; gap: 10px; }

/* ================= Recipes (INV-1b; redesigned WEB-36) =================
   Picker on the left, editor on the right. The editor leads with the COST — the
   number the recipe exists to produce — and only then asks for the ingredients. */
.rcp-split { display: grid; grid-template-columns: 340px 1fr; gap: 18px; align-items: start; }
.rcp-list { min-width: 0; }

/* Desktop shows both panes; the back button belongs to the phone only. */
.rcp-back {
    display: none;
    background: transparent; border: 0; padding: 0 0 10px; cursor: pointer;
    color: var(--muted); font-size: .86rem; font-weight: 600;
}
.rcp-back:hover { color: var(--gold); }
[dir="rtl"] .rcp-back { transform: scaleX(-1); }
[dir="rtl"] .rcp-back:hover { color: var(--gold); }

@media (max-width: 900px) {
    .rcp-split { grid-template-columns: 1fr; }
    /* MASTER-DETAIL, not stacked panes: one screen at a time, like every phone app.
       Stacked, a tap on row 4 of 300 scrolls nothing and the editor stays below the
       fold — the page looks broken even though it worked. */
    .rcp-split.has-sel .rcp-list { display: none; }
    .rcp-split:not(.has-sel) .rcp-editor { display: none; }
    .rcp-back { display: inline-flex; align-items: center; }
}
.rcp-search { margin-bottom: 10px; }
.rcp-search .search { flex: 1; min-width: 0; }

/* Filter chips — costing a menu is a hunt for the gaps, so "No recipe" is one tap. */
.rcp-chips { display: flex; gap: 6px; margin-bottom: 10px; flex-wrap: wrap; }
.rcp-chips .chip {
    padding: 6px 11px; border-radius: 999px; font-size: .82rem;
    background: var(--panel2); border: 1px solid var(--line); color: var(--muted);
    cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
}
.rcp-chips .chip:hover { border-color: var(--gold); color: var(--text); }
.rcp-chips .chip.active {
    background: rgba(212,175,55,.14); border-color: var(--gold);
    color: var(--gold-hi); font-weight: 700;
}
.rcp-chip-n { font-variant-numeric: tabular-nums; opacity: .75; font-size: .76rem; }

.rcp-products {
    display: flex; flex-direction: column; gap: 6px;
    max-height: calc(100vh - 300px); overflow-y: auto; padding-inline-end: 4px;
}
.rcp-prod {
    /* flex:none is LOAD-BEARING: the parent is a height-capped column flex, and flex
       items SHRINK by default — every card compressed and the SKU/category line
       rendered half-clipped under the name (the owner's screenshot). */
    flex: none;
    display: flex; flex-direction: column; gap: 5px; text-align: start;
    background: var(--panel); color: var(--text); border: 1px solid var(--line);
    border-radius: 10px; padding: 10px 12px; min-height: 0; cursor: pointer;
    transition: border-color .14s ease, background .14s ease;
}
.rcp-prod:hover { border-color: var(--gold); background: var(--panel2); }
.rcp-prod.active { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold) inset; }
.rcp-prod-top { display: flex; align-items: center; gap: 8px; }
.rcp-prod-name { font-weight: 600; flex: 1; min-width: 0; }

/* A dot, not a pill: 200 rows of "no recipe" badges is a wall of shouting. The
   colour carries it; the title says it for screen readers and hover. */
.rcp-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.rcp-dot.ok { background: var(--ok); }
.rcp-dot.warn { background: var(--warn, #e6a23c); }

.rcp-prod-meta {
    display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    font-size: .76rem; color: var(--muted);
}
.rcp-prod-cat, .rcp-prod-ing { white-space: nowrap; }
.rcp-prod-ing { margin-inline-start: auto; font-variant-numeric: tabular-nums; }

/* Loading: shaped like the thing that's coming, not a spinner over nothing. */
.rcp-skeleton { display: flex; flex-direction: column; gap: 6px; }
.rcp-skeleton div {
    height: 52px; border-radius: 10px; background: var(--panel);
    animation: dash-pulse 1.2s ease-in-out infinite alternate;
}

.rcp-editor { min-width: 0; }
.rcp-editor .drawer-card { margin-bottom: 14px; }
.rcp-meta-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 640px) { .rcp-meta-row { grid-template-columns: 1fr; } }

/* ---- the hero: the answer before the form ---- */
.rcp-hero {
    background: linear-gradient(180deg, rgba(212,175,55,.08), var(--panel) 60%);
    border: 1px solid var(--line); border-radius: 14px;
    padding: 15px 17px; margin-bottom: 14px;
}
.rcp-hero-id { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 13px; }
.rcp-hero-id h2 { margin: 0; font-size: 1.2rem; }
.rcp-hero-nums {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px;
    padding-top: 12px; border-top: 1px solid var(--line-soft);
}
.rcp-stat { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.rcp-stat-l {
    color: var(--muted); font-size: .68rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .07em; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
}
.rcp-stat-v { font-size: 1.25rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.rcp-stat-v.good { color: var(--ok); }
.rcp-stat-v.bad { color: var(--err); }
/* Food cost is the verdict — it gets the tint, so the eye lands there first. */
.rcp-stat-fc { border-radius: 9px; padding: 4px 9px; margin: -4px -4px -4px 0; }
.rcp-stat-fc.good { background: rgba(46,204,113,.12); }
.rcp-stat-fc.good .rcp-stat-v { color: var(--ok); }
.rcp-stat-fc.warn { background: rgba(243,156,18,.14); }
.rcp-stat-fc.warn .rcp-stat-v { color: var(--warn, #e6a23c); }
.rcp-stat-fc.bad { background: rgba(231,76,60,.14); }
.rcp-stat-fc.bad .rcp-stat-v { color: var(--err); }

@media (max-width: 640px) {
    .rcp-hero-nums { grid-template-columns: repeat(2, 1fr); gap: 12px; }
    .rcp-stat-v { font-size: 1.1rem; }
}

/* ---- left-list sizes badge ---- */
.rcp-prod-sizes {
    white-space: nowrap; font-variant-numeric: tabular-nums;
    color: var(--muted); font-weight: 700;
}

/* ---- size switcher: Base + each sellable size ---- */
.rcp-sizes {
    display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px;
}
.rcp-size {
    display: flex; flex-direction: column; gap: 4px; align-items: flex-start;
    min-width: 118px; padding: 8px 12px; cursor: pointer; text-align: start;
    border: 1px solid var(--line); border-radius: 12px; background: var(--panel);
    color: var(--text); transition: border-color .15s, background .15s, transform .05s;
}
.rcp-size:hover { border-color: var(--gold, #d4af37); }
.rcp-size:active { transform: translateY(1px); }
.rcp-size.active {
    border-color: var(--gold, #d4af37);
    background: linear-gradient(180deg, rgba(212,175,55,.14), var(--panel) 70%);
    box-shadow: 0 0 0 1px var(--gold, #d4af37) inset;
}
.rcp-size-name {
    display: flex; align-items: center; gap: 5px;
    font-weight: 800; font-size: .86rem; white-space: nowrap;
}
.rcp-size-def { color: var(--gold, #d4af37); font-size: .8rem; }
.rcp-size-sub {
    display: flex; align-items: center; gap: 7px;
    font-size: .76rem; color: var(--muted); font-variant-numeric: tabular-nums;
}
.rcp-size-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.rcp-size-dot.ok { background: var(--ok, #2ecc71); }
.rcp-size-dot.warn { background: var(--line-strong, #b9b9b9); }
/* A size that inherits reads quieter than one with its own recipe. */
.rcp-size.inherits { opacity: .82; }
.rcp-size.inherits.active { opacity: 1; }

/* ---- a size that follows the base recipe ---- */
.rcp-inherit {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    border: 1px dashed var(--line-strong, var(--line)); border-radius: 14px;
    background: var(--panel); padding: 16px 18px; margin-bottom: 14px;
}
.rcp-inherit-ico {
    font-size: 1.7rem; line-height: 1; color: var(--gold, #d4af37);
    flex: 0 0 auto;
}
.rcp-inherit-txt { display: flex; flex-direction: column; gap: 3px; min-width: 180px; flex: 1 1 240px; }
.rcp-inherit-txt strong { font-size: .95rem; }
.rcp-inherit-txt .muted { font-size: .82rem; }
.rcp-inherit-acts { display: flex; gap: 8px; flex-wrap: wrap; margin-inline-start: auto; }

.rcp-hint, .rcp-note {
    font-size: .8rem; margin: 8px 0 0; line-height: 1.45;
}
.rcp-hint {
    background: rgba(243,156,18,.10); border: 1px solid rgba(243,156,18,.35);
    color: var(--text); border-radius: 9px; padding: 9px 12px; margin-bottom: 14px;
}
.warn-note { color: var(--warn, #e6a23c); }

/* ---- ingredient rows: item · qty · unit · waste% · cost · opt · ✕ ---- */
.rcp-ing-head, .rcp-ing {
    display: grid;
    grid-template-columns: 1fr 74px 72px 72px 84px 34px 32px;
    gap: 8px; align-items: center;
}
.rcp-ing-head {
    color: var(--muted); font-size: .66rem; text-transform: uppercase;
    letter-spacing: .07em; font-weight: 700; padding: 0 0 6px;
}
.rcp-ing-head .num { text-align: end; }
.rcp-ing { padding: 4px 0; }
.rcp-ing input, .rcp-ing select {
    width: 100%; background: var(--bg); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px;
    padding: 8px 10px; font-size: .9rem; font-family: inherit; min-height: 38px;
}
.rcp-ing input:focus, .rcp-ing select:focus {
    outline: none; border-color: var(--gold); box-shadow: var(--focus);
}
.rcp-ing input.num { text-align: end; }
.rcp-ing-cost {
    text-align: end; font-weight: 700; font-variant-numeric: tabular-nums;
    font-size: .92rem; white-space: nowrap;
}
.rcp-ing-opt { text-align: center; }
.rcp-ing input[type="checkbox"] {
    width: 17px; height: 17px; min-height: 0; accent-color: var(--gold); padding: 0;
}
/* Optional = not deducted, not costed. It should LOOK subtracted. */
.rcp-ing.is-opt .rcp-ing-item, .rcp-ing.is-opt .rcp-ing-qty,
.rcp-ing.is-opt .rcp-ing-unit, .rcp-ing.is-opt .rcp-ing-waste { opacity: .55; }

.rcp-actions { margin-top: 4px; }

@media (max-width: 760px) {
    /* Seven columns at 375px gives each field ~40px. Stack into a labelled card
       instead — same data-l trick the report tables use, hand-written here because
       these are inputs, not cells. */
    .rcp-ing-head { display: none; }
    .rcp-ing {
        grid-template-columns: 1fr 1fr;
        gap: 8px 10px; padding: 11px 12px; margin-bottom: 8px;
        border: 1px solid var(--line); border-radius: 11px; background: var(--panel);
        position: relative;
    }
    .rcp-ing > span { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
    .rcp-ing > span[data-l]::before {
        content: attr(data-l);
        color: var(--muted); font-size: .64rem; font-weight: 700;
        text-transform: uppercase; letter-spacing: .06em;
    }
    .rcp-ing-item { grid-column: 1 / -1; padding-inline-end: 34px; }
    .rcp-ing-cost {
        text-align: start; align-self: end;
        justify-content: flex-end; font-size: 1rem;
    }
    /* The checkbox keeps its label beside it, not above — a lone tick in a stacked
       card is a mystery box. */
    .rcp-ing-opt { flex-direction: row-reverse !important; justify-content: flex-end; align-items: center; gap: 7px; }
    /* ✕ pins to the card's corner rather than eating a grid cell. */
    .rcp-ing-x { position: absolute; top: 8px; inset-inline-end: 8px; }
}

/* Empty state: says what the screen is FOR, not just "nothing selected". */
.rcp-blank {
    display: flex; flex-direction: column; align-items: center; text-align: center;
    gap: 6px; padding: 54px 24px;
    border: 1px dashed var(--line); border-radius: 14px; background: var(--panel);
}
.rcp-blank-ico { font-size: 2.4rem; line-height: 1; margin-bottom: 4px; opacity: .85; }
.rcp-blank h3 { margin: 0; font-size: 1.02rem; }
.rcp-blank p { margin: 0; max-width: 46ch; font-size: .86rem; line-height: 1.5; }

/* Purchases (INV-2) */
tr.po-row { cursor: pointer; }
tr.po-row:hover td { background: var(--panel2); }

/* Transfer drawer rows: item · qty · ✕ */
.var-row.trf-row { grid-template-columns: 1fr 90px 30px; }

/* ================= WEB-33: branch identity + switcher in the chrome =========
   "Which branch am I looking at?" must never be a guess — every number on the
   portal is branch-scoped. One branch → a calm label; several → the same chip
   IS the picker (no extra button competing with it). */
.branch-pick {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 5px 10px; border-radius: 9px;
    background: var(--panel2); border: 1px solid var(--line);
    max-width: 40vw;
    /* MOB-5 — the <select> is the only hit target inside this chip, and it's narrow:
       a thumb landing on the 🏬 or the chip's padding hit NOTHING, which is why the
       picker "needed two taps" (the first one missed). Make the whole chip the
       target by stretching the select across it — the icon sits behind, the select
       is invisible chrome on top. */
    position: relative;
}
.branch-pick.switchable .branch-sel {
    position: absolute; inset: 0; width: 100%; max-width: none;
    opacity: 0; cursor: pointer; z-index: 1;
}
/* The transparent select can't show anything, so .branch-name (always rendered now)
   is what the operator actually reads; the caret marks the chip as a control. */
.branch-pick.switchable .branch-caret { font-size: .62rem; opacity: .7; flex: none; }
.branch-ico { font-size: .95rem; line-height: 1; flex: none; }
.branch-name {
    font-weight: 700; font-size: .86rem; color: var(--text);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.branch-sel {
    background: transparent; border: 0; color: var(--text);
    font-weight: 700; font-size: .86rem; font-family: inherit;
    padding: 0 2px; cursor: pointer; max-width: 30vw;
}
.branch-sel:focus { outline: none; }
.branch-sel:disabled { opacity: .55; cursor: wait; }
.branch-sel option { background: var(--panel); color: var(--text); }

@media (max-width: 560px) {
    /* The phone keeps the branch — it's identity, not decoration — but yields
       the room the full name would eat. */
    .branch-pick { padding: 4px 7px; max-width: 46vw; }
    .branch-name, .branch-sel { font-size: .78rem; max-width: 36vw; }
}

/* ================= WEB-33: every report table fits a phone =================
   A report table is 6–9 columns; on a phone that's a horizontal-scroll puzzle
   where the reader loses the row identity two swipes in. So on ≤760px every
   `.grid.stack` row becomes a CARD: first cell is the title, the rest are
   label/value lines fed by data-l (stamped from the table's own <th> by
   corexLabelTables — see _Host.cshtml). Desktop keeps the real table.
   The 2-column P&L statement opts out (.pnl) — it already fits. */
@media (max-width: 760px) {
    .grid.stack {
        display: block !important; width: 100%;
        white-space: normal !important; overflow: visible !important;
        border-collapse: separate; border-spacing: 0;
    }
    .grid.stack thead { display: none; }
    .grid.stack tbody { display: block; }

    .grid.stack tr {
        display: block; padding: 11px 13px;
        border: 1px solid var(--line); border-radius: 12px;
        background: var(--panel); margin-bottom: 8px;
    }
    .grid.stack tr:last-child { margin-bottom: 0; }
    .grid.stack tr:hover td { background: transparent; }

    .grid.stack td {
        display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
        padding: 4px 0 !important; border: 0 !important;
        white-space: normal; text-align: start !important;
        font-variant-numeric: tabular-nums;
    }
    .grid.stack td::before {
        content: attr(data-l);
        flex: none; color: var(--muted);
        font-size: .68rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
    }
    /* Unlabelled cells (actions column, spacers) keep no prefix and stay inline. */
    .grid.stack td:not([data-l])::before { content: none; }
    .grid.stack td:not([data-l]):empty { display: none; }

    /* First cell = the card's title: no label, bigger, its own hairline. */
    .grid.stack td:first-child {
        justify-content: flex-start; font-weight: 700; font-size: 1rem;
        padding: 0 0 8px !important; margin-bottom: 6px;
        border-bottom: 1px solid var(--line-soft) !important;
    }
    .grid.stack td:first-child::before { content: none; }

    /* The value side wins the space; long product names wrap instead of truncating. */
    .grid.stack td > * { min-width: 0; }
    .grid.stack .bar-track { display: none; }   /* share bars are noise at this width */

    .pager { flex-wrap: wrap; }
}

/* ================= WEB-32: responsive report bodies ================= */
/* One dataset, two presentations — CSS picks, both stay in sync by construction.
   These are UTILITIES, so they carry !important on purpose: a component's own
   `display` (e.g. .dlv-cards{display:flex}) is single-class too and, sitting later
   in the file, silently WON — which showed the phone cards on desktop. A utility
   that any component can out-cascade isn't a utility. */
.only-narrow { display: none !important; }
@media (max-width: 760px) {
    .only-wide { display: none !important; }
    .only-narrow { display: block !important; }
    .dlv-cards.only-narrow { display: flex !important; }
}

/* Delivery on a phone: a card per company — the 8-column table it replaces was a
   horizontal-scroll puzzle. Net is the hero (that's what the owner keeps). */
.dlv-cards { flex-direction: column; gap: 10px; }   /* display owned by .only-narrow */
.dlv-card {
    background: var(--panel); border: 1px solid var(--line); border-radius: 13px;
    padding: 13px 14px;
}
.dlv-top { display: flex; align-items: center; gap: 9px; }
.dlv-ico { font-size: 1.15rem; line-height: 1; }
.dlv-name { font-weight: 700; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dlv-share { color: var(--muted); font-size: .8rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.dlv-bar {
    height: 5px; border-radius: 999px; background: var(--panel2);
    overflow: hidden; margin: 9px 0 11px;
}
.dlv-bar span { display: block; height: 100%; border-radius: 999px; }
.dlv-net {
    display: flex; align-items: baseline; justify-content: space-between;
    padding-bottom: 9px; border-bottom: 1px solid var(--line-soft);
}
.dlv-net-l { color: var(--muted); font-size: .74rem; text-transform: uppercase; letter-spacing: .1em; font-weight: 700; }
.dlv-net b { font-size: 1.2rem; color: var(--gold); font-variant-numeric: tabular-nums; }
.dlv-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 9px 12px; padding-top: 10px;
}
.dlv-grid span {
    display: flex; flex-direction: column; gap: 2px;
    font-weight: 600; font-variant-numeric: tabular-nums; font-size: .9rem;
}
.dlv-grid span i {
    font-style: normal; color: var(--muted); font-size: .68rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .07em;
}
.dlv-grid span.neg { color: var(--err); }

/* KPI value that holds a NAME rather than a number (e.g. "Top seller"). */
.kpi-value.sm {
    font-size: 1.05rem; line-height: 1.3; overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap;
}

/* ================= WEB-30: reports index (cards by category) ================= */
/* WEB-44 — the way back to the index must be unmissable: a gold-bordered pill,
   not a muted text link (owners kept hunting for how to reach the other reports).
   `button.rpt-back` (not bare `.rpt-back`): the button lives inside .page-head, whose
   `.page-head button` rule ties it on specificity — the element+class selector wins. */
button.rpt-back {
    display: inline-flex; align-items: center; gap: 7px; margin: 0 0 10px;
    min-height: 40px; padding: 8px 18px; cursor: pointer;
    border: 1.5px solid var(--gold); border-radius: 999px;
    background: rgba(212,175,55,.10);
    color: var(--gold-hi, var(--gold)); font-size: .9rem; font-weight: 700;
    transition: background .14s ease, transform .08s ease, box-shadow .14s ease;
    box-shadow: 0 2px 10px rgba(212,175,55,.12);
}
button.rpt-back:hover { background: rgba(212,175,55,.2); color: var(--gold-hi, var(--gold));
    border-color: var(--gold); box-shadow: 0 4px 16px rgba(212,175,55,.22); }
button.rpt-back:active { transform: scale(.97); }
:root[data-theme="light"] button.rpt-back { color: #8a6410; background: rgba(212,175,55,.14); }

.rpt-cat { margin-bottom: 22px; }
.rpt-cat-title {
    margin: 0 0 8px; font-size: .74rem; font-weight: 800;
    text-transform: uppercase; letter-spacing: .1em; color: var(--muted);
}

/* One card per CATEGORY, reports as numbered lines inside it — a printed
   index, not a wall of tiles. Hairlines separate; the whole row is the target. */
.rpt-list {
    background: var(--panel); border: 1px solid var(--line);
    border-radius: 13px; overflow: hidden;
}
.rpt-row {
    display: flex; align-items: center; gap: 12px; width: 100%;
    padding: 13px 16px; text-align: start; cursor: pointer;
    background: transparent; color: var(--text);
    border: 0; border-bottom: 1px solid var(--line-soft, var(--line));
    transition: background .14s ease, padding-inline-start .14s ease;
    -webkit-tap-highlight-color: transparent;
}
.rpt-row:last-child { border-bottom: 0; }
.rpt-row:hover { background: var(--panel2); padding-inline-start: 20px; }
.rpt-row:active { background: var(--panel2); }

/* Tabular so 1 and 15 occupy the same width — the column stays a column. */
.rpt-no {
    min-width: 20px; flex: none; text-align: end;
    font-size: .8rem; font-weight: 800; color: var(--muted);
    font-variant-numeric: tabular-nums;
}
.rpt-row:hover .rpt-no { color: var(--gold); }

.rpt-ico { font-size: 1.25rem; line-height: 1; flex: none; width: 24px; text-align: center; }
.rpt-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.rpt-name { font-weight: 700; font-size: .94rem; }
.rpt-blurb {
    color: var(--muted); font-size: .78rem; line-height: 1.35;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rpt-go { color: var(--line); font-size: 1.25rem; flex: none; transition: color .14s ease; }
.rpt-row:hover .rpt-go { color: var(--gold); }
[dir="rtl"] .rpt-go { transform: rotate(180deg); }

/* Phones: the blurb wraps instead of truncating — there's room below, not beside. */
@media (max-width: 560px) {
    .rpt-blurb { white-space: normal; }
    .rpt-row:hover { padding-inline-start: 16px; }
}

.kpi-card.accent-err .kpi-value { color: var(--err); }
.grid td.num.neg, .grid .num.neg { color: var(--err); }

/* ================= WEB-28: mobile app shell — bottom tab bar ================= */
.tabbar { display: none; }
.nav-signout { display: none; }

@media (max-width: 760px) {
    /* The top bar must NEVER scroll or clip sideways: account + Sign out hand
       over to the tab bar's Settings tab and the drawer's sign-out row, the
       branch chip yields (ellipsis) before the toggles do, and what remains
       (burger · branch · bell · theme · lang) fits a 360px phone. */
    header.top { flex-wrap: nowrap; min-width: 0; }
    header.top .user-link, header.top button.logout { display: none; }
    header.top .who { gap: 6px; flex: none; }
    .branch-pick { flex: 0 1 auto; min-width: 0; }
    header.top button.lang { padding: 6px 9px; }

    /* Drawer sign-out — the escape hatch for what the top bar dropped. */
    .nav-signout {
        display: block; margin-top: 14px; padding: 12px 14px; border-radius: 10px;
        background: transparent; border: 1px dashed var(--line); color: var(--muted);
        font-weight: 700; text-align: start; cursor: pointer; width: 100%;
    }
    .nav-signout:hover { color: var(--err); border-color: var(--err); }

    .tabbar {
        position: fixed; bottom: 0; inset-inline: 0; z-index: 58;
        /* 5th column = WEB-31 "More" (opens the grouped drawer). */
        display: grid; grid-template-columns: repeat(5, 1fr); gap: 2px;
        padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
        background: color-mix(in srgb, var(--panel) 88%, transparent);
        -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
        border-top: 1px solid var(--line);
    }
    /* Content never hides behind the bar. */
    .content { padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }
}

.tabbar .tab {
    position: relative;
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    padding: 6px 2px 4px; border-radius: 12px;
    background: transparent; border: 0; cursor: pointer;   /* "More" is a <button> */
    color: var(--muted); text-decoration: none;
    font-size: .66rem; font-weight: 600; letter-spacing: .02em;
    -webkit-tap-highlight-color: transparent;
    transition: color .15s ease, background .15s ease, transform .1s ease;
}
.tabbar .tab svg { width: 23px; height: 23px; }
.tabbar .tab:active { transform: scale(.94); }
.tabbar .tab.active { color: var(--gold); background: rgba(212,175,55,.10); }
.tabbar .tab.active svg { filter: drop-shadow(0 2px 8px rgba(212,175,55,.35)); }

.tab-badge {
    position: absolute; top: 2px; inset-inline-end: calc(50% - 22px);
    min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    background: var(--gold); color: #141414;
    font-size: .6rem; font-weight: 800; line-height: 1;
}
.tab-badge.alert { background: var(--err); color: #fff; }

/* Notifications page (full-page bell feed) */
.notif-list {
    background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
    padding: 6px 16px; max-width: 720px;
}
.notif-list .bp-item { padding: 11px 0; }
.notif-guard { max-width: 720px; margin-bottom: 16px; }

/* ================= WEB-38: A4 stock-transfer note =================
   Hidden on screen — it exists only for the printer. The print block isolates it
   with the same visibility trick as the QR table tent, and styles it like the paper
   document it is: black on white, hairline-boxed lines table, three signature
   blocks. A transfer note is the thing the DRIVER carries — it must survive a
   glovebox, not match the console theme. */
.trf-print { display: none; }

@media print {
    /* The one authoritative page box (last @page in the file wins). 12mm rather than
       14mm: it buys ~30px of paper, which is the difference between a statement ending
       on its page and stranding its signature block on a second, near-empty one. */
    @page { size: A4; margin: 12mm; }

    /* :has-scoped ON PURPOSE: a bare `body{visibility:hidden}` would blank a plain
       Ctrl+P on any page carrying this stylesheet even when no note is selected. */
    body:has(.trf-print) { visibility: hidden; background: #fff; }
    .trf-print, .trf-print * { visibility: visible; }
    .trf-print {
        display: block; position: static; width: 100%;
        background: #fff; color: #111; font-size: 12pt;
    }

    .trf-print .tp-head {
        display: flex; justify-content: space-between; align-items: flex-start;
        border-bottom: 2px solid #111; padding-bottom: 10px; margin-bottom: 16px;
    }
    .trf-print h1 { margin: 0 0 4px; font-size: 17pt; letter-spacing: .02em; }
    .trf-print .tp-no { font-size: 11pt; }
    .trf-print .tp-meta { text-align: end; font-size: 10.5pt; line-height: 1.7; }

    .trf-print .tp-route {
        display: flex; align-items: stretch; gap: 12px; margin-bottom: 18px;
    }
    .trf-print .tp-branch {
        flex: 1; border: 1px solid #111; border-radius: 4px; padding: 9px 13px;
        display: flex; flex-direction: column; gap: 3px;
    }
    .trf-print .tp-branch span {
        font-size: 8.5pt; text-transform: uppercase; letter-spacing: .08em; color: #444;
    }
    .trf-print .tp-branch b { font-size: 13pt; }
    .trf-print .tp-arrow { align-self: center; font-size: 16pt; }

    .trf-print .tp-lines { width: 100%; border-collapse: collapse; margin-bottom: 14px; }
    .trf-print .tp-lines th, .trf-print .tp-lines td {
        border: 1px solid #111; padding: 6px 9px; text-align: start; font-size: 10.5pt;
    }
    .trf-print .tp-lines th {
        background: #eee; font-size: 8.5pt; text-transform: uppercase; letter-spacing: .06em;
    }
    .trf-print .tp-lines td:nth-child(n+3), .trf-print .tp-lines th:nth-child(n+3) { text-align: end; }
    .trf-print .tp-lines td:first-child { width: 8mm; text-align: center; }
    .trf-print .tp-lines tfoot td { font-weight: 700; background: #f5f5f5; }

    .trf-print .tp-notes { margin: 0 0 18px; font-size: 10.5pt; }

    /* Signatures pin to the sheet's rhythm: three equal boxes, a real line to sign on. */
    .trf-print .tp-signs { display: flex; gap: 14px; margin-top: 26px; }
    .trf-print .tp-sign {
        flex: 1; display: flex; flex-direction: column; gap: 26px; text-align: center;
    }
    .trf-print .tp-sign span { font-weight: 700; font-size: 10.5pt; }
    .trf-print .tp-sign i { display: block; border-bottom: 1px solid #111; }
    .trf-print .tp-sign small { font-size: 8pt; color: #555; margin-top: -22px; padding-top: 24px; }
}

/* ---- Foldable panel head (WEB-40): a whole panel-head that's a button ----
   Inherits .panel-head's layout; resets only what `button` imposes so a fold and a
   plain head look identical apart from the caret. */
.fold-head {
    width: 100%; background: transparent; border: 0; border-radius: 0;
    padding: 0; min-height: 0; cursor: pointer; text-align: start;
    color: inherit; font: inherit;
}
.fold-head:hover:not(:disabled) { border-color: transparent; }
.fold-head:hover h2 { color: var(--gold); }
.fold-caret {
    color: var(--muted); font-size: 1rem; line-height: 1;
    transform: rotate(-90deg); transition: transform .16s ease, color .16s ease;
}
.fold-caret.open { transform: rotate(0deg); color: var(--gold); }
.fold-head:hover .fold-caret { color: var(--gold); }

/* ---- WEB-40: menu-insights category rail ---- */
.mi-cats { margin: 4px 0 12px; }
.mi-cats .chip { display: inline-flex; align-items: center; gap: 6px; }

/* ---- INV-4b: searchable supplier combo (Purchases create drawer) ---- */
.sup-combo { position: relative; }
.sup-combo input {
    width: 100%; background: var(--bg); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px;
    padding: 9px 11px; font-size: 1rem; font-family: inherit;
}
.sup-combo input:focus { outline: none; border-color: var(--gold); box-shadow: var(--focus); }
.sup-combo-list {
    position: absolute; top: calc(100% + 4px); inset-inline: 0; z-index: 30;
    background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
    overflow: hidden; box-shadow: 0 14px 40px rgba(0,0,0,.45);
    max-height: 280px; overflow-y: auto;
}
.sup-combo-row {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    width: 100%; padding: 10px 13px; text-align: start;
    background: transparent; border: 0; border-bottom: 1px solid var(--line-soft);
    border-radius: 0; min-height: 0; color: var(--text); font-size: .92rem; cursor: pointer;
}
.sup-combo-row:last-child { border-bottom: 0; }
.sup-combo-row:hover { background: var(--panel2); border-color: var(--line-soft); }
.sup-combo-name { font-weight: 600; }
.sup-combo-add { color: var(--gold-hi, var(--gold)); font-weight: 600; }

.sup-picked {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    background: rgba(212,175,55,.10); border: 1px solid var(--gold); border-radius: 8px;
    padding: 9px 12px;
}
.sup-add-card {
    margin-top: 10px; background: var(--panel2); border: 1px solid var(--line);
    border-radius: 10px; padding: 12px 14px;
}

/* ---- Recipes: read-only unit chip (mirrors the item) ---- */
.rcp-ing-unit-ro {
    display: flex; align-items: center; justify-content: center;
    min-height: 38px; padding: 0 6px;
    color: var(--muted); font-size: .88rem; font-weight: 600;
    background: var(--panel2); border: 1px dashed var(--line); border-radius: 8px;
}

/* ================= WEB-41: shared A4 account statement =================
   One print skeleton for the supplier AND customer statements (كشف حساب). Hidden on
   screen; the print block isolates it — `:has(.a4-doc)`-scoped so a plain Ctrl+P on a
   page that merely carries this stylesheet doesn't print blank. Black on white, the way
   an account statement is read and filed. Each page fills the same header/summary/table/
   footer slots with its own data. */
.a4-doc { display: none; }

@media print {
    body:has(.a4-doc) { visibility: hidden; background: #fff; }
    .a4-doc, .a4-doc * { visibility: visible; }
    .a4-doc {
        display: block; position: static; width: 100%;
        background: #fff; color: #111; font-size: 12.5pt;
    }

    /* A long statement crosses pages: repeat the column heads on each sheet and never
       split a row down the middle — the page break lands between orders, not inside one. */
    .a4-doc .ad-lines thead { display: table-header-group; }
    .a4-doc .ad-lines tfoot { display: table-footer-group; }
    .a4-doc .ad-lines tr { break-inside: avoid; page-break-inside: avoid; }
    .a4-doc .ad-head, .a4-doc .ad-party, .a4-doc .ad-sum { break-inside: avoid; }
    .a4-doc .ad-foot { break-inside: avoid; }

    .a4-doc .ad-head {
        display: flex; justify-content: space-between; align-items: flex-start;
        border-bottom: 2px solid #111; padding-bottom: 10px; margin-bottom: 8px;
    }
    .a4-doc .ad-title { margin: 0 0 2px; font-size: 19pt; letter-spacing: .02em; }
    .a4-doc .ad-sub { font-size: 11pt; color: #333; }
    .a4-doc .ad-meta { text-align: end; font-size: 11pt; line-height: 1.6; }

    /* Party block: who this statement is FOR. */
    .a4-doc .ad-party {
        border: 1px solid #111; border-radius: 4px; padding: 9px 13px; margin-bottom: 14px;
    }
    .a4-doc .ad-party b { font-size: 14pt; }
    .a4-doc .ad-party span { color: #333; font-size: 11pt; }

    /* Summary figures — a labeled row, the headline numbers before the ledger. */
    .a4-doc .ad-sum {
        display: flex; gap: 0; margin-bottom: 16px;
        border: 1px solid #111; border-radius: 4px; overflow: hidden;
    }
    .a4-doc .ad-sum > div {
        flex: 1; padding: 8px 12px; border-inline-end: 1px solid #ccc;
    }
    .a4-doc .ad-sum > div:last-child { border-inline-end: 0; }
    .a4-doc .ad-sum span {
        display: block; font-size: 9pt; text-transform: uppercase;
        letter-spacing: .06em; color: #444;
    }
    .a4-doc .ad-sum b { font-size: 14pt; }
    .a4-doc .ad-sum .neg b { color: #b00; }

    .a4-doc table.ad-lines { width: 100%; border-collapse: collapse; margin-bottom: 12px; }
    .a4-doc .ad-lines th, .a4-doc .ad-lines td {
        border: 1px solid #111; padding: 5px 8px; text-align: start; font-size: 11pt;
    }
    .a4-doc .ad-lines th {
        background: #eee; font-size: 9pt; text-transform: uppercase; letter-spacing: .05em;
    }
    .a4-doc .ad-lines td.n, .a4-doc .ad-lines th.n { text-align: end; font-variant-numeric: tabular-nums; }
    .a4-doc .ad-lines tfoot td { font-weight: 700; background: #f5f5f5; }
    /* Overdue rows earn a quiet flag — nothing screams in print. */
    .a4-doc .ad-lines tr.od td:first-child::after { content: " ⚑"; color: #b00; }

    /* The closing block is the lightest thing on the sheet on purpose: a tall footer is
       what pushes a one-page statement onto a second, otherwise-empty page. */
    .a4-doc .ad-foot {
        display: flex; justify-content: space-between; align-items: flex-end;
        margin-top: 14px; padding-top: 8px; border-top: 1px solid #111;
    }
    .a4-doc .ad-closing { font-size: 14pt; font-weight: 700; }
    .a4-doc .ad-sign { text-align: center; min-width: 55mm; }
    .a4-doc .ad-sign i { display: block; border-bottom: 1px solid #111; margin-bottom: 4px; height: 26px; }
    .a4-doc .ad-sign small { font-size: 9pt; color: #444; }
    .a4-doc .ad-note { margin-top: 10px; font-size: 10pt; color: #444; }
    /* No trailing whitespace after the last block — it is enough to start a new page. */
    .a4-doc > *:last-child { margin-bottom: 0; }

    /* FIN-3 — P&L income statement: section / subtotal / bottom-line rows. */
    .a4-doc .pnl-a4 tr.a4-sec td { background: #eee; font-weight: 700; text-transform: uppercase;
        font-size: 8.5pt; letter-spacing: .04em; }
    .a4-doc .pnl-a4 tr.a4-tot td { font-weight: 700; border-top: 1.5px solid #111; }
    .a4-doc .pnl-a4 tr.a4-net td { font-weight: 800; font-size: 11.5pt; background: #f0f0f0;
        border-top: 2px solid #111; border-bottom: 2px double #111; }
}

/* ================= DLV-STMT2: full-screen platform statement =================
   A financial document gets the whole viewport, not a drawer: fixed overlay above
   the shell, its own scroll, the reconciliation KPIs re-using .inv-kpis. */
.dstmt-overlay {
    position: fixed; inset: 0; z-index: 60; overflow-y: auto;
    background: var(--bg); padding: 22px clamp(16px, 4vw, 48px) 48px;
}
.dstmt-head {
    display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
    margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--line);
}
.dstmt-title { display: flex; flex-direction: column; gap: 2px; }
.dstmt-title h1 { margin: 0; font-size: 1.35rem; }
.dstmt-actions { margin-inline-start: auto; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dstmt-custom {
    display: flex; align-items: end; gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
    background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 10px 14px;
}
.dstmt-custom label { display: flex; flex-direction: column; gap: 4px; font-size: .82rem; color: var(--muted); }

/* Customer statement: history heading with an inline print button. */
.st-history-head { display: flex; align-items: center; gap: 10px; }
.st-history-head h2 { margin: 0; }
.st-history-head .hist-split { margin-inline-start: auto; color: var(--muted); font-size: .8rem; white-space: nowrap; }
.cust-tier { margin-inline-start: auto; margin-inline-end: 10px; white-space: nowrap; align-self: center; }
/* History rows: order number with its channel as a sub-caption; live rows tinted. */
.cust-hist .ch-type { display: block; color: var(--muted); font-size: .74rem; margin-top: 1px; }
.cust-hist .ch-date { white-space: nowrap; }
.cust-hist tr.row-open td { background: color-mix(in srgb, var(--warn) 4%, transparent); }
.ad-note { color: #555; font-size: .78rem; margin: -6px 0 10px; font-style: italic; }

/* PO create: pay-now quick chip + advance-payment hint */
.pay-quick-row { margin: 2px 0 8px; }
.pay-quick-row .chip { font-variant-numeric: tabular-nums; }
.pay-hint { font-size: .8rem; margin: 4px 0 0; }

/* ---- INV-4: supplier account drawer ---- */
.sup-acc-actions { margin-bottom: 14px; }

/* Hero — balance due is THE number; overdue rides as a red side block. */
.sup-hero {
    display: flex; align-items: stretch; gap: 14px; margin: 4px 0 10px;
    padding: 16px 18px; border-radius: 14px;
    border: 1px solid rgba(212,175,55,.4);
    background: linear-gradient(135deg, color-mix(in srgb, var(--gold) 10%, transparent), transparent 65%);
}
.sup-hero.late { border-color: rgba(231,76,60,.45); }
.sup-hero.settled { border-color: rgba(46,204,113,.4);
    background: linear-gradient(135deg, color-mix(in srgb, #2ECC71 8%, transparent), transparent 65%); }
.sh-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sh-label { color: var(--muted); font-size: .74rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .09em; }
.sh-value { font-size: 2rem; font-weight: 800; line-height: 1.15;
    color: var(--gold); font-variant-numeric: tabular-nums; }
.sup-hero.settled .sh-value { color: var(--ok); }
.sh-due { color: var(--muted); font-size: .82rem; margin-top: 4px; }
.sh-due b { color: var(--text); }
.sh-due.ok { color: var(--ok); }
.sh-overdue {
    margin-inline-start: auto; align-self: center; text-align: center;
    padding: 10px 16px; border-radius: 12px;
    border: 1px solid rgba(231,76,60,.5);
    background: color-mix(in srgb, var(--err) 10%, transparent);
    display: flex; flex-direction: column; gap: 1px;
}
.sh-od-n { color: var(--err); font-weight: 800; font-size: 1.15rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sh-od-l { color: var(--err); font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; }

/* Lifetime stats — one quiet row under the hero. */
.sup-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 0 0 14px; }
.sup-stats .ss {
    display: flex; flex-direction: column; gap: 1px; align-items: center;
    padding: 8px 10px; border-radius: 10px; border: 1px solid var(--line);
}
.sup-stats .ss-n { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.sup-stats .ss-l { color: var(--muted); font-size: .68rem; text-transform: uppercase; letter-spacing: .07em; }

/* Statement list — 2-line entry cards; NOTHING wraps mid-value. */
.led-head { display: flex; align-items: baseline; justify-content: space-between;
    margin: 4px 0 8px; font-weight: 700; }
.led-head .lh-count { color: var(--muted); font-size: .8rem; font-weight: 500; }
.led-list { display: flex; flex-direction: column; gap: 7px; }
.led-row {
    display: flex; flex-direction: column; gap: 4px;
    padding: 9px 12px; border-radius: 11px;
    border: 1px solid var(--line); border-inline-start-width: 4px;
}
.led-row.inv { border-inline-start-color: var(--gold); }
.led-row.inv.late { border-inline-start-color: var(--err);
    background: color-mix(in srgb, var(--err) 4%, transparent); }
.led-row.inv.ok { border-inline-start-color: var(--ok); opacity: .85; }
.led-row.pay { border-inline-start-color: var(--ok);
    background: color-mix(in srgb, #2ECC71 4%, transparent); }
.lr-1 { display: flex; align-items: center; gap: 8px; min-width: 0; }
.lr-1 code { font-size: .84rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lr-amt { margin-inline-start: auto; font-size: .98rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.lr-amt.credit { color: var(--ok); }
.lr-pm { font-weight: 600; white-space: nowrap; }
.lr-ref { color: var(--muted); font-size: .8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lr-2 { display: flex; align-items: baseline; gap: 4px 12px; flex-wrap: wrap;
    color: var(--muted); font-size: .78rem; }
.lr-date { white-space: nowrap; }
.lr-left { color: var(--warn); font-weight: 600; white-space: nowrap; }
.lr-bal { margin-inline-start: auto; white-space: nowrap; }
.lr-bal b { color: var(--text); font-variant-numeric: tabular-nums; }

/* Ledger / history server-side pager — compact first/prev/page/next/last. */
.led-pager { display: flex; align-items: center; justify-content: center; gap: 6px; margin: 12px 0 2px; }
.led-pager button {
    min-width: 34px; height: 34px; border-radius: 8px; cursor: pointer;
    background: var(--panel2); color: var(--text); border: 1px solid var(--line); font-weight: 700;
}
.led-pager button:hover:not(:disabled) { border-color: var(--gold); color: var(--gold); }
.led-pager button:disabled { opacity: .4; cursor: default; }
.led-pager span { color: var(--muted); font-size: .84rem; font-variant-numeric: tabular-nums; padding: 0 6px; }

/* INV-6 — supplier payment-due alert card */
.dues-alert {
    border: 1px solid rgba(243,156,18,.4); border-radius: 14px;
    background: color-mix(in srgb, var(--warn) 7%, transparent);
    padding: 14px 16px; margin: 0 0 16px;
}
.dues-alert.late { border-color: rgba(231,76,60,.45);
    background: color-mix(in srgb, var(--err) 6%, transparent); }
.da-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.da-title { font-weight: 800; font-size: 1.02rem; }
.da-pill { font-size: .78rem; font-weight: 700; border-radius: 999px; padding: 3px 10px; white-space: nowrap;
    font-variant-numeric: tabular-nums; }
.da-pill.err { background: color-mix(in srgb, var(--err) 16%, transparent); color: #ff8a7a; }
.da-pill.warn { background: color-mix(in srgb, var(--warn) 18%, transparent); color: var(--warn); }
.da-list { display: flex; flex-direction: column; gap: 4px; }
.da-row { display: flex; align-items: center; gap: 12px; width: 100%; text-align: start;
    background: transparent; border: 0; border-top: 1px dashed var(--line); padding: 8px 4px; cursor: pointer; }
.da-row:first-child { border-top: 0; }
.da-row:hover { background: color-mix(in srgb, var(--gold) 5%, transparent); border-radius: 8px; }
.da-name { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.da-amt { font-variant-numeric: tabular-nums; font-weight: 700; }
.da-amt.err { color: #ff8a7a; }
.da-amt.warn { color: var(--warn); }
.da-when { font-size: .82rem; color: var(--muted); white-space: nowrap; min-width: 96px; text-align: end; }
.da-when.err { color: #ff8a7a; font-weight: 600; }

@media (max-width: 480px) {
    .sup-hero { flex-direction: column; gap: 10px; }
    .sh-overdue { margin-inline-start: 0; align-self: stretch; }
    .sh-value { font-size: 1.7rem; }
}

/* Transfer history list (inside the drawer) */
.trf-hist-row {
    display: flex; align-items: baseline; gap: 8px; padding: 7px 2px;
    border-bottom: 1px solid var(--line); font-size: .88rem;
}
.trf-hist-row:last-child { border-bottom: 0; }
.trf-hist-dir { font-weight: 700; }
.trf-hist-dir.out { color: var(--warn, #e6a23c); }
.trf-hist-dir.in { color: var(--ok); }
.trf-hist-main { flex: 1; min-width: 0; }
.trf-hist-meta { white-space: nowrap; font-size: .78rem; }
.filter-row select {
    background: var(--panel); color: var(--text); border: 1px solid var(--line);
    border-radius: 8px; padding: 7px 10px; font-size: .9rem;
}

/* ================= WEB-48: Permissions manager (role → toggle-card grid) ================= */
.perm-info {
    display: flex; gap: 8px; align-items: flex-start;
    background: color-mix(in srgb, var(--gold) 8%, transparent);
    border: 1px solid rgba(212,175,55,.3); border-radius: 12px;
    padding: 12px 16px; margin: 0 0 16px; font-size: .88rem; color: var(--text);
}
.perm-picker {
    background: var(--panel); border: 1px solid var(--line); border-radius: 14px;
    padding: 16px 18px; margin: 0 0 18px;
    display: flex; flex-direction: column; gap: 8px;
}
.pp-label { color: var(--muted); font-size: .78rem; font-weight: 700;
    text-transform: uppercase; letter-spacing: .06em; }
.pp-select {
    background: var(--panel2); color: var(--text); border: 1px solid var(--line);
    border-radius: 10px; padding: 11px 14px; font-size: 1rem; font-weight: 600;
    font-family: inherit; cursor: pointer; max-width: 420px;
}
.pp-select:focus { outline: none; border-color: var(--gold); }
.perm-empty { margin-top: 24px; }

/* Sticky action bar — title, live counter, grant/revoke, Save. */
.perm-bar {
    position: sticky; top: 8px; z-index: 6;
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    background: color-mix(in srgb, var(--panel) 92%, transparent);
    -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
    border: 1px solid var(--line); border-radius: 12px;
    padding: 12px 16px; margin: 0 0 14px; box-shadow: 0 4px 14px rgba(0,0,0,.22);
}
.pb-title { font-size: 1.05rem; font-weight: 700; display: flex; align-items: center; gap: 8px; }
.pb-title b { color: var(--gold); }
.pb-count { color: var(--muted); font-size: .82rem; font-weight: 600;
    font-variant-numeric: tabular-nums; background: var(--panel2);
    border-radius: 999px; padding: 2px 10px; }
.pb-actions { margin-inline-start: auto; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.pb-actions .ghost {
    background: transparent; border: 1px solid var(--line); color: var(--muted);
    border-radius: 9px; padding: 8px 12px; font-weight: 600; cursor: pointer; font-size: .85rem;
}
.pb-actions .ghost:hover:not(:disabled) { border-color: var(--gold); color: var(--text); }
.pb-save { min-height: 40px; }
.pb-save:disabled { opacity: .5; }
.perm-search { max-width: 340px; margin: 0 0 16px; }

/* Module section — heading + its card grid. */
.perm-module { margin: 0 0 20px; }
.pm-head { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; }
.pm-icon { font-size: 1.15rem; }
.pm-name { font-size: 1.05rem; font-weight: 800; letter-spacing: .01em; }
.pm-count { color: var(--muted); font-size: .78rem; font-variant-numeric: tabular-nums;
    background: var(--panel2); border-radius: 999px; padding: 2px 9px; }
.pm-toggle { margin-inline-start: auto; background: transparent; border: 0;
    color: var(--gold); font-weight: 700; font-size: .82rem; cursor: pointer; padding: 4px 6px; }
.pm-toggle:hover:not(:disabled) { text-decoration: underline; }

/* The card grid — responsive, auto-fills the row. */
.perm-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.perm-card {
    display: flex; align-items: stretch; gap: 12px; text-align: start;
    background: var(--panel); border: 1px solid var(--line);
    border-inline-start: 3px solid var(--line);
    border-radius: 12px; padding: 13px 14px; cursor: pointer;
    transition: border-color .13s ease, background .13s ease, transform .06s ease;
}
.perm-card:hover:not(:disabled) { border-color: rgba(212,175,55,.5); }
.perm-card:active:not(:disabled) { transform: scale(.99); }
.perm-card.on { border-inline-start-color: var(--gold);
    background: color-mix(in srgb, var(--gold) 6%, transparent); }
.perm-card.sens-critical.on { border-inline-start-color: var(--err); }
.perm-card.sens-sensitive.on { border-inline-start-color: var(--warn); }
.pc-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.pc-top { display: flex; align-items: center; gap: 7px; }
.pc-name { font-weight: 700; font-size: .96rem; }
.pc-badge { flex: none; width: 17px; height: 17px; border-radius: 5px; display: inline-flex;
    align-items: center; justify-content: center; font-size: .68rem; font-weight: 800; }
.pc-badge.crit { background: color-mix(in srgb, var(--err) 22%, transparent); color: #ff8a7a; }
.pc-badge.sens { background: color-mix(in srgb, var(--gold) 22%, transparent); color: var(--gold); }
.pc-desc { color: var(--muted); font-size: .8rem; line-height: 1.35; }
.pc-approval { color: var(--gold); font-size: .74rem; margin-top: 2px; }

/* The toggle switch — the reference's hero interaction. */
.pc-switch {
    flex: none; align-self: center; width: 44px; height: 25px; border-radius: 999px;
    background: var(--panel2); border: 1px solid var(--line); position: relative;
    transition: background .15s ease, border-color .15s ease;
}
.pc-knob {
    position: absolute; top: 2px; inset-inline-start: 2px; width: 19px; height: 19px;
    border-radius: 50%; background: var(--muted); transition: transform .16s cubic-bezier(.3,.8,.3,1), background .15s ease;
}
.perm-card.on .pc-switch { background: var(--gold); border-color: var(--gold); }
.perm-card.on .pc-knob { background: #1a1a1a; transform: translateX(19px); }
[dir="rtl"] .perm-card.on .pc-knob { transform: translateX(-19px); }
.perm-card.sens-critical.on .pc-switch { background: var(--err); border-color: var(--err); }

@media (max-width: 560px) {
    .perm-grid { grid-template-columns: 1fr; }
    .perm-bar { position: static; }
    .pb-actions { width: 100%; }
    .pb-save { flex: 1; }
}

/* ============ APR — owner approval requests (Requests page + nav badge) ============ */
.nav-badge {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 18px; height: 18px; padding: 0 5px; margin-inline-start: 8px;
    border-radius: 999px; background: var(--err); color: #fff;
    font-size: .68rem; font-weight: 800; line-height: 1;
}
.apr-sec { font-size: 1.02rem; margin: 18px 0 10px; }
.apr-empty {
    border: 1px dashed var(--line); border-radius: 12px; padding: 18px;
    color: var(--muted); text-align: center; margin-bottom: 8px;
}
.apr-grid {
    display: grid;
    /* min(100%, 300px): a card never demands more than the viewport, so a 280px
       phone can't force a sideways scroll. */
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
    gap: 12px; margin-bottom: 20px;
}
.apr-card {
    background: var(--card); border: 1px solid var(--line); border-radius: 14px;
    padding: 14px 16px; border-inline-start: 4px solid var(--gold);
}
.apr-card.t-void   { border-inline-start-color: var(--err); }
.apr-card.t-line   { border-inline-start-color: #e67e22; }
.apr-card.t-refund { border-inline-start-color: #9b59b6; }
.apr-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.apr-type { font-weight: 700; font-size: .92rem; }
.apr-val  { font-weight: 800; font-size: 1.08rem; color: var(--err); font-variant-numeric: tabular-nums; }
.apr-target { font-size: .9rem; margin-bottom: 6px; }
.apr-meta { display: flex; gap: 14px; font-size: .8rem; color: var(--muted); margin-bottom: 6px; }
.apr-reason { font-size: .86rem; font-style: italic; color: var(--muted); margin-bottom: 12px; }
.apr-actions { display: flex; gap: 10px; }
.apr-approve, .apr-reject {
    flex: 1; min-height: 42px; border-radius: 10px; font-weight: 700; cursor: pointer;
    border: 1.5px solid transparent; font-size: .92rem;
}
.apr-approve { background: rgba(46,204,113,.14); color: var(--ok); border-color: rgba(46,204,113,.4); }
.apr-approve:hover:not(:disabled) { background: rgba(46,204,113,.26); }
.apr-reject { background: rgba(231,76,60,.10); color: var(--err); border-color: rgba(231,76,60,.35); }
.apr-reject:hover:not(:disabled) { background: rgba(231,76,60,.22); }

/* ============ APR — live rotating approval code (Requests page) ============ */
.totp-card {
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    background: var(--card); border: 1px solid rgba(212,175,55,.45); border-radius: 14px;
    padding: 14px 18px; margin-bottom: 16px;
}
.totp-card.off { border-color: var(--line); }
.totp-left { display: flex; flex-direction: column; gap: 3px; }
.totp-label { font-weight: 700; font-size: .95rem; }
.totp-hint { font-size: .8rem; color: var(--muted); }
.totp-right { display: flex; align-items: center; gap: 14px; }
.totp-code {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 2rem; font-weight: 800; letter-spacing: .12em; color: var(--gold);
    font-variant-numeric: tabular-nums;
}
.totp-ring {
    flex: none; width: 40px; height: 40px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-weight: 800; font-size: .9rem; font-variant-numeric: tabular-nums;
    color: var(--gold); border: 3px solid rgba(212,175,55,.3);
    background: conic-gradient(var(--gold) calc(var(--totp-pct,100) * 1%), transparent 0);
    position: relative;
}
.totp-setup {
    background: rgba(212,175,55,.14); border: 1.5px solid rgba(212,175,55,.5);
    color: var(--gold); font-weight: 700; padding: 8px 16px; border-radius: 10px;
    text-decoration: none; white-space: nowrap;
}
.totp-setup:hover { background: rgba(212,175,55,.24); }
@media (max-width: 560px) {
    .totp-card { flex-direction: column; align-items: stretch; }
    .totp-right { justify-content: space-between; }
}

/* ============ APR — Requests page phone polish (≤760px) ============ */
@media (max-width: 760px) {
    .apr-sec { font-size: .95rem; margin: 16px 0 8px; }
    .apr-card { padding: 13px 14px; }
    /* Type + value on one row; value can't shove the type off-screen. */
    .apr-head { gap: 8px; }
    .apr-type { font-size: .9rem; min-width: 0; }
    .apr-val { font-size: 1rem; flex: none; }
    /* Approve / Reject stay big, thumb-sized, side by side. */
    .apr-actions { gap: 8px; }
    .apr-approve, .apr-reject { min-height: 46px; font-size: .9rem; }
    /* Rotating-code card: code + ring share a row, label above. */
    .totp-card { padding: 12px 14px; gap: 10px; }
    .totp-code { font-size: 1.7rem; letter-spacing: .1em; }
    .totp-setup { text-align: center; }
}

/* ==================== MOB-1: touch-device scroll performance ====================
   The owner opens this portal on a phone, and scrolling stuttered. Root cause,
   measured by reading what the compositor must do per frame:

   • header.top (sticky) and .tabbar (fixed) BOTH carry backdrop-filter blur.
     A blur-behind surface re-samples and re-blurs the pixels underneath it on
     EVERY scroll frame — and on mobile the two run simultaneously, top and
     bottom. This is the classic mobile-web jank, and it is invisible on a
     desktop GPU, which is why it was never felt during development.
   • .db-badge and .ticket.late animate BOX-SHADOW on an infinite loop. Shadow
     is a paint property, not a compositor one, so those loops force continuous
     repaint even while the page is otherwise idle.

   The fix degrades ONLY the expensive part and only on touch devices
   (pointer: coarse), so the desktop keeps the glass look untouched:

   • Blur-behind → near-opaque solid. At 88% opacity + blur the surface reads
     almost identical to 97% opacity without it; var(--panel) keeps it
     theme-aware in light mode for free.
   • The two shadow loops freeze at their strong keyframe: the late ticket
     still shows its red ring on the kitchen tablet, the DB badge still glows —
     they just stop paying rent every frame. */
@media (pointer: coarse) {
    header.top,
    .perm-bar {
        -webkit-backdrop-filter: none; backdrop-filter: none;
        background: color-mix(in srgb, var(--panel) 97%, transparent);
    }
    .tabbar {
        -webkit-backdrop-filter: none; backdrop-filter: none;
        background: color-mix(in srgb, var(--panel) 98%, transparent);
    }
    .db-badge {
        animation: none;
        box-shadow: 0 0 16px rgba(59, 130, 246, 0.4), inset 0 0 20px rgba(59, 130, 246, 0.08);
    }
    .ticket.late {
        animation: none;
        box-shadow: 0 0 10px 1px rgba(231, 76, 60, .65);
    }
}

/* The same shadow loops are also the right thing to stop for people who asked
   the OS for less motion — on every device, not just touch. */
@media (prefers-reduced-motion: reduce) {
    .db-badge, .ticket.late, .bell.has-alerts { animation: none; }
}

/* ==================== MOB-5: controls that answer the FIRST tap ====================
   Three separate reports — the sign-in language button "not working", the password
   eye "not working", the branch chip "needs pressing twice" — were ONE bug.

   A touch browser has no pointer to hover with, so it EMULATES hover: the first tap
   on an element that has :hover styling applies that styling instead of clicking,
   and only a second tap fires the click. Every one of those three controls carries a
   :hover rule, which is exactly why every one of them ate a tap. (The branch chip had
   a second, independent problem — a hit target far smaller than it looked — fixed at
   .branch-pick.switchable above.)

   The fix is to stop shipping hover styling to devices that can't hover, and to tell
   the browser these are taps, not candidates for double-tap-zoom. */
@media (hover: none) {
    /* Each rule below repeats the control's RESTING look, so a phantom hover is a
       no-op rather than a style change the browser charges a tap for. */
    .lgx-tool:hover { transform: none; box-shadow: none;
        background: rgba(38,38,44,.72); border-color: rgba(212,175,55,.42); }
    :root[data-theme="light"] .lgx-tool:hover { background: rgba(255,255,255,.7);
        border-color: rgba(169,127,22,.35); }
    .lgx-ff .ff-eye:hover { background: transparent; color: var(--muted); }
    .lgx-acct .a-switch:hover { transform: none; }
    .branch-pick.switchable:hover { border-color: var(--line); }
    .nav-cat:hover { background: color-mix(in srgb, var(--gold) 5%, transparent);
        border-color: var(--line); }
    button.lang:hover { border-color: var(--line); }
}

/* No 300ms double-tap-zoom wait, on every pointer type — this is a tap target, and
   the delay is what makes a control feel like it "didn't register". */
.lgx-tool, .lgx-ff .ff-eye, .lgx-btn, .lgx-acct .a-switch, button.lang,
.branch-sel, .nav-cat, .nav-toggle, .tabbar .tab, .bell {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* --- the sign-in utility cluster: centred glyphs, and legible on a dark backdrop ---
   The theme toggle's ☀️/🌙 are EMOJI in an inline span: an inline box sits on the text
   baseline, so `place-items: center` centred the LINE BOX and left the glyph riding
   low. Making each child a centred block puts the glyph itself in the middle. */
.lgx-tool > span { display: grid; place-items: center; width: 100%; height: 100%;
    line-height: 1; }
.lgx-tool > svg { display: block; }
/* Brighter chrome — at .55 alpha over a dark hero these read as smudges on a phone. */
.lgx-tool { background: rgba(38,38,44,.72); border-color: rgba(212,175,55,.42);
    color: #f0d98a; }
.lgx-lang-lb { font-size: 14px; font-weight: 800; }
/* A pressed state is the only feedback a touch device gets — make it unmistakable. */
.lgx-tool:active { background: rgba(212,175,55,.22); border-color: var(--gold); }
.lgx-ff .ff-eye:active { background: rgba(212,175,55,.16); color: var(--gold); }

/* ================== MOB-6: the sign-in theme toggle, rebuilt ==================
   Deleted and written again from scratch, because patching it kept failing.

   WHY IT KEPT BREAKING. The button wore three shared class names — `.lgx-tool`,
   `.theme-toggle`, and (in the top bar) `.lang` — whose rules are spread across three
   regions of this file. Each fix landed on one selector and then lost the cascade to a
   more specific one written elsewhere; the last attempt lost to a `display: inline`
   declared ~1200 lines earlier, which re-baselined the glyph and pushed it off centre.
   Sizing was also duplicated in two places, so the gate's copy and the top bar's copy
   drifted apart.

   THE FIX IS STRUCTURAL, NOT COSMETIC. `cxtheme` is a namespace nothing else in this
   file touches, so there is no cascade to lose. Everything the button needs is in this
   one block — box, colours, both icon states, both themes, focus, press, and the
   touch rules. Centring is therefore provable rather than hopeful.

   Read this before adding a class to this button: giving it a shared class name is
   what caused the bug, twice. */

/* ONE definition for both gate buttons. They are deliberately not two rules: the last
   bug happened because the gate's copy and the top bar's copy of a button were sized in
   two places and drifted. */
.cxtheme, .cxlang {
    /* grid + place-items is the only centring mechanism here, and both icons occupy
       the SAME cell (see grid-area below) — so the box can never resize on flip. */
    display: grid;
    place-items: center;
    width: 42px; height: 42px;
    padding: 0;
    border: 1px solid rgba(212,175,55,.42);
    border-radius: 12px;
    background: rgba(38,38,44,.72);
    color: #f0d98a;
    cursor: pointer;
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    /* A tap is a tap: no 300ms double-tap-zoom wait, no grey flash. */
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    transition: border-color .14s ease, background .14s ease;
}

/* Both icons live in the same 1x1 grid cell; CSS picks which one is visible.
   `display: block` (not inline) is load-bearing: an inline SVG sits on the text
   baseline, which is exactly what left a descender's worth of gap under the old
   icon and pushed it visibly high in the button. */
.cxtheme .cxtheme-i {
    grid-area: 1 / 1;
    display: block;
    width: 20px; height: 20px;
}

/* Dark theme (the default) offers the SUN — press it to go light. Light offers the
   moon. Keyed off :root[data-theme], so a flip needs no Blazor state and no re-render. */
.cxtheme .cxtheme-moon { visibility: hidden; }
:root[data-theme="light"] .cxtheme .cxtheme-sun { visibility: hidden; }
:root[data-theme="light"] .cxtheme .cxtheme-moon { visibility: visible; }
/* visibility, not display: the hidden icon keeps its box, so the two states are
   guaranteed to be identical in size. */

:root[data-theme="light"] .cxtheme,
:root[data-theme="light"] .cxlang {
    background: rgba(255,255,255,.72);
    border-color: rgba(169,127,22,.4);
    color: #8a6410;
}

/* Hover only where a pointer can actually hover. On a touch screen a :hover rule is
   what makes the first tap "do nothing" — the browser applies the hover state instead
   of firing the click, and the user has to press twice. */
@media (hover: hover) and (pointer: fine) {
    .cxtheme:hover, .cxlang:hover { border-color: var(--gold, #d4af37);
        background: rgba(52,52,58,.78); }
    :root[data-theme="light"] .cxtheme:hover,
    :root[data-theme="light"] .cxlang:hover { background: rgba(255,255,255,.9);
        border-color: rgba(169,127,22,.7); }
}

/* On touch the pressed state is the ONLY feedback the operator gets — make it obvious. */
.cxtheme:active, .cxlang:active { background: rgba(212,175,55,.22); border-color: var(--gold, #d4af37); }

.cxtheme:focus-visible, .cxlang:focus-visible {
    outline: none;
    box-shadow: 0 0 0 2px var(--bg, #0b0b0d), 0 0 0 4px var(--gold, #d4af37);
}

@media (max-width: 560px) { .cxtheme, .cxlang { width: 38px; height: 38px; }
    .cxtheme .cxtheme-i { width: 18px; height: 18px; } }

@media (prefers-reduced-motion: reduce) { .cxtheme, .cxlang { transition: none; } }

/* The language label. Same script in both states (AR / EN) means one set of font
   metrics, which is the whole reason this centres reliably — see the comment on the
   button in SignInGate.razor.

   line-height:1 pins the label's box to exactly one em, and `display:block` keeps it
   off the text baseline; grid then centres that box. With Latin caps sitting almost
   exactly on the em-box centre, the ink lands centred too. */
.cxlang .cxlang-lb {
    display: block;
    line-height: 1;
    font-size: 14px;
    font-weight: 800;
    letter-spacing: .04em;
    /* Never let a right-to-left page reorder a two-letter Latin code. */
    direction: ltr;
    unicode-bidi: isolate;
}
@media (max-width: 560px) { .cxlang .cxlang-lb { font-size: 13px; } }

/* STAB-P2 — PageBoundary: shown when a routed page faults. The shell around it
   (nav, bell, branch switcher) stays alive, so this is a panel, not a page. */
.pb-error { max-width: 520px; margin: 48px auto; padding: 28px 24px; text-align: center;
    border: 1px solid var(--border); border-radius: 14px; background: var(--surface); }
.pb-error .pb-icon { font-size: 2.4rem; line-height: 1; margin-bottom: 10px; }
.pb-error h2 { margin: 0 0 8px; font-size: 1.15rem; }
.pb-error p { margin: 0 0 18px; color: var(--muted); line-height: 1.6; }

/* ==================== MOB-6: drawers, and closing them, on a phone ====================
   Everything a manager reads away from the till arrives in a drawer — the Z / shift
   report, an order, a supplier account, a tenant file. On a phone all of them were
   wrong in the same two ways.

   1) `.drawer { width: 100vw; max-width: 100vw }` has sat in the ≤980px block since W1
      and has NEVER applied: an unconditional `.drawer { width: min(440px, 94vw) }`
      further down the file has equal specificity and wins on source order. (The exact
      trap the `.grid` rule in that same block already had to be rescued from — see the
      note there.) So a drawer opened as a 94%-wide panel with a dead 6% sliver of
      dimmed page beside it: too narrow to aim at deliberately, wide enough to look
      like a mistake, and it stole ~24px from a 375px screen that the Z report's
      label/value rows badly needed. `.z-drawer`'s 96vw was worse.
   2) The ✕ was a 1.15rem glyph with 2px of padding — roughly a 20×24px target, less
      than half the 44px minimum, floated in the corner a thumb reaches last.

   So: below 640px a drawer is a full-bleed sheet, its header sticky (the way out never
   scrolls away), and the ✕ is a real 40px chip. Placed at the END of the stylesheet on
   purpose — that is what stops the next unconditional `.drawer { width: … }` from
   silently undoing it a third time.
   Both writing directions are named explicitly: `[dir="rtl"] .drawer` (0,2,0) outranks
   a bare `.drawer`, so the LTR rule alone would leave Arabic on the old geometry. */
@media (max-width: 640px) {
    .drawer, .drawer.wide, .z-drawer, .tenants .drawer,
    [dir="rtl"] .drawer, [dir="rtl"] .drawer.wide, [dir="rtl"] .z-drawer {
        inset: 0; width: 100vw; max-width: 100vw;
        height: 100vh; height: 100dvh;
        border: 0; border-radius: 0; box-shadow: none;
        animation: sheet-up .22s cubic-bezier(.3, .8, .3, 1);
    }
    /* A sheet rises; it does not slide in from an edge it no longer has. */
    @keyframes sheet-up {
        from { transform: translateY(16px); opacity: 0; }
        to   { transform: none; opacity: 1; }
    }

    .drawer-head {
        position: sticky; top: 0; z-index: 2;
        padding: 12px 14px; gap: 10px; align-items: center;
        background: var(--panel);
    }
    .drawer-head h2 { font-size: 1.05rem; }
    .drawer-code { font-size: 1rem; }
    .drawer-name { font-size: .85rem; margin-top: 2px; }

    .drawer-close {
        flex: none; width: 40px; height: 40px; padding: 0;
        display: grid; place-items: center; border-radius: 10px;
        background: var(--panel2); border: 1px solid var(--line); color: var(--text);
        font-size: 1.05rem;
    }

    /* env() keeps the last row clear of a gesture bar; max() means a browser without
       safe-area insets still gets real breathing room rather than 0. */
    .drawer-body { padding: 14px; gap: 12px;
        padding-bottom: max(24px, calc(env(safe-area-inset-bottom) + 16px)); }
    .drawer-card { padding: 12px 14px; border-radius: 12px; }
    /* Full-width actions: a drawer's primary action is the reason the sheet is open.
       Direct children only — a card can also hold a row of small inline controls
       (row-actions, chips) that must stay inline. */
    .drawer-card > button { width: 100%; min-height: 44px; }
    .dc-actions { flex-direction: column; }
    .dc-actions > button { width: 100%; min-height: 44px; }

    /* Label/value rows: the label wraps, the money never does — a broken figure is
       worse than a two-line label. tabular-nums keeps a column of them aligned.
       Child position, not element type: these rows are written as span+b in some
       places and span+span in others, and a `span:last-child` selector matches the
       LABEL on the span+b rows — pinning the one thing that has to be free to wrap. */
    .z-row, .kv { gap: 14px; padding: 6px 0; align-items: baseline; }
    .z-row > :first-child, .kv > :first-child { flex: 1 1 auto; min-width: 0; }
    .z-row > :last-child, .kv > :last-child {
        flex: 0 0 auto; white-space: nowrap; font-variant-numeric: tabular-nums;
    }
}

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

/* SYNC-UI — /sync-status */
.warn-text { color: var(--warn); }
.kpi.warn { border-color: rgba(245, 158, 11, .5); }
.kpi .kpi-small { font-size: 1em; }
.panel-title { margin: 26px 0 10px; font-size: 1.05em; }
