/* ============================================================================
   OrderPoint — "Nocturne" design system
   ----------------------------------------------------------------------------
   A quiet, compact, dark interface for the customer ordering app.

     ground      near-neutral blue-grey  #161826
     surface     one step up             #232532
     accent      a single blurple        #9184d9 / #d2cefd (text)

   The accent is used as a line and a glow, never a flood: buttons are an accent
   outline on transparent, prices carry the accent, and separators are hairline
   rules that fade at their ends. Contrast comes from the tonal ramp, not from
   saturation. Inter throughout, with IBM Plex Mono reserved for the small
   letter-spaced labels. Every primary target sits in the bottom third of the
   screen, within a thumb's reach.

   No Bootstrap: the app loads on a phone in a cold shop, so every kilobyte of
   framework CSS we don't ship is a kilobyte faster.
   ============================================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap');

:root {
    /* ── Ground and surfaces ── */
    /* The dark ramp — a soft slate rather than near-black, so light text doesn't read as
       harsh against it. Cards keep a clear lift above the ground. */
    --surface: #363b50;        /* cards, inputs, header, sheets */
    --surface-2: #262a3a;      /* the page ground */
    --surface-3: #2f3446;      /* raised sheet / subtle fill */

    /* ── Ink ── */
    --ink: #e9e9ed;
    --ink-2: #b2b6ca;
    --ink-3: #75798c;
    --ink-4: #595d6c;

    /* ── Hairlines ── */
    --line: #3f424d;           /* visible borders: inputs, cards, frame */
    --line-2: #23252f;         /* subtle list separators */

    /* ── Accent: a single blurple, used as a line and a glow ── */
    --accent: #9184d9;         /* borders, active marks */
    --accent-ink: #d2cefd;     /* text and prices on the dark ground */
    --accent-2: #b5abfc;       /* secondary accent text */
    --accent-hover: #2b2741;   /* accent-900 tint, for hovers */
    --accent-soft: #2b2741;    /* accent tint fill */
    --accent-line: #423a6a;    /* accent-800 border */

    /* Errors are the one place a warm hue appears — desaturated, so it reads as
       a fault without shouting on a calm dark ground. */
    --urgent: #e0a1a1;
    --urgent-bg: #2a1f26;
    --urgent-line: #5c3a44;

    /* Offers reuse the accent — the mono palette has no second hue. */
    --offer: #b5abfc;

    /* ── Shape ── */
    --r-panel: 14px;
    --r-card: 8px;
    --r-row: 8px;
    --r-control: 8px;
    --r-chip: 8px;

    /* Elevation on a dark ground is a hairline edge plus ambient darkness, never
       a stack of soft shadows. */
    --shadow-card: 0 0 0 1px var(--line);
    --shadow-lift: 0 -24px 60px rgba(0, 0, 0, .55);
    --scrim: rgba(10, 11, 20, .6);

    /* ── Type ── */
    --font: 'Inter', system-ui, -apple-system, sans-serif;
    --font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', monospace;

    /* Safe-area aware bottom chrome, for phones with a home indicator. */
    --tab-h: calc(58px + env(safe-area-inset-bottom, 0px));
    --bar-h: calc(64px + env(safe-area-inset-bottom, 0px));
}

/* Wholesaler branding overrides --accent at runtime; everything else follows. */

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    font-family: var(--font);
    font-size: 15px;
    line-height: 1.5;
    color: var(--ink);
    background: var(--surface-2);
    -webkit-font-smoothing: antialiased;
    /* Stops iOS zooming when a form field is focused. */
    -webkit-text-size-adjust: 100%;
}

h1, h2, h3, h4 { margin: 0; font-weight: 500; letter-spacing: -.03em; color: var(--ink); }
h1 { font-size: 30px; }
h2 { font-size: 24px; }
h3 { font-size: 20px; }
p { margin: 0 0 10px; color: var(--ink-2); }
a { color: var(--accent-ink); text-decoration: none; }
a:hover { color: var(--accent-2); }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--accent) 30%, transparent); }

/* Numerics — prices, quantities, weights — line up with tabular figures. The
   design sets these in Inter, not a monospace, so they sit with the body text. */
.num, .price, .qty { font-variant-numeric: tabular-nums; }
.price { color: var(--accent-ink); font-weight: 600; letter-spacing: -.02em; }
.accent { color: var(--accent-ink); }

.muted { color: var(--ink-3); }
.small { font-size: 13px; }
.tiny { font-size: 11.5px; }
.eyebrow {
    font-family: var(--font-mono);
    font-size: 11px; font-weight: 500; letter-spacing: .16em;
    text-transform: uppercase; color: var(--ink-3);
}

/* ── Layout ────────────────────────────────────────────────────────── */

.op-shell { min-height: 100dvh; display: flex; flex-direction: column; }

.op-header {
    position: sticky; top: 0; z-index: 40;
    background: var(--surface-2);
    border-bottom: 1px solid var(--line-2);
    padding: 12px 16px;
}
.op-header-row { display: flex; align-items: center; gap: 10px; }
.op-header img.logo { height: 28px; width: auto; }
.op-header .title { font-weight: 600; font-size: 16px; letter-spacing: -.015em; }

/* The slim next-delivery / cut-off line under the brand row: compact, always visible, and a
   tap-through to the full delivery-options page. */
.op-deliverystrip {
    display: flex; align-items: baseline; gap: 8px;
    margin-top: 8px; font-size: 12px; color: var(--ink-3);
    text-decoration: none;
}
.op-deliverystrip:hover { color: var(--ink-2); }
.op-deliverystrip .grow {
    flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.op-deliverystrip .left { color: var(--accent-ink); font-weight: 500; white-space: nowrap; }
.op-deliverystrip .chev { color: var(--ink-3); }
/* The supplier's own mark — a colour swatch stands in when there's no logo. */
.op-brand-mark {
    width: 26px; height: 26px; flex: none; border-radius: 7px;
    background: var(--accent);
}

.op-main { flex: 1; padding: 16px; padding-bottom: calc(var(--tab-h) + 20px); }
.op-main.no-tabs { padding-bottom: 20px; }
.op-main.has-bar { padding-bottom: calc(var(--tab-h) + var(--bar-h) + 12px); }

.container-narrow { max-width: 760px; margin: 0 auto; }

/* Ordering-for banner. Deliberately prominent: with an active-customer switcher
   the real risk is human — placing an order against the wrong account. */
.acting-as {
    display: flex; align-items: center; gap: 10px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    color: var(--accent-ink);
    border-radius: var(--r-row);
    padding: 10px 13px;
    font-size: 13.5px;
    margin-bottom: 14px;
}
.acting-as strong { font-weight: 600; }
.acting-as button { margin-left: auto; }

/* ── Cards and rows ────────────────────────────────────────────────── */

.card {
    background: var(--surface);
    border-radius: var(--r-card);
    padding: 16px;
}
.card + .card { margin-top: 12px; }
.card-h { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }

/* Panels group a list of rows on the plain ground — no fill, the rules do the
   work of separating them. */
.panel { border-radius: var(--r-card); overflow: hidden; }

.row {
    display: flex; align-items: center; gap: 14px;
    padding: 15px 0;
    background: transparent;
}
.row + .row { border-top: 1px solid var(--line-2); }
.row .grow { flex: 1; min-width: 0; }
.row .name { font-weight: 500; letter-spacing: -.01em; }
/* min-width:0 on the flex child so long product names truncate instead of
   forcing the row wider than a phone screen. */
.row .name, .row .meta { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .meta { font-size: 12.5px; color: var(--ink-3); margin-top: 3px; }

.list-sep > * + * { border-top: 1px solid var(--line-2); }

/* An info row that stacks its label above its value — for long values (a week's worth of
   day names) that would otherwise collide with the label on a narrow phone. */
.row.info-stack { flex-direction: column; align-items: flex-start; gap: 4px; }

/* Product rows get a more pronounced divider than the subtle list rule — a full
   catalogue scrolls past quickly and the eye needs a clear break between lines. */
.row.prow { padding: 17px 0; }
.row.prow + .row.prow { border-top: 1px solid var(--line); }


/* ── Buttons — an accent outline on transparent, never a fill ──────── */

.btn {
    appearance: none;
    font-family: inherit; font-size: 15px; font-weight: 500;
    border-radius: var(--r-control);
    background: transparent;
    border: 1px solid transparent;
    color: var(--ink);
    padding: 12px 18px;
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    /* 44px is the accepted minimum touch target; these are used in a cold shop
       with gloved or wet hands. */
    min-height: 44px;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.btn:disabled { opacity: .45; cursor: not-allowed; }

.btn-primary { border-color: var(--accent); color: var(--accent-ink); }
.btn-primary:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.btn-primary:active:not(:disabled) { background: color-mix(in srgb, var(--accent) 24%, transparent); }

.btn-secondary { border-color: var(--line); color: var(--ink-2); }
.btn-secondary:hover:not(:disabled) { background: color-mix(in srgb, var(--ink) 7%, transparent); }

.btn-ghost { background: transparent; color: var(--accent-ink); }
.btn-ghost:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 10%, transparent); }

.btn-sm { min-height: 36px; padding: 8px 13px; font-size: 13.5px; }
.btn-block { width: 100%; }

/* ── Inputs ────────────────────────────────────────────────────────── */

.field { margin-bottom: 14px; }
.field label {
    display: block; font-size: 12px; letter-spacing: .04em; font-weight: 500;
    color: var(--ink-3); margin-bottom: 7px;
}

.input, select.input, textarea.input {
    width: 100%;
    font-family: inherit;
    /* 16px minimum: anything smaller makes iOS zoom the viewport on focus. */
    font-size: 16px;
    color: var(--ink);
    caret-color: var(--accent);
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-control);
    padding: 14px;
    min-height: 48px;
}
.input::placeholder { color: var(--ink-3); }
.input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

/* Native select: keeps the OS picker (best on a phone), but the closed control is fully
   themed — its own chrome removed and a custom accent chevron drawn in, so it reads as a
   filter rather than a second text box. Must sit AFTER the shared .input rule above, which
   lists select.input in its group at equal specificity and would otherwise win on order
   (its `background` shorthand clears the chevron, its `padding` the chevron gutter). The
   open option list is OS-drawn, so color-scheme hints it dark where the browser honours it. */
select.input {
    color-scheme: dark;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 42px;
    font-weight: 500;
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%239184d9'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M6%209l6%206%206-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 18px;
}
select.input::-ms-expand { display: none; }
select.input:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }

/* ── Badges and chips ──────────────────────────────────────────────── */

.badge {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 10px; font-weight: 500; letter-spacing: .09em; text-transform: uppercase;
    padding: 3px 7px; border-radius: 5px;
    white-space: nowrap;
}
.badge-offer { border: 1px solid var(--accent-line); color: var(--offer); }
.badge-weighed { border: 1px solid var(--line); color: var(--ink-2); }
.badge-urgent {
    text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 400;
    background: var(--urgent-bg); border: 1px solid var(--urgent-line); color: var(--urgent);
    border-radius: var(--r-control);
}

.chip {
    font-family: inherit; font-size: 13px; font-weight: 500;
    padding: 9px 15px; border-radius: var(--r-chip);
    border: 1px solid var(--line); background: transparent; color: var(--ink-2);
    cursor: pointer; min-height: 40px; white-space: nowrap;
    transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.chip:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
.chip.on { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-ink); }

.chip-row { display: flex; gap: 8px; flex-wrap: wrap; }

/* ── Quantity entry ────────────────────────────────────────────────── */

.stepper { display: flex; align-items: center; gap: 12px; }
.stepper button {
    width: 52px; height: 52px; flex: none;
    border-radius: var(--r-control);
    border: 1px solid var(--line); background: transparent;
    font-size: 24px; font-weight: 400; color: var(--accent-ink); cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: background .15s ease, border-color .15s ease;
}
.stepper button:last-of-type { border-color: var(--accent); }
.stepper button:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.stepper input {
    width: 66px; text-align: center;
    font-family: inherit; font-size: 20px; font-weight: 600; font-variant-numeric: tabular-nums;
    color: var(--ink); background: transparent;
    border: 1px solid var(--line); border-radius: var(--r-control);
    padding: 10px 4px; min-height: 52px;
}

/* Weighed goods can only ever be priced approximately — the butcher cuts to
   roughly the requested weight — so estimated totals are always marked. */
.approx::before { content: "approx "; color: var(--ink-3); font-weight: 400; }

/* The + affordance on a catalogue / usuals / offers row. */
.add-btn {
    width: 48px; height: 48px; flex: none;
    border-radius: 12px; border: 1px solid var(--accent);
    background: transparent; color: var(--accent-ink);
    font-size: 22px; cursor: pointer;
    display: grid; place-items: center;
}
.add-btn:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }

/* ── Prep notes / instructions ─────────────────────────────────────── */
/* A per-line note the supplier sees on the picking sheet. Generic wording — not every
   supplier is a butcher. Native <details> so it needs no script. */
.prep { width: 100%; margin-top: 12px; }
.prep summary {
    list-style: none; cursor: pointer;
    font-size: 12.5px; color: var(--accent-ink);
}
.prep summary::-webkit-details-marker { display: none; }
.prep summary::before { content: "＋ "; color: var(--ink-3); }
.prep[open] summary::before { content: "− "; }
.prep textarea { margin-top: 8px; font-size: 15px; min-height: 64px; }

/* A saved note shown read-only against a basket line. */
.line-note {
    margin-top: 9px; padding: 8px 11px;
    background: var(--surface); border-radius: var(--r-row);
    font-size: 12px; color: var(--accent-2);
}

/* ── Offline banner ────────────────────────────────────────────────── */
.offline-banner {
    background: var(--surface-3);
    border-bottom: 1px solid var(--line-2);
    color: var(--ink-2);
    font-size: 12.5px; text-align: center;
    padding: 9px 16px;
}

/* ── Cut-off strip — the real deadline carries the accent ──────────── */

.cutoff {
    padding: 14px 15px; border-radius: var(--r-card);
    background: linear-gradient(90deg, var(--accent-soft), var(--surface-3));
    border: 1px solid var(--accent-line);
}
.cutoff-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px; }
.cutoff-head .label { font-size: 13px; color: var(--accent-2); }
.cutoff-head .time { font-size: 15px; font-weight: 600; color: var(--accent-ink); }
.cutoff-track { height: 2px; background: var(--line-2); position: relative; margin-bottom: 9px; }
.cutoff-track > i {
    position: absolute; left: 0; top: 0; height: 2px;
    background: linear-gradient(90deg, var(--accent), rgba(145, 132, 217, 0));
}

/* ── Sticky bottom bar (review order) — sits above the tab bar ─────── */

.op-bar {
    position: fixed; left: 0; right: 0; z-index: 45;
    bottom: var(--tab-h);
    background: var(--surface-3);
    border-top: 1px solid var(--line-2);
    padding: 12px 16px;
    display: flex; align-items: center; gap: 12px;
}
.op-bar .total { font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }

/* ── Bottom tab bar ────────────────────────────────────────────────── */

.op-tabs {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    display: flex;
    background: var(--surface-2);
    border-top: 1px solid var(--line-2);
    padding-bottom: env(safe-area-inset-bottom, 0px);
}
.op-tab {
    flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px;
    padding: 10px 0 9px;
    color: var(--ink-3); text-decoration: none;
    font-size: 10.5px; letter-spacing: .01em;
}
.op-tab svg { width: 20px; height: 20px; display: block; }
.op-tab:hover { color: var(--ink-2); }
.op-tab.active { color: var(--accent-ink); }

/* ── "powered by orderpoint." sign-off ─────────────────────────────── */

.op-foot {
    display: flex; align-items: center; justify-content: center; gap: 9px;
    padding: 26px 0 8px; color: var(--ink-4);
    font-size: 11.5px;
}
.op-foot .mark {
    display: grid; grid-template-columns: repeat(2, 7px); grid-template-rows: repeat(2, 7px); gap: 2px;
}
.op-foot .mark > i { border-radius: 1px; background: var(--line); }
.op-foot .mark > i:last-child { background: var(--accent); }

/* ── Empty states ──────────────────────────────────────────────────── */
/* Every empty state explains what to do next — never a bare "no results". */

.empty { text-align: center; padding: 48px 20px; color: var(--ink-3); }
.empty h3 { color: var(--ink); margin-bottom: 8px; }
.empty p { color: var(--ink-3); }

/* Order-placed confirmation tick. */
.tick {
    width: 64px; height: 64px; margin: 0 auto 24px;
    border-radius: 32px; border: 1px solid var(--accent);
    display: grid; place-items: center;
    box-shadow: 0 0 34px rgba(145, 132, 217, .35);
}
.tick > i {
    width: 20px; height: 11px; margin-top: -5px;
    border-left: 2px solid var(--accent-ink); border-bottom: 2px solid var(--accent-ink);
    transform: rotate(-45deg);
}

/* ── Scrim and dialog / bottom sheet ───────────────────────────────── */

.scrim { position: fixed; inset: 0; background: var(--scrim); z-index: 1000; }
.dialog {
    position: fixed; z-index: 1001; left: 50%; top: 50%;
    transform: translate(-50%, -50%);
    width: min(440px, calc(100vw - 32px));
    max-height: min(600px, calc(100dvh - 48px));
    display: flex; flex-direction: column;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--r-panel); box-shadow: var(--shadow-lift);
    overflow: hidden;
}
.dialog-h { padding: 16px 18px; border-bottom: 1px solid var(--line-2); font-weight: 500; }
.dialog-b { padding: 16px 18px; overflow-y: auto; }
.dialog-f { padding: 14px 18px; border-top: 1px solid var(--line-2); display: flex; gap: 10px; justify-content: flex-end; }

/* On a phone a centred dialog is worse than a sheet that comes up from the
   bottom — it is closer to the thumb and matches platform convention. */
@media (max-width: 560px) {
    .dialog {
        top: auto; bottom: 0; left: 0; transform: none;
        width: 100%; max-height: 88dvh;
        border-radius: var(--r-panel) var(--r-panel) 0 0;
        border-bottom: none;
    }
}

/* ── Loading ───────────────────────────────────────────────────────── */

.skeleton {
    background: linear-gradient(90deg, var(--surface) 25%, var(--surface-3) 50%, var(--surface) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.3s infinite;
    border-radius: var(--r-row);
}
@keyframes shimmer { to { background-position: -200% 0; } }

@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ── Favourite star ────────────────────────────────────────────────── */

.fav {
    background: none; border: none; cursor: pointer;
    font-size: 20px; line-height: 1; color: var(--ink-3);
    width: 34px; height: 34px; flex: none;
    display: flex; align-items: center; justify-content: center;
    align-self: flex-start;
}
.fav.on { color: var(--accent); }

/* ── Header nav ─────────────────────────────────────────────────────── */

.op-nav { display: flex; gap: 4px; margin-left: auto; }
.op-nav a {
    font-size: 13.5px; font-weight: 500; color: var(--ink-3);
    padding: 7px 11px; border-radius: var(--r-control);
}
.op-nav a.active { color: var(--accent-ink); }
.op-nav a:hover { color: var(--ink); }

/* ── Boot and error ────────────────────────────────────────────────── */

.boot {
    min-height: 100dvh;
    display: flex; align-items: center; justify-content: center;
    color: var(--ink-3); font-size: 14.5px;
    background: var(--surface-2);
}

#blazor-error-ui {
    display: none;
    position: fixed; bottom: 0; left: 0; right: 0; z-index: 2000;
    background: var(--urgent-bg); color: var(--urgent);
    border-top: 1px solid var(--urgent-line);
    padding: 12px 16px; font-size: 14px;
}
#blazor-error-ui .reload { color: var(--urgent); text-decoration: underline; margin-left: 8px; }
#blazor-error-ui .dismiss { float: right; cursor: pointer; font-size: 18px; line-height: 1; }
