/* ============================================================
   Delivery Management System — Design System
   These tokens (colors, spacing, fonts, shadows) are reused across
   the Shop, Admin, and Driver portals. Every class name below was
   already in use before this pass — this file only refines how
   they look, so no HTML or JS needed to change alongside it.
   ============================================================ */

:root {
    /* Colors — softened slightly from the original palette, same
       overall navy + teal identity. */
    --color-bg: #F5F7FA;
    --color-surface: #FFFFFF;
    --color-ink: #202942;
    --color-ink-soft: #667085;
    --color-border: #E5E9F0;
    --color-border-soft: #EEF1F6;

    --color-primary: #362A7A;
    --color-primary-soft: #4E3AAE;

    --color-accent: #6B4FE0;
    --color-accent-hover: #4E3AAE;
    --color-accent-soft: #EFEAFC;

    --color-warning: #C77C1F;
    --color-warning-soft: #FDF1DE;
    --color-danger: #C0392B;
    --color-danger-soft: #FBEAE7;
    --color-success: #1E8E5A;
    --color-success-soft: #E7F5EE;
    --color-info: #1B5FA8;
    --color-info-soft: #E3F0FC;
    --color-neutral-soft: #EAEEF5;

    /* Layout */
    --radius-sm: 8px;
    --radius: 12px;
    --radius-lg: 18px;
    --radius-full: 999px;

    --shadow-sm: 0 1px 2px rgba(32, 41, 66, 0.05);
    --shadow-card: 0 1px 2px rgba(32, 41, 66, 0.05), 0 6px 20px rgba(32, 41, 66, 0.07);
    --shadow-lift: 0 2px 4px rgba(32, 41, 66, 0.06), 0 12px 28px rgba(32, 41, 66, 0.10);

    /* Motion — subtle and quick, never gratuitous */
    --transition-fast: 120ms ease;
    --transition: 180ms ease;

    /* Type */
    --font-body: "Inter", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --font-heading: "Inter", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* Dark theme — applied by setting data-theme="dark" on <html>, done by
   public/js/theme.js on every page based on the admin's Settings choice.
   Because every component in this file is styled using the variables
   above rather than hardcoded colors, overriding them here is enough
   to re-theme the whole app without touching any component rule. */
[data-theme="dark"] {
    --color-bg: #12161F;
    --color-surface: #1B212E;
    --color-ink: #E8ECF3;
    --color-ink-soft: #9AA3B5;
    --color-border: #2A3242;
    --color-border-soft: #232B39;

    --color-primary: #B3A2FA;
    --color-primary-soft: #8C74F5;

    --color-accent: #8C74F5;
    --color-accent-hover: #B3A2FA;
    --color-accent-soft: #241A55;

    --color-warning: #E0A339;
    --color-warning-soft: #362B18;
    --color-danger: #E27C6E;
    --color-danger-soft: #38211D;
    --color-success: #4FC98A;
    --color-success-soft: #17301F;
    --color-info: #6FA8DC;
    --color-info-soft: #1C2C3D;
    --color-neutral-soft: #232B39;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.35);
    --shadow-lift: 0 2px 4px rgba(0, 0, 0, 0.35), 0 12px 28px rgba(0, 0, 0, 0.45);
}

* {
    box-sizing: border-box;
}

/* This is the real, permanent fix for a bug that's bitten this project
   twice now: any class that sets "display: flex/grid/etc." will, at
   equal CSS specificity, override the browser's default "[hidden] {
   display: none }" rule, simply because it loads later in the
   cascade. Rather than adding a matching [hidden] override every time
   a new component needs a non-block display value (easy to forget —
   see .modal-overlay, .error-message, .success-message, .empty-state
   above, all of which needed this patched in individually), this one
   rule guarantees the hidden attribute always wins, everywhere,
   permanently. The individual [hidden] overrides above are now
   redundant but left in place as harmless documentation.
*/
[hidden] {
    display: none !important;
}

body {
    margin: 0;
    font-family: var(--font-body);
    background-color: var(--color-bg);
    color: var(--color-ink);
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
    font-family: var(--font-heading);
    font-weight: 700;
    color: var(--color-primary);
    letter-spacing: -0.01em;
    margin: 0 0 8px 0;
}

/* ---- Shared small pieces, used across every page ---- */

.badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--color-accent);
    background: var(--color-accent-soft);
    padding: 5px 11px;
    border-radius: var(--radius-full);
    margin-bottom: 16px;
}

.badge svg {
    width: 12px;
    height: 12px;
}

.subtitle {
    color: var(--color-ink-soft);
    margin-top: 0;
}

.error-message {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: var(--color-danger);
    background: var(--color-danger-soft);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    margin: 4px 0 4px 0;
    animation: fadeSlideIn var(--transition) ease-out;
}

.error-message[hidden] {
    display: none;
}

/* Same shape as .error-message, informational rather than an error —
   e.g. the Whish Money payment instructions on storefront checkout. */
.info-callout {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    font-size: 14px;
    color: var(--color-info);
    background: var(--color-info-soft);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    margin: 4px 0;
    animation: fadeSlideIn var(--transition) ease-out;
}

.info-callout[hidden] {
    display: none;
}

.info-callout svg {
    flex-shrink: 0;
    margin-top: 2px;
}

.error-message svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.primary-button,
.secondary-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 600;
    border-radius: var(--radius-sm);
    padding: 11px 20px;
    border: none;
    cursor: pointer;
    text-decoration: none;
    transition: background-color var(--transition), border-color var(--transition), transform var(--transition-fast), box-shadow var(--transition);
}

.primary-button svg,
.secondary-button svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.primary-button {
    background: var(--color-accent);
    color: #FFFFFF;
    box-shadow: 0 1px 2px rgba(107, 79, 224, 0.15);
}

.primary-button:hover {
    background: var(--color-accent-hover);
    box-shadow: 0 4px 10px rgba(107, 79, 224, 0.25);
}

.primary-button:active {
    transform: translateY(1px);
}

.primary-button:disabled {
    background: var(--color-border);
    color: var(--color-ink-soft);
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

/* Same shape/sizing as .primary-button/.secondary-button, but reserved
   for genuinely destructive or urgent actions — the driver's Emergency
   button, the confirm-send inside its modal. */
.danger-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    font-family: var(--font-body);
    font-size: 15px;
    font-weight: 600;
    border-radius: var(--radius-sm);
    padding: 11px 20px;
    border: none;
    cursor: pointer;
    text-decoration: none;
    background: var(--color-danger);
    color: #FFFFFF;
    box-shadow: 0 1px 2px rgba(192, 57, 43, 0.2);
    transition: background-color var(--transition), transform var(--transition-fast), box-shadow var(--transition);
}

.danger-button svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.danger-button:hover {
    background: #A8321F;
    box-shadow: 0 4px 10px rgba(192, 57, 43, 0.3);
}

.danger-button:active {
    transform: translateY(1px);
}

.danger-button:disabled {
    background: var(--color-border);
    color: var(--color-ink-soft);
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

.secondary-button {
    background: var(--color-surface);
    color: var(--color-primary);
    border: 1px solid var(--color-border);
}

.secondary-button:hover {
    background: var(--color-bg);
    border-color: var(--color-ink-soft);
}

.secondary-button:active {
    transform: translateY(1px);
}

/* ---- Portal selection page (the homepage) ---- */

.portal-select {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 24px;
    gap: 32px;
}

.portal-header {
    text-align: center;
    max-width: 480px;
}

.portal-cards {
    display: grid;
    grid-template-columns: repeat(3, minmax(180px, 220px));
    gap: 20px;
}

.portal-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 28px 24px;
    text-decoration: none;
    color: inherit;
    display: block;
    transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}

.portal-card:hover {
    border-color: var(--color-accent);
    box-shadow: var(--shadow-lift);
    transform: translateY(-2px);
}

.portal-card-icon {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-sm);
    background: var(--color-accent-soft);
    color: var(--color-accent);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 14px;
}

.portal-card-icon svg {
    width: 20px;
    height: 20px;
}

.portal-card h2 {
    color: var(--color-primary);
    margin-bottom: 8px;
}

.portal-card p {
    color: var(--color-ink-soft);
    font-size: 14px;
    margin: 0;
}

@media (max-width: 640px) {
    .portal-cards {
        grid-template-columns: 1fr;
        width: 100%;
        max-width: 320px;
    }
}

/* ---- Login pages (Admin, Shop, Driver) ---- */

.auth-page {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.auth-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 40px;
    max-width: 380px;
    width: 100%;
    display: flex;
    flex-direction: column;
}

.auth-card label {
    font-size: 13px;
    font-weight: 600;
    color: var(--color-ink);
    margin-top: 16px;
    margin-bottom: 6px;
}

.auth-card input {
    font-family: var(--font-body);
    font-size: 15px;
    padding: 10px 12px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-ink);
    transition: border-color var(--transition), box-shadow var(--transition), background-color var(--transition);
}

.auth-card input:focus {
    outline: none;
    border-color: var(--color-accent);
    background: var(--color-surface);
    box-shadow: 0 0 0 3px var(--color-accent-soft);
}

.auth-card .primary-button {
    margin-top: 24px;
}

.back-link {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    text-align: center;
    margin-top: 20px;
    font-size: 13px;
    color: var(--color-ink-soft);
    text-decoration: none;
    transition: color var(--transition-fast);
}

.back-link svg {
    width: 14px;
    height: 14px;
}

.back-link:hover {
    color: var(--color-accent);
}

/* ---- Placeholder dashboard pages ---- */

.dashboard-placeholder {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}

.dashboard-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 40px;
    max-width: 480px;
    width: 100%;
}

.dashboard-card .secondary-button {
    margin-top: 8px;
}

/* ---- Real dashboard layout ---- */

.dashboard {
    max-width: 1100px;
    margin: 0 auto;
    padding: 32px 24px 64px;
}

.dashboard-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 28px;
}

.dashboard-header h1 {
    margin: 0;
}

.panel {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 28px;
    margin-bottom: 24px;
    animation: fadeSlideIn var(--transition) ease-out;
}

.panel h2 {
    font-size: 18px;
    margin-bottom: 20px;
}

/* ---- Forms (new order, manage order, driver/shop forms) ---- */

.form-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px 20px;
}

.form-field {
    display: flex;
    flex-direction: column;
}

.form-field-wide {
    grid-column: 1 / -1;
}

.form-hint {
    font-size: 13px;
    color: var(--color-ink-soft);
}

.form-hint-success {
    color: var(--color-success);
}

.form-hint-error {
    color: var(--color-danger);
}

.location-field-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 14px;
}

.form-field label {
    font-size: 13px;
    font-weight: 600;
    color: var(--color-ink);
    margin-bottom: 6px;
}

.form-field input,
.form-field textarea,
.form-field select {
    font-family: var(--font-body);
    font-size: 15px;
    padding: 10px 12px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-ink);
    resize: vertical;
    transition: border-color var(--transition), box-shadow var(--transition), background-color var(--transition);
}

.form-field input:focus,
.form-field textarea:focus,
.form-field select:focus {
    outline: none;
    border-color: var(--color-accent);
    background: var(--color-surface);
    box-shadow: 0 0 0 3px var(--color-accent-soft);
}

.order-form .error-message,
.order-form .success-message {
    margin-top: 18px;
}

.success-message {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    color: var(--color-success);
    background: var(--color-success-soft);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    animation: fadeSlideIn var(--transition) ease-out;
}

.success-message[hidden] {
    display: none;
}

.success-message svg {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.order-form .primary-button {
    margin-top: 18px;
}

@media (max-width: 640px) {
    .form-grid {
        grid-template-columns: 1fr;
    }
}

/* ---- Tabs ---- */

.tabs {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--color-border);
    margin-bottom: 20px;
}

/* A tab bar with more than a couple of buttons (e.g. admin-expansion's
   four) doesn't fit a phone's width — rather than let it overflow the
   page or squish every label, it scrolls horizontally on its own,
   same "contain the overflow, don't fight it" approach as
   .table-scroll below. Labels stay intact and tappable instead of
   getting truncated or icon-only. */
@media (max-width: 640px) {
    .tabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    .tab-button {
        flex-shrink: 0;
    }
}

.tab-button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: 600;
    color: var(--color-ink-soft);
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    padding: 10px 4px;
    margin-right: 20px;
    cursor: pointer;
    transition: color var(--transition-fast), border-color var(--transition-fast);
}

.tab-button:hover {
    color: var(--color-primary);
}

.tab-button.active {
    color: var(--color-primary);
    border-bottom-color: var(--color-accent);
}

.tab-panel {
    padding-top: 4px;
    animation: fadeSlideIn var(--transition) ease-out;
}

/* ---- Tables ---- */

.table-scroll {
    overflow-x: auto;
}

/* A tall table (e.g. shop-reports.html's Delivery Cash Received list)
   otherwise just grows the whole page taller with every row — this
   caps it to a fixed viewport and scrolls internally instead, with
   the header pinned so column labels stay visible while scrolling. */
.table-scroll-bounded {
    max-height: 340px;
    overflow-y: auto;
}
.table-scroll-bounded thead th {
    position: sticky;
    top: 0;
    background: var(--color-surface);
    z-index: 1;
}

.orders-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}

.orders-table th {
    text-align: left;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--color-ink-soft);
    padding: 8px 10px;
    border-bottom: 1px solid var(--color-border);
    white-space: nowrap;
}

.orders-table td {
    padding: 12px 10px;
    border-bottom: 1px solid var(--color-border-soft);
    white-space: nowrap;
}

.orders-table tbody tr {
    transition: background-color var(--transition-fast);
}

.orders-table tbody tr:hover {
    background: var(--color-bg);
}

/* Rows that open a details view on click (see shop-dashboard.js's
   openOrderDetailsModal) — buttons inside them (Cancel, Start
   Preparing, etc.) still work as normal since the click handler skips
   anything inside .actions-cell or a prep-cell button. */
.orders-table tbody tr.order-row-clickable {
    cursor: pointer;
}

.orders-table tbody tr:last-child td {
    border-bottom: none;
}

/* The actions cell (row buttons like Cancel/Edit/Deactivate) pins to
   the right edge of .table-scroll instead of scrolling away with the
   rest of a wide row — a cashier or shop owner shouldn't have to
   scroll all the way across a 10-column order row just to reach the
   Cancel button. */
.orders-table th.actions-cell,
.orders-table td.actions-cell {
    position: sticky;
    right: 0;
    z-index: 1;
    background: var(--color-surface);
    box-shadow: -8px 0 12px -8px rgba(0, 0, 0, 0.18);
}

.orders-table tbody tr:hover td.actions-cell {
    background: var(--color-bg);
}

/* Purchase List (shop-inventory.html) above the card-layout breakpoint
   below: with up to 10 columns, its width was almost entirely driven
   by the HEADER labels ("Qty to Purchase", "Current Stock", etc.)
   forcing themselves onto one line via .orders-table th's own
   white-space: nowrap, even though every cell's actual data (a short
   number, a two-word select) needs far less room — letting the
   header text wrap, and giving the two free-width form controls
   (Paid/Supplier, native <select>s with no width of their own) a firm
   cap, was enough on its own to fit a normal desktop width with no
   horizontal scroll at all, without shrinking any real data. */
#purchaseListTable {
    font-size: 13px;
}
#purchaseListTable th {
    white-space: normal;
    line-height: 1.25;
    font-size: 10.5px;
}
#purchaseListTable td, #purchaseListTable th {
    padding: 8px 5px;
}
#purchaseListTable .purchase-payment-select {
    max-width: 92px;
}
#purchaseListTable .purchase-supplier-select {
    max-width: 110px;
}

/* Purchase List (shop-inventory.html) has too many columns (up to 10
   in ingredients mode) to ever fit a phone-width screen as a real
   table — below this width it drops the row/column grid entirely and
   restacks each row as its own card, one field per line via the
   row's own data-label attributes (set in shop-inventory.js's
   renderPurchaseListTable), so nothing needs a sideways drag to read
   or fill in. Scoped to this one table by id, not every .orders-table
   in the app, since every other table here still fits its own content
   fine within .table-scroll's ordinary horizontal scroll. */
@media (max-width: 640px) {
    #purchaseListTable thead {
        display: none;
    }
    #purchaseListTable, #purchaseListTable tbody, #purchaseListTable tr, #purchaseListTable td {
        display: block;
        width: 100%;
    }
    #purchaseListTable tbody tr {
        border: 1px solid var(--color-border);
        border-radius: 10px;
        padding: 10px 12px;
        margin-bottom: 10px;
    }
    #purchaseListTable tbody tr:last-child {
        margin-bottom: 0;
    }
    #purchaseListTable td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        white-space: normal;
        padding: 6px 0;
        border-bottom: 1px solid var(--color-border-soft);
    }
    #purchaseListTable td:last-child {
        border-bottom: none;
    }
    #purchaseListTable td::before {
        content: attr(data-label);
        font-size: 12px;
        font-weight: 600;
        letter-spacing: 0.03em;
        text-transform: uppercase;
        color: var(--color-ink-soft);
        flex-shrink: 0;
    }
    /* The name is this card's own title, not a label:value pair like
       every other field — full-width, no label, bolder. */
    #purchaseListTable td[data-label="Name"], #purchaseListTable td[data-label="Item"] {
        font-weight: 700;
        font-size: 15px;
    }
    #purchaseListTable td[data-label="Name"]::before, #purchaseListTable td[data-label="Item"]::before {
        content: none;
    }
    #purchaseListTable input, #purchaseListTable select {
        width: auto;
        max-width: 55%;
    }
}

/* Dispatcher's Current/Completed Orders tables (dispatcher-dashboard.html)
   — same "too many columns for their own header labels" problem as
   Purchase List above, made worse by two genuinely free-text columns
   (Customer, Address) that can run long. Same header-wrap/padding fix
   for the columns that fit fine once their labels can wrap, PLUS a
   firm cap + ellipsis on Customer/Address specifically — the full text
   is still one tap away via the row's own details modal (or a hover
   tooltip on desktop, via each cell's title attribute set in
   dispatcher-dashboard.js), so nothing is actually lost, just not
   forced to blow out the whole table's width for one long address. */
.dispatcher-orders-table {
    font-size: 12px;
}
.dispatcher-orders-table th {
    white-space: normal;
    line-height: 1.25;
    font-size: 10px;
}
.dispatcher-orders-table td, .dispatcher-orders-table th {
    padding: 7px 4px;
}
.dispatcher-orders-table td[data-label="Customer"] {
    max-width: 110px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dispatcher-orders-table td[data-label="Address"] {
    max-width: 170px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Fee/COD use CurrencyKit.dualHtml() (not .dual()) specifically in this
   table: the L.L. amount renders as a block-level .dual-lbp span, which
   always drops to its own line below the USD figure instead of competing
   with it for horizontal space, so the column only needs to be as wide
   as the longer of the two lines rather than both combined. */
.dispatcher-orders-table td[data-label="Fee"],
.dispatcher-orders-table td[data-label="COD"] {
    max-width: 80px;
}
.dispatcher-orders-table .dual-lbp {
    display: block;
    font-size: 10.5px;
    font-weight: 500;
    color: var(--color-ink-soft);
    margin-top: 1px;
}
/* Created/Last Updated is a full localized date+time string — too long
   to fit one line at this column budget. Rather than truncate part of a
   timestamp (misleading) it's allowed to wrap onto two lines. */
.dispatcher-orders-table td[data-label="Created"],
.dispatcher-orders-table td[data-label="Last Updated"] {
    max-width: 88px;
    white-space: normal;
    line-height: 1.3;
}
/* Prep's "Start Preparing"/"Mark Ready" button label is allowed to wrap
   the same way, and shrinks slightly further since it's a UI label, not
   data. */
.dispatcher-orders-table td[data-label="Prep"] {
    max-width: 90px;
}
.dispatcher-orders-table td[data-label="Prep"] .text-button {
    font-size: 11px;
    white-space: normal;
    text-align: left;
}

/* Below phone width, drop the grid entirely and restack each order as
   its own card — same technique and same reasoning as #purchaseListTable
   above (see that block's own comment). Customer/Address go back to
   wrapping normally here instead of the desktop ellipsis, since a
   stacked card has no row-width to protect. */
@media (max-width: 640px) {
    .dispatcher-orders-table thead {
        display: none;
    }
    .dispatcher-orders-table, .dispatcher-orders-table tbody, .dispatcher-orders-table tr, .dispatcher-orders-table td {
        display: block;
        width: 100%;
    }
    .dispatcher-orders-table tbody tr {
        border: 1px solid var(--color-border);
        border-radius: 10px;
        padding: 10px 12px;
        margin-bottom: 10px;
    }
    .dispatcher-orders-table tbody tr:last-child {
        margin-bottom: 0;
    }
    .dispatcher-orders-table td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        max-width: none;
        overflow: visible;
        text-overflow: clip;
        white-space: normal;
        padding: 6px 0;
        border-bottom: 1px solid var(--color-border-soft);
    }
    .dispatcher-orders-table td:last-child {
        border-bottom: none;
    }
    .dispatcher-orders-table td::before {
        content: attr(data-label);
        font-size: 12px;
        font-weight: 600;
        letter-spacing: 0.03em;
        text-transform: uppercase;
        color: var(--color-ink-soft);
        flex-shrink: 0;
    }
    .dispatcher-orders-table td[data-label="Order #"] {
        font-weight: 700;
        font-size: 15px;
    }
    .dispatcher-orders-table td[data-label="Order #"]::before {
        content: none;
    }
    .dispatcher-orders-table td.actions-cell {
        justify-content: flex-start;
        flex-wrap: wrap;
        position: static;
        box-shadow: none;
    }
    .dispatcher-orders-table td[data-label="Prep"] .text-button {
        font-size: 13px;
        text-align: right;
    }
}

/* Same card-stacking treatment as .dispatcher-orders-table above,
   generalized as a reusable class instead of tied to one page — used
   by admin-expansion.html's Today/Prospects tables, each of which has
   too many columns (up to 10, on Prospects) to stay readable at phone
   width even with .table-scroll's horizontal scroll. */
@media (max-width: 640px) {
    .expansion-table thead {
        display: none;
    }
    .expansion-table, .expansion-table tbody, .expansion-table tr, .expansion-table td {
        display: block;
        width: 100%;
    }
    .expansion-table tbody tr {
        border: 1px solid var(--color-border);
        border-radius: 10px;
        padding: 10px 12px;
        margin-bottom: 10px;
    }
    .expansion-table tbody tr:last-child {
        margin-bottom: 0;
    }
    .expansion-table td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        white-space: normal;
        text-align: right;
        padding: 6px 0;
        border-bottom: 1px solid var(--color-border-soft);
    }
    .expansion-table td:last-child {
        border-bottom: none;
    }
    .expansion-table td::before {
        content: attr(data-label);
        font-size: 12px;
        font-weight: 600;
        letter-spacing: 0.03em;
        text-transform: uppercase;
        color: var(--color-ink-soft);
        flex-shrink: 0;
        text-align: left;
    }
    .expansion-table td[data-label="Business"] {
        font-weight: 700;
        font-size: 15px;
    }
    .expansion-table td[data-label="Business"]::before {
        content: none;
    }
    .expansion-table td.actions-cell {
        justify-content: flex-start;
        flex-wrap: wrap;
        position: static;
        box-shadow: none;
    }
}

/* Same card-stacking treatment again, for admin-subscriptions.html's
   Billing/Fees tables — copied rather than shared with
   .expansion-table since the two pages' tables have different
   emphasized first column, but otherwise identical. */
@media (max-width: 640px) {
    .subscriptions-table thead {
        display: none;
    }
    .subscriptions-table, .subscriptions-table tbody, .subscriptions-table tr, .subscriptions-table td {
        display: block;
        width: 100%;
    }
    .subscriptions-table tbody tr {
        border: 1px solid var(--color-border);
        border-radius: 10px;
        padding: 10px 12px;
        margin-bottom: 10px;
    }
    .subscriptions-table tbody tr:last-child {
        margin-bottom: 0;
    }
    .subscriptions-table td {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        white-space: normal;
        text-align: right;
        padding: 6px 0;
        border-bottom: 1px solid var(--color-border-soft);
    }
    .subscriptions-table td:last-child {
        border-bottom: none;
    }
    .subscriptions-table td::before {
        content: attr(data-label);
        font-size: 12px;
        font-weight: 600;
        letter-spacing: 0.03em;
        text-transform: uppercase;
        color: var(--color-ink-soft);
        flex-shrink: 0;
        text-align: left;
    }
    .subscriptions-table td[data-label="Business"] {
        font-weight: 700;
        font-size: 15px;
    }
    .subscriptions-table td[data-label="Business"]::before {
        content: none;
    }
    .subscriptions-table td.actions-cell {
        justify-content: flex-start;
        flex-wrap: wrap;
        position: static;
        box-shadow: none;
    }
}

.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
    color: var(--color-ink-soft);
    font-size: 14px;
    padding: 40px 0;
}

.empty-state[hidden] {
    display: none;
}

.empty-state svg {
    width: 32px;
    height: 32px;
    color: var(--color-border);
}

.text-button {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    color: var(--color-accent);
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    transition: color var(--transition-fast);
}

.text-button svg {
    width: 14px;
    height: 14px;
}

.text-button:hover {
    text-decoration: underline;
}

/* ---- Status badges ---- */

.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    font-weight: 600;
    padding: 4px 10px;
    border-radius: var(--radius-full);
    white-space: nowrap;
}

.status-badge svg {
    width: 11px;
    height: 11px;
}

.status-new {
    background: var(--color-neutral-soft);
    color: var(--color-primary);
}

.status-assigned {
    background: var(--color-warning-soft);
    color: var(--color-warning);
}

.status-progress {
    background: var(--color-info-soft);
    color: var(--color-info);
}

.status-success {
    background: var(--color-accent-soft);
    color: var(--color-success);
}

.status-cancelled {
    background: var(--color-danger-soft);
    color: var(--color-danger);
}

/* ---- Admin dashboard stats ---- */

.stats-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 24px;
}

.stat-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    transition: box-shadow var(--transition), transform var(--transition);
}

.stat-card:hover {
    box-shadow: var(--shadow-lift);
    transform: translateY(-1px);
}

.stat-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--color-ink-soft);
}

.stat-label svg {
    width: 14px;
    height: 14px;
    color: var(--color-accent);
}

.stat-value {
    font-size: 30px;
    font-weight: 700;
    color: var(--color-primary);
}

/* CurrencyKit.dualHtml() values ("$1,029.00" + a muted "(92,610,000
   L.L.)" line) run much longer than the plain-USD figures .stat-value
   was sized for elsewhere in the app — at the default 30px on one
   line this overflows a narrow card in a 4-up grid. Sized down and
   the .dual-lbp span (below) breaks onto its own smaller line instead
   of the two currencies competing for space at equal size. */
.stats-grid-dual-currency .stat-value {
    font-size: clamp(17px, 2vw, 24px);
    line-height: 1.25;
    overflow-wrap: break-word;
}

.stats-grid-dual-currency .stat-value .dual-lbp {
    display: block;
    font-size: 13px;
    font-weight: 600;
    color: var(--color-ink-soft);
    margin-top: 2px;
}

/* Cards in this row can end up taller than their content (e.g. a
   short "66" next to a wrapped two-line dual-currency figure) since
   grid rows stretch every card to match the tallest — center each
   card's content instead of leaving it pinned to the top with dead
   space below. */
.stats-grid-dual-currency .stat-card {
    justify-content: center;
}

.cash-balance-figure {
    font-size: 44px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--color-warning);
}

@media (max-width: 800px) {
    .stats-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 480px) {
    .stats-grid {
        grid-template-columns: 1fr;
    }
}

/* ---- Panel header row (title + filter dropdown) ---- */

.panel-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 20px;
}

.panel-header-row h2 {
    margin-bottom: 0;
}

/* A panel-header h2 wrapped in a button, so the whole title row toggles
   a collapsible section below it (see shop-dashboard.js's storefront
   panel) — reset all the default button chrome so it reads exactly
   like the plain, non-interactive h2 it replaces. */
.panel-collapse-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
    text-align: left;
}

/* Rotated on its own <span> wrapper rather than directly on the lucide
   <svg> icon — CSS transform on a root <svg> element computes
   unreliably in some environments, a plain HTML element doesn't have
   that problem. */
.panel-collapse-chevron {
    display: inline-flex;
    flex-shrink: 0;
    transition: transform var(--transition-fast);
}

.panel-collapse-chevron svg {
    width: 18px;
    height: 18px;
    color: var(--color-ink-soft);
}

.panel-collapse-toggle[aria-expanded="true"] .panel-collapse-chevron {
    transform: rotate(90deg);
}

.filter-select {
    font-family: var(--font-body);
    font-size: 14px;
    padding: 8px 10px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-ink);
    transition: border-color var(--transition-fast);
}

.filter-select:focus {
    outline: none;
    border-color: var(--color-accent);
}

.actions-cell {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
}

.danger-text {
    color: var(--color-danger);
}

.prep-timer {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--color-warning);
}

/* ---- Modal ---- */

.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(32, 41, 66, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    z-index: 100;
    animation: fadeIn var(--transition) ease-out;
}

/* Without this, the hidden attribute has no effect: an author
   stylesheet rule like "display: flex" above beats the browser's
   built-in "[hidden] { display: none }" rule at equal specificity,
   since ours loads later in the cascade. This rule restores it. */
.modal-overlay[hidden] {
    display: none;
}

.modal {
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lift);
    padding: 32px;
    max-width: 560px;
    width: 100%;
    max-height: 90vh;
    overflow-y: auto;
    animation: modalPopIn var(--transition) ease-out;
}

.modal h2 {
    font-size: 18px;
    margin-bottom: 20px;
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 20px;
}

.modal-header h2 {
    margin-bottom: 0;
}

.modal-close-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: var(--radius-full);
    border: none;
    background: none;
    color: var(--color-ink-soft);
    cursor: pointer;
    transition: background-color var(--transition-fast), color var(--transition-fast);
}

.modal-close-btn:hover {
    background: var(--color-bg);
    color: var(--color-ink);
}

.modal-close-btn svg {
    width: 18px;
    height: 18px;
}

.modal .error-message {
    margin-top: 16px;
}

.modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    margin-top: 24px;
}

/* ---- Order timeline (Manage Order modal) ---- */

.order-timeline {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 20px;
    padding: 16px;
    background: var(--color-bg);
    border-radius: var(--radius-sm);
}

.timeline-item {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13px;
}

.timeline-item svg {
    width: 15px;
    height: 15px;
    color: var(--color-accent);
    flex-shrink: 0;
}

.timeline-item-label {
    font-weight: 600;
    color: var(--color-ink);
}

.timeline-item-time {
    color: var(--color-ink-soft);
    margin-left: auto;
    white-space: nowrap;
}

/* ---- Search + sort controls above tables ---- */

.table-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 16px;
}

.search-input-wrap {
    position: relative;
    flex: 1;
    min-width: 200px;
}

.search-input-wrap svg {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    width: 15px;
    height: 15px;
    color: var(--color-ink-soft);
    pointer-events: none;
}

.search-input-wrap input {
    width: 100%;
    font-family: var(--font-body);
    font-size: 14px;
    padding: 9px 12px 9px 34px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-ink);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.search-input-wrap input:focus {
    outline: none;
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px var(--color-accent-soft);
}

/* ---- Printing a single order ---- */

.print-only {
    display: none;
}

@media print {
    body * {
        visibility: hidden;
    }
    .print-only, .print-only * {
        visibility: visible;
    }
    .print-only {
        display: block;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        padding: 24px;
    }
    .print-only h2 {
        margin-bottom: 4px;
    }
    .print-only table {
        width: 100%;
        border-collapse: collapse;
        margin-top: 16px;
    }
    .print-only td {
        padding: 6px 4px;
        border-bottom: 1px solid #ccc;
        font-size: 13px;
    }
    .print-only td:first-child {
        font-weight: 600;
        width: 160px;
    }

    /* The rule above was written for the single-order label/value
       table (admin-dashboard.js's printArea) — wrong for a real
       multi-column table like the cash movements report, where the
       first column is just a timestamp like any other cell. */
    .print-only table.report-table td:first-child {
        font-weight: normal;
        width: auto;
    }

    /* visibility:hidden keeps an element's box in the layout (unlike
       display:none), so the full-height dashboard behind .print-only
       was still forcing extra blank pages based on its own height —
       collapse it outright so pagination is based on the printed
       content alone. */
    .dashboard {
        display: none !important;
    }
    /* Text inherits --color-ink, which is a near-white color under
       the dark theme — fine on a dark screen, but it printed as
       barely-visible pale gray on white paper. Force solid ink
       regardless of which theme is active on screen. */
    :root, [data-theme="dark"] {
        --color-ink: #000000;
        --color-ink-soft: #333333;
    }
}

/* ---- Toast notifications ---- */

.toast-container {
    position: fixed;
    bottom: 24px;
    right: 24px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    z-index: 200;
    max-width: calc(100vw - 48px);
}

.toast {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--color-surface);
    color: var(--color-ink);
    border: 1px solid var(--color-border);
    border-left: 4px solid var(--color-accent);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lift);
    padding: 12px 16px;
    font-size: 14px;
    min-width: 240px;
    max-width: 360px;
    animation: toastIn var(--transition) ease-out;
}

.toast.toast-leaving {
    animation: toastOut var(--transition) ease-in forwards;
}

.toast svg {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
}

.toast-success {
    border-left-color: var(--color-success);
}

.toast-success svg {
    color: var(--color-success);
}

.toast-error {
    border-left-color: var(--color-danger);
}

.toast-error svg {
    color: var(--color-danger);
}

.toast-info svg {
    color: var(--color-accent);
}

@media (max-width: 480px) {
    .toast-container {
        left: 16px;
        right: 16px;
        bottom: 16px;
    }

    .toast {
        min-width: 0;
        max-width: none;
        width: 100%;
    }
}

/* ---- Skeleton loaders ---- */

.skeleton-row td {
    padding: 12px 10px;
}

.skeleton-bar {
    height: 14px;
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg, var(--color-border-soft) 25%, var(--color-border) 37%, var(--color-border-soft) 63%);
    background-size: 400% 100%;
    animation: skeletonShimmer 1.4s ease infinite;
}

.skeleton-bar--short {
    width: 60%;
}

.skeleton-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    padding: 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* ---- Motion ---- */

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes fadeSlideIn {
    from { opacity: 0; transform: translateY(4px); }
    to { opacity: 1; transform: translateY(0); }
}

@keyframes modalPopIn {
    from { opacity: 0; transform: scale(0.96) translateY(6px); }
    to { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes toastIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

@keyframes toastOut {
    from { opacity: 1; transform: translateY(0); }
    to { opacity: 0; transform: translateY(8px); }
}

@keyframes skeletonShimmer {
    0% { background-position: 100% 0; }
    100% { background-position: 0 0; }
}

@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
    }
}

/* ---- Menu items (Shop's own catalog) ---- */

.category-heading {
    font-size: 15px;
    font-weight: 700;
    color: var(--color-primary);
    margin: 24px 0 12px 0;
}

.category-heading:first-child {
    margin-top: 0;
}

.menu-items-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 16px;
    margin-bottom: 8px;
}

.menu-item-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-card);
    display: flex;
    flex-direction: column;
    transition: box-shadow var(--transition), transform var(--transition);
}

.menu-item-card:hover {
    box-shadow: var(--shadow-lift);
    transform: translateY(-2px);
}

.menu-item-card.menu-item-unavailable {
    opacity: 0.6;
}

.menu-item-image,
.menu-item-image-placeholder {
    width: 100%;
    height: 140px;
    background: var(--color-bg);
}

.menu-item-image {
    object-fit: cover;
    display: block;
}

.menu-item-image-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-border);
}

.menu-item-image-placeholder svg {
    width: 36px;
    height: 36px;
}

.menu-item-body {
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
}

.menu-item-name-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}

.menu-item-name {
    font-weight: 600;
    color: var(--color-ink);
    min-width: 0;
}

/* CurrencyKit.dual() values ("$1,029.00 (92,610,000 L.L.)") are much
   longer than a plain price and don't fit on one line in a 220px-min
   card — wrap and shrink instead of overflowing past the card edge. */
.menu-item-price {
    font-weight: 700;
    color: var(--color-primary);
    font-size: clamp(12px, 3vw, 15px);
    text-align: right;
    overflow-wrap: break-word;
    flex-shrink: 0;
    max-width: 45%;
}

.menu-item-description {
    font-size: 13px;
    color: var(--color-ink-soft);
}

.menu-item-meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 12px;
    color: var(--color-ink-soft);
    margin-top: 4px;
}

.badge-popular {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 11px;
    font-weight: 700;
    color: var(--color-warning);
    background: var(--color-warning-soft);
    padding: 2px 8px;
    border-radius: var(--radius-full);
}

.badge-popular svg {
    width: 11px;
    height: 11px;
}

.menu-item-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    padding: 10px 16px;
    border-top: 1px solid var(--color-border-soft);
}

/* ---- Extras editor (inside Add/Edit Item modal) ---- */

.extra-row {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}

.extra-row input.extra-nutrition-input {
    flex: 0 0 60px;
}

.extra-row input[type="text"] {
    flex: 2;
    font-family: var(--font-body);
    font-size: 14px;
    padding: 8px 10px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-ink);
}

.extra-row input[type="number"] {
    flex: 1;
    font-family: var(--font-body);
    font-size: 14px;
    padding: 8px 10px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-ink);
}

/* ---- Ingredient/Variant rows (inside Add/Edit Item modal, and the
   extra-row's own optional ingredient link) — same row layout as
   .extra-row above, just also covering <select>. ---- */

.ingredient-row, .variant-row {
    display: flex;
    gap: 8px;
    align-items: center;
    flex-wrap: wrap;
}

.ingredient-row input, .ingredient-row select,
.variant-row input, .variant-row select,
.extra-row select {
    font-family: var(--font-body);
    font-size: 14px;
    padding: 8px 10px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-bg);
    color: var(--color-ink);
}

.variant-row input:disabled {
    color: var(--color-ink-soft);
    cursor: not-allowed;
}

/* ---- Item picker (New Order form) ---- */

.menu-picker-categories {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 10px;
}

.menu-picker-category-pill {
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    color: var(--color-ink-soft);
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-full);
    padding: 5px 12px;
    cursor: pointer;
    transition: background-color var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}

.menu-picker-category-pill:hover {
    border-color: var(--color-accent);
}

.menu-picker-category-pill.active {
    background: var(--color-accent);
    border-color: var(--color-accent);
    color: #fff;
}

.menu-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 8px;
    max-height: 320px;
    overflow-y: auto;
    padding: 2px;
}

.menu-picker-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    text-align: left;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    cursor: pointer;
    transition: border-color var(--transition-fast), background-color var(--transition-fast);
}

.menu-picker-card:hover {
    border-color: var(--color-accent);
    background: var(--color-accent-soft);
}

.menu-picker-card-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--color-ink);
    line-height: 1.3;
}

.menu-picker-card-price {
    font-size: 12px;
    color: var(--color-ink-soft);
}

.order-items-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 12px 0;
}

.order-items-list-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 8px 12px;
    background: var(--color-bg);
    border-radius: var(--radius-sm);
    font-size: 14px;
}

.cart-qty-stepper {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.cart-qty-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    color: var(--color-primary);
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.cart-qty-btn:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
}

.order-items-subtotal {
    display: flex;
    justify-content: space-between;
    font-weight: 700;
    padding: 8px 12px;
    font-size: 14px;
    color: var(--color-primary);
}

/* ---- Real-time connection indicator ---- */

.connection-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    color: var(--color-ink-soft);
}

.connection-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-ink-soft);
    flex-shrink: 0;
}

.connection-connected .connection-dot {
    background: var(--color-success);
}
.connection-connected .connection-text {
    color: var(--color-success);
}

.connection-reconnecting .connection-dot {
    background: var(--color-warning);
    animation: connectionPulse 1s ease-in-out infinite;
}
.connection-reconnecting .connection-text {
    color: var(--color-warning);
}

.connection-disconnected .connection-dot {
    background: var(--color-danger);
}
.connection-disconnected .connection-text {
    color: var(--color-danger);
}

@keyframes connectionPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

/* ---- Notification bell ---- */

.notification-bell-wrap {
    position: relative;
}

.notification-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    background: var(--color-danger);
    color: #FFFFFF;
    font-size: 10px;
    font-weight: 700;
    min-width: 16px;
    height: 16px;
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 4px;
    pointer-events: none;
}

/* A small header chip linking to /portal/driver/profile — a round
   photo (or a fallback icon when the driver hasn't set one) plus their
   first name, styled to sit alongside the other icon buttons in
   .actions-cell. */
.profile-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px 6px 6px;
    border-radius: var(--radius-full);
    border: 1px solid var(--color-border);
    background: var(--color-surface);
    color: var(--color-text);
    text-decoration: none;
    font-size: 13px;
    font-weight: 600;
}

.profile-chip:hover {
    background: var(--color-surface-alt, var(--color-bg-soft));
}

.profile-chip-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    object-fit: cover;
    background: var(--color-primary-soft, var(--color-border-soft));
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.profile-chip-avatar img {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
}

.profile-chip-avatar i {
    width: 16px;
    height: 16px;
    color: var(--color-primary);
}

/* position/top/left/width/max-height are all set in JS (see
   public/js/notifications.js's positionDropdown()) every time this
   opens — the bell is rarely the last button in the header's row (more
   nav buttons usually follow it), so a fixed CSS `right: 0` anchored to
   the bell's own narrow wrapper routinely pushed this off the LEFT edge
   of the screen, leaving it mostly invisible. position: fixed +
   viewport-clamped coordinates computed at open-time is the only way
   to guarantee this stays fully on-screen regardless of where the bell
   ends up sitting in the header, on any screen size — so there's no
   separate mobile breakpoint needed here either, the same JS logic
   handles both. */
.notification-dropdown {
    position: fixed;
    overflow-y: auto;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lift);
    z-index: 150;
}

.notification-dropdown-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--color-border);
    font-weight: 600;
    font-size: 13px;
    color: var(--color-primary);
}

.notification-item {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--color-border-soft);
    cursor: pointer;
    transition: background-color var(--transition-fast);
}

.notification-item:last-child {
    border-bottom: none;
}

.notification-item:hover {
    background: var(--color-bg);
}

.notification-item.unread {
    background: var(--color-accent-soft);
}

.notification-item-title {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--color-ink);
}

.notification-item-body {
    font-size: 12px;
    color: var(--color-ink-soft);
}

.notification-item-time {
    font-size: 11px;
    color: var(--color-ink-soft);
}

.notification-priority-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--color-danger);
    flex-shrink: 0;
}

/* ---- Shop pickup-location banner ---- */

.location-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 12px;
    padding: 12px 18px;
    border-radius: var(--radius-sm);
    margin-bottom: 20px;
    font-size: 14px;
}

.location-banner-text {
    display: flex;
    align-items: center;
    gap: 8px;
}

.location-banner.location-unset {
    background: var(--color-warning-soft);
    color: var(--color-warning);
}

.location-banner.location-set {
    background: var(--color-success-soft);
    color: var(--color-success);
}

/* ---- Emergency alert banner (admin) ---- */

@keyframes emergencyPulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}

.emergency-banner {
    background: var(--color-danger-soft);
    border: 2px solid var(--color-danger);
    border-radius: var(--radius-lg);
    padding: 16px 20px;
    margin-bottom: 24px;
}

.emergency-banner-header {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 15px;
    font-weight: 700;
    color: var(--color-danger);
    margin-bottom: 12px;
}

.emergency-banner-icon {
    width: 20px;
    height: 20px;
    animation: emergencyPulse 1.2s ease-in-out infinite;
}

.emergency-alert-item {
    background: var(--color-surface);
    border: 1px solid var(--color-danger);
    border-radius: var(--radius-sm);
    padding: 12px 14px;
    margin-bottom: 10px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px 16px;
}

.emergency-alert-item:last-child {
    margin-bottom: 0;
}

.emergency-alert-main {
    flex: 1;
    min-width: 220px;
    font-size: 13px;
}

.emergency-alert-main strong {
    font-size: 14px;
    color: var(--color-ink);
}

.emergency-alert-time {
    color: var(--color-ink-soft);
    margin-left: 8px;
}

.emergency-alert-detail {
    color: var(--color-ink-soft);
    margin-top: 3px;
}

.emergency-alert-actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

/* ---- Dispatch offer popup (driver) ---- */

.dispatch-offer-modal {
    max-width: 380px;
    border: 2px solid var(--color-accent);
    box-shadow: var(--shadow-lift);
}

.dispatch-offer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px 0 20px;
}

.dispatch-offer-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 700;
    color: var(--color-accent);
}

.dispatch-offer-badge svg {
    width: 15px;
    height: 15px;
}

.dispatch-countdown-text {
    font-size: 20px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--color-warning);
}

.dispatch-countdown-bar-track {
    height: 5px;
    background: var(--color-border-soft);
    margin: 10px 20px 0 20px;
    border-radius: var(--radius-full);
    overflow: hidden;
}

.dispatch-countdown-bar-fill {
    height: 100%;
    width: 100%;
    background: var(--color-accent);
    border-radius: var(--radius-full);
}

.dispatch-countdown-bar-fill.dispatch-countdown-running {
    transition: width 20s linear, background-color 4s linear;
    width: 0%;
    background: var(--color-danger);
}

.dispatch-offer-body {
    padding: 18px 20px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.dispatch-offer-body h3 {
    font-size: 19px;
    font-weight: 700;
    color: var(--color-ink);
}

.dispatch-offer-detail {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    font-size: 14px;
    color: var(--color-ink-soft);
}

.dispatch-offer-detail svg {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    margin-top: 2px;
    color: var(--color-primary);
}

.dispatch-offer-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 16px 24px;
    margin-top: 6px;
    padding-top: 12px;
    border-top: 1px solid var(--color-border-soft);
}

.dispatch-offer-stats > div {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.dispatch-stat-label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--color-ink-soft);
}

.dispatch-stat-value {
    font-size: 18px;
    font-weight: 700;
    color: var(--color-ink);
}

.dispatch-order-id {
    font-size: 12px;
    color: var(--color-ink-soft);
}

.dispatch-offer-actions {
    display: flex;
    gap: 10px;
    padding: 0 20px 20px 20px;
}

.dispatch-offer-actions button {
    flex: 1;
}

/* ---- Guided status-update stepper (driver dashboard) ---- */

.status-step-tracker {
    display: flex;
    align-items: flex-start;
    padding: 4px 8px 20px;
}

.status-step {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
    position: relative;
}

.status-step:not(:first-child)::before {
    content: '';
    position: absolute;
    top: 17px;
    right: 50%;
    width: 100%;
    height: 2px;
    background: var(--color-border);
    z-index: 0;
}

.status-step.is-done:not(:first-child)::before,
.status-step.is-current:not(:first-child)::before {
    background: var(--color-accent);
}

.status-step-dot {
    width: 34px;
    height: 34px;
    border-radius: var(--radius-full);
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-neutral-soft);
    color: var(--color-ink-soft);
    position: relative;
    z-index: 1;
    flex: none;
}

.status-step-dot svg {
    width: 16px;
    height: 16px;
}

.status-step.is-done .status-step-dot {
    background: var(--color-accent);
    color: #fff;
}

.status-step.is-current .status-step-dot {
    background: var(--color-primary);
    color: #fff;
    box-shadow: 0 0 0 4px var(--color-accent-soft);
}

.status-step-label {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--color-ink-soft);
}

.status-step.is-current .status-step-label {
    color: var(--color-ink);
}

.status-step-context {
    font-size: 13.5px;
    color: var(--color-ink-soft);
    background: var(--color-bg);
    border-radius: var(--radius-sm);
    padding: 12px 14px;
    margin: 0 0 16px;
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.status-step-context svg {
    width: 15px;
    height: 15px;
    flex: none;
    margin-top: 2px;
    color: var(--color-ink-soft);
}

.status-step-navigate {
    margin: 0 0 16px;
}

.status-step-navigate a {
    width: 100%;
    justify-content: center;
}

/* ---- POS Register ---- */

.pos-layout {
    display: grid;
    grid-template-columns: 1fr 340px;
    gap: 20px;
    align-items: start;
}
@media (max-width: 900px) {
    .pos-layout { grid-template-columns: 1fr; }
}

.pos-category-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 16px;
}
.pos-category-tab {
    font-family: var(--font-body);
    font-size: 13px;
    font-weight: 600;
    color: var(--color-ink-soft);
    background: var(--color-neutral-soft);
    border: 1px solid transparent;
    border-radius: var(--radius-full);
    padding: 7px 14px;
    cursor: pointer;
}
.pos-category-tab.active {
    color: #fff;
    background: var(--color-primary);
}

.pos-product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 12px;
}
.pos-product-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 12px;
    text-align: left;
    cursor: pointer;
    box-shadow: var(--shadow-sm);
    transition: box-shadow var(--transition-fast), transform var(--transition-fast);
}
.pos-product-card:hover {
    box-shadow: var(--shadow-lift);
    transform: translateY(-1px);
}
.pos-product-card img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--radius-sm);
    margin-bottom: 8px;
    background: var(--color-neutral-soft);
}
.pos-product-name {
    font-weight: 600;
    font-size: 14px;
    color: var(--color-ink);
    margin: 0 0 4px;
}
.pos-product-price {
    font-weight: 700;
    font-size: 14px;
    color: var(--color-accent);
    margin: 0;
}

.pos-cart {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: 16px;
    position: sticky;
    top: 16px;
}
.pos-cart h3 {
    margin: 0 0 12px;
    font-size: 16px;
}
.pos-cart-line {
    display: flex;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 0;
    border-bottom: 1px solid var(--color-border-soft);
    font-size: 14px;
}
.pos-cart-line-info { flex: 1; }
.pos-cart-line-name { font-weight: 600; color: var(--color-ink); }
.pos-cart-line-extras { font-size: 12px; color: var(--color-ink-soft); }
.pos-cart-line-remove {
    width: 24px; height: 24px;
    border-radius: var(--radius-full);
    border: 1px solid var(--color-border);
    background: var(--color-surface);
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    flex: none;
}
.pos-cart-total {
    display: flex;
    justify-content: space-between;
    font-size: 18px;
    font-weight: 700;
    padding: 14px 0;
    margin-top: 4px;
    border-top: 1px solid var(--color-border);
}

/* A Subtotal/Discount row (see #posSubtotalRow/#posDiscountAmountRow)
   is smaller/lighter than the final Total below it — only the actual
   amount due should read as the "big number" on the register. */
.pos-cart-total.pos-cart-subtotal-row {
    font-size: 14px;
    font-weight: 500;
    color: var(--color-ink-soft);
    padding: 4px 0;
    margin-top: 0;
    border-top: none;
}

.pos-discount-row {
    display: flex;
    gap: 8px;
    margin-top: 8px;
}

.pos-discount-row select {
    flex: 1;
}

.pos-discount-row input {
    width: 90px;
}

.pos-extras-picker {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 12px 0;
}
.pos-extras-picker label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 500;
}

.pos-qty-stepper {
    display: flex;
    align-items: center;
    gap: 10px;
    justify-content: center;
    margin: 12px 0;
}
.pos-qty-stepper button {
    width: 32px; height: 32px;
    border-radius: var(--radius-full);
    border: 1px solid var(--color-border);
    background: var(--color-surface);
    font-size: 16px;
    cursor: pointer;
}
.pos-qty-stepper span {
    font-size: 18px;
    font-weight: 700;
    min-width: 24px;
    text-align: center;
}

.pos-payment-methods {
    display: flex;
    gap: 8px;
    margin-bottom: 16px;
}
/* .store-payment-btn/.dine-in-payment-method-btn/.cash-direction-btn
   all share this exact look but each needs its own class — every one
   of these toggles' JS scopes its click handler to the class name
   alone, not the data attribute, so reusing a class would make two
   unrelated toggles fight over each other's active state. */
.pos-payment-method-btn,
.store-payment-btn,
.dine-in-payment-method-btn,
.cash-direction-btn {
    flex: 1;
    padding: 12px;
    border-radius: var(--radius-sm);
    border: 1.5px solid var(--color-border);
    background: var(--color-surface);
    font-weight: 600;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}
.pos-payment-method-btn.active,
.store-payment-btn.active,
.dine-in-payment-method-btn.active,
.cash-direction-btn.active {
    border-color: var(--color-accent);
    background: var(--color-accent-soft);
    color: var(--color-accent);
}

/* The Daily/Monthly/Yearly granularity toggle on the shop Reports
   page's Sales Performance panel — a lighter-weight active state than
   .pos-payment-method-btn etc. above, since these sit inline next to
   plain text labels rather than as large tap-target cards. */
.view-btn.active {
    border-color: var(--color-accent);
    background: var(--color-accent-soft);
    color: var(--color-accent);
}

.pos-receipt {
    font-family: 'Courier New', monospace;
    font-size: 13px;
}
.pos-receipt-line {
    display: flex;
    justify-content: space-between;
    padding: 4px 0;
}
.pos-receipt-total {
    border-top: 1px dashed var(--color-border);
    margin-top: 8px;
    padding-top: 8px;
    font-weight: 700;
}

.pos-receipt-header {
    text-align: center;
    padding-bottom: 10px;
    margin-bottom: 8px;
    border-bottom: 1px dashed var(--color-border);
}
.pos-receipt-logo {
    width: 64px;
    height: 64px;
    object-fit: contain;
    margin: 0 auto 6px;
    display: block;
}
.pos-receipt-shop-name {
    font-weight: 700;
    font-size: 14px;
}
/* Same size/weight as the rest of the receipt (.pos-receipt is 13px
   regular) rather than the smaller/lighter treatment this line and
   .pos-receipt-powered-by originally had — a thermal printer's
   ~203 DPI print head doesn't have enough dots to render small, thin
   glyphs as solid black; they come out as faint, sparse dithering no
   matter what color they're nominally set to. Confirmed on a real
   receipt: the always-13px+/bold lines (shop name, item lines, Total)
   printed crisp while these two, at 11-12px regular, printed faint
   even after they were already forced to #000. Bumping size+weight
   fixes the actual cause; color was never the problem. */
.pos-receipt-shop-meta {
    font-size: 13px;
    font-weight: 600;
}

.pos-receipt-curiosity {
    text-align: center;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed var(--color-border);
}
.pos-receipt-curiosity-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.pos-receipt-curiosity-question {
    font-style: italic;
    margin: 4px 0 8px;
}
.pos-receipt-curiosity-caption {
    font-size: 11px;
    margin-top: 4px;
}

.pos-receipt-footer {
    text-align: center;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed var(--color-border);
}
.pos-receipt-qr {
    width: 96px;
    height: 96px;
    display: block;
    margin: 0 auto 6px;
    background: #fff;
}
.pos-receipt-powered-by {
    font-size: 13px;
    font-weight: 600;
}

@media print {
    /* The @page size override for this receipt (80mm thermal roll,
       auto height) lives in backend/views/cashier-dashboard.html
       instead of here — @page has no selector scoping, so putting it
       in this SHARED stylesheet would also apply it to the unrelated
       "print a single order" feature above (.print-only, used on
       admin-dashboard.html), which is a normal full-page printout and
       would break under an 80mm page size. */

    body * { visibility: hidden; }
    #posReceiptPrintArea, #posReceiptPrintArea * { visibility: visible; }
    #posReceiptPrintArea { position: absolute; top: 0; left: 0; width: 100%; padding: 8px; }

    /* Every line of the receipt prints pure black, full stop — no
       reliance on --color-ink/--color-ink-soft resolving correctly
       through inheritance and the theme override below. Belt-and-
       suspenders: on a real thermal printer, faint lines turned out to
       be caused by font-size/weight (see .pos-receipt-shop-meta's
       comment), not color — but there's no reason to leave any
       cascade/inheritance path where a line COULD come out as
       anything but solid black either. */
    .pos-receipt, .pos-receipt * {
        color: #000000 !important;
    }

    /* Same two fixes as the .print-only block above: collapse the
       full-height POS screen behind the receipt (visibility:hidden
       alone left it forcing extra blank pages), and force solid ink
       so the receipt doesn't print as pale gray under the dark theme. */
    .dashboard {
        display: none !important;
    }
    :root, [data-theme="dark"] {
        --color-ink: #000000;
        --color-ink-soft: #333333;
    }
}

/* ---- Shop-side Offers management (shop-menu.html) ---- */

.offers-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.offer-items-picker {
    max-height: 220px;
    overflow-y: auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.offer-item-picker-row {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13.5px;
}

.offer-item-picker-row input[type="checkbox"] {
    width: auto;
}

.offer-item-picker-row .offer-item-qty {
    width: 56px;
    margin-left: auto;
}

.offer-card {
    display: flex;
    align-items: stretch;
    gap: 16px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
}

.offer-card.offer-card-inactive {
    opacity: 0.6;
}

.offer-card-image {
    width: 140px;
    flex: none;
    object-fit: cover;
    display: block;
}

.offer-card-image.offer-card-image-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-bg);
    color: var(--color-border);
}

.offer-card-body {
    flex: 1;
    padding: 14px 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    justify-content: center;
    min-width: 0;
}

.offer-card .menu-item-actions {
    border-top: none;
    border-left: 1px solid var(--color-border-soft);
    flex-direction: column;
    justify-content: center;
    flex-wrap: nowrap;
    padding: 10px 16px;
}

/* ==========================================================================
   PUBLIC STOREFRONT (public/store.html)
   Deliberately its own namespace (store-*), separate from the admin/
   cashier UI's pos-* classes above — a customer-facing marketing page
   has different goals (make the food look good, build trust fast) than
   an internal work tool, even though they share the same token system.
   ========================================================================== */

.store-page {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 20px 60px;
}

.store-hero {
    position: relative;
    margin: 0 -20px 28px;
    padding: 48px 20px 40px;
    background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-soft) 100%);
    color: #fff;
    text-align: center;
}

/* A shop-uploaded banner (see store.js's shop.banner_data_url handling)
   — background-size/position live here rather than as inline styles so
   the mobile override below can actually win. Same fix and reasoning as
   brand.css's .gp-marketplace .store-hero.has-custom-hero-image: on a
   phone this box is much narrower than the wide banner image is
   designed for, so a "cover" crop centered on the image's horizontal
   middle mostly shows empty background and misses the subject, which
   typically sits right-of-center. Biasing the crop right matches what
   desktop shows instead of cropping it out. */
.store-hero.has-custom-hero-image {
    background-size: cover;
    background-position: center;
}

@media (max-width: 640px) {
    .store-hero.has-custom-hero-image {
        background-position: 75% center;
    }
}

.store-hero-back-link {
    position: absolute;
    top: 16px;
    left: 20px;
    padding: 7px 14px;
    font-size: 13px;
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.3);
}

.store-hero-back-link:hover {
    background: rgba(255, 255, 255, 0.24);
}

@media (max-width: 520px) {
    .store-hero-back-link {
        position: static;
        display: inline-flex;
        margin-bottom: 14px;
    }
}

/* .store-hero-back-row wraps the back-link together with its ghost
   mascot sibling (see below) — ONLY on store.html, which is the only
   page that uses this wrapper (track.html, marketplace.html,
   my-orders.html, and group-order.html all use a bare
   .store-hero-back-link with no wrapper, so its own positioning above
   must stay untouched for them). Takes over the exact same corner
   position the bare link used to occupy, and demotes the link itself
   to a plain flex child via the more-specific override just below —
   so the link and its ghost move together as one unit in both
   layouts, without the ghost needing its own breakpoint-specific
   position math to stay visually anchored next to the button. */
.store-hero-back-row {
    position: absolute;
    top: 16px;
    left: 20px;
    display: flex;
    align-items: center;
    gap: 4px;
}

.store-hero-back-row .store-hero-back-link {
    position: static;
    margin-bottom: 0;
}

@media (max-width: 520px) {
    .store-hero-back-row {
        position: static;
        display: inline-flex;
        margin-bottom: 14px;
    }
}

/* ---- Ghost mascot — the GhostPatch character, simplified into a
   small friendly floating mark, nudging attention toward "All Shops"
   so a customer notices there's a whole marketplace beyond this one
   shop. Purely decorative (aria-hidden — the existing text link is
   still the one real control), so it's safe to disable entirely for
   prefers-reduced-motion without losing any functionality. ---- */

.store-hero-ghost-mascot {
    position: relative;
    width: 24px;
    height: 26px;
    margin-left: 8px;
    flex: none;
}

.store-hero-ghost-arrow {
    position: absolute;
    left: -9px;
    top: 6px;
    width: 9px;
    height: 9px;
    color: #fff;
    opacity: 0.85;
    animation: store-hero-ghost-nudge 1.4s ease-in-out infinite;
}

.store-hero-ghost-svg {
    /* Matches the width/height attributes already on the <svg> tag in
       store.html — those are the real fallback (an <svg> with only a
       viewBox and no explicit size defaults to a fixed ~300x150 box,
       which is exactly what made this render enormous when a caching
       layer somewhere between origin and a customer's phone served
       this file stale, mid-rollout). These rules just need to not
       fight that baseline; they don't need to establish it. */
    width: 100%;
    height: 100%;
    filter: drop-shadow(0 2px 4px rgba(20, 10, 50, 0.4));
    animation: store-hero-ghost-float 2.6s ease-in-out infinite;
    transform-origin: 50% 85%;
}

@keyframes store-hero-ghost-float {
    0%, 100% { transform: translateY(0) rotate(-3deg); }
    50% { transform: translateY(-6px) rotate(3deg); }
}

@keyframes store-hero-ghost-nudge {
    0%, 100% { transform: translateX(0); opacity: 0.5; }
    50% { transform: translateX(-4px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .store-hero-ghost-arrow,
    .store-hero-ghost-svg {
        animation: none;
    }
}

/* ---- Customer account (optional sign-in, alongside guest checkout —
   see public/js/customer-auth.js) — same top-right chip treatment as
   .store-hero-back-link gets on the opposite corner. ---- */

.store-hero-account {
    position: absolute;
    top: 16px;
    right: 20px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.store-hero-account-signed-in {
    display: flex;
    align-items: center;
    gap: 8px;
}

.store-hero-account-name {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.85);
}

.store-hero-chip {
    padding: 7px 14px;
    font-size: 13px;
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.3);
}

.store-hero-chip:hover {
    background: rgba(255, 255, 255, 0.24);
}

@media (max-width: 520px) {
    .store-hero-account {
        position: static;
        justify-content: center;
        margin-bottom: 14px;
    }
}

/* ---- Customer sign-in / create-account modal tabs — same look as the
   store's category-filter tabs (.store-category-tab), just repurposed
   for a 2-way form switch instead of a category filter. ---- */

.customer-auth-tabs {
    display: flex;
    gap: 8px;
    margin-bottom: 18px;
}

.store-hero .badge {
    background: rgba(255, 255, 255, 0.16);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.3);
}

.store-hero h1 {
    margin: 14px 0 6px;
    font-size: 34px;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: #fff;
}

.store-hero-meta {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex-wrap: wrap;
}

.store-hero-meta a {
    color: #fff;
    text-decoration: underline;
}

.store-hero-meta svg {
    width: 14px;
    height: 14px;
}

/* ---- Offers strip ---- */

.store-offers {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    padding: 4px 4px 16px;
    margin-bottom: 20px;
    scrollbar-width: thin;
}

.store-offer-card {
    flex: none;
    width: 280px;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-card);
}

.store-offer-image,
.store-offer-image-placeholder {
    width: 100%;
    height: 110px;
    object-fit: cover;
    display: block;
    background: linear-gradient(135deg, var(--color-accent-soft), var(--color-warning-soft));
}

.store-offer-body {
    padding: 12px 14px 14px;
}

.store-offer-title {
    font-weight: 700;
    font-size: 14px;
    color: var(--color-ink);
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 4px;
}

.store-offer-title svg {
    width: 15px;
    height: 15px;
    color: var(--color-warning);
    flex: none;
}

.store-offer-description {
    font-size: 12.5px;
    color: var(--color-ink-soft);
    margin: 0;
}

.store-offer-price-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-top: 8px;
}

.store-offer-price {
    font-size: 17px;
    font-weight: 700;
    color: var(--color-accent);
}

.store-offer-price-original {
    font-size: 13px;
    color: var(--color-ink-soft);
    text-decoration: line-through;
}

.store-offer-add-btn {
    width: 100%;
    margin-top: 10px;
    justify-content: center;
}

/* ---- Category tabs ---- */

.store-category-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 18px;
    position: sticky;
    top: 0;
    background: var(--color-bg);
    padding: 10px 0;
    z-index: 5;
}

.store-category-tab {
    font-family: var(--font-body);
    font-size: 13.5px;
    font-weight: 600;
    color: var(--color-ink-soft);
    background: var(--color-surface);
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-full);
    padding: 8px 16px;
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}

.store-category-tab.active {
    color: #fff;
    background: var(--color-primary);
    border-color: var(--color-primary);
}

/* ---- Layout + product grid ---- */

.store-layout {
    display: grid;
    grid-template-columns: 1fr 340px;
    gap: 24px;
    align-items: start;
}
@media (max-width: 900px) {
    .store-layout { grid-template-columns: 1fr; }
}

.store-product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 18px;
}

.store-product-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    text-align: left;
    cursor: pointer;
    box-shadow: var(--shadow-card);
    transition: box-shadow var(--transition-fast), transform var(--transition-fast);
    display: flex;
    flex-direction: column;
}

.store-product-card:hover {
    box-shadow: var(--shadow-lift);
    transform: translateY(-3px);
}

.store-product-image,
.store-product-image-placeholder {
    width: 100%;
    height: 150px;
    object-fit: cover;
    display: block;
    background: var(--color-neutral-soft);
}

.store-product-image-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-border);
}

.store-product-body {
    padding: 14px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
}

.store-product-name-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
}

.store-product-name {
    font-weight: 600;
    font-size: 15px;
    color: var(--color-ink);
}

.store-product-description {
    font-size: 12.5px;
    color: var(--color-ink-soft);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    flex: 1;
}

.store-product-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 4px;
}

.store-product-price {
    font-weight: 700;
    font-size: 15px;
    color: var(--color-accent);
}

.store-product-add {
    width: 32px;
    height: 32px;
    border-radius: var(--radius-full);
    border: none;
    background: var(--color-primary);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

.store-product-add svg {
    width: 16px;
    height: 16px;
}

/* ---- Marketplace directory (/marketplace) ----
   Reuses .store-hero/.store-category-tabs/.store-product-card/
   .store-product-* wherever the shape already matches a shop-directory
   card — the rules below only cover what's genuinely different: the
   search+distance row in the hero, and a shop card's category/rating/
   address/featured-ribbon content. */

.marketplace-hero {
    padding-bottom: 28px;
}

.marketplace-search-row {
    display: flex;
    gap: 10px;
    max-width: 560px;
    margin: 22px auto 0;
}

.marketplace-search-input-wrap input {
    border: none;
}

.marketplace-distance-btn {
    background: rgba(255, 255, 255, 0.92);
    flex: none;
    white-space: nowrap;
}

@media (max-width: 560px) {
    .marketplace-search-row {
        flex-direction: column;
    }

    .marketplace-distance-btn {
        justify-content: center;
    }
}

.marketplace-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 18px;
    margin-top: 20px;
}

/* ---- Marketplace: Announcements carousel — full-width, auto-advancing
   platform banners for upcoming events/marketing, above the shop-level
   Hot Offers strip below. Hand-rolled flexbox carousel (see
   marketplace.js) — the outer element clips to one slide's width via
   overflow: hidden, the track shifts by whole container-widths. ---- */

.marketplace-announcements-carousel {
    position: relative;
    width: 100%;
    aspect-ratio: 21 / 7;
    max-height: 320px;
    border-radius: 24px;
    overflow: hidden;
    margin: 24px 0;
    background: var(--color-neutral-soft);
}

.marketplace-carousel-track {
    display: flex;
    width: 100%;
    height: 100%;
    transition: transform 0.6s cubic-bezier(0.65, 0, 0.35, 1);
}

.marketplace-carousel-slide {
    position: relative;
    flex: 0 0 100%;
    width: 100%;
    height: 100%;
    display: block;
    text-decoration: none;
    color: inherit;
}

.marketplace-carousel-image,
.marketplace-carousel-image-placeholder {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    background: linear-gradient(135deg, var(--gp-purple-700), var(--gp-purple-500));
}

.marketplace-carousel-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 40px 28px 24px;
    background: linear-gradient(to top, rgba(8, 6, 15, 0.85), transparent);
    color: #fff;
    pointer-events: none;
}

.marketplace-carousel-title {
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: 0.01em;
    font-size: clamp(18px, 2.6vw, 28px);
    margin: 0 0 4px;
}

.marketplace-carousel-description {
    font-size: 13.5px;
    color: rgba(255, 255, 255, 0.85);
    margin: 0;
    max-width: 560px;
}

.marketplace-carousel-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(8, 6, 15, 0.45);
    color: #fff;
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s ease;
}

.marketplace-carousel-arrow:hover {
    background: rgba(8, 6, 15, 0.7);
}

.marketplace-carousel-arrow-prev { left: 14px; }
.marketplace-carousel-arrow-next { right: 14px; }

.marketplace-carousel-arrow svg {
    width: 18px;
    height: 18px;
}

.marketplace-carousel-dots {
    position: absolute;
    bottom: 14px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 6px;
}

.marketplace-carousel-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.45);
    border: none;
    padding: 0;
    cursor: pointer;
    transition: background 0.15s ease, transform 0.15s ease;
}

.marketplace-carousel-dot.active {
    background: #fff;
    transform: scale(1.3);
}

@media (max-width: 640px) {
    .marketplace-announcements-carousel {
        aspect-ratio: 4 / 3;
        border-radius: 18px;
    }

    .marketplace-carousel-caption {
        padding: 28px 18px 18px;
    }
}

/* ---- Marketplace: "Hot Offers" strip — a distinct promotional band,
   deliberately louder than the plain shop grid below it (gradient
   background, pulsing discount badge, hover lift) so it reads as a
   dedicated marketing placement rather than just more shop cards. ---- */

.marketplace-offers-section {
    position: relative;
    margin: 24px 0 28px;
    padding: 22px 20px 18px;
    border-radius: 24px;
    background: linear-gradient(135deg, var(--gp-purple-800), var(--gp-purple-600));
    overflow: hidden;
}

.marketplace-offers-section::before {
    content: '';
    position: absolute;
    top: -110px;
    right: -60px;
    width: 320px;
    height: 320px;
    background: radial-gradient(circle, rgba(140, 116, 245, 0.45), transparent 70%);
    pointer-events: none;
}

.marketplace-offers-header {
    position: relative;
    margin-bottom: 14px;
}

.marketplace-offers-header h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    color: #fff;
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: 0.01em;
    font-size: 19px;
    margin: 0 0 3px;
}

.marketplace-offers-header h2 svg {
    width: 19px;
    height: 19px;
    color: #FFB648;
}

.marketplace-offers-header p {
    color: var(--gp-purple-200);
    font-size: 12.5px;
    margin: 0;
}

.marketplace-offers-strip {
    position: relative;
    display: flex;
    gap: 14px;
    overflow-x: auto;
    padding: 2px 2px 6px;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
}

.marketplace-offer-card {
    flex: none;
    scroll-snap-align: start;
    width: 210px;
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: 0 10px 24px rgba(20, 10, 50, 0.28);
    text-decoration: none;
    color: inherit;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.marketplace-offer-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 16px 30px rgba(20, 10, 50, 0.38);
}

.marketplace-offer-image-wrap {
    position: relative;
}

.marketplace-offer-image,
.marketplace-offer-image-placeholder {
    width: 100%;
    height: 96px;
    object-fit: cover;
    display: block;
    background: linear-gradient(135deg, var(--color-accent-soft), #FFE8CC);
}

.marketplace-offer-image-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-accent);
}

.marketplace-offer-image-placeholder svg {
    width: 22px;
    height: 22px;
}

.marketplace-offer-badge {
    position: absolute;
    top: 8px;
    right: 8px;
    background: var(--color-danger);
    color: #fff;
    font-size: 10.5px;
    font-weight: 800;
    letter-spacing: 0.02em;
    padding: 3px 9px;
    border-radius: var(--radius-full);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
    animation: marketplace-offer-badge-pulse 2s ease-in-out infinite;
}

@keyframes marketplace-offer-badge-pulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.08); }
}

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

.marketplace-offer-body {
    padding: 9px 11px 12px;
}

.marketplace-offer-shop {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--color-accent);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.marketplace-offer-shop svg {
    width: 11px;
    height: 11px;
}

.marketplace-offer-title {
    font-weight: 700;
    font-size: 13.5px;
    color: var(--color-ink);
    margin: 4px 0 0;
    line-height: 1.3;
}

.marketplace-offer-description {
    font-size: 12px;
    color: var(--color-ink-soft);
    margin: 4px 0 0;
}

.marketplace-offer-price-row {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-top: 6px;
}

.marketplace-offer-price {
    font-size: 16px;
    font-weight: 800;
    color: var(--color-accent);
}

.marketplace-offer-price-original {
    font-size: 12px;
    color: var(--color-ink-soft);
    text-decoration: line-through;
}

/* ---- Marketplace: "Top Sellers" strip — same promotional-band shape
   as Hot Offers above, but reads as a leaderboard (deeper gradient,
   gold/silver/bronze rank badges) rather than a deal — the marketing
   hook here is "this is what people are actually ordering", not a
   discount. ---- */

.marketplace-top-products-section {
    position: relative;
    margin: 24px 0 28px;
    padding: 22px 20px 18px;
    border-radius: 24px;
    background: linear-gradient(135deg, var(--gp-purple-900), var(--gp-purple-700) 85%);
    overflow: hidden;
}

.marketplace-top-products-section::before {
    content: '';
    position: absolute;
    bottom: -100px;
    left: -60px;
    width: 300px;
    height: 300px;
    background: radial-gradient(circle, rgba(240, 169, 59, 0.3), transparent 70%);
    pointer-events: none;
}

.marketplace-top-products-header {
    position: relative;
    margin-bottom: 14px;
}

.marketplace-top-products-header h2 {
    display: flex;
    align-items: center;
    gap: 8px;
    color: #fff;
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: 0.01em;
    font-size: 19px;
    margin: 0 0 3px;
}

.marketplace-top-products-header h2 svg {
    width: 19px;
    height: 19px;
    color: #F0A93B;
}

.marketplace-top-products-header p {
    color: var(--gp-purple-200);
    font-size: 12.5px;
    margin: 0;
}

.marketplace-top-products-strip {
    position: relative;
    display: flex;
    gap: 14px;
    overflow-x: auto;
    padding: 2px 2px 6px;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
}

.marketplace-top-product-card {
    flex: none;
    scroll-snap-align: start;
    width: 170px;
    background: var(--color-surface);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: 0 10px 24px rgba(20, 10, 50, 0.28);
    text-decoration: none;
    color: inherit;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.marketplace-top-product-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 16px 30px rgba(20, 10, 50, 0.38);
}

.marketplace-top-product-image-wrap {
    position: relative;
}

.marketplace-top-product-image,
.marketplace-top-product-image-placeholder {
    width: 100%;
    height: 96px;
    object-fit: cover;
    display: block;
    background: linear-gradient(135deg, var(--color-accent-soft), #FFE8CC);
}

.marketplace-top-product-image-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-accent);
}

.marketplace-top-product-image-placeholder svg {
    width: 22px;
    height: 22px;
}

.marketplace-top-product-rank {
    position: absolute;
    top: 8px;
    left: 8px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.02em;
    padding: 3px 8px;
    border-radius: var(--radius-full);
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
    color: #fff;
}

.marketplace-top-product-rank-1 {
    background: linear-gradient(135deg, #FFD966, #E0A937);
    color: #4A3200;
}

.marketplace-top-product-rank-2 {
    background: linear-gradient(135deg, #E2E4EA, #B9BCC6);
    color: #33353C;
}

.marketplace-top-product-rank-3 {
    background: linear-gradient(135deg, #D7A16A, #A96A34);
}

.marketplace-top-product-rank-other {
    background: rgba(32, 41, 66, 0.6);
}

.marketplace-top-product-body {
    padding: 9px 11px 12px;
}

.marketplace-top-product-shop {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--color-accent);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.marketplace-top-product-shop svg {
    width: 11px;
    height: 11px;
}

.marketplace-top-product-name {
    font-weight: 700;
    font-size: 13.5px;
    color: var(--color-ink);
    margin: 4px 0 0;
    line-height: 1.3;
}

.marketplace-top-product-price {
    display: block;
    font-size: 15px;
    font-weight: 800;
    color: var(--color-accent);
    margin-top: 6px;
}

.shop-card {
    position: relative;
    /* .store-product-card was only ever a <button> before this reused
       it on an <a> — reset the browser's default link styling so card
       text doesn't render blue/underlined. */
    text-decoration: none;
    color: inherit;
}

.shop-card-category,
.shop-card-view-btn {
    text-decoration: none;
}

.shop-card-featured-ribbon {
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 11px;
    font-weight: 700;
    color: var(--color-warning);
    background: var(--color-warning-soft);
    padding: 3px 9px;
    border-radius: var(--radius-full);
}

.shop-card-featured-ribbon svg {
    width: 11px;
    height: 11px;
}

.shop-card-meta-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 12.5px;
    color: var(--color-ink-soft);
}

.shop-card-category {
    background: var(--color-neutral-soft);
    padding: 2px 8px;
    border-radius: var(--radius-full);
}

.shop-card-rating {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    white-space: nowrap;
}

.marketplace-star {
    width: 13px;
    height: 13px;
    color: var(--color-warning);
    fill: var(--color-warning);
}

.marketplace-rating-count {
    color: var(--color-ink-soft);
}

.shop-card-address {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 12.5px;
    color: var(--color-ink-soft);
}

.shop-card-address svg {
    width: 13px;
    height: 13px;
    flex: none;
}

/* Was reserved for open/closed + delivery-fee/ETA/minimum-order badges
   until real per-shop data existed for them — now used by the "Closed"
   pill below (see marketplace.js's shopCard()). Zero height/margin so
   an empty row (an open shop, no badge) never shows as a visible gap. */
.shop-card-badge-row:empty {
    display: none;
}

.shop-card-closed-badge {
    display: inline-flex;
    align-items: center;
    font-size: 11px;
    font-weight: 700;
    color: var(--color-danger);
    background: var(--color-danger-soft);
    padding: 2px 8px;
    border-radius: var(--radius-full);
}

.shop-card-view-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    align-self: flex-start;
    margin-top: 4px;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--color-accent);
}

.shop-card-view-btn svg {
    width: 13px;
    height: 13px;
}

/* ---- Cart panel ---- */

.store-cart {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: 18px;
    position: sticky;
    top: 70px;
    box-shadow: var(--shadow-card);
}

/* Floating "jump to cart" bar — mobile only, see store.html's comment on
   why: .store-layout collapses to one column under 900px, so the cart
   (and its checkout button) would otherwise be below the entire product
   grid with nothing to scroll to it. Hidden on desktop, where the cart
   panel is already sticky in the sidebar. */
.store-mobile-checkout-bar {
    display: none;
}

@media (max-width: 900px) {
    .store-mobile-checkout-bar {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        position: fixed;
        left: 12px;
        right: 12px;
        bottom: calc(12px + env(safe-area-inset-bottom, 0px));
        z-index: 30;
        background: var(--color-primary);
        color: #fff;
        border: none;
        border-radius: var(--radius-lg);
        padding: 14px 18px;
        font-family: var(--font-body);
        font-size: 14px;
        font-weight: 600;
        cursor: pointer;
        box-shadow: var(--shadow-lift);
    }

    .store-mobile-checkout-bar[hidden] {
        display: none;
    }

    .store-mobile-checkout-cta {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        flex-shrink: 0;
    }

    .store-mobile-checkout-cta svg {
        width: 15px;
        height: 15px;
    }
}

.store-cart h3 {
    margin: 0 0 14px;
    font-size: 17px;
}

.store-cart-line {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    padding: 11px 0;
    border-bottom: 1px solid var(--color-border-soft);
    font-size: 14px;
}

.store-cart-line-info { flex: 1; min-width: 0; }
.store-cart-line-name { font-weight: 600; color: var(--color-ink); }
.store-cart-line-extras { font-size: 12px; color: var(--color-ink-soft); }

.store-cart-line-remove {
    width: 24px;
    height: 24px;
    border-radius: var(--radius-full);
    border: 1px solid var(--color-border);
    background: var(--color-surface);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
}

.store-cart-total {
    display: flex;
    justify-content: space-between;
    font-size: 19px;
    font-weight: 700;
    padding: 16px 0;
    margin-top: 4px;
    border-top: 1px solid var(--color-border);
}

.store-extras-picker {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin: 14px 0;
}
.store-extras-picker label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    font-weight: 500;
}

.store-nutrition-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    margin: 14px 0;
    padding: 10px 12px;
    background: var(--color-neutral-soft);
    border-radius: var(--radius-sm);
    font-size: 13px;
    color: var(--color-ink-soft);
}
.store-nutrition-summary span:first-child {
    display: flex;
    align-items: center;
    gap: 4px;
    font-weight: 600;
    color: var(--color-ink);
}
.store-nutrition-summary svg {
    width: 14px;
    height: 14px;
}

.store-qty-stepper {
    display: flex;
    align-items: center;
    gap: 14px;
    justify-content: center;
    margin: 16px 0;
}
.store-qty-stepper button {
    width: 34px;
    height: 34px;
    border-radius: var(--radius-full);
    border: 1px solid var(--color-border);
    background: var(--color-surface);
    font-size: 17px;
    cursor: pointer;
}
.store-qty-stepper span {
    font-size: 19px;
    font-weight: 700;
    min-width: 26px;
    text-align: center;
}

.store-badge-popular {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--color-warning);
    background: var(--color-warning-soft);
    border-radius: var(--radius-full);
    padding: 3px 8px;
    align-self: flex-start;
}
.store-badge-popular svg { width: 10px; height: 10px; }

/* ---- Order tracking timeline ---- */

.track-timeline {
    display: flex;
    flex-direction: column;
}

.track-step {
    display: flex;
    gap: 14px;
    position: relative;
    padding-bottom: 28px;
}
.track-step:last-child {
    padding-bottom: 0;
}
.track-step::before {
    content: "";
    position: absolute;
    left: 15px;
    top: 32px;
    bottom: 0;
    width: 2px;
    background: var(--color-border);
}
.track-step:last-child::before {
    display: none;
}
.track-step.done::before {
    background: var(--color-accent);
}

.track-step-dot {
    flex: none;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-neutral-soft);
    color: var(--color-ink-soft);
    border: 2px solid var(--color-border);
}
.track-step-dot svg { width: 16px; height: 16px; }

.track-step.done .track-step-dot {
    background: var(--color-accent);
    border-color: var(--color-accent);
    color: #fff;
}
.track-step.current .track-step-dot {
    background: var(--color-primary);
    border-color: var(--color-primary);
    color: #fff;
    box-shadow: 0 0 0 4px var(--color-accent-soft);
}

.track-step-body {
    padding-top: 4px;
}
.track-step-label {
    font-weight: 600;
    font-size: 14.5px;
    color: var(--color-ink);
}
.track-step.done .track-step-label,
.track-step.current .track-step-label {
    color: var(--color-ink);
}
.track-step:not(.done):not(.current) .track-step-label {
    color: var(--color-ink-soft);
}
.track-step-time {
    font-size: 12.5px;
    color: var(--color-ink-soft);
    margin-top: 2px;
}

.track-cancelled-banner {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
    padding: 12px 14px;
    background: var(--color-danger-soft);
    color: var(--color-danger);
    border-radius: var(--radius-sm);
    font-weight: 600;
    font-size: 14px;
}

.track-item-row {
    display: flex;
    justify-content: space-between;
    padding: 8px 0;
    border-bottom: 1px solid var(--color-border-soft);
    font-size: 14px;
}
.track-item-row:last-child { border-bottom: none; }

.scheduled-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 4px;
    font-size: 11px;
    font-weight: 600;
    color: var(--color-warning);
    background: var(--color-warning-soft);
    border-radius: var(--radius-full);
    padding: 2px 8px;
    white-space: nowrap;
}
.scheduled-badge svg { width: 10px; height: 10px; }

/* ---- Reviews (shop moderation page) ---- */

.reviews-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.review-card {
    display: flex;
    gap: 14px;
    padding: 14px;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
}

.review-photo {
    flex: none;
    width: 72px;
    height: 72px;
    object-fit: cover;
    border-radius: var(--radius-sm);
}

.review-body {
    flex: 1;
    min-width: 0;
}

.review-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-size: 14px;
}

.review-stars {
    color: var(--color-warning);
    letter-spacing: 1px;
}

.review-item-name {
    font-size: 12.5px;
    color: var(--color-ink-soft);
    margin-top: 2px;
}

.review-text {
    font-size: 14px;
    margin: 8px 0 0;
}

.review-meta {
    font-size: 12px;
    color: var(--color-ink-soft);
    margin-top: 8px;
}

.review-actions {
    display: flex;
    gap: 10px;
    margin-top: 10px;
}

/* ---- Reviews (storefront display) ---- */

.store-rating-summary {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 12px;
    color: var(--color-warning);
    font-weight: 600;
}
.store-rating-summary svg { width: 12px; height: 12px; }

.store-reviews-section {
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--color-border);
}

.store-review-item {
    display: flex;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid var(--color-border-soft);
}
.store-review-item:last-child { border-bottom: none; }

.store-review-photo {
    flex: none;
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: var(--radius-sm);
}

.store-write-review-form {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px dashed var(--color-border);
}

.store-star-picker {
    display: flex;
    gap: 4px;
    font-size: 24px;
    color: var(--color-border);
    cursor: pointer;
}
.store-star-picker .active {
    color: var(--color-warning);
}

/* ---- Upsell strip ("Goes well with") ---- */

.store-upsell-strip {
    margin: 14px 0;
    padding-top: 14px;
    border-top: 1px dashed var(--color-border);
}

.store-upsell-card {
    flex: none;
    width: 110px;
    text-align: center;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    padding: 8px;
    cursor: pointer;
}
.store-upsell-card img,
.store-upsell-card .store-upsell-placeholder {
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: var(--color-neutral-soft);
    margin-bottom: 6px;
}
.store-upsell-name {
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.store-upsell-price {
    font-size: 11.5px;
    color: var(--color-accent);
    font-weight: 600;
}

/* ---- Language toggle (see public/js/i18n.js) -------------------------
   A small segmented EN / عربي control rendered into any element marked
   [data-i18n-toggle]. Each operational window carries its own, because
   the language choice is per-window and per-device, not per-account. */
.lang-toggle {
    display: inline-flex;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    overflow: hidden;
    flex-shrink: 0;
}

.lang-toggle-btn {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--color-ink-soft);
    font: inherit;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1;
    padding: 7px 11px;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.lang-toggle-btn + .lang-toggle-btn {
    border-inline-start: 1px solid var(--color-border);
}

.lang-toggle-btn:hover {
    background: var(--color-surface-soft, rgba(0, 0, 0, 0.04));
    color: var(--color-ink);
}

.lang-toggle-btn.active {
    background: var(--color-primary);
    color: #fff;
}

.lang-toggle-btn:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: -2px;
}

/* ---- "Still needs filling" highlight (dispatcher New Order form) -----
   A live indicator of which required fields are still empty, so a
   dispatcher taking an order over the phone can see at a glance what's
   left rather than discovering it at submit. Applied to the .form-field
   wrapper so the label turns red with the control.

   Deliberately a border + tint rather than an error message per field:
   an empty field that simply hasn't been reached yet isn't an error,
   and a form that shouts a validation message at every untouched box
   trains people to ignore it. */
.form-field.field-missing > label {
    color: var(--color-danger);
}

.form-field.field-missing input,
.form-field.field-missing select,
.form-field.field-missing textarea {
    border-color: var(--color-danger);
    background: var(--color-danger-soft, rgba(220, 38, 38, 0.05));
}

.form-field.field-missing input:focus,
.form-field.field-missing select:focus,
.form-field.field-missing textarea:focus {
    outline-color: var(--color-danger);
    border-color: var(--color-danger);
}

/* A field that stops being required (the zone once a customer location
   has been pasted) drops the highlight entirely rather than turning
   some other colour — nothing to do means nothing to look at. */

/* A product's "was" price, struck through beside the real one (see
   menu_items.original_price). Display only — what a customer is
   actually charged is always .store-product-price. Sits immediately
   after that price so the pair reads as one unit, rather than being
   pushed to the far end by .store-product-footer's space-between. */
.store-product-price-original {
    font-size: 12.5px;
    color: var(--color-ink-soft);
    text-decoration: line-through;
    margin-inline-start: 6px;
}
