/* ============================================================
   08-customer-final.css — Customer menu, final pass

   The last word on the student menu, navbar and deal cards, including the density
   pass for large menus. These rules exist to settle conflicts among the layers
   above and must stay last.

   Part of an ordered set linked in fragments/head.html. The browser applies these
   in link order and THAT ORDER IS THE CASCADE — a rule here can only override one
   in an earlier file. Do not reorder the links, and do not move a rule between
   files without checking what it then stops overriding.
   ============================================================ */

/* ============================================================
   10-student-menu.css — AUTHORITATIVE student menu layer.
   Scoped to the student menu page. This is the final winning
   layer for the hero, ticker, and menu-card layout. It exists to
   neutralize the conflicting earlier menu rules (floating Add
   disc over the photo, absolute .menu-card-actions) and replace
   them with a normal-flow, reserved-footer layout that cannot
   overlap the name, price, or image.
   ============================================================ */

/* ---------- Hero ---------- */
.menu-hero {
    position: relative;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    padding: 2rem 0 1.5rem;
}
.menu-hero-title {
    font-family: var(--font-display);
    font-size: clamp(2.4rem, 7vw, 4.5rem);
    line-height: 0.95;
    letter-spacing: -0.03em;
    text-transform: uppercase;
    color: var(--color-ink);
    margin: 0;
}
.menu-hero-title .outline {
    color: transparent;
    -webkit-text-stroke: 2px var(--color-ink);
    display: block;
}
.menu-hero-shout {
    display: block;
    font-family: var(--font-body);
    font-weight: 700;
    font-size: clamp(1rem, 2.6vw, 1.25rem);
    letter-spacing: 0.02em;
    text-transform: none;
    color: var(--color-primary);
    margin-top: 0.9rem;
}
.menu-hero-outlet {
    margin-top: 1.1rem;
    max-width: 300px;
}
.menu-hero-outlet .form-select {
    border: 3px solid var(--color-ink);
    border-radius: 0;
    box-shadow: 4px 4px 0 var(--color-ink);
    font-weight: 700;
    font-family: var(--font-display);
    text-transform: uppercase;
    font-size: 0.85rem;
}
.menu-hero-sticker {
    flex: 0 0 auto;
    width: clamp(84px, 14vw, 128px);
    height: clamp(84px, 14vw, 128px);
    border-radius: 50%;
    background: var(--color-accent-tint);
    border: 3px solid var(--color-ink);
    box-shadow: 6px 6px 0 var(--color-ink);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    transform: rotate(8deg);
}
.menu-hero-sticker span {
    font-family: var(--font-display);
    font-size: clamp(0.9rem, 2.4vw, 1.2rem);
    line-height: 1;
    letter-spacing: 0.02em;
    color: var(--color-ink);
}

/* ---------- Ticker ---------- */
.ticker {
    background: var(--color-primary);
    border-top: 3px solid var(--color-ink);
    border-bottom: 3px solid var(--color-ink);
    overflow: hidden;
    margin: 0 0 1.75rem;
}
.ticker-track {
    display: flex;
    white-space: nowrap;
    animation: ticker-scroll 18s linear infinite;
}
.ticker-track span {
    /* Stated directly rather than inherited from the track, so this cannot be undone
       again by a universal rule. */
    white-space: nowrap;
    flex: none;
    font-family: var(--font-display);
    font-size: 0.95rem;
    letter-spacing: 0.05em;
    color: #fff;
    padding: 0.55rem 0;
}
@keyframes ticker-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* ---------- Menu card: normal-flow footer controls ---------- */
/* Neutralize the earlier floating-disc and absolute actions rules. */
.menu-card-actions {
    position: static;
    right: auto;
    bottom: auto;
    margin-top: 0.85rem;
    border-top: 3px solid var(--color-ink);
    padding-top: 0.85rem;
}
.menu-card-actions .btn-add {
    border: 3px solid var(--color-ink);
}

/* The card itself: keep the photo square-ish and the body stacked,
   so the footer sits below the text and can never overlap it. */
.menu-card {
    display: flex;
    flex-direction: column;
    border: 3px solid var(--color-ink);
    border-radius: 0;
    box-shadow: 5px 5px 0 var(--color-ink);
    background: var(--color-surface);
    overflow: hidden;
}
.menu-card-media {
    position: relative;
    overflow: hidden;
    background: var(--color-surface-deep);
}
.menu-card-photo {
    display: block;
    width: 100%;
    height: 100%;
}
.menu-card-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.menu-card-body {
    display: flex;
    flex-direction: column;
    flex: 1;
}
.menu-card-name {
    font-family: var(--font-display);
    line-height: 1.15;
    text-transform: uppercase;
    letter-spacing: 0.01em;
}
.menu-card-price {
    font-weight: 700;
}
.price-strike {
    color: var(--color-ink-muted);
    text-decoration: line-through;
    margin-right: 0.4rem;
    font-weight: 600;
}

/* The cart control: a full-width, no-overlap action row. */
.menu-card-actions .cart-control {
    display: flex;
    width: 100%;
}
.menu-card-actions .cart-control__add {
    flex: 1;
    display: flex;
}
.menu-card-actions .btn-add {
    flex: 1;
    width: 100%;
    height: 44px;
    border-radius: 0;
    background: var(--color-primary);
    color: #fff;
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    box-shadow: 3px 3px 0 var(--color-ink);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: transform 100ms ease, box-shadow 100ms ease;
}
.menu-card-actions .btn-add:hover {
    background: var(--color-primary-dark);
    transform: translate(2px, 2px);
    box-shadow: 1px 1px 0 var(--color-ink);
}
.menu-card-actions .btn-add:active { transform: translate(3px, 3px); box-shadow: none; }

/* Stepper: replaces the Add button when .is-active. */
.menu-card-actions .cart-control__stepper {
    display: none;
    flex: 1;
    width: 100%;
    height: 44px;
    border: 3px solid var(--color-ink);
    border-radius: 0;
    background: var(--color-accent-tint);
    box-shadow: 3px 3px 0 var(--color-ink);
    align-items: stretch;
    overflow: hidden;
}
.menu-card-actions .cart-control.is-active .cart-control__add { display: none; }
.menu-card-actions .cart-control.is-active .cart-control__stepper { display: flex; }
.menu-card-actions .cart-control__stepper button {
    flex: 1;
    background: transparent;
    border: none;
    color: var(--color-ink);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.3rem;
    line-height: 1;
    transition: background-color 120ms ease;
}
.menu-card-actions .cart-control__stepper button:hover { background: rgba(20, 16, 13, 0.08); }
.menu-card-actions .cart-control__stepper .cart-qty-value {
    flex: 1.4;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-display);
    font-size: 1.05rem;
    border-left: 3px solid var(--color-ink);
    border-right: 3px solid var(--color-ink);
}

/* ---------- Deal cards (today's specials) ---------- */
.deal-card {
    border: 3px solid var(--color-ink);
    border-radius: 0;
    box-shadow: 4px 4px 0 var(--color-ink);
    overflow: hidden;
    background: var(--color-accent-tint);
}
.deal-card .deal-card-body { padding: 0.85rem; }
.deal-card .deal-card-name {
    font-family: var(--font-display);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    font-size: 0.95rem;
}
.deal-card .btn-add.deal-card-add {
    width: auto;
    height: 38px;
    padding: 0 1.1rem;
    border-radius: 0;
    border: 3px solid var(--color-ink);
    background: var(--color-primary);
    color: #fff;
    box-shadow: 3px 3px 0 var(--color-ink);
    font-family: var(--font-display);
    text-transform: uppercase;
    font-size: 0.8rem;
    letter-spacing: 0.04em;
}

/* ---------- Search + chips stay tidy ---------- */
.search-bar {
    border: 3px solid var(--color-ink);
    border-radius: 0;
    box-shadow: 4px 4px 0 var(--color-ink);
    background: var(--color-field);
}
/* This layer turned the chip from a borderless icon-and-label into a bordered card, but
   left the sizing it had as a label: `padding: 0` and `min-width: 72px` with no fixed
   width. So the chip sized itself to its text — 83px for "All Dishes", 72px for "Meals" —
   which put the 62px icon at an 11px inset in one chip and a 5px inset in the next, and
   ran "ALL DISHES" flush into its own border. The label also still carried
   `text-overflow: ellipsis`, which is why "Beverages" rendered as "BEVERAG…".

   A fixed width fixes all of it at once: every chip identical, every icon on the same
   rhythm, and the label free to wrap instead of being cut. Category names are authored by
   outlets and can be any length, so the label is clamped to two lines at a fixed height —
   that keeps the row even no matter what a canteen types. */
.category-chip {
    border: 3px solid var(--color-ink);
    border-radius: 0;
    background: var(--color-surface);
    font-family: var(--font-display);
    text-transform: uppercase;
    font-size: 0.8rem;
    letter-spacing: 0.03em;
    color: var(--color-ink);
    box-shadow: 3px 3px 0 var(--color-ink);

    flex: 0 0 100px;
    width: 100px;
    min-width: 100px;
    padding: 8px 8px 10px;
    gap: 8px;
    justify-content: flex-start;
}

.category-chip .cat-chip-icon {
    width: 58px;
    height: 58px;
    flex: none;
}

.category-chip .cat-chip-label {
    max-width: 100%;
    width: 100%;
    text-align: center;
    font-size: 0.62rem;
    line-height: 1.2;
    letter-spacing: 0.02em;
    /* Two lines, always the same height, so a one-word category and a three-word one
       produce chips of identical size. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    white-space: normal;
    overflow: hidden;
    /* Break at spaces only. `anywhere` split "BEVERAGES" into "BEVERAGE" and an orphaned
       "S" on the second line; a multi-word name like "All Dishes" still wraps normally. */
    overflow-wrap: normal;
    word-break: normal;
    hyphens: none;
    text-overflow: clip;
    min-height: 2.4em;
}
.category-chip.active {
    background: var(--color-primary);
    color: #fff;
}

/* ---------- Sticky cart bar ---------- */
#sticky-cart-bar {
    border-top: 3px solid var(--color-ink);
    box-shadow: 0 -4px 0 var(--color-ink);
    background: var(--color-surface);
}

/* ============================================================
   10-menu-final.css — authoritative menu-page layer.
   Renders LAST, so it wins every earlier menu rule. Scoped to
   the student menu page only. Fixes: deal-card button placement,
   photo placeholder (no pre-made SVG), mobile deal layout, and
   the broken navbar.
   ============================================================ */

/* ---------- Photo placeholder (no pre-made food SVG) ---------- */
.photo-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--color-surface-deep);
    color: var(--color-ink-muted);
}
.photo-placeholder .material-symbols-outlined {
    font-size: 34px;
    color: var(--color-ink-muted);
    opacity: 0.75;
}
.deal-card-photo,
.menu-card-photo {
    position: relative;
    overflow: hidden;
    display: block;
}
.deal-card-photo img,
.menu-card-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* ---------- Deal card: stacked body, full-width add bar ---------- */
.deal-card {
    flex: 0 0 200px;
    width: 200px;
}
.deal-card-name {
    margin: 0;
    font-size: 0.95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.deal-card-price {
    margin: 0;
}
.deal-card-add-form {
    margin-top: 4px;
}

/* ---------- Mobile: deal cards fill width, no cramped buttons ---------- */
@media (max-width: 575.98px) {
    .featured-scroll {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 12px;
        overflow: visible;
    }
    .deal-card {
        flex: none;
        width: auto;
    }
}

/* ---------- Navbar fixes ---------- */
.navbar .navbar-brand {
    font-family: var(--font-display);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: -0.01em;
    color: var(--color-ink) !important;
}
.navbar .navbar-toggler-custom {
    border: 2px solid var(--color-ink);
    border-radius: 0;
    color: var(--color-ink);
}

/* ============================================================
   11-navbar-final.css — authoritative navbar layer.
   Wins the cascade over every earlier .navbar definition.
   ============================================================ */

.navbar {
    position: sticky;
    top: 0;
    z-index: 1030;
    background: var(--color-bg) !important;
    border-bottom: 3px solid var(--color-ink);
    box-shadow: none;
    
    
    min-height: 60px;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
}

.navbar-brand {
    font-family: var(--font-display);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: -0.01em;
    font-size: 1.05rem;
    color: var(--color-ink) !important;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 55vw;
}

.brand-mark {
    height: 28px;
    width: auto;
    flex: none;
}

.navbar-right {
    margin-left: auto;
    min-width: 0;
}

.navbar-toggler-custom {
    border: 2px solid var(--color-ink) !important;
    border-radius: 0 !important;
    background: transparent;
    color: var(--color-ink);
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    box-shadow: 3px 3px 0 var(--color-ink);
}

.navbar-toggler-custom:active {
    transform: translate(2px, 2px);
    box-shadow: 1px 1px 0 var(--color-ink);
}

.navbar .nav-link {
    color: var(--color-ink) !important;
    font-weight: 600;
    font-size: 0.9rem;
    border-radius: 0;
    white-space: nowrap;
}

.navbar .nav-link:hover {
    background: var(--color-accent-tint);
    color: var(--color-ink) !important;
}

.navbar .top-nav-links .nav-link {
    border-radius: 0;
}


/* Logout / login buttons match the brutalist language */
.navbar .btn-outline-secondary {
    border: 2px solid var(--color-ink) !important;
    border-radius: 0 !important;
    color: var(--color-ink) !important;
    background: transparent;
    font-weight: 700;
    box-shadow: 3px 3px 0 var(--color-ink);
    white-space: nowrap;
    flex: none;
}

.navbar .btn-outline-secondary:hover {
    background: var(--color-accent-tint) !important;
    color: var(--color-ink) !important;
}

.navbar .btn-outline-secondary .material-symbols-outlined {
    font-size: 18px;
    vertical-align: -4px;
}

/* Collapsed staff/admin menu on mobile */
.navbar-links-collapse.is-open {
    border: 3px solid var(--color-ink);
    border-top: none;
    box-shadow: 5px 5px 0 var(--color-ink);
    background: var(--color-bg);
}

@media (max-width: 991.98px) {
    .navbar-links-collapse {
        position: absolute;
        left: 0;
        right: 0;
        top: 100%;
        z-index: 1040;
        padding: 8px 16px 12px;
        display: none;
    }
    .navbar-links-collapse.is-open {
        display: flex;
        flex-direction: column;
        align-items: stretch;
    }
    .navbar-links-collapse .nav-link {
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 10px 8px;
    }
}

/* ---------- Student mobile: bottom-nav safe ---------- */
@media (max-width: 991.98px) {
    .navbar .top-nav-links {
        display: none !important;
    }
}

/* ============================================================
   12-deal-cards-final.css — Today's specials, final layer.
   ============================================================ */

.deal-card-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.deal-card-add-form {
    display: block;
    width: 100%;
    margin: 4px 0 0;
}

.deal-card-add {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 40px;
    background: var(--color-primary);
    color: #fff;
    border: none;
    border-radius: 0;
    font-family: var(--font-display);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    cursor: pointer;
}

.deal-card-add::before {
    content: 'add';
    /* Ligature-selected, so the inherited uppercase from the button would turn
       'add' into 'ADD' and render the word instead of the glyph. */
    text-transform: none;
    letter-spacing: normal;
    font-family: 'Material Symbols Outlined';
    font-size: 18px;
    margin-right: 6px;
}

/* Very narrow phones: one column so cards never crush */
@media (max-width: 359.98px) {
    .featured-scroll {
        grid-template-columns: 1fr;
    }
}

/* ============================================================
   13-menu-density.css — scale fix for large menus (60+ items).
   Dense cards, tighter grid, compact category headers.
   ============================================================ */

/* Category headers: compact label rows, not big display blocks */
.menu-category-section h5 {
    font-family: var(--font-display);
    font-size: 1rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding-bottom: 4px;
    border-bottom: 3px solid var(--color-ink);
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Grid: 2 cols phone, 3 small tablet, 4 desktop — already set via
   Bootstrap cols, but tighten gutters so more fits per screen. */
.menu-category-section .row { --bs-gutter-x: 12px; --bs-gutter-y: 14px; }

/* Cards: smaller type, tighter padding — density without crowding */
.menu-card-body { padding: 10px 12px 12px; }
.menu-card-name { font-size: 0.9rem; margin-bottom: 0.2rem; }
.menu-card-price { font-size: 0.95rem; margin-bottom: 0.4rem; }

/* Card photos: 4:3 instead of square — shorter cards, more per screen */
.menu-card-media { aspect-ratio: 4 / 3; }

/* Compact stock notes so low-stock/sold-out doesn't inflate card height */
.stock-note {
    font-size: 0.72rem;
    padding: 2px 6px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.stock-note .material-symbols-outlined { font-size: 14px; }

/* Stepper/add controls: full-width but slimmer */
.menu-card-actions .cart-control { min-height: 40px; }
.menu-card-actions .btn-add { font-size: 0.8rem; padding: 6px 0; }
.menu-card-actions .cart-control__stepper button { width: 36px; height: 36px; }

/* Sticky chip strip: solid background so cards sliding under don't show
   through, and a hard bottom border in the design language */
@media (max-width: 767.98px) {
    .category-chips-wrapper {
        position: sticky;
        top: 60px;
        z-index: 1020;
        background: var(--color-bg);
        border-bottom: 3px solid var(--color-ink);
        margin-inline: -1rem;
        padding: 8px 1rem 10px;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .category-chips-wrapper::-webkit-scrollbar { display: none; }
}

/* Defensive: never let snap/overflow rules touch vertical page scroll */
html { scroll-behavior: auto !important; }
body { overscroll-behavior-y: auto !important; }


/* ============================================================
   ALERTS — readable sentences, not banners.

   07-brutalist styles .alert in uppercase Archivo Black with letter-spacing. That reads
   well for "SAVED" and badly for "Payment cancelled. Your order is still held — tap Pay
   to try again." — which is what this app actually puts in alerts. 09-console already
   exempts the staff portals; these are the customer-facing ones.
   ============================================================ */

.alert {
    font-family: var(--font-body);
    font-weight: 500;
    text-transform: none;
    letter-spacing: normal;
    font-size: 0.92rem;
    line-height: 1.45;
    text-align: left;
    padding: 0.75rem 0.9rem;
}

.alert-success { background: var(--color-accent-tint); color: var(--color-ink); }
.alert-warning { background: var(--color-accent-tint); color: var(--color-ink); }
.alert-danger  { background: var(--color-primary-tint); color: var(--color-ink); }
.alert-info    { background: var(--color-surface-deep); color: var(--color-ink); }

/* The payment failure notice is injected directly after the pay button, which put it
   flush against the "Cancel and return to cart" link below with no separation at all —
   the two read as one block. */
#pay-notice { margin-bottom: 1.25rem; }


/* ============================================================
   CART PAY BAR + CHECKOUT — squaring-up fallout.
   ============================================================ */

/* The label wrapped to two lines once the bar lost its pill shape, which pushed the
   amount out of the bar entirely — "To Pay" with no total under it. */
.sticky-pay-inner .btn-primary {
    white-space: nowrap;
    padding-inline: 1rem;
    font-size: 0.92rem;
}

/* The amount was inheriting ink from the price styling and rendering near-black on the
   near-black bar — present in the DOM, invisible on screen. The bar is a dark surface, so
   its contents have to state their own colour rather than inherit the page's. */
.sticky-pay-total span {
    white-space: nowrap;
    color: var(--color-bg);
}
.sticky-pay-total small {
    color: rgba(242, 234, 217, 0.7);
}

/* The bar is taller than the pill it replaced, and cart.html reserves a fixed 90px of
   scroll clearance for it, so the closing paragraph was sliding underneath. Reserving
   the space here keeps the number next to the bar's real height rather than in a style
   attribute in the template. */
/* Clearance for the sticky bar. It is taller than it looks: 80px of bar plus the 76px
   of bottom padding that lifts it above the tab nav, so ~157px total. The old inline
   90px predated the bottom nav and left the closing paragraph underneath it. */
.cart-page-body {
    padding-bottom: 176px !important;
}

/* Everything else on these screens is square; this was the last circle. */
.icon-circle {
    border-radius: 0;
    border: 3px solid var(--color-ink);
    box-shadow: var(--shadow-sm);
}


/* ============================================================
   BOTTOM TAB NAV — one authoritative definition.

   Three separate sheets were each setting part of this, and between them the bar was
   64px tall while its contents only filled 61px: 8px of padding-top, 53px of item, and
   no padding-bottom. That left a 3px strip of bare canvas along the bottom edge of a bar
   that is supposed to sit flush to the screen, which reads as a rendering fault.

   Items were also a fixed 72px each. Five of those plus the bar's own 16px side padding
   comes to 392px against a 390px viewport, so they were pressed together with nothing
   between them. They now divide the width evenly and centre inside the full bar height.
   ============================================================ */

@media (max-width: 991.98px) {
    .bottom-nav {
        display: flex;
        align-items: stretch;
        height: calc(var(--bottom-nav-height) + var(--safe-area-bottom));
        padding: 0 4px var(--safe-area-bottom);
        border-top: 3px solid var(--color-ink);
        background: var(--color-surface);
    }

    .bottom-nav-item {
        /* Even division rather than a fixed width, so the row fits any viewport and the
           tap target grows on wider phones instead of leaving a gutter. */
        flex: 1 1 0;
        min-width: 0;
        display: flex;
        flex-direction: column;
        align-items: center;
        /* Centred in the full height — this is what closes the strip along the bottom. */
        justify-content: center;
        height: 100%;
        padding: 0 2px;
        gap: 3px;
        font-size: 0.62rem;
        letter-spacing: 0.01em;
        line-height: 1;
    }

    .bottom-nav-item .material-symbols-outlined {
        font-size: 22px;
        line-height: 1;
    }

    /* The active tab was marked twice: a red colour change and a 3px red bar pinned to
       the top edge of the item. The bar sat hard against the bar's own black border and
       added a second horizontal rule to a component that already has one. Colour alone
       carries it. */
    .bottom-nav-item.active::before {
        display: none;
    }

    .bottom-nav-item.active {
        color: var(--color-primary-dark);
    }

    .bottom-nav-item.active .material-symbols-outlined {
        font-variation-settings: 'FILL' 1;
        transform: none;
    }

    /* Long labels ("Account", "Support") must not wrap and shove the icons out of line. */
    .bottom-nav-item > span:not(.material-symbols-outlined) {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 100%;
    }
}


/* ============================================================
   ACTIVE ORDER STRIP

   Sits under the top bar on every customer screen whenever an order is unfinished. The
   colour states the situation before the text is read: ink for in-progress, yellow while
   cooking, red when money is outstanding, and ink-with-yellow when food is waiting on the
   counter — the one state where a student losing track has a real cost.
   ============================================================ */

.active-order-strip {
    /* Deliberately in normal flow, not sticky. `html, body { overflow-x: hidden }` in
       02-base makes the body the nearest scrollport, and a sticky child of a scrollport
       whose height is its own content has nothing to stick within — the top navbar is
       already inert for the same reason. Rather than leave a declaration that does
       nothing, the strip sits at the top of every customer page (so it is seen on every
       load and every navigation) and the Orders tab badge in the bottom nav carries the
       persistent signal while scrolling. */
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    border-bottom: 3px solid var(--color-ink);
    background: var(--color-ink);
    color: var(--color-bg);
    text-decoration: none;
    font-family: var(--font-body);
}

.active-order-strip:hover,
.active-order-strip:focus {
    color: var(--color-bg);
    text-decoration: none;
}

.active-order-strip__pulse {
    width: 10px;
    height: 10px;
    flex: none;
    border: 2px solid currentColor;
    background: currentColor;
    animation: strip-pulse 1.8s ease-in-out infinite;
}

@keyframes strip-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.25; }
}

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

.active-order-strip__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.2;
}

.active-order-strip__text strong {
    font-family: var(--font-display);
    font-weight: 400;
    text-transform: uppercase;
    font-size: 0.78rem;
    letter-spacing: 0.03em;
}

.active-order-strip__meta {
    font-size: 0.72rem;
    opacity: 0.75;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.active-order-strip__cta {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: none;
    font-family: var(--font-display);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border: 2px solid currentColor;
    padding: 5px 9px;
}

.active-order-strip__cta .material-symbols-outlined { font-size: 16px; }

/* Ready to collect — the loudest pairing in the palette, and used nowhere else. */
.active-order-strip.is-ready {
    background: var(--color-ink);
    color: var(--color-accent-tint);
}

/* Being prepared. */
.active-order-strip.is-preparing {
    background: var(--color-accent-tint);
    color: var(--color-ink);
}

/* Money outstanding: nothing happens until this is resolved. */
.active-order-strip.is-unpaid {
    background: var(--color-primary-dark);
    color: #fff;
}

/* Confirmed, not yet started. */
.active-order-strip.is-paid {
    background: var(--color-ink);
    color: var(--color-bg);
}

/* ---------- Orders screen grouping ---------- */

.orders-group--active {
    margin-bottom: 1.75rem;
}

.orders-group--active .section-label {
    display: flex;
    align-items: center;
    gap: 0.45rem;
}

.orders-group--active .order-card {
    border-width: 3px;
    box-shadow: 5px 5px 0 var(--color-ink);
}

/* The category strip offsets 60px for the top navbar, but that bar does not stay put —
   it is `sticky` inside a wrapper exactly its own height, so it scrolls away. Pinning the
   strip below a bar that is not there left it floating with scrolled content showing
   through the gap. On phones it pins flush instead. */
@media (max-width: 991.98px) {
    .category-chips-wrapper { top: 0; }
}

/* ============================================================
   PHONE DENSITY — get food onto the first screen.

   Reordering search and categories above the specials rail moved them from 725px and
   819px up to 370px and 464px, but the first dish still sat at 1029px on an 844px
   screen: the hero, the ticker and a 287px carousel between them account for most of a
   viewport before anything orderable appears.

   Nothing is removed — the greeting, the ticker and the rail all still do their job.
   They are simply sized for a phone rather than a desktop hero.
   ============================================================ */

@media (max-width: 767.98px) {
    .menu-hero {
        margin-bottom: 0.75rem;
    }

    .menu-hero-title {
        font-size: clamp(1.6rem, 9vw, 2.2rem);
        line-height: 1.04;
    }

    .menu-hero-sticker {
        width: 76px;
        height: 76px;
    }

    /* Decorative, so it takes a decorative amount of room. */
    .ticker {
        margin-bottom: 1rem;
    }

    .ticker-track span {
        font-size: 0.8rem;
        padding: 0.35rem 0;
    }

    .search-bar {
        margin-bottom: 0.85rem;
    }

    .category-chips-wrapper {
        margin-bottom: 1rem;
    }

    .category-chips {
        gap: 8px;
        padding: 2px 2px 6px;
    }

    .cat-chip-icon {
        width: 52px;
        height: 52px;
    }

    /* The rail is discovery you pass on the way down, not a gate in front of the menu. */
    .featured-scroll .deal-card {
        width: 150px;
    }

    .featured-scroll .deal-card-photo {
        aspect-ratio: 1;
    }

    .deal-card-name {
        font-size: 0.85rem;
    }
}

/* The deal card's photo is 120px but the card is 279px: the name, price and Add control
   below it were sized for a desktop card. On a phone the rail is a glance, not a
   destination. */
@media (max-width: 767.98px) {
    .featured-scroll .deal-card-photo { margin-bottom: 8px; }
    .featured-scroll .deal-card-body { gap: 2px; }
    .featured-scroll .deal-card-name { font-size: 0.8rem; line-height: 1.15; }
    .featured-scroll .deal-card-price { font-size: 0.9rem; }
    .featured-scroll .deal-card-add {
        padding: 0.3rem 0.6rem;
        font-size: 0.72rem;
        min-height: 0;
    }
    .featured-scroll .deal-card-add-form { margin-top: 4px; }

    /* Section heading above the rail. */
    .featured-scroll ~ *, .featured-scroll { margin-top: 0; }
}

@media (max-width: 767.98px) {
    .cat-chip-icon { width: 46px; height: 46px; }
    .cat-chip-label { font-size: 0.62rem; }
    .category-chip { min-width: 58px; }
}
