@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Fraunces:opsz,wght@9..144,600;9..144,700&display=swap');

/* ============================================================
   Design tokens - single source of truth for the whole system.
   Every page (staff shell pages and guest-facing pages alike)
   links this one stylesheet, so changing a token here re-themes
   the entire product consistently.
   ============================================================ */
:root {
    /* Primary brand accent for light/bright mode - blue. Dark mode has
       its own separate override (search for .app-shell.dark-mode) that
       keeps orange as its primary instead - these are intentionally
       different per mode. */
    /* Steel blue, not the brighter #0077C5 this was.

       The navy chrome (#101B33) and a saturated mid-blue were two
       different blues sitting next to each other - the button read as
       belonging to a different product from the menu beside it. This is
       the same hue family as the rail, a couple of steps lighter, so a
       primary button looks like it came from the same place.

       Contrast checked, because this is the colour every button, link
       and focus ring uses: #1A5A8A on white is 7.3:1, comfortably past
       WCAG AA for normal text, and white on #1A5A8A is the same figure
       inverted. The old #0077C5 was 4.7:1 - passing, but only just, and
       a hotel manager reading this at the end of a shift is not reading
       it in ideal light.

       Still named --qb-green. Every one of the fifty uses across this
       file refers to the token, so the value moves in one place - but
       the name has meant "blue" since long before today, and renaming it
       would touch far more than it is worth. */
    --qb-green: #1A5A8A;
    --qb-green-dark: #134671;
    --qb-green-tint: #EAF2F8;
    --ink: #1A1A1A;
    --ink-soft: #5E5E5E;
    --border: #E3E5E8;
    --bg: #F7F8FA;
    --card: #FFFFFF;
    --blue: #1A5A8A;
    --blue-tint: #EAF4FF;
    --danger: #C0392B;
    --danger-tint: #FBEAEA;
    --warn: #B7791F;
    --warn-tint: #FDF3DC;
    --radius: 14px;
    /* Chrome (icon rail + topbar) - back to white, matching the rest of
       the light theme. */
    --chrome-bg: #FFFFFF;
    --chrome-border: var(--border);
    --chrome-text: var(--ink-soft);
    --chrome-text-hover: var(--qb-green-dark);
    --chrome-accent-tint: var(--qb-green-tint);
    --chrome-accent-text: var(--qb-green-dark);
    /* Subtle elevation system - used sparingly so depth reads as premium
       polish, not visual noise. shadow-sm for resting cards, shadow-md
       for cards on hover/focus, shadow-lg for floating elements like
       dropdown panels. */
    --shadow-sm: 0 1px 2px rgba(16,24,16,0.04), 0 1px 3px rgba(16,24,16,0.06);
    --shadow-md: 0 4px 10px rgba(16,24,16,0.06), 0 2px 4px rgba(16,24,16,0.05);
    --shadow-lg: 0 12px 32px rgba(16,24,16,0.12), 0 4px 10px rgba(16,24,16,0.06);
}

* { box-sizing: border-box; }


body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: var(--bg);
    margin: 0;
    padding: 36px 15px 60px;
    color: var(--ink);
    font-size: 16px;
    /* 1.5 is tight for the paragraph-length text this now carries -
       dish descriptions, allergen notes, the terms page. */
    line-height: 1.55;
}



a { color: var(--blue); text-decoration: none; }
a:hover { text-decoration: underline; }
button { font-family: inherit; cursor: pointer; }
input, select { font-family: inherit; }

/* ============================================================
   Guest-facing pages: centered container (menu.php, checkout,
   confirmations, booking flow). Staff app-shell pages override
   body padding to 0 - see the shell block further down.
   ============================================================ */
.container { max-width: 950px; margin: 0 auto; }

.eyebrow {
    display: block;
    text-align: center;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--qb-green-dark);
    margin-bottom: 8px;
}

/* ============================================================
   TYPE
   ------------------------------------------------------------
   Two families, each doing one job.

   Fraunces (serif) for the page title only. It has warmth that a
   hospitality product wants and that Inter does not, but it is a
   display face - set it at 17px on a card heading and it reads as
   mannered rather than characterful. So it is confined to h1 and
   .headline.

   Inter for everything else, including h2 and h3. Card headings,
   table headers and form labels are functional text; they want the
   family that stays legible at 15px on a phone in a dim dining room.

   Sizes are fluid via clamp(), so a title that reads well on a 380px
   phone is not the same size on a 1400px laptop. The old scale was
   fixed at 30px, which is slightly small on a desktop hero and
   slightly large on a narrow phone - the usual result of one number
   trying to serve both.
   ============================================================ */
h1, .headline {
    font-family: 'Fraunces', Georgia, 'Times New Roman', serif;
    font-weight: 700;
    font-size: clamp(27px, 1.4rem + 1.6vw, 40px);
    line-height: 1.15;
    text-align: center;
    /* Tighter than the old -0.3px: a serif at display size carries
       more optical space between letters, so it needs more pulling in
       than a sans did at the same nominal tracking. */
    letter-spacing: -0.6px;
    margin: 0 0 10px;
    color: var(--ink);
    text-wrap: balance;   /* stops a two-line title leaving one orphan word */
}

.subtitle {
    text-align: center;
    color: var(--ink-soft);
    margin-bottom: 18px;
    font-size: 15.5px;
    line-height: 1.5;
    /* A subtitle under a centred title reads badly when it runs the full
       width of a desktop card - the eye loses the line. */
    max-width: 52ch;
    margin-left: auto;
    margin-right: auto;
    text-wrap: pretty;
}

/* Prices, totals and quantities line up in columns on the menu, the
   receipt and every report. Proportional digits make those columns ragged;
   tabular ones do not. Scoped rather than global because tabular figures
   look wrong inside a sentence. */
.menu-item-price, #cartTotal, .order-total, td, th, .qty-value {
    font-variant-numeric: tabular-nums;
}
.subtitle strong {
    font-weight: 700;
    display: inline-block;
    background: var(--qb-green);
    color: #fff;
    padding: 2px 10px;
    border-radius: 6px;
    letter-spacing: 0.3px;
    font-style: normal;
}

h1 + p.subtitle { margin-bottom: 24px; }

h2 {
    /* Fraunces, matching h1 and matching marketing.css line 13, so a
       heading looks the same whether a hotel is reading the public site
       or its own dashboard. style.css line 1 already imports the family,
       and _header.php loads this file too, so both sides are covered by
       this one rule - nothing else needs adding. */
    font-family: 'Fraunces', Georgia, 'Times New Roman', serif;
    font-weight: 700;
    /* 17px was too close to the 15px body text to read as a heading at
       a glance - the step between levels is what does the work, not the
       absolute size. */
    font-size: 19px;
    line-height: 1.3;
    color: var(--ink);
    margin: 0 0 14px;
    letter-spacing: -0.3px;
}

h3 {
    font-family: 'Fraunces', Georgia, 'Times New Roman', serif;
    font-weight: 700;
    font-size: 16px;
    line-height: 1.35;
    color: var(--ink);
    margin: 0 0 10px;
    letter-spacing: -0.3px;
}

.card {
    background: var(--card);
    border-radius: var(--radius);
    border: 1px solid var(--border);
    padding: 24px;
    margin-bottom: 20px;
}

.flash {
    padding: 12px 16px;
    border-radius: 8px;
    margin-bottom: 18px;
    font-weight: 500;
    font-size: 14px;
    border: 1px solid transparent;
}
.flash.success { background: #EAF7E9; color: var(--qb-green-dark); border-color: #C9E9C4; }
.flash.error { background: var(--danger-tint); color: var(--danger); border-color: #F1CFCF; }

form.booking-form,
.qb-form { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; }
form.booking-form .full,
.qb-form .full { grid-column: 1 / -1; }
@media (max-width: 700px) { form.booking-form, .qb-form { grid-template-columns: 1fr 1fr; } }

label {
    font-size: 12px;
    font-weight: 600;
    color: var(--ink-soft);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    display: block;
    margin-bottom: 6px;
}
input, select, textarea {
    width: 100%;
    padding: 11px 12px;
    border: 1px solid var(--border);
    border-radius: 8px;
    font-size: 14px;
    background: #fff;
    color: var(--ink);
    /* Without this a textarea falls back to monospace, which is why the
       opening-hours box looked like a code editor sitting under two
       ordinary text fields. */
    font-family: inherit;
}
textarea {
    line-height: 1.55;
    /* Free text needs room. Three default rows is not enough for opening
       hours, let alone a description - and a box that is too small to
       show what you typed is a box people stop typing into. */
    min-height: 110px;
    resize: vertical;
}
input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--qb-green);
    box-shadow: 0 0 0 3px rgba(26,90,138,0.15);
}

/* BUTTONS
 *
 * Navy, matching the navigation, rather than the bright --qb-green
 * (#0077C5 - blue despite the name).
 *
 * A dedicated token rather than changing --qb-green itself: that variable
 * is used 21 times in this file for links, focus rings, active states and
 * accent text, and those should stay bright. A link has to read as a link
 * against body copy; a button does not - it has a shape and a background
 * already doing that work.
 *
 * Change --btn-bg in one place to restyle every button in the product.
 */
:root {
    --btn-bg: #12344D;
    --btn-bg-hover: #0D2638;
}
button, .qb-btn {
    background: var(--btn-bg);
    color: #fff;
    border: 1px solid var(--btn-bg);
    padding: 12px 22px;
    border-radius: 9px;
    font-size: 15px;
    cursor: pointer;
    font-weight: 600;
    letter-spacing: 0.1px;
    transition: background 0.15s ease, transform 0.12s ease, box-shadow 0.15s ease;
    display: inline-block;
    text-decoration: none;
    box-shadow: 0 1px 2px rgba(26,90,138,0.15);
}
button:hover, .qb-btn:hover { background: var(--qb-green-dark); color: #fff; text-decoration: none; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(26,90,138,0.22); }
button:active, .qb-btn:active { transform: translateY(0); }
button:disabled { background: #ccc; border-color: #ccc; color: #888; cursor: not-allowed; transform: none; box-shadow: none; }

table, .qb-table { width: 100%; border-collapse: collapse; }
th, td, .qb-table th, .qb-table td { padding: 11px 10px; text-align: left; border-bottom: 1px solid var(--border); font-size: 13.5px; }
/* Belt-and-suspenders: explicit, direct rule for table cell text in the
   dark staff app - doesn't rely on inheriting color from any ancestor,
   so it can't silently break regardless of inheritance order. */
.app-shell td, .app-shell .qb-table td { color: var(--ink); }
th, .qb-table th {
    background: transparent;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--ink-soft);
    font-weight: 600;
    border-bottom: 2px solid var(--border);
}
tr:hover td { background: #FAFBFC; }
td:first-child strong, .pill-table {
    font-family: 'Inter', monospace;
    background: var(--blue-tint);
    color: var(--blue);
    padding: 2px 9px;
    border-radius: 6px;
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: 0.2px;
}

.badge {
    padding: 3px 12px;

    border-radius: 14px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.2px;
    text-transform: uppercase;
    display: inline-block;
}
.badge.Booked, .badge.Ready { background: var(--warn-tint); color: var(--warn); }
.badge.Completed { background: #E8F6E6; color: var(--qb-green-dark); }
.badge.Cancelled { background: var(--danger-tint); color: var(--danger); }
.badge.pay-Paid { background: #E8F6E6; color: var(--qb-green-dark); }
.badge.pay-Partial { background: var(--warn-tint); color: var(--warn); }
.badge.pay-Unpaid { background: var(--danger-tint); color: var(--danger); }
.badge.pay-Failed { background: var(--warn-tint); color: var(--warn); }

.actions a, .row-actions a {
    margin-right: 10px;
    font-size: 12px;
    text-decoration: none;
    font-weight: 600;
    letter-spacing: 0.1px;
}
.actions a.complete, .row-actions a.complete { color: var(--qb-green-dark); }
.actions a.cancel, .row-actions a.cancel { color: var(--warn); }
.actions a.delete, .row-actions a.delete { color: var(--danger); }
.actions a.pay, .row-actions a.pay { color: var(--blue); }
.actions a:hover, .row-actions a:hover { opacity: 0.75; }
.row-actions details { display: inline-block; }
.row-actions summary { display: inline; cursor: pointer; font-size: 12px; font-weight: 600; color: var(--blue); list-style: none; }
.row-actions summary::-webkit-details-marker { display: none; }
.move-form { margin-top: 6px; display: flex; gap: 6px; }
.move-form input { font-size: 12px; padding: 6px; width: 100px; }
.move-form button { font-size: 12px; padding: 6px 10px; }

/* Chef / order screens */
.order-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
.order-card { border: 1px solid var(--border); border-radius: var(--radius); padding: 18px; background: var(--card); box-shadow: var(--shadow-sm); transition: box-shadow 0.15s ease; }
.order-card:hover { box-shadow: var(--shadow-md); }
.order-table {
    font-family: 'Inter', monospace;
    display: inline-block;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.3px;
    color: var(--blue);
    background: var(--blue-tint);
    padding: 4px 12px;
    border-radius: 6px;
    margin-bottom: 8px;
}
.order-meal { font-weight: 600; margin-bottom: 8px; color: var(--ink); }
.order-detail { font-size: 13px; color: var(--ink-soft); margin-bottom: 4px; }
.order-detail.timestamps { line-height: 1.5; }
.complete-btn {
    display: block;
    text-align: center;
    margin-top: 12px;
    background: var(--qb-green);
    color: #fff;
    padding: 10px;
    border-radius: 8px;
    font-weight: 700;
    font-size: 13px;
    letter-spacing: 0.1px;
    text-decoration: none;
}
.complete-btn:hover { background: var(--qb-green-dark); text-decoration: none; }

/* Customer menu / ordering page */
/* MENU ROW LAYOUT
 *
 * The row is: photo | name+price+allergens | quantity stepper, with a
 * notes field that appears underneath once the guest adds one of
 * something.
 *
 * The bug this fixes: .item-notes-area carries width:100% inline, so the
 * moment it appeared it became a fourth flex item demanding the whole
 * row. With no flex-wrap, flex had nowhere to put it and instead shrank
 * every sibling to its minimum content width - which is why the dish
 * name collapsed to one word per line and the allergen box turned into a
 * tall thin column. It was always latent; the allergen line just gave it
 * enough content to become obvious.
 *
 * Two things fix it, and both are needed:
 *   flex-wrap on the row, so the notes field can drop to its own line
 *   a flex-basis on the info column, so it stops volunteering to shrink
 */
.menu-item {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 14px 0;
    border-bottom: 1px solid var(--border);
}
.menu-item:last-child { border-bottom: none; }
.menu-item-photo { width: 56px; height: 56px; min-width: 56px; border-radius: 10px; object-fit: cover; background: var(--bg); }
.menu-item-photo-fallback { display: flex; align-items: center; justify-content: center; color: var(--qb-green); }

/* grow, may shrink, but never start below 200px - and never past the
 * 150px floor, at which point the stepper wraps to its own line instead
 * of squeezing the name any further. */
.menu-item-info { flex: 1 1 200px; min-width: 150px; }
.menu-item-name { font-weight: 600; color: var(--ink); overflow-wrap: break-word; }
.menu-item-price { color: var(--qb-green-dark); font-size: 13px; font-weight: 600; }

/* The allergen notice sits inside the info column and is the tallest
 * thing in it, so it needs to be free to use the full column width
 * rather than being treated as something to squeeze. */
.menu-item-info .allergen-line { width: 100%; box-sizing: border-box; }

.qty-control { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }

/* Always its own full-width line, never a competitor for space on the
 * main row. The fade-in is a keyframe rather than a transition because
 * the toggle switches display, which transitions cannot animate. */
.item-notes-area { flex: 1 0 100%; animation: menuNotesIn .18s ease-out; }
@keyframes menuNotesIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .item-notes-area { animation: none; }
}
.qty-btn {
    width: 32px; height: 32px; border-radius: 50%; border: 1px solid var(--qb-green);
    background: #fff; color: var(--qb-green-dark); font-size: 18px; cursor: pointer; padding: 0; line-height: 1;
    font-weight: 600;
}
.qty-btn:hover { background: var(--qb-green-tint); }
.qty-value { min-width: 20px; text-align: center; font-weight: 600; }
#submitOrderBtn:disabled { background: #ccc; border-color: #ccc; cursor: not-allowed; }

/* Branches management portal */
.branches-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 18px; }
.branch-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 14px; }
.branch-stats div { text-align: center; background: var(--bg); border-radius: 8px; padding: 8px 4px; }
.branch-stats strong { display: block; font-size: 17px; color: var(--qb-green-dark); }
.branch-stats span { font-size: 9px; text-transform: uppercase; letter-spacing: 0.3px; color: var(--ink-soft); }

.branch-switcher { padding: 18px 26px; }
.branch-pills { display: flex; flex-wrap: wrap; gap: 8px; }
.branch-pill {
    display: inline-block; padding: 7px 16px; border-radius: 20px;
    border: 1px solid var(--border); background: var(--card); color: var(--ink-soft);
    font-size: 13px; font-weight: 600; text-decoration: none; transition: all 0.15s ease;
}
.branch-pill:hover { border-color: var(--qb-green); text-decoration: none; transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.branch-pill.active { background: var(--qb-green); color: #fff; border-color: var(--qb-green); box-shadow: 0 3px 8px rgba(26,90,138,0.28); }

/* Waiter screen timing text */
.waiter-timing { font-size: 11px; color: var(--ink-soft); margin: 4px 0 10px; }
.waiter-assigned { font-size: 11px; font-weight: 600; color: var(--warn); margin: 4px 0; }

/* Reports analytics */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; }
.stat-box {
    background: var(--card); border: 1px solid var(--border); border-top: 3px solid var(--border); border-radius: 12px;
    padding: 18px 16px; text-align: center; box-shadow: var(--shadow-sm); transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.stat-box:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.stat-box .stat-icon { font-size: 20px; margin-bottom: 6px; display: block; }
.stat-box strong { display: block; font-size: 26px; color: var(--qb-green-dark); font-weight: 800; }
.stat-box span { font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; color: var(--ink-soft); font-weight: 600; }
.stat-box.positive { border-top-color: var(--qb-green); }
.stat-box.positive strong { color: var(--qb-green-dark); }
.stat-box.negative { border-top-color: var(--danger); }
.stat-box.negative strong { color: var(--danger); }
.stat-box.warn { border-top-color: var(--warn); }
.stat-box.warn strong { color: var(--warn); }
.stat-box.neutral { border-top-color: var(--blue); }
.stat-box.neutral strong { color: var(--blue); }
.bar-row { display: grid; grid-template-columns: 160px 1fr 90px; align-items: center; gap: 12px; margin-bottom: 10px; font-size: 13px; }
.bar-row > span:first-child { font-weight: 600; }
.bar-track { background: var(--border); border-radius: 8px; height: 16px; overflow: hidden; }
.bar-fill { background: linear-gradient(90deg, var(--qb-green), var(--qb-green-dark)); height: 100%; border-radius: 8px; transition: width 0.4s ease; }
.bar-row > span:last-child { color: var(--ink-soft); font-variant-numeric: tabular-nums; }

/* Guest order-tracker steps */
.track-steps { display: flex; justify-content: space-between; margin: 24px 0 6px; position: relative; }
.track-steps::before { content: ''; position: absolute; top: 15px; left: 8%; right: 8%; height: 3px; background: var(--border); z-index: 0; }
.track-step { position: relative; z-index: 1; flex: 1; text-align: center; }
.track-dot {
    width: 32px; height: 32px; border-radius: 50%; background: #fff; border: 3px solid var(--border);
    margin: 0 auto 8px; display: flex; align-items: center; justify-content: center; font-size: 15px;
}
.track-step.done .track-dot { border-color: var(--qb-green); background: var(--qb-green); color: #fff; }
.track-step.active .track-dot { border-color: var(--warn); background: var(--warn-tint); color: var(--warn); animation: pulse 1.6s infinite; }
.track-label { font-size: 12px; font-weight: 600; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.2px; }
.track-time { font-size: 11px; color: var(--ink-soft); margin-top: 2px; }

.pulse { animation: pulse 1.6s infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.55; } }

@media print { .no-print { display: none !important; } body { padding: 0; background: #fff; } .card { box-shadow: none; } }

/* ============================================================
   Staff app shell (icon rail + topbar + main panel + optional
   right Tasks panel) - used by index.php, chef.php, waiter.php,
   reports.php, menu_admin.php, qr_codes.php, branches.php,
   staff_admin.php, table_assignments.php via shell_open.php /
   shell_close.php. Scoped under .app-shell so it never leaks
   into the guest-facing .container pages above.
   ============================================================ */
body:has(.app-shell) { padding: 0; }

.app-shell {
    display: flex; min-height: 100vh;
}
.app-shell input, .app-shell select, .app-shell textarea { background: var(--card); color: var(--ink); }
.app-shell tr:hover td { background: #FAFBFC; }
.app-shell th, .app-shell .qb-table th { border-bottom-color: var(--border); }

/* ============================================================
   Dark mode - opt-in via the theme toggle in the topbar (adds
   .dark-mode to .app-shell, remembered in localStorage). Reuses the same
   token-scoping trick as before: overriding --ink/--card/--border/--bg
   here cascades through every component built on those variables, no
   need to touch each one individually. Guest-facing pages (menu
   ordering, booking flow) don't have this toggle and always stay light -
   intentional, a guest scanning a QR code shouldn't see a staff-tool
   aesthetic either way.
   ============================================================ */
.app-shell.dark-mode {
    --ink: #EDEDED;
    --ink-soft: rgba(237,237,237,0.6);
    --border: rgba(255,255,255,0.09);
    --bg: #121212;
    --card: #1C1C1C;
    --qb-green: #E8600C;
    --qb-green-dark: #C24E08;
    --qb-green-tint: #FDEEE2;
    --chrome-bg: #1C1512;
    --chrome-border: rgba(255,255,255,0.08);
    --chrome-text: rgba(255,255,255,0.68);
    --chrome-text-hover: #FFFFFF;
    --chrome-accent-tint: rgba(232,96,12,0.20);
    --chrome-accent-text: #FF8A42;
    color: var(--ink);
}
.app-shell.dark-mode input, .app-shell.dark-mode select, .app-shell.dark-mode textarea { background: var(--card); color: var(--ink); }
.app-shell.dark-mode tr:hover td { background: rgba(255,255,255,0.035); }
.app-shell.dark-mode .rail-item:hover { background: rgba(255,255,255,0.06); }
.app-shell.dark-mode .rail-item.active { box-shadow: inset 0 0 0 1px rgba(232,96,12,0.35); }
.app-shell.dark-mode .brand { color: #fff; }
.app-shell.dark-mode .search-wrap form { background: rgba(255,255,255,0.07); }
.app-shell.dark-mode .search-wrap form:focus-within { background: rgba(255,255,255,0.12); box-shadow: 0 0 0 3px rgba(232,96,12,0.18); }
.app-shell.dark-mode .search-wrap input { color: #fff; }
.app-shell.dark-mode .search-wrap input::placeholder { color: rgba(255,255,255,0.45); }
.app-shell.dark-mode .search-wrap svg { color: rgba(255,255,255,0.5); }
.app-shell.dark-mode .icon-btn { color: rgba(255,255,255,0.65); }
.app-shell.dark-mode .icon-btn:hover { background: rgba(255,255,255,0.08); color: #fff; }
.app-shell.dark-mode .avatar { box-shadow: 0 1px 3px rgba(0,0,0,0.25); }
.app-shell.dark-mode .topbar { box-shadow: 0 1px 0 rgba(0,0,0,0.1); }
.app-shell.dark-mode button, .app-shell.dark-mode .qb-btn { box-shadow: 0 1px 2px rgba(232,96,12,0.20); }
.app-shell.dark-mode button:hover, .app-shell.dark-mode .qb-btn:hover { box-shadow: 0 4px 12px rgba(232,96,12,0.28); }
.app-shell.dark-mode .branch-pill.active { box-shadow: 0 3px 8px rgba(232,96,12,0.32); }
/* Theme toggle switch itself */
.theme-toggle {
    width: 52px !important; height: 28px !important; padding: 0 !important; border-radius: 999px !important;
    background: var(--bg) !important; border: 1px solid var(--border) !important; position: relative;
    cursor: pointer; flex-shrink: 0; transition: background 0.2s ease; box-shadow: none !important;
}
.theme-toggle:hover { border-color: var(--qb-green); }
.theme-toggle .toggle-track { display: flex; align-items: center; justify-content: space-between; width: 100%; height: 100%; padding: 0 6px; }
.theme-toggle .toggle-track svg { width: 13px; height: 13px; color: var(--ink-soft); position: relative; z-index: 1; }
.theme-toggle .toggle-thumb {
    position: absolute; top: 2px; left: 2px; width: 22px; height: 22px; border-radius: 50%;
    background: var(--card); box-shadow: 0 1px 3px rgba(0,0,0,0.2); transition: transform 0.2s ease;
    display: flex; align-items: center; justify-content: center;
}
.app-shell.dark-mode .theme-toggle { background: var(--chrome-bg) !important; border-color: var(--chrome-border) !important; }
.app-shell.dark-mode .theme-toggle .toggle-thumb { transform: translateX(24px); background: var(--qb-green); }
.app-shell.dark-mode .theme-toggle .toggle-track svg.icon-sun { color: rgba(255,255,255,0.35); }
.app-shell.dark-mode .theme-toggle .toggle-track svg.icon-moon { color: rgba(255,255,255,0.75); }

/* THE RAIL LIVES HERE, AND ONLY HERE.
   shell_close.php used to write these as inline styles, which meant this
   block was dead code that only appeared when its script failed - and the
   two never matched. The script now sets width and the collapsed class;
   everything you can see is below. */
.icon-rail {
    width: 128px; flex-shrink: 0; background: var(--chrome-bg); border-right: 1px solid var(--chrome-border);
    display: flex; flex-direction: column; align-items: stretch; padding: 20px 0 10px; gap: 6px;
    box-shadow: none; position: relative; z-index: 2;
    transition: width 0.2s ease;
}
.icon-rail.is-collapsed { width: 72px; align-items: center; }
.rail-item {
    width: calc(100% - 16px); margin: 0 8px; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 6px;
    padding: 12px 6px; color: var(--chrome-text); font-size: 11.5px; font-weight: 300;
    line-height: 1.25; text-align: center; border-radius: 12px;
    /* Wrapping, not nowrap: a longer label added later would be clipped
       silently, and nobody notices a truncated nav item until a customer
       asks what "Housekeepi" means. */
    white-space: normal; word-break: break-word;
    position: relative; transition: background 0.15s ease, color 0.15s ease;
}
.icon-rail.is-collapsed .rail-item { font-size: 10.5px; padding: 10px 4px; }
.rail-item:hover { background: var(--chrome-accent-tint); color: var(--chrome-text-hover); text-decoration: none; }
.rail-item.active { color: var(--chrome-accent-text); background: var(--chrome-accent-tint); font-weight: 700; box-shadow: inset 0 0 0 1px rgba(26,90,138,0.15); }
.rail-item svg { width: 22px; height: 22px; flex-shrink: 0; }
.apps-dropdown { position: relative; width: 100%; }
.apps-dropdown summary { list-style: none; cursor: pointer; }
.apps-dropdown summary::-webkit-details-marker { display: none; }

.main-shell { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.topbar {
    height: 64px; background: var(--chrome-bg); border-bottom: 1px solid var(--chrome-border);
    display: flex; align-items: center; gap: 18px; padding: 0 22px; flex-shrink: 0;
    position: relative; z-index: 3; box-shadow: 0 1px 0 rgba(16,24,16,0.02);
}
/* The hotel name in the topbar sits next to a solid colour badge and a
   search field. At 700 it competed with both; at 300 it reads as a label
   for the workspace rather than a headline, which is what it is.
   letter-spacing opens up slightly because a light weight set tight
   starts to look cramped at small sizes. */
.brand { display: flex; align-items: center; gap: 8px; font-weight: 300; font-size: 15px; letter-spacing: 0.2px; white-space: nowrap; color: var(--ink); }

/* The badge keeps its weight: two or three characters in a 30px square
   need the mass, and it is the one thing in the bar that has to be
   readable at a glance across a kitchen. */
.brand-badge {
    width: 30px; height: 30px; border-radius: 9px; background: linear-gradient(150deg, var(--qb-green), var(--qb-green-dark));
    color: #fff; display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700;
    box-shadow: 0 2px 5px rgba(26,90,138,0.28);
}
.search-wrap { flex: 1; max-width: 620px; }
.search-wrap form {
    display: flex; align-items: center; background: var(--bg); border: 1px solid var(--border);
    border-radius: 24px; padding: 9px 16px; gap: 8px; transition: all 0.15s ease;
}
.search-wrap form:focus-within { background: #fff; border-color: var(--qb-green); box-shadow: 0 0 0 3px rgba(26,90,138,0.12); }
.search-wrap input { border: none; background: transparent; outline: none; flex: 1; font-size: 14px; color: var(--ink); }
.search-wrap input::placeholder { color: var(--ink-soft); }
.search-wrap svg { width: 17px; height: 17px; color: var(--ink-soft); flex-shrink: 0; }
.topbar-right { display: flex; align-items: center; gap: 14px; margin-left: auto; }
.icon-btn {
    width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
    color: var(--ink-soft); background: none; border: none; flex-shrink: 0; transition: all 0.15s ease;
}
.icon-btn:hover { background: var(--qb-green-tint); color: var(--qb-green-dark); text-decoration: none; }
.icon-btn svg { width: 19px; height: 19px; }
.avatar {
    width: 32px; height: 32px; border-radius: 50%; background: #EDE7F6; color: #5E35B1;
    display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 13px; flex-shrink: 0;
    box-shadow: 0 1px 3px rgba(94,53,177,0.25);
}
.branch-badge {
    width: 30px; height: 30px; border-radius: 50%; background: var(--blue); color: #fff;
    display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 12px; flex-shrink: 0;
    box-shadow: 0 1px 3px rgba(0,0,0,0.25);
}
.tasks-toggle { border: 1px solid transparent; }
.tasks-toggle.on { background: var(--blue-tint); border-color: #B9DDFF; }
.tasks-toggle svg { color: var(--blue); }

.content-row { flex: 1; display: flex; min-width: 0; overflow: hidden; }
/* min-width: 0 is the fix for the sideways scrollbar.
 *
 * A flex item defaults to min-width:auto, which means it refuses to
 * shrink below the width of its widest child. So one long thing - a hotel
 * name that will not wrap, a wide table, a heading at the top of the
 * clamp - pushes .main-panel wider than the row, and the whole shell
 * gains a horizontal scrollbar. The panel scrolls vertically by design;
 * it was never meant to scroll sideways.
 *
 * overflow-wrap catches the other half: a single unbroken string, which
 * no amount of shrinking will fit, breaks rather than pushing. Hotel
 * names and email addresses are the usual offenders. */
.main-panel { flex: 1; min-width: 0; overflow-y: auto; overflow-x: hidden; padding: 26px 28px 60px; background: var(--bg); overflow-wrap: anywhere; }

/* Tables are the one thing that legitimately needs more width than the
   panel has - reports, stock, staff lists. They scroll inside their own
   box rather than dragging the page with them. */
.main-panel .qb-table, .main-panel table { max-width: 100%; }
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.main-panel-inner { max-width: 1080px; }
/* The fluid h1 scale is set for a guest page, which is a single centred
   column. A staff page puts it in a panel beside a sidebar and a task
   rail, so the top of that range is too big and starts wrapping headings
   that should fit on one line. */
.app-shell h1, .app-shell .headline { font-size: clamp(24px, 1.2rem + 0.9vw, 30px); text-align: left; }
.app-shell .subtitle { text-align: left; margin-left: 0; }
.main-panel-inner.wide { max-width: none; }

.qb-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; margin-bottom: 20px; box-shadow: var(--shadow-sm); }
.qb-card h2 { font-size: 17px; font-weight: 700; margin: 0 0 14px; }

.hero {
    background: linear-gradient(135deg, #F2F9FF 0%, #E6F3FC 55%, #D9ECFA 100%);
    border-color: #C8E1F5; position: relative; overflow: hidden; box-shadow: var(--shadow-md);
}
.app-shell.dark-mode .hero {
    background: linear-gradient(135deg, #FFF7F0 0%, #FDECDD 55%, #FBE2CB 100%);
    border-color: #F5D9BC;
}
.app-shell.dark-mode .hero::before { background: radial-gradient(circle, rgba(232,96,12,0.12), transparent 70%); }
.app-shell.dark-mode .hero-step .num { box-shadow: 0 2px 6px rgba(232,96,12,0.22); border-color: #F5D9BC; }
.hero::before {
    content: ''; position: absolute; top: -60px; right: -60px; width: 220px; height: 220px;
    border-radius: 50%; background: radial-gradient(circle, rgba(26,90,138,0.10), transparent 70%);
}
.hero h1 { font-size: 29px; text-align: left; font-weight: 800; line-height: 1.15; margin: 0 0 10px; letter-spacing: -0.3px; position: relative; color: #1A1A1A; }
.hero p.lead { color: #5E5E5E; font-size: 15px; margin: 0 0 22px; text-align: left; position: relative; }
.hero-steps { display: flex; gap: 22px; flex-wrap: wrap; position: relative; }
.hero-step { flex: 1; min-width: 220px; display: flex; gap: 14px; align-items: flex-start; }
.hero-step .num {
    width: 32px; height: 32px; flex-shrink: 0; border-radius: 50%; background: #fff; color: var(--qb-green-dark);
    font-size: 15px; font-weight: 800; line-height: 1; display: flex; align-items: center; justify-content: center;
    box-shadow: 0 2px 6px rgba(26,90,138,0.18); border: 1.5px solid #C8E1F5;
}
.hero-step .txt { font-size: 13px; padding-top: 5px; color: #1A1A1A; }
.hero-step .txt strong { display: block; font-size: 14px; margin-bottom: 2px; color: #1A1A1A; }

/* Right Tasks panel (index.php) */
.tasks-panel { width: 380px; flex-shrink: 0; background: var(--card); border-left: 1px solid var(--border); overflow-y: auto; box-shadow: -2px 0 8px rgba(16,24,16,0.02); }
.tasks-panel.hidden { display: none; }
.tasks-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 20px; border-bottom: 1px solid var(--border); }
.tasks-head h2 { font-size: 16px; margin: 0; font-weight: 700; }
.tasks-tabs { display: grid; grid-template-columns: 1fr 1fr; border-bottom: 1px solid var(--border); background: var(--bg); }
.tasks-tab {
    text-align: center; padding: 12px 6px; font-size: 12.5px; font-weight: 600; color: var(--ink-soft);
    border-bottom: 2px solid transparent; cursor: pointer; display: flex; align-items: center; justify-content: center;
    gap: 5px; background: var(--card); border-right: 1px solid var(--border); transition: background 0.12s ease;
}
.tasks-tab:nth-child(2n) { border-right: none; }
.tasks-tab:hover { background: var(--qb-green-tint); }
.tasks-tab.active { color: var(--qb-green-dark); border-bottom-color: var(--qb-green); background: var(--qb-green-tint); }
.tasks-body { padding: 20px; }
.tasks-body h3 { font-size: 17px; font-weight: 700; margin: 0 0 4px; }
.progress-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px; }
.progress-pct { font-size: 26px; font-weight: 800; color: var(--qb-green-dark); }
.progress-label { font-size: 12px; color: var(--ink-soft); font-weight: 600; }
.progress-track { background: var(--border); border-radius: 6px; height: 8px; overflow: hidden; margin-bottom: 22px; }
.progress-fill { background: var(--qb-green); height: 100%; border-radius: 6px; transition: width 0.3s ease; }
.task-card { border: 1px solid var(--border); border-radius: 12px; padding: 13px 14px; margin-bottom: 10px; transition: border-color 0.12s ease, box-shadow 0.12s ease; box-shadow: var(--shadow-sm); }
.task-card:hover { border-color: var(--qb-green); box-shadow: var(--shadow-md); }
.task-card-head { display: flex; align-items: center; gap: 12px; }
.task-ring { width: 36px; height: 36px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.task-ring::before { content: ''; width: 25px; height: 25px; border-radius: 50%; background: var(--card); }
.task-card-title { font-weight: 700; font-size: 13.5px; }
.task-card-sub { font-size: 11.5px; color: var(--ink-soft); margin-top: 1px; }
.task-card-toggle {
    margin-left: auto; font-size: 11.5px; font-weight: 700; color: var(--qb-green-dark);
    background: var(--qb-green-tint); padding: 5px 10px; border-radius: 14px; white-space: nowrap;
}
.task-list { margin: 12px 0 0; padding: 12px 0 0; list-style: none; border-top: 1px solid var(--border); }
.task-list li { display: flex; align-items: center; gap: 8px; font-size: 12.5px; padding: 5px 0; }
.task-check { width: 16px; height: 16px; border-radius: 50%; border: 2px solid var(--border); flex-shrink: 0; }
.task-check.done { background: var(--qb-green); border-color: var(--qb-green); position: relative; }
.task-check.done::after { content: '✓'; color: #fff; font-size: 10px; position: absolute; left: 2px; top: -1px; }
.ongoing-row { display: flex; align-items: center; justify-content: space-between; padding: 12px 0; border-bottom: 1px solid var(--border); }
.ongoing-row:last-child { border-bottom: none; }
.ongoing-num { font-size: 22px; font-weight: 700; }
.ongoing-num.warn { color: var(--warn); }
.ongoing-num.danger { color: var(--danger); }

/* Waiter screen columns */
.waiter-columns { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
@media (max-width: 1100px) { .waiter-columns { grid-template-columns: 1fr 1fr; } }
@media (max-width: 620px) { .waiter-columns { grid-template-columns: 1fr; } }
.waiter-col h2 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--ink-soft); margin-bottom: 12px; font-weight: 700; }
/* Ready to Pay - filterable/sortable alert section on the waiter screen */
.ready-to-pay-card { border-color: var(--qb-green); margin-bottom: 20px; }
.rtp-header { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 16px; }
.rtp-controls { display: flex; gap: 8px; flex-wrap: wrap; }
.rtp-search { font-size: 13px; padding: 8px 12px; width: 180px; }
.rtp-sort { font-size: 13px; padding: 8px 10px; }
.rtp-grid { display: flex; flex-wrap: wrap; gap: 14px; }
.rtp-row {
    display: flex; flex-direction: column; gap: 10px; padding: 14px 16px; border-radius: 10px;
    background: var(--bg); border: 1px solid var(--border); border-left: 4px solid var(--border);
    flex: 1 1 260px; max-width: 320px;
}
.rtp-row.urgency-low { border-left-color: var(--blue); }
.rtp-row.urgency-medium { border-left-color: var(--warn); background: var(--warn-tint); }
.rtp-row.urgency-high { border-left-color: var(--danger); background: var(--danger-tint); }
.rtp-top { display: flex; align-items: center; gap: 8px; }
.rtp-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--blue); }
.urgency-medium .rtp-dot { background: var(--warn); }
.urgency-high .rtp-dot { background: var(--danger); animation: rtp-pulse 1.4s infinite; }
@keyframes rtp-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.rtp-meta { font-size: 12px; color: var(--ink-soft); }
.rtp-actions { flex-shrink: 0; }
.waiter-card { border-radius: 12px; padding: 16px; margin-bottom: 12px; border: 1px solid var(--border); background: var(--card); }
.waiter-card.ready { background: var(--warn-tint); border-color: var(--warn); }
.waiter-card.preparing { background: #FBF3E3; border-color: var(--warn); }
.waiter-card.waiting { background: var(--bg); }
.waiter-card.served { background: var(--qb-green-tint); border-color: #B9D6C1; opacity: 0.85; }
/* .ready/.preparing/.served are deliberately light-tinted status cards
   regardless of the surrounding theme (same idea as the hero card) - lock
   their text dark so it stays readable instead of inheriting the
   dark-mode light ink color meant for actually-dark card backgrounds. */
.waiter-card.ready .waiter-items, .waiter-card.ready .waiter-timing,
.waiter-card.preparing .waiter-items, .waiter-card.preparing .waiter-timing,
.waiter-card.served .waiter-items, .waiter-card.served .waiter-timing {
    color: #5E5E5E;
}
.waiter-table-num {
    font-family: 'Inter', monospace; display: inline-block; font-size: 14px; font-weight: 700; letter-spacing: 0.3px;
    color: var(--blue); background: var(--blue-tint); padding: 4px 12px; border-radius: 6px; margin-bottom: 6px;
}
.waiter-items { font-size: 13px; color: var(--ink-soft); margin: 6px 0; }

@media (max-width: 1100px) { .tasks-panel { display: none; } }
@media (max-width: 720px) {
    .icon-rail { width: 64px; }
    .rail-item span { display: none; }
}

/* ======================================================================
   MENU LIST - one column on a phone, more columns as there is room.
   ======================================================================
   .menu-item is display:flex with justify-content:space-between, so a
   wide row pushes the dish name to the far left and the + button to the
   far right with a lake of whitespace between them. That is why the
   order popup used to be pinned at 780px: past roughly 800 the row stops
   reading as one item.

   Capping the width was treating the symptom. Extra space should buy
   MORE DISHES ON SCREEN rather than the same rows stretched wider, so
   the list becomes a grid that adds columns as the container grows, and
   each row stays the compact width it was designed for.

   auto-fill with a 330px minimum: a menu row has to hold a 56px photo,
   the name, the price, an allergen line and a three-part stepper. Below
   about 330 the stepper wraps onto its own line, which is fine on a
   phone and looks like a fault in a column next to one that didn't. */
.menu-item-list { display: grid; grid-template-columns: 1fr; }

@media (min-width: 860px) {
    .menu-item-list {
        grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
        column-gap: 26px;
    }
    /* In a single column the last item's divider is a stray line above
       the card edge. In a grid it is the only thing separating a cell
       from the one below it, so it comes back. */
    .menu-item-list .menu-item:last-child { border-bottom: 1px solid var(--border); }
}