/* ==========================================================================
   OnePOS :: Interface stylesheet
   --------------------------------------------------------------------------
   Every colour, font and metric here comes from a CSS custom property that
   the server writes from the `theme` table. Nothing is hard-coded, so a new
   theme row is enough to reskin the whole application.

   The layout targets an 11" 1366x768 panel: 34px chrome top and bottom,
   22px table rows, 12px base type. Everything scrolls inside its pane so
   the page itself never scrolls.
   ========================================================================== */

/* Fallbacks, in case a page renders before the server tokens land. */
:root {
    --bg-app: #c5d3e8;         --bg-panel: #fffdf2;      --bg-card: #fffdf2;
    --bg-input: #ffffff;       --bg-topbar: #1c3e70;     --bg-statusbar: #1c3e70;
    --bg-sidepanel: #dbe5f4;   --bg-table-head: #c9d9f0; --bg-row-alt: #f7f3e0;
    --bg-selected: #1b6ec2;    --text-selected: #ffffff;
    --text-primary: #10233f;   --text-secondary: #3c4d66; --text-muted: #7b8798;
    --text-inverse: #ffffff;   --text-topbar: #ffffff;
    --border-color: #a9bcd8;   --border-strong: #7e93b3;
    --accent: #1c3e70;         --accent-hover: #16325c;  --accent-soft: #e5edfa;
    --success: #1a7f47;        --warning: #b8860b;       --danger: #b31b1b;
    --info: #1b6ec2;           --key-hint: #b31b1b;
    --font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    --font-mono: Consolas, "Courier New", monospace;
    --font-size: 12px;         --font-size-sm: 11px;     --font-size-lg: 14px;
    --font-bold: 600;          --line-height: 1.35;      --radius: 2px;
    --row-height: 22px;        --cell-pad: 4px 6px;
    --topbar-h: 34px;          --statusbar-h: 24px;      --menubar-h: 26px;
    --icon-weight: 400;
}

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

/**
 * Icon weight, in one place.
 *
 * The classic Font Awesome styles are one family at four weights, so the
 * whole application's icon style is a single number: 100 thin, 300 light,
 * 400 regular, 900 solid. Setting it here rather than in the markup means
 * it also governs the icons the JavaScript builds and the ones stored
 * against payment methods and trades in the database, which no amount of
 * editing markup would reach.
 *
 * Brands and duotone are separate families and are deliberately untouched.
 */
.fa, .fas, .fa-solid, .far, .fa-regular,
.fal, .fa-light, .fat, .fa-thin {
    font-weight: var(--icon-weight);
}

/* For the rare icon that has to carry weight of its own, such as a warning
   sitting alone in an empty table. */
.op-icon-strong { font-weight: 900; }

/**
 * Links carry no browser blue and no underline.
 *
 * Almost every anchor here is a control: a button, a nav item, a row action.
 * Those already say what they are through their own styling, and an
 * inherited underline on top of them only adds noise. Colour is inherited
 * from whatever contains the link, so one sitting on the navy chrome stays
 * legible without a rule of its own.
 */
a {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

/* A bare text link, with no class to mark it out, warms to the accent on
   hover so it is still discoverable without being permanently loud. */
a:not([class]):hover { color: var(--accent); }

/* Keyboard users must still see where they are. */
a:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 1px;
}

html, body {
    height: 100%;
    overflow: hidden;
    font-family: var(--font-family);
    font-size: var(--font-size);
    line-height: var(--line-height);
    color: var(--text-primary);
    background: var(--bg-app);
    -webkit-font-smoothing: antialiased;
}

/* Tabular figures everywhere money appears: columns of numbers line up. */
.num, td.num, th.num, .amount, input[type="number"] {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    text-align: right;
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--border-strong);
    border-radius: 5px;
    border: 2px solid var(--bg-panel);
}
::-webkit-scrollbar-thumb:hover { background: var(--accent); }

/* ==========================================================================
   Shell
   ========================================================================== */

.op-app {
    display: grid;
    grid-template-rows: var(--topbar-h) var(--menubar-h) minmax(0, 1fr) var(--statusbar-h);
    height: 100vh;
    width: 100vw;
}

/* --- title bar --- */
.op-topbar {
    background: var(--bg-topbar);
    color: var(--text-topbar);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 10px;
    user-select: none;
    border-bottom: 1px solid rgba(0, 0, 0, .25);
}
.op-brand { display: flex; align-items: center; gap: 8px; font-weight: 700; letter-spacing: .3px; }
.op-brand .op-logo {
    width: 20px; height: 20px; display: grid; place-items: center;
    background: var(--text-topbar); color: var(--bg-topbar);
    border-radius: var(--radius); font-size: 11px; font-weight: 800;
}
.op-topbar-centre { font-size: var(--font-size-sm); opacity: .92; text-align: center; }
.op-topbar-right { display: flex; align-items: center; gap: 12px; font-size: var(--font-size-sm); }
.op-topbar-right .op-chip {
    background: rgba(255, 255, 255, .14);
    padding: 2px 8px; border-radius: var(--radius); white-space: nowrap;
}
.op-topbar-right .op-chip.is-alert { background: var(--danger); }
.op-topbar-right .op-chip.is-ok { background: var(--success); }

/* --- menu bar --- */
.op-menubar {
    background: var(--bg-sidepanel);
    border-bottom: 1px solid var(--border-color);
    display: flex; align-items: center; gap: 2px;
    padding: 0 6px;
    user-select: none;
}
.op-menu-item {
    padding: 3px 10px;
    font-size: var(--font-size-sm);
    cursor: pointer;
    border-radius: var(--radius);
    color: var(--text-secondary);
    white-space: nowrap;
}
.op-menu-item:hover { background: var(--accent-soft); color: var(--text-primary); }
.op-menu-item.active { background: var(--bg-selected); color: var(--text-selected); font-weight: var(--font-bold); }
.op-menubar-spacer { flex: 1; }

/* --- body: nav + work area + button panel --- */
/* The middle track carries the whole work area, so it needs the same
   `minmax(0, …)` floor as the register grid inside it. Without it the widest
   view decides the column width and the side panels get pushed off. */
.op-body { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; overflow: hidden; }

/* The register runs full width: no side navigation, no button column. */
.op-body.is-register { grid-template-columns: minmax(0, 1fr); }

.op-nav {
    width: 178px;
    background: var(--bg-panel);
    border-right: 1px solid var(--border-color);
    overflow-y: auto;
    padding: 4px 0;
}
.op-nav.collapsed { width: 42px; }
.op-nav.collapsed .op-nav-text, .op-nav.collapsed .op-nav-group { display: none; }
.op-nav.collapsed .op-nav-link { justify-content: center; padding: 6px 0; }

.op-nav-group {
    font-size: 10px; text-transform: uppercase; letter-spacing: .7px;
    color: var(--text-muted); font-weight: 700;
    padding: 8px 10px 3px;
}
.op-nav-link {
    display: flex; align-items: center; gap: 8px;
    padding: 4px 10px;
    cursor: pointer;
    color: var(--text-secondary);
    border-left: 3px solid transparent;
    white-space: nowrap;
}
.op-nav-link i { width: 14px; text-align: center; font-size: 12px; }
.op-nav-link:hover { background: var(--accent-soft); color: var(--text-primary); }
.op-nav-link.active {
    background: var(--bg-selected); color: var(--text-selected);
    border-left-color: var(--key-hint); font-weight: var(--font-bold);
}

.op-work {
    background: var(--bg-app);
    overflow: auto;
    padding: 8px;
    /* Clears the grid item's automatic minimum so a wide view scrolls inside
       this pane instead of widening the column that holds it. */
    min-width: 0;
    min-height: 0;
}

/* The register fills the pane exactly and manages its own scrolling. */
.op-work.is-register { padding: 6px; overflow: hidden; }

/* Tally's right-hand button column: the keyboard map, always visible. */
.op-buttons {
    width: 150px;
    background: var(--bg-sidepanel);
    border-left: 1px solid var(--border-color);
    overflow-y: auto;
    padding: 4px;
    display: flex; flex-direction: column; gap: 3px;
}
.op-btn-panel {
    display: flex; align-items: center; justify-content: space-between; gap: 6px;
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    padding: 4px 7px;
    font-size: var(--font-size-sm);
    cursor: pointer;
    color: var(--text-primary);
    text-align: left;
    width: 100%;
}
.op-btn-panel:hover { background: var(--bg-selected); color: var(--text-selected); border-color: var(--bg-selected); }
.op-btn-panel:hover .op-key { color: var(--text-selected); }
.op-btn-panel:disabled { opacity: .45; cursor: not-allowed; }
.op-btn-panel .op-key { color: var(--key-hint); font-weight: 700; }
.op-btn-group-label {
    font-size: 10px; text-transform: uppercase; letter-spacing: .6px;
    color: var(--text-muted); font-weight: 700; padding: 6px 4px 2px;
}

/* --- status bar --- */
.op-statusbar {
    background: var(--bg-statusbar);
    color: var(--text-topbar);
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 10px;
    font-size: var(--font-size-sm);
    user-select: none;
}
.op-statusbar .op-status-group { display: flex; align-items: center; gap: 14px; }
.op-statusbar b { font-weight: 700; }

/* ==========================================================================
   Panels, tables, forms
   ========================================================================== */

.op-panel {
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    margin-bottom: 8px;
}
.op-panel-head {
    background: var(--bg-table-head);
    border-bottom: 1px solid var(--border-color);
    padding: 4px 8px;
    font-weight: var(--font-bold);
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.op-panel-title { display: flex; align-items: center; gap: 6px; }
.op-panel-body { padding: 8px; }
.op-panel-body.flush { padding: 0; }

.op-page-title {
    font-size: var(--font-size-lg);
    font-weight: 700;
    margin-bottom: 2px;
}
.op-page-sub { color: var(--text-muted); font-size: var(--font-size-sm); margin-bottom: 8px; }

table.op-table { width: 100%; border-collapse: collapse; background: var(--bg-panel); }
table.op-table thead th {
    background: var(--bg-table-head);
    color: var(--text-primary);
    font-weight: var(--font-bold);
    text-align: left;
    padding: var(--cell-pad);
    border-bottom: 1px solid var(--border-strong);
    position: sticky; top: 0; z-index: 2;
    white-space: nowrap;
    font-size: var(--font-size-sm);
}
table.op-table tbody td {
    padding: var(--cell-pad);
    border-bottom: 1px solid var(--border-color);
    height: var(--row-height);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
table.op-table tbody tr:nth-child(even) { background: var(--bg-row-alt); }
table.op-table tbody tr:hover { background: var(--accent-soft); }
table.op-table tbody tr.selected,
table.op-table tbody tr.selected:hover {
    background: var(--bg-selected); color: var(--text-selected);
}
table.op-table tbody tr.selected .op-muted { color: var(--text-selected); opacity: .8; }
table.op-table tfoot td {
    padding: var(--cell-pad);
    font-weight: 700;
    background: var(--bg-table-head);
    border-top: 1px solid var(--border-strong);
}
.op-table-wrap { overflow: auto; max-height: 100%; }

/* Forms */
.op-field { margin-bottom: 7px; }
.op-label {
    display: block;
    font-size: var(--font-size-sm);
    color: var(--text-secondary);
    margin-bottom: 2px;
    font-weight: var(--font-bold);
}
.op-input, .op-select, .op-textarea {
    width: 100%;
    padding: 3px 6px;
    height: 26px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: inherit;
    font-size: var(--font-size);
    outline: none;
}
.op-textarea { height: auto; min-height: 52px; resize: vertical; }
.op-input:focus, .op-select:focus, .op-textarea:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 2px var(--accent-soft);
}
.op-input:disabled { background: var(--bg-row-alt); color: var(--text-muted); }
.op-input.is-error { border-color: var(--danger); }

.op-row { display: flex; gap: 8px; flex-wrap: wrap; }
.op-row > * { flex: 1; min-width: 0; }
.op-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.op-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.op-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }

/* Buttons */
.op-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 5px;
    padding: 4px 11px;
    height: 26px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    background: var(--bg-panel);
    color: var(--text-primary);
    font-family: inherit;
    font-size: var(--font-size);
    font-weight: var(--font-bold);
    cursor: pointer;
    white-space: nowrap;
}
.op-btn:hover { background: var(--accent-soft); border-color: var(--accent); }
.op-btn:active { transform: translateY(1px); }
.op-btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
.op-btn-primary { background: var(--accent); border-color: var(--accent); color: var(--text-inverse); }
.op-btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--text-inverse); }
.op-btn-success { background: var(--success); border-color: var(--success); color: #fff; }
.op-btn-danger  { background: var(--danger);  border-color: var(--danger);  color: #fff; }
.op-btn-warning { background: var(--warning); border-color: var(--warning); color: #fff; }
.op-btn-lg { height: 34px; padding: 6px 16px; font-size: var(--font-size-lg); }
.op-btn-sm { height: 21px; padding: 1px 7px; font-size: var(--font-size-sm); }
.op-btn-block { width: 100%; }

/* Badges */
.op-badge {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 9px;
    font-size: 10px;
    font-weight: 700;
    background: var(--accent-soft);
    color: var(--accent);
    white-space: nowrap;
}
.op-badge-success { background: color-mix(in srgb, var(--success) 15%, transparent); color: var(--success); }
.op-badge-danger  { background: color-mix(in srgb, var(--danger) 15%, transparent);  color: var(--danger); }
.op-badge-warning { background: color-mix(in srgb, var(--warning) 18%, transparent); color: var(--warning); }
.op-badge-muted   { background: color-mix(in srgb, var(--text-muted) 15%, transparent); color: var(--text-muted); }

/* Stat tiles */
.op-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; margin-bottom: 8px; }
.op-stat {
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius);
    padding: 6px 9px;
}
.op-stat-label { font-size: 10px; text-transform: uppercase; letter-spacing: .6px; color: var(--text-muted); font-weight: 700; }
.op-stat-value { font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums; margin-top: 1px; }
.op-stat-note { font-size: 10px; color: var(--text-muted); }
.op-stat.is-success { border-left-color: var(--success); }
.op-stat.is-danger  { border-left-color: var(--danger); }
.op-stat.is-warning { border-left-color: var(--warning); }

/* Helpers */
.op-muted { color: var(--text-muted); }
.op-danger { color: var(--danger); }
.op-success { color: var(--success); }
.op-warning { color: var(--warning); }
.op-right { text-align: right; }
.op-centre { text-align: center; }
.op-bold { font-weight: 700; }
.op-mono { font-family: var(--font-mono); }
.op-nowrap { white-space: nowrap; }
.op-flex { display: flex; align-items: center; gap: 6px; }
.op-flex-between { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.op-spacer { flex: 1; }
.op-mt { margin-top: 8px; }
.op-mb { margin-bottom: 8px; }
.op-hidden { display: none !important; }
.op-key {
    color: var(--key-hint);
    font-weight: 700;
    font-family: var(--font-mono);
}
.op-kbd {
    display: inline-block;
    padding: 0 4px;
    border: 1px solid var(--border-strong);
    border-bottom-width: 2px;
    border-radius: 3px;
    background: var(--bg-panel);
    font-family: var(--font-mono);
    font-size: 10px;
    color: var(--text-secondary);
}

/* ==========================================================================
   Modal
   ========================================================================== */

.op-modal-backdrop {
    position: fixed; inset: 0;
    background: rgba(8, 16, 30, .55);
    display: grid; place-items: center;
    z-index: 900;
}
.op-modal {
    background: var(--bg-panel);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    box-shadow: 0 12px 40px rgba(0, 0, 0, .35);
    width: min(94vw, 560px);
    max-height: 88vh;
    display: flex; flex-direction: column;
}
.op-modal.wide { width: min(96vw, 900px); }
.op-modal.narrow { width: min(94vw, 380px); }
.op-modal-head {
    background: var(--bg-topbar);
    color: var(--text-topbar);
    padding: 6px 10px;
    font-weight: 700;
    display: flex; align-items: center; justify-content: space-between;
}
.op-modal-close { background: none; border: 0; color: inherit; cursor: pointer; font-size: 15px; line-height: 1; }
.op-modal-body { padding: 10px; overflow: auto; }
.op-modal-foot {
    padding: 7px 10px;
    border-top: 1px solid var(--border-color);
    background: var(--bg-table-head);
    display: flex; justify-content: flex-end; gap: 6px;
}

/* Toasts */
.op-toasts { position: fixed; top: 44px; right: 12px; z-index: 1000; display: flex; flex-direction: column; gap: 6px; }
.op-toast {
    background: var(--bg-panel);
    border: 1px solid var(--border-strong);
    border-left: 4px solid var(--accent);
    border-radius: var(--radius);
    padding: 7px 12px;
    min-width: 220px; max-width: 380px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .22);
    animation: op-slide-in .16s ease-out;
}
.op-toast.is-success { border-left-color: var(--success); }
.op-toast.is-danger  { border-left-color: var(--danger); }
.op-toast.is-warning { border-left-color: var(--warning); }
.op-toast-title { font-weight: 700; }
.op-toast-msg { font-size: var(--font-size-sm); color: var(--text-secondary); }
@keyframes op-slide-in { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
    .op-toast { animation: none; }
    .op-btn:active { transform: none; }
}

.op-empty { padding: 26px 14px; text-align: center; color: var(--text-muted); }
.op-empty i { font-size: 26px; display: block; margin-bottom: 6px; opacity: .5; }

.op-loading { padding: 20px; text-align: center; color: var(--text-muted); }
.op-spinner {
    width: 15px; height: 15px; display: inline-block;
    border: 2px solid var(--border-color);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: op-spin .7s linear infinite;
}
@keyframes op-spin { to { transform: rotate(360deg); } }

/* ==========================================================================
   Register (till)
   ========================================================================== */

/* A `1fr` track has an automatic minimum of min-content, so it refuses to
   shrink past the widest thing inside it. The scan input carries a browser
   default width, the category chips do not wrap, and the tile grid has a
   112px floor, so without `minmax(0, …)` the left column grows past its share
   and slides under the basket. The same default applies down the block axis,
   where it stops the tile list and the basket from scrolling and makes them
   push the totals off instead. */
.op-register { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 6px; height: 100%; overflow: hidden; }
.op-reg-left  { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 6px; overflow: hidden; min-width: 0; }
.op-reg-right { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 6px; overflow: hidden; min-width: 0; }

/* Clear the same floor on the children, including the unclassed wrapper that
   holds the scan bar and the category strip. */
.op-reg-left > *, .op-reg-right > * { min-width: 0; min-height: 0; }

.op-scan-bar {
    display: flex; gap: 6px; align-items: center;
    background: var(--bg-panel);
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    padding: 6px;
}
.op-scan-input {
    /* Without min-width an input keeps its default character width as a floor,
       which is what pushes the search button out of the bar on a narrow till. */
    flex: 1; min-width: 0; height: 32px;
    font-size: var(--font-size-lg); font-weight: var(--font-bold);
    padding: 4px 9px;
    border: 2px solid var(--accent);
    border-radius: var(--radius);
    background: var(--bg-input); color: var(--text-primary);
    outline: none;
}
.op-scan-input::placeholder { color: var(--text-muted); font-weight: 400; }

.op-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
    gap: 0;
    overflow-y: auto;
    align-content: start;
    padding: 0;
    /* Tiles carry only their top and left edges, so neighbours share one
       hairline instead of stacking two. These two close the grid off. */
    border-right: .5px solid var(--border-color);
    border-bottom: .5px solid var(--border-color);
}
.op-tile {
    background: var(--bg-panel);
    /* Top and left only: with no gap between tiles, a full border would draw
       every interior line twice. The container supplies the closing right and
       bottom edges. The accent stays as the tile's only tint, along the top.
       Sub-pixel widths are rounded by the renderer, so on a 1x panel this
       lands on the thinnest line the screen can draw. */
    border: 0 solid var(--border-color);
    border-width: .5px 0 0 .5px;
    border-top-color: var(--accent);
    border-radius: 0;
    padding: 5px 6px;
    cursor: pointer;
    min-height: 56px;
    display: flex; flex-direction: column; justify-content: space-between;
    text-align: left;
    overflow: hidden;
}
.op-tile:hover { background: var(--accent-soft); border-color: var(--accent); }
.op-tile-name {
    font-weight: var(--font-bold);
    font-size: var(--font-size-sm);
    line-height: 1.25;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}
.op-tile-price { font-weight: 800; font-variant-numeric: tabular-nums; }
.op-tile-meta { font-size: 10px; color: var(--text-muted); display: flex; justify-content: space-between; gap: 4px; }
/* Out of stock: the tile stays readable but stops competing for attention.
   The border is already a hairline on every tile, so opacity alone carries
   the distinction. */
.op-tile.out-of-stock { opacity: .5; }

.op-cat-strip { display: flex; gap: 4px; overflow-x: auto; padding-bottom: 3px; }
.op-cat-chip {
    padding: 3px 9px;
    border: 1px solid var(--border-color);
    border-radius: 11px;
    background: var(--bg-panel);
    cursor: pointer;
    font-size: var(--font-size-sm);
    white-space: nowrap;
}
.op-cat-chip.active { background: var(--bg-selected); color: var(--text-selected); border-color: var(--bg-selected); font-weight: var(--font-bold); }

/* Basket */
.op-basket { overflow: auto; background: var(--bg-panel); border: 1px solid var(--border-color); border-radius: var(--radius); }
.op-basket table { width: 100%; border-collapse: collapse; }
.op-basket thead th {
    background: var(--bg-table-head);
    padding: 3px 5px;
    font-size: 10px; text-transform: uppercase; letter-spacing: .4px;
    text-align: left; position: sticky; top: 0; z-index: 2;
    border-bottom: 1px solid var(--border-strong);
}
.op-basket tbody td { padding: 3px 5px; border-bottom: 1px solid var(--border-color); vertical-align: top; }
.op-basket tbody tr.active { background: var(--bg-selected); color: var(--text-selected); }
.op-basket tbody tr.active .op-muted { color: var(--text-selected); opacity: .85; }
.op-basket-item { font-weight: var(--font-bold); line-height: 1.2; }
.op-basket-sub { font-size: 10px; color: var(--text-muted); }

.op-totals { background: var(--bg-panel); border: 1px solid var(--border-color); border-radius: var(--radius); padding: 7px 9px; }
.op-total-row { display: flex; justify-content: space-between; padding: 1px 0; font-variant-numeric: tabular-nums; }
.op-total-row.grand {
    border-top: 2px solid var(--border-strong);
    margin-top: 4px; padding-top: 5px;
    font-size: 19px; font-weight: 800;
}
.op-total-row.grand .op-total-value { color: var(--accent); }

/* A business can rename its payment methods, so a long unbroken name like
   "Card (Visa/Mastercard)" must wrap inside the button rather than widen the
   column the basket shares. */
.op-pay-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 5px; }
.op-pay-btn span { overflow-wrap: anywhere; text-align: center; }
.op-pay-btn {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    padding: 7px 4px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    background: var(--bg-panel);
    cursor: pointer;
    font-size: var(--font-size-sm);
    font-weight: var(--font-bold);
    color: var(--text-primary);
}
.op-pay-btn i { font-size: 15px; color: var(--accent); }
.op-pay-btn:hover { background: var(--accent-soft); border-color: var(--accent); }
.op-pay-btn.active { background: var(--bg-selected); color: var(--text-selected); border-color: var(--bg-selected); }
.op-pay-btn.active i { color: var(--text-selected); }

/* Numeric keypad */
.op-keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.op-keypad button {
    height: 38px;
    font-size: var(--font-size-lg); font-weight: 700;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    background: var(--bg-panel);
    color: var(--text-primary);
    cursor: pointer;
    font-family: inherit;
}
.op-keypad button:hover { background: var(--accent-soft); }
.op-keypad button.wide { grid-column: span 2; }
.op-keypad button.op-key-action { background: var(--accent); color: var(--text-inverse); border-color: var(--accent); }

.op-amount-display {
    background: var(--bg-input);
    border: 2px solid var(--accent);
    border-radius: var(--radius);
    padding: 6px 10px;
    font-size: 24px;
    font-weight: 800;
    text-align: right;
    font-variant-numeric: tabular-nums;
    margin-bottom: 6px;
}

/* Theme picker on the settings page */
.op-theme-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 8px; }
.op-theme-card {
    border: 2px solid var(--border-color);
    border-radius: var(--radius);
    overflow: hidden;
    cursor: pointer;
    background: var(--bg-panel);
}
.op-theme-card:hover { border-color: var(--accent); }
.op-theme-card.active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.op-theme-preview { height: 74px; position: relative; display: flex; flex-direction: column; }
.op-theme-preview-bar { height: 15px; }
.op-theme-preview-body { flex: 1; display: flex; }
.op-theme-preview-nav { width: 26%; }
.op-theme-preview-main { flex: 1; padding: 4px; }
.op-theme-preview-line { height: 4px; border-radius: 2px; margin-bottom: 3px; }
.op-theme-info { padding: 5px 7px; border-top: 1px solid var(--border-color); }
.op-theme-name { font-weight: 700; }
.op-theme-font { font-size: 10px; color: var(--text-muted); }

/* Print: receipts and reports leave the chrome behind. */
@media print {
    .op-topbar, .op-menubar, .op-nav, .op-buttons, .op-statusbar, .op-toasts, .no-print { display: none !important; }
    .op-app { display: block; height: auto; }
    .op-work { overflow: visible; padding: 0; background: #fff; }
    body { background: #fff; color: #000; overflow: visible; }
}

/* Smaller panels: 11" and below get a tighter chrome. */
@media (max-width: 1400px) {
    .op-nav { width: 158px; }
    .op-buttons { width: 138px; }
    .op-register { grid-template-columns: minmax(0, 1fr) 348px; }
}
@media (max-width: 1200px) {
    .op-nav { width: 46px; }
    .op-nav .op-nav-text, .op-nav .op-nav-group { display: none; }
    .op-nav .op-nav-link { justify-content: center; }
    .op-register { grid-template-columns: minmax(0, 1fr) 320px; }
}

/* ---------------------------------------------------------------- guide ---
   The in-app instructions. Content comes from pos/data/guide.json and is
   filtered to the signed-in user's role before it ever reaches the browser. */

.op-guide { max-height: 62vh; overflow-y: auto; padding-right: 4px; }

.op-guide-topic { margin-bottom: 16px; }
.op-guide-topic:last-child { margin-bottom: 0; }

.op-guide-topic h4 {
    margin: 0 0 3px;
    font-size: var(--font-size-lg);
    color: var(--accent);
}

.op-guide-topic > p {
    margin: 0 0 6px;
    font-size: var(--font-size-sm);
}

.op-guide-topic ol {
    margin: 0;
    padding-left: 18px;
}

.op-guide-topic li {
    margin-bottom: 5px;
    line-height: 1.45;
}

.op-guide-topic li:last-child { margin-bottom: 0; }

/* Separator between topics, without a heavy rule. */
.op-guide-topic + .op-guide-topic {
    border-top: 1px solid var(--border-color);
    padding-top: 12px;
}

/* ------------------------------------------------------------- checkboxes ---
   A checkbox and its label read as one control, so the whole row is the hit
   target rather than the 13px box alone. */

.op-check {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 6px;
    cursor: pointer;
    user-select: none;
}

.op-check input[type="checkbox"] {
    width: 14px;
    height: 14px;
    margin: 0;
    flex: none;
    accent-color: var(--accent);
    cursor: pointer;
}

.op-check span { line-height: 1.35; }
.op-check:hover span { color: var(--text-primary); }

/* Marks the row you are currently standing in, as distinct from the row you
   have selected. Used by the branch list for the branch you are signed in to. */
.op-table tbody tr.op-row-active > td {
    background: var(--accent-soft);
    box-shadow: inset 2px 0 0 var(--accent);
}

/* ------------------------------------------------------------ date picker ---
   Replaces the native calendar, which keeps the browser's own colours and so
   looks wrong on a dark till and different on every machine. Every value here
   is a theme token, so it reskins with the rest of the application. */

.op-date { padding-right: 24px; }

/* The calendar glyph, drawn in the theme's accent rather than the browser's. */
.op-date-wrap { position: relative; display: inline-block; }
.op-date-wrap::after {
    content: "\f133";                       /* Font Awesome calendar */
    font-family: "Font Awesome 6 Pro";
    font-weight: var(--icon-weight);
    font-size: 11px;
    position: absolute;
    right: 8px; top: 50%;
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: none;
}
.op-date-wrap:focus-within::after { color: var(--accent); }

.op-datepicker {
    position: absolute;
    z-index: 900;                            /* above dialogs */
    display: none;
    width: 232px;
    padding: 6px;
    background: var(--bg-panel);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    box-shadow: 0 6px 20px rgba(0, 0, 0, .22);
    font-size: var(--font-size-sm);
    color: var(--text-primary);
    user-select: none;
}

.op-datepicker.is-open { display: block; }

/* --- head: month and year, with single and twelve month steps --- */

.op-dp-head {
    display: flex;
    align-items: center;
    gap: 3px;
    margin-bottom: 5px;
}

.op-dp-nav {
    flex: none;
    width: 20px; height: 20px;
    display: grid; place-items: center;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    background: var(--bg-input);
    color: var(--text-secondary);
    font: inherit;
    line-height: 1;
    cursor: pointer;
}
.op-dp-nav:hover { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }

.op-dp-month, .op-dp-year {
    height: 20px;
    min-width: 0;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    background: var(--bg-input);
    color: var(--text-primary);
    font: inherit;
    padding: 0 2px;
    cursor: pointer;
}
.op-dp-month { flex: 1 1 auto; }
.op-dp-year  { flex: 0 0 58px; }
.op-dp-month:focus, .op-dp-year:focus { outline: none; border-color: var(--accent); }

/* --- grid --- */

.op-dp-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 1px;
}

.op-dp-dow {
    text-align: center;
    font-size: 9.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .4px;
    color: var(--text-muted);
    padding-bottom: 3px;
}

.op-dp-day {
    height: 24px;
    border: 1px solid transparent;
    border-radius: var(--radius);
    background: transparent;
    color: var(--text-primary);
    font: inherit;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    padding: 0;
}

.op-dp-day:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent); }

/* Days spilling in from the neighbouring months stay readable but recede. */
.op-dp-day.is-outside { color: var(--text-muted); opacity: .55; }

/* Today is outlined; the chosen day is filled. Both can be true at once, so
   the fill has to win. */
.op-dp-day.is-today { border-color: var(--accent); font-weight: var(--font-bold); }

.op-dp-day.is-selected {
    background: var(--bg-selected);
    border-color: var(--bg-selected);
    color: var(--text-selected);
    font-weight: var(--font-bold);
}

.op-dp-day:disabled,
.op-dp-day.is-blocked {
    color: var(--text-muted);
    opacity: .3;
    cursor: default;
    text-decoration: line-through;
}

.op-dp-day:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* --- foot --- */

.op-dp-foot {
    display: flex;
    gap: 4px;
    margin-top: 5px;
    padding-top: 5px;
    border-top: 1px solid var(--border-color);
}

.op-dp-btn {
    flex: 1;
    height: 21px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius);
    background: var(--bg-input);
    color: var(--text-secondary);
    font: inherit;
    cursor: pointer;
}
.op-dp-btn:hover { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
    .op-datepicker { box-shadow: 0 2px 8px rgba(0, 0, 0, .18); }
}

/* --------------------------------------------------------- keyboard sheet ---
   The cheat sheet on F1. Built from the live binding list, so it shows exactly
   what this user can press on this screen and nothing they cannot. */

.op-keys-overlay {
    position: fixed;
    inset: 0;
    z-index: 950;
    background: rgba(0, 0, 0, .45);
    display: grid;
    place-items: center;
    padding: 20px;
}

.op-keys-sheet {
    width: min(94vw, 760px);
    max-height: 86vh;
    display: flex;
    flex-direction: column;
    background: var(--bg-panel);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    box-shadow: 0 10px 34px rgba(0, 0, 0, .3);
    overflow: hidden;
}

.op-keys-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    background: var(--bg-table-head);
    border-bottom: 1px solid var(--border-color);
}

.op-keys-body {
    padding: 10px;
    overflow-y: auto;
    columns: 2;
    column-gap: 22px;
}

.op-keys-group {
    break-inside: avoid;
    margin-bottom: 12px;
}

.op-keys-group h4 {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .7px;
    color: var(--accent);
    margin-bottom: 3px;
    padding-bottom: 2px;
    border-bottom: 1px solid var(--border-color);
}

.op-keys-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 1.5px 0;
}

/* The combos column is fixed so the descriptions line up down the page. */
.op-keys-combo {
    flex: 0 0 116px;
    text-align: right;
    white-space: nowrap;
}

.op-keys-label { flex: 1; color: var(--text-secondary); }

@media (max-width: 720px) {
    .op-keys-body { columns: 1; }
}

/* ----------------------------------------------------------- sign-in ---
   Two panels: the form on the left, what the product is on the right. The
   inputs are ruled rather than boxed, which keeps a dense form quiet, and
   the corners stay square so it reads as a business tool. */

.op-signin {
    width: min(96vw, 940px);
    max-height: 92vh;
    display: flex;
    /* .op-modal lays its children out in a column; these two sit side by side. */
    flex-direction: row;
    /* Square, so it reads as a business tool rather than a web dialog. */
    border-radius: 0;
    border: 0;
    box-shadow: 0 18px 50px rgba(0, 0, 0, .4);
    overflow: hidden;
}

.op-signin-form {
    flex: 1 1 52%;
    min-width: 0;
    background: var(--bg-input);
    padding: 40px 44px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.op-signin-form h2 {
    font-size: 24px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 4px;
}

.op-signin-form .lead {
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 28px;
}

/* Ruled inputs: a line under the field, not a box around it. */
.op-signin .op-field { margin-bottom: 20px; }

.op-signin .op-input,
.op-signin .op-select {
    width: 100%;
    height: 38px;
    border: 0;
    border-bottom: 1px solid var(--border-strong);
    border-radius: 0;
    background: transparent;
    padding: 0 2px;
    font-size: 14px;
    color: var(--text-primary);
    transition: border-color .15s;
}

.op-signin .op-input:focus,
.op-signin .op-select:focus {
    outline: none;
    border-bottom: 2px solid var(--accent);
}

.op-signin .op-input::placeholder { color: var(--text-muted); }

.op-signin .op-label {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--text-muted);
    font-weight: 700;
    margin-bottom: 2px;
    display: block;
}

.op-signin-submit {
    width: 100%;
    height: 46px;
    border: 0;
    border-radius: 0;
    background: var(--accent);
    color: var(--text-inverse);
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    cursor: pointer;
    margin-top: 6px;
}
.op-signin-submit:hover { background: var(--accent-hover); }

.op-signin-links { margin-top: 22px; display: grid; gap: 9px; }
.op-signin-links a { font-size: 13px; color: var(--text-secondary); }
.op-signin-links a:hover { color: var(--accent); }

/* The right panel: cream, the way the worksheet is. */
.op-signin-aside {
    flex: 1 1 48%;
    min-width: 0;
    background: var(--bg-row-alt);
    border-left: 1px solid var(--border-color);
    padding: 40px 38px 32px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.op-signin-aside .brand { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; }
.op-signin-aside .brand .op-logo { width: 34px; height: 34px; font-size: 17px; }
.op-signin-aside .brand b { font-size: 19px; line-height: 1.1; }
.op-signin-aside .brand small { display: block; font-size: 10.5px; font-weight: 400; color: var(--text-muted); }

.op-signin-aside h3 {
    font-size: 21px;
    font-weight: 750;
    line-height: 1.2;
    letter-spacing: -.015em;
    margin-bottom: 14px;
    text-wrap: balance;
}

.op-signin-aside ul { list-style: none; display: grid; gap: 9px; margin-bottom: 20px; }
.op-signin-aside li { display: flex; gap: 9px; font-size: 13px; line-height: 1.45; color: var(--text-secondary); }
.op-signin-aside li i { color: var(--accent); margin-top: 2px; }

.op-signin-aside .foot { font-size: 11px; color: var(--text-muted); }

@media (max-width: 760px) {
    .op-signin { flex-direction: column; max-height: 94vh; overflow-y: auto; }
    .op-signin-aside { border-left: 0; border-top: 1px solid var(--border-color); }
    .op-signin-form { padding: 26px 24px; }
}
