/* ============================================================
   02-base.css — Base and Bootstrap overrides

   Reset, view transitions, the top and bottom navigation, and the overrides that
   retune Bootstrap's buttons, cards, forms, badges, tables and alerts to this
   design system. Everything else builds on what is here.

   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.
   ============================================================ */

/* ============================================================
   app.css — BiteSite consolidated component stylesheet.

   This file merges the former 02-base → 08-redesign cascade into a
   single ordered sheet. 01-tokens.css (design tokens) loads before it
   and is the only other stylesheet this app ships.

   The merge is faithful: where the old files overrode each other,
   the winning (later-file) value is preserved here, so rendering is
   unchanged. The content remains in its original cascade order; a
   scoped polish layer is appended at the end.
   ============================================================ */
/* ============================================================
   02-base.css  (2 of 6)

   Shared primitives used by every portal: view transitions, navbar, bottom nav,
   buttons, cards, forms, badges, tables, alerts, and the Bootstrap overrides
   that retone them.

   Part of an ordered set. The browser concatenates these in the order they
   are linked in fragments/head.html, and that order IS the cascade. Do not
   reorder the <link> tags, and do not move a rule between files without
   checking what it would then stop overriding.
   ============================================================ */

/* ============================================================
   CROSS-DOCUMENT VIEW TRANSITIONS
   This is a traditional server-rendered app, not an SPA — every
   link click and form submit is a full page navigation. Without
   this, that's a hard white-flash reload; with it, the browser
   cross-fades outgoing/incoming pages natively, no JS involved.
   Safe progressive enhancement: browsers that don't support it
   (Safari < 18.2, older Firefox) just keep the instant navigation
   they already have.
   ============================================================ */

@media (prefers-reduced-motion: no-preference) {
    @view-transition {
        navigation: auto;
    }
}

::view-transition-old(root) {
    animation: view-transition-fade-out 160ms cubic-bezier(0.4, 0, 1, 1) both;
}

::view-transition-new(root) {
    animation: view-transition-fade-in 260ms cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes view-transition-fade-in {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

@keyframes view-transition-fade-out {
    from { opacity: 1; }
    to   { opacity: 0; }
}

html, body {
    background-color: var(--color-bg);
    /* Flat. The grain texture belonged to the cream canvas; on this near-white one it
       reads as noise, and the design it is ported from has no texture layer at all. */
    color: var(--color-ink);
    font-family: var(--font-body);
    font-size: var(--text-body-lg);
    line-height: var(--lh-body-lg);
    -webkit-font-smoothing: antialiased;
}

/* One family across every role, so hierarchy is carried by weight and tracking rather
   than by a second typeface — see the export's fontFamily config, which maps display
   through label all to Inter. */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    color: var(--color-ink);
}

h1 { font-size: var(--text-display-lg);  line-height: var(--lh-display-lg);  font-weight: 700; letter-spacing: -0.02em; }
h2 { font-size: var(--text-headline-lg); line-height: var(--lh-headline-lg); font-weight: 700; letter-spacing: -0.01em; }
h3 { font-size: var(--text-headline-lg); line-height: var(--lh-headline-lg); font-weight: 700; letter-spacing: -0.01em; }
h4 { font-size: var(--text-headline-md); line-height: var(--lh-headline-md); font-weight: 600; }
h5 { font-size: var(--text-headline-md); line-height: var(--lh-headline-md); font-weight: 600; }
h6 { font-size: var(--text-label-lg);    line-height: var(--lh-label-lg);    font-weight: 600; }

/* Material Symbols, the icon set used across the whole product. */
.material-symbols-outlined {
    /* The font-family used to come from the Google CDN stylesheet; now that the
       font is self-hosted this rule must carry it, or ligatures render as text. */
    font-family: 'Material Symbols Outlined';
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
    vertical-align: middle;
    user-select: none;

    /* An icon is chosen by ligature: the element's text is the icon's name, and the
       font substitutes a glyph for that exact lowercase letter sequence. Anything that
       alters the letters or their spacing before shaping stops the substitution
       matching, and the name renders as words instead.
       `.btn` sets `text-transform: uppercase` and `letter-spacing: 0.05em`, so every
       icon inside a button was drawing the literal text — "LOGOUT" beside the word
       Logout. These three lines are load-bearing, not defensive tidying. */
    text-transform: none;
    letter-spacing: normal;
    font-variant-ligatures: normal;
    /* The names contain underscores and can be long; nothing here should ever wrap. */
    white-space: nowrap;
    word-break: normal;
}
.material-symbols-outlined.is-filled { font-variation-settings: 'FILL' 1; }
.ms-20 { font-size: 20px; }
.ms-16 { font-size: 16px; }

a {
    color: var(--color-primary-dark);
    text-decoration: none;
}
a:hover { color: var(--color-primary); }


/* ---------- Layout ---------- */

.container {
    max-width: 1100px;
}

/* On mobile, add bottom padding for the bottom nav */
@media (max-width: 767.98px) {
    body.has-bottom-nav {
        padding-bottom: calc(var(--bottom-nav-height) + var(--safe-area-bottom) + 12px);
    }
}

/* ============================================================
   TOP NAVBAR
   ============================================================ */

/* The dark bar is gone. It was the loudest remaining piece of dashboard chrome —
   a heavy near-black slab pinned above a warm cream page, which is exactly the
   "generic SaaS with an orange button" read. The reference has no dark surfaces
   at all; the canvas simply continues to the top of the screen and the brand mark
   carries the identity. */

/* A phone should never scroll sideways. Anything that overflows its container is a bug,
   but this keeps one from taking the whole page with it.

   `clip`, not `hidden`. They look the same and behave very differently: `hidden` makes
   the element a scroll container, which silently disables `position: sticky` for every
   descendant — the top navbar and the menu's category strip both declared `sticky` and
   neither ever stuck. `clip` crops the overflow without creating a scrollport, so the
   guard stays and sticky works. */
html, body { overflow-x: clip; }

.navbar-toggler-custom {
    font-size: 1.5rem;
    line-height: 1;
    padding: 4px 8px;
    transition: background-color 150ms ease;
}
.navbar-toggler-custom:hover,
.navbar-toggler-custom:active {
    background: var(--color-surface-deep);
}

/* Staff/admin nav links — collapsed behind the hamburger on mobile (no bottom-nav
   fallback for these roles), always inline on desktop. */
.navbar-links-collapse {
    display: none;
}
.navbar-links-collapse.is-open {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
    padding: 0.5rem 1rem 1rem;
    z-index: 1030;
    animation: fade-up 200ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
.navbar-links-collapse.is-open .nav-link {
    padding: 0.6rem 0.7rem !important;
}

@media (min-width: 992px) {
    .navbar-toggler-custom {
        display: none;
    }
    .navbar-links-collapse {
        display: flex !important;
        flex-direction: row;
        align-items: center;
        gap: 0.5rem;
        position: static;
        background: none;
        padding: 0;
        box-shadow: none;
        animation: none !important;
    }
}

/* Terracotta wordmark on cream — the brand carries the top of the page now that
   there's no dark slab doing it. Matches the reference, whose own wordmark is the
   one strongly orange element on the screen. */

.navbar-brand img {
    border-radius: 0;
}

.navbar .nav-link {
    padding: 0.45rem 0.85rem !important;
    transition: color 150ms ease, background-color 150ms ease;
}

.navbar .navbar-text {
    font-size: 0.85rem;
    color: var(--color-ink-muted) !important;
}

/* Hide top-nav user links on mobile (bottom nav takes over) */
@media (max-width: 767.98px) {
    .navbar .top-nav-links {
        display: none !important;
    }
    .navbar {
        padding-top: 0.65rem;
        padding-bottom: 0.65rem;
    }
}

/* ============================================================
   BOTTOM TAB NAVIGATION (mobile only)
   ============================================================ */

.bottom-nav {
    display: none;
}

@media (max-width: 767.98px) {
    /* Floating rounded glassmorphism bar */
    .bottom-nav {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 1050;
        height: calc(var(--bottom-nav-height) + var(--safe-area-bottom));
        padding-bottom: var(--safe-area-bottom);
        
        
        border: none;
        align-items: stretch;
    }

    .bottom-nav-item {
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        text-decoration: none;
        color: var(--color-ink-muted);
        font-size: 0.7rem;
        font-weight: 700;
        font-family: var(--font-display);
        letter-spacing: 0.01em;
        transition: all 180ms ease;
        position: relative;
        -webkit-tap-highlight-color: transparent;
    }

    .bottom-nav-item i {
        font-size: 1.45rem;
        line-height: 1;
        transition: transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1);
    }


    .bottom-nav-item.active i {
        transform: scale(1.15) translateY(-2px);
    }

    .bottom-nav-item:active i {
        transform: scale(0.9);
    }

    /* Cart badge on bottom nav */
    .bottom-nav-badge {
        position: absolute;
        top: 5px;
        right: calc(50% - 18px);
        min-width: 18px;
        height: 18px;
        border-radius: 0;
        background: var(--color-accent-strong);
        color: #fff;
        font-size: 0.65rem;
        font-weight: 800;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0 5px;
        line-height: 1;
        box-shadow: none;
        animation: badge-pop 320ms cubic-bezier(0.34, 1.56, 0.64, 1);
    }

    @keyframes badge-pop {
        0% { transform: scale(0); }
        80% { transform: scale(1.2); }
        100% { transform: scale(1); }
    }
}

/* ============================================================
   BUTTONS
   ============================================================ */

/* Soft pills. The reference's buttons are fully rounded and generously padded —
   at phone size they're the most tactile thing on screen, which is right for the
   one control that commits an order. */
.btn {
    font-weight: 700;
    font-size: 0.95rem;
    padding: 0.6rem 1.4rem;
}
/* Bootstrap ships .btn-sm, but this file loads after Bootstrap and .btn matches at
   the same specificity, so the padding above was silently beating it and every
   "small" button rendered full size. That is fine on a desktop table row and
   overflows a card on a phone, which is what broke the outlet and admin screens
   at narrow widths. Restated here so the modifier actually modifies. */
.btn-sm {
    padding: 0.35rem 0.8rem;
    font-size: 0.85rem;
}

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

.btn-primary {
    box-shadow: var(--shadow-sm);
}
.btn-primary:hover, .btn-primary:focus {
    box-shadow: var(--shadow-sm);
}


/* Secondary reads as a soft peach chip rather than a hairline outline — an outlined
   button on a peach card is two thin lines competing; a filled tonal chip is calmer. */
.btn-outline-secondary:hover {
    background: var(--color-coral-deep);
    border-color: transparent;
    color: var(--color-ink);
}

/* Terracotta button — for appetite/brand moments, never for confirm/pay.
   Uses the strong tone so white label text clears 5.37:1. */
.btn-accent {
    border-color: var(--color-accent-strong);
}
.btn-accent:hover, .btn-accent:focus {
    border-color: var(--color-ink);
}

.btn-success {border-color: var(--color-primary);}
.btn-success:hover {border-color: var(--color-primary-dark);}

.btn-warning { background: var(--color-warning); border-color: var(--color-warning); color: #fff; }
.btn-warning:hover { background: var(--color-coral-deep); border-color: var(--color-ink); color: #fff; }

.btn-danger, .btn-outline-danger:hover { background: var(--color-danger); border-color: var(--color-danger); }


/* ============================================================
   CARDS

   Generic .card stays a pale-cream block — it's shared with the canteen and
   admin portals, which are deliberately outside this redesign and need dense,
   legible surfaces. The student-facing peach blocking lives on the specific
   component classes further down (.menu-card, .cart-item-card, .order-card,
   .account-section, .outlet-card, .auth-card).
   ============================================================ */

.card {
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    transition: box-shadow 180ms ease, transform 180ms ease;
}
.card:hover {
    box-shadow: var(--shadow-md);
}

.card-title {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.01em;
}

/* ============================================================
   FORMS
   ============================================================ */

/* Pale cream fields sitting inside the warmer surfaces around them — the reference
   lights its inputs slightly *brighter* than the card they're on, which is what makes
   a form read as a set of soft slots rather than a stack of outlined boxes. */
.form-control, .form-select {
    border-radius: var(--radius-sm);
    border: 1.5px solid var(--color-field-border);
    padding: 0.8rem 1rem;
    font-size: 0.95rem;
    color: var(--color-ink);
    transition: border-color 150ms ease, background-color 150ms ease, box-shadow 150ms ease;
}
.form-control::placeholder { color: var(--color-ink-muted); }

.form-label {
    font-weight: 600;
    color: var(--color-ink);
    margin-bottom: 0.4rem;
}

.input-group-text {
    border-radius: var(--radius-sm) 0 0 var(--radius-sm) !important;
    border: 1.5px solid var(--color-field-border);
    border-right: none;
    background: var(--color-field);
    color: var(--color-ink-muted);
}
.input-group .form-control {
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    border-left: none;
}

/* Buttons are pills globally, but a pill welded to the end of a field reads as a
   detached blob floating beside it. Inside an input group the trailing button takes
   the field's own corner radius so the two read as one control. */
.input-group > .btn {
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.input-group > .form-control:not(:last-child) {
    border-radius: 0;
}
.input-group:focus-within .input-group-text {
    border-color: var(--color-primary);
    background: #FFFFFF;
}

/* Toggle switches pick up the action color rather than Bootstrap's blue. */
.form-check-input:focus {
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px var(--color-primary-tint);
}

/* ============================================================
   BADGES (status pills)
   ============================================================ */

.badge {
    font-family: var(--font-body);
    font-weight: 700;
    letter-spacing: 0.01em;
    padding: 0.45em 0.85em;
}

.badge.bg-success { background: var(--color-primary) !important; color: #fff !important; }
.badge.bg-warning { background: var(--color-warning-tint) !important; color: var(--color-warning) !important; }
.badge.bg-info { background: var(--color-info-tint) !important; color: var(--color-info) !important; }
.badge.bg-primary { background: var(--color-primary) !important; color: #fff !important; }
.badge.bg-secondary { background: var(--color-surface-deep) !important; color: var(--color-ink-muted) !important; }
.badge.bg-danger { background: var(--color-danger-tint) !important; color: var(--color-danger) !important; }

/* ============================================================
   TABLES
   ============================================================ */

.table {
    overflow: hidden;
}
.table thead th {
    font-size: 0.82rem;
    letter-spacing: 0.04em;
    border-bottom-width: 1px;
}
.table td, .table th { vertical-align: middle; border-color: var(--color-border); }

/* ============================================================
   ALERTS
   ============================================================ */

.alert-secondary { background: var(--color-surface-food); color: var(--color-ink-muted); }
.alert-success { background: var(--color-primary-tint); color: var(--color-primary-dark); }
.alert-info { background: var(--color-info-tint); color: var(--color-info); }
.alert-primary { background: var(--color-primary-tint); color: var(--color-primary-dark); }

/* ============================================================
   BOOTSTRAP UTILITY OVERRIDES

   The templates lean on .text-muted (39 uses) and .text-danger (30) — Bootstrap
   ships those as cold grays/reds (#6c757d, #dc3545) which read as foreign against
   a cream-and-terracotta page. Repointing them at the warm palette fixes the
   inconsistency everywhere at once instead of per template.
   ============================================================ */

.text-muted { color: var(--color-ink-muted) !important; }
.text-danger { color: var(--color-danger) !important; }
.text-dark   { color: var(--color-ink) !important; }
.bg-light    { background-color: var(--color-surface) !important; }
.border-bottom, .border-top { border-color: var(--color-border) !important; }

/* ============================================================
   NAV DRAWER — every destination for the signed-in role.

   In 02-base because all three portals use it. It slides from the right so the opening
   gesture starts near the button that triggers it, and so it never fights the bottom tab
   bar on a phone.
   ============================================================ */

.nav-drawer-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    flex: none;
    padding: 0;
    background: var(--color-surface);
    border: 2px solid var(--color-ink);
    border-radius: 0;
    color: var(--color-ink);
    box-shadow: 3px 3px 0 var(--color-ink);
    cursor: pointer;
}

.nav-drawer-btn:hover { background: var(--color-accent-tint); }
.nav-drawer-btn:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--color-ink); }
.nav-drawer-btn .material-symbols-outlined { font-size: 22px; }

.nav-drawer-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1100;
    background: rgba(20, 16, 13, 0.55);
    opacity: 0;
    transition: opacity 180ms ease;
}
.nav-drawer-backdrop.is-open { opacity: 1; }

.nav-drawer {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 1101;
    width: min(340px, 86vw);
    display: flex;
    flex-direction: column;
    background: var(--color-surface);
    border-left: 3px solid var(--color-ink);
    transform: translateX(100%);
    transition: transform 220ms cubic-bezier(0.16, 1, 0.3, 1);
    overscroll-behavior: contain;
}
.nav-drawer.is-open { transform: translateX(0); }

@media (prefers-reduced-motion: reduce) {
    .nav-drawer, .nav-drawer-backdrop { transition: none; }
}

/* The page behind must not scroll while the drawer is over it. */
body.has-drawer-open { overflow: hidden; }

.nav-drawer__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 12px 14px;
    border-bottom: 3px solid var(--color-ink);
    background: var(--color-ink);
    color: var(--color-bg);
}

.nav-drawer__who {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    font-family: var(--font-display);
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.nav-drawer__who .material-symbols-outlined { font-size: 20px; flex: none; }

.nav-drawer__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    flex: none;
    padding: 0;
    background: transparent;
    border: 2px solid var(--color-bg);
    border-radius: 0;
    color: var(--color-bg);
    cursor: pointer;
}
.nav-drawer__close:hover { background: var(--color-primary-dark); }

.nav-drawer__body {
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 4px 0 12px;
}

.nav-drawer__group { padding: 8px 0; }
.nav-drawer__group + .nav-drawer__group { border-top: 2px solid var(--color-field-rule); }

.nav-drawer__label {
    margin: 0 0 2px;
    padding: 4px 16px;
    font-family: var(--font-display);
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--color-ink-muted);
}

.nav-drawer__link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 16px;
    min-height: 44px;
    color: var(--color-ink);
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
}
.nav-drawer__link .material-symbols-outlined { font-size: 20px; flex: none; }
.nav-drawer__link:hover { background: var(--color-accent-tint); color: var(--color-ink); }

.nav-drawer__link[aria-current="page"] {
    background: var(--color-ink);
    color: var(--color-accent-tint);
    font-family: var(--font-display);
    text-transform: uppercase;
    font-size: 0.78rem;
    letter-spacing: 0.03em;
}

/* Counts ride to the right of their row, so cart and order state is visible without
   opening either page. */
.nav-drawer__count {
    margin-left: auto;
    min-width: 22px;
    padding: 1px 6px;
    text-align: center;
    background: var(--color-primary-dark);
    color: #fff;
    border: 2px solid var(--color-ink);
    font-family: var(--font-display);
    font-size: 0.68rem;
}

/* Legal links are references, not destinations you go to often. */
.nav-drawer__group--quiet .nav-drawer__link {
    font-size: 0.8rem;
    color: var(--color-ink-muted);
    min-height: 38px;
    padding-block: 8px;
}

.nav-drawer__foot {
    flex: none;
    padding: 12px 14px calc(12px + var(--safe-area-bottom));
    border-top: 3px solid var(--color-ink);
    margin: 0;
}
