/*
    Theme 01 — Midnight Gold.

    Every number in this file is counted off the design, not chosen here: the
    hexes come from MIDNIGHT.md's token table, and each measurement is the one
    written into the inline style of the screen it belongs to. The client's
    instruction was literal — "عايزه يطلع زي ما هو بالظبط" — so where a rule
    below looks arbitrary (14.5px, .985 on :active, a 22-second Ken Burns) it
    is arbitrary in the design and copied rather than rounded.

    Three things the design draws that are NOT here, because they are the
    mockup's phone and not the theme: the 390x844 frame, the 52px device
    radius, and the 9:41 status bar with its battery and signal glyphs.

    Direction. The design is drawn RTL and must be equally correct in LTR, so
    every inset, margin and padding that has a side is written logically —
    inset-inline-start, padding-inline, margin-block-start. The only physical
    sides left are the ones that are genuinely physical: top and bottom.
*/

/* ---------------------------------------------------------------- tokens */

:root {
    --mn-bg: #0A161D;
    --mn-raised: #0E1C27;
    --mn-card: #122231;
    --mn-line: #1C2A38;
    --mn-ink: #F4F7FA;
    --mn-ink-2: #C9D3DD;
    --mn-muted: #A9B6C3;
    --mn-muted-2: #8593A2;
    --mn-off: #6E7D8C;
    --mn-gold: #D9A441;
    --mn-gold-text: var(--mn-gold);
    --mn-gold-hi: #E7B95A;
    --mn-gold-soft: #F2D58E;
    --mn-gold-ink: #1A1206;
    --mn-ground: #05090C;

    /* Derived, and named so the rules below never restate an rgba() twice. */
    --mn-hairline: rgba(255, 255, 255, .07);
    --mn-hairline-2: rgba(255, 255, 255, .08);
    --mn-glass-line: rgba(255, 255, 255, .14);
    --mn-photo: #12181C;
    --mn-gold-line: rgba(217, 164, 65, .45);
    --mn-gold-wash: rgba(217, 164, 65, .14);
    --mn-live: #2FB37A;
    --mn-footnote: #3C4A57;

    --mn-sans: 'Tajawal', system-ui, sans-serif;
    --mn-grotesk: 'Space Grotesk', system-ui, sans-serif;
    --mn-mono: 'IBM Plex Mono', ui-monospace, monospace;

    /* The accessibility sheet writes these two and nothing else. Every
       font-size below is calc(<drawn px> * var(--mn-scale)); everything that
       must thicken reads --mn-weight-bump. Declared here AND defaulted at each
       use site — public/css/midnight-promo.css carries the same calc() and is
       served by the shipped layout too, where no theme has defined this. */
    --mn-scale: 1;
    --mn-weight-bump: 0;
}

/* Midnight is a dark design: dark IS the default and light is the derived
   setting, which is the opposite of how most themes are built. The sheet
   stamps data-mn-scheme="light" on <html>; nothing here reads
   prefers-color-scheme, because the theme's own choice outranks the phone's. */
:root[data-mn-scheme="light"] {
    --mn-bg: #F7F9FB;
    --mn-raised: #FFFFFF;
    --mn-card: #FFFFFF;
    --mn-line: #DCE3EA;
    --mn-ink: #0A161D;
    --mn-ink-2: #29394A;
    --mn-muted: #4A5B6C;
    --mn-muted-2: #5C6B7A;
    --mn-off: #7A8794;
    /* One step deeper than the #A5750F this block shipped with. That value
       read at 3.86:1 as a word and 4.08:1 under white — both under AA, on a
       scheme nobody measured because there was no second theme to compare it
       against. The surface keeps a gold that carries white at 5.43:1. */
    --mn-gold: #8C6209;
    --mn-gold-text: #7A5507;
    --mn-gold-hi: #7A5507;
    --mn-gold-soft: #654705;
    --mn-gold-ink: #FFFFFF;
    --mn-ground: #E9EEF3;

    --mn-hairline: rgba(10, 22, 29, .09);
    --mn-hairline-2: rgba(10, 22, 29, .11);
    --mn-glass-line: rgba(10, 22, 29, .16);
    --mn-photo: #E4EAF0;
    --mn-gold-line: rgba(165, 117, 15, .45);
    --mn-gold-wash: rgba(165, 117, 15, .12);
    --mn-footnote: #93A0AC;
}

/* ------------------------------------------------------------ the ground */

html {
    /*
        The accessibility sheet's two size buttons, and what they actually move.

        Every measurement in this file is the one written into the design's own
        inline styles, and the design writes them in PIXELS — so the type scale
        here is `calc(19px * var(--mn-scale))` and not `1.1875rem`. The drawn
        number stays legible in the source, which is the only way this file can
        be diffed against screen_*.html; converting the scale to rem would have
        replaced 65 counted numbers with 65 divisions by sixteen.
        Line-heights are unitless throughout, so they follow on their own.

        The root size is scaled as well, and it is not redundant: the pages this
        theme does not draw arrive with jadtags.css, whose type IS in rem, and
        the sheet has to move that too — a person who needs 140% type needs it
        at the checkout more than anywhere else.

        What deliberately does NOT scale: 44px, 56px and 58px tap targets, the
        78px bar, the ring diameters. A thumb is a thumb at every setting.
    */
    font-size: calc(16px * var(--mn-scale, 1));
    background: var(--mn-ground);
}

body {
    margin: 0;
    background: var(--mn-bg);
    color: var(--mn-ink);
    font-family: var(--mn-sans);
    -webkit-font-smoothing: antialiased;
    min-height: 100vh;
    min-height: 100dvh;
}

a { color: var(--mn-gold-text); text-decoration: none; }
a:hover { color: var(--mn-gold-hi); }
input, textarea, button, select { font-family: inherit; }

/* The design hides the scrollbar. Kept, but never on the keyboard path:
   overflow still scrolls, and :focus-visible below is what a keyboard user
   follows instead of a bar they cannot see. */
::-webkit-scrollbar { width: 0; height: 0; }

:focus-visible {
    outline: 2px solid var(--mn-gold);
    outline-offset: 2px;
    border-radius: 4px;
}

img { max-width: 100%; }

/*
    [hidden] is the last word on visibility, and in this file it was not.

    A class that sets `display` beats the browser's own `[hidden] { display:
    none }` — an author rule outranks a UA rule whatever the specificity — so
    .mn-dish[hidden], .mn-empty[hidden] and a hidden service block on the
    checkout all stayed on screen. jadtags.css says this for the pages it
    dresses; on a page THIS theme draws, that stylesheet is deliberately not
    loaded, and .mn-otp[hidden] beside the code cells is the same fix written
    once for one class.
*/
[hidden] { display: none !important; }

.mn-sr {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* The app column. The design is a phone layout; on anything wider it centres
   rather than stretching, because a 46px headline across a desktop is not the
   design at a different size, it is a different design. */
.mn-app {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    max-width: 480px;
    margin-inline: auto;
    background: var(--mn-bg);
    position: relative;
}

.mn-scroll {
    flex: 1;
    min-height: 0;
    position: relative;
}

/* ----------------------------------------------------------- animations */

@keyframes mUp { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes mIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes mKen { from { transform: scale(1.05); } to { transform: scale(1.15) translateY(-1.5%); } }
@keyframes mDot { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
@keyframes mSheet { from { opacity: 0; transform: translateY(40px); } to { opacity: 1; transform: none; } }

.mn-in { animation: mIn .35s ease-out both; }
.mn-in-fast { animation: mIn .3s ease-out both; }

/* A 22-second Ken Burns on a hero photograph is exactly the kind of motion
   that makes some people ill. The design's animation is a decoration; the
   information is the photograph, and it is all still there without it. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

/* ------------------------------------------------------- shared controls */

.mn-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    height: 58px;
    padding-inline: 26px;
    border: 0;
    border-radius: 999px;
    background: var(--mn-gold);
    color: var(--mn-gold-ink);
    font-size: calc(19px * var(--mn-scale, 1));
    font-weight: calc(800 + var(--mn-weight-bump));
    cursor: pointer;
    box-shadow: 0 14px 38px -14px rgba(217, 164, 65, .7);
    text-align: center;
}
.mn-cta:hover { background: var(--mn-gold-hi); color: var(--mn-gold-ink); }
.mn-cta:active { transform: scale(.985); }
.mn-cta[disabled] { background: var(--mn-off); box-shadow: none; cursor: not-allowed; }

/*
    The secondary action: the same pill, in the card colour.

    None of the six drawn screens needed one, because each of them asks for
    exactly one thing. The club, the preference centre and the unsubscribe page
    each offer several, and a screen with three gold pills has no primary action
    on it at all.

    52px rather than the CTA's 58, which is the height the design already gives
    every other tappable row on a form -- the .mn-a11y button and the cart
    stepper both sit there.
*/
.mn-ghost {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    height: 52px;
    padding-inline: 22px;
    border: 1px solid var(--mn-hairline-2);
    border-radius: 999px;
    background: var(--mn-card);
    color: var(--mn-ink);
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    cursor: pointer;
    text-align: center;
}
.mn-ghost:hover { border-color: rgba(217, 164, 65, .55); color: var(--mn-ink); }
.mn-ghost:active { transform: scale(.985); }
.mn-ghost[disabled] { opacity: .45; cursor: not-allowed; }

/* A number the eye has to compare — a price, a count, a clock. Space Grotesk
   with tabular figures, which is what EXTENDING.md asks of every number in
   this theme and what stops a total shifting sideways as it changes. */
.mn-amount {
    font-family: var(--mn-grotesk);
    font-variant-numeric: tabular-nums;
}

/* The design's arrow points along the reading direction. One rule, so the
   glyph is never mirrored twice — the SVG itself is never flipped in markup. */
[dir="rtl"] .mn-arrow { transform: scaleX(-1); }

.mn-eyebrow {
    font-family: var(--mn-mono);
    font-size: calc(11px * var(--mn-scale, 1));
    letter-spacing: .2em;
    color: var(--mn-gold-text);
}

.mn-glass {
    height: 44px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--mn-bg) 60%, transparent);
    backdrop-filter: blur(14px);
    border: 1px solid var(--mn-glass-line);
    display: grid;
    place-items: center;
    cursor: pointer;
    color: var(--mn-ink);
}
.mn-glass:hover { border-color: rgba(217, 164, 65, .7); color: var(--mn-ink); }
.mn-glass-icon { width: 44px; }
.mn-glass-pill {
    min-width: 64px;
    padding-inline: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    font-family: var(--mn-mono);
    font-size: calc(12px * var(--mn-scale, 1));
}

/* ------------------------------------------------------------ HOME: hero */

.mn-hero {
    position: relative;
    height: 512px;
    background: var(--mn-photo);
    overflow: hidden;
}

.mn-hero-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    animation: mKen 22s ease-in-out infinite alternate;
}

.mn-hero-veil {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top,
        var(--mn-bg) 2%,
        color-mix(in srgb, var(--mn-bg) 90%, transparent) 24%,
        color-mix(in srgb, var(--mn-bg) 22%, transparent) 62%,
        rgba(7, 18, 26, .62) 100%);
}

.mn-hero-top {
    position: absolute;
    top: 14px;
    inset-inline: 18px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.mn-logo {
    width: 50px;
    height: 50px;
    border-radius: 16px;
    overflow: hidden;
    border: 1px solid var(--mn-gold-line);
    background: var(--mn-bg);
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    color: var(--mn-gold-text);
}
.mn-logo img { width: 100%; height: 100%; object-fit: cover; }

.mn-hero-tools { display: flex; gap: 8px; }

.mn-hero-foot {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    padding: 0 20px 26px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.mn-live {
    display: flex;
    align-items: center;
    gap: 9px;
    animation: mUp .6s cubic-bezier(.2, .7, .2, 1) .05s both;
}
.mn-live-dot {
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: var(--mn-live);
    animation: mDot 2.6s ease-in-out infinite;
    flex: 0 0 auto;
}
.mn-live-dot.is-shut { background: var(--mn-off); animation: none; }
.mn-live-text {
    font-family: var(--mn-mono);
    font-size: calc(11px * var(--mn-scale, 1));
    letter-spacing: .14em;
    color: var(--mn-gold-soft);
}

.mn-hero-name {
    display: flex;
    flex-direction: column;
    gap: 8px;
    animation: mUp .65s cubic-bezier(.2, .7, .2, 1) .12s both;
}
.mn-hero-name h1 {
    margin: 0;
    font-size: calc(46px * var(--mn-scale, 1));
    font-weight: calc(900 + var(--mn-weight-bump));
    line-height: 1.02;
    letter-spacing: -.025em;
    color: #FFFFFF;
}
:root[data-mn-scheme="light"] .mn-hero-name h1 { color: var(--mn-ink); }
.mn-hero-name p {
    margin: 0;
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(500 + var(--mn-weight-bump));
    line-height: 1.5;
    color: var(--mn-ink-2);
    max-width: 300px;
}

.mn-hero-cta { animation: mUp .65s cubic-bezier(.2, .7, .2, 1) .2s both; }

/* ------------------------------------------------------- HOME: the body */

.mn-home-body {
    padding: 22px 20px 30px;
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.mn-block { display: flex; flex-direction: column; gap: 14px; }

/* A horizontal rail that bleeds to the edge of the column. The negative
   margin and the matching padding-inline are how the design lets the first
   card sit flush with the text above it while still scrolling past the edge. */
.mn-rail {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 4px;
    margin-inline: -20px;
    padding-inline: 20px;
    scroll-snap-type: x proximity;
}
.mn-rail > * { scroll-snap-align: start; }

.mn-hot {
    flex: 0 0 auto;
    width: 150px;
    display: flex;
    flex-direction: column;
    gap: 9px;
    cursor: pointer;
    color: inherit;
    transition: transform .18s ease;
}
.mn-hot:hover { transform: translateY(-4px); color: inherit; }
.mn-hot-photo {
    height: 150px;
    border-radius: 18px;
    overflow: hidden;
    background: var(--mn-photo);
    position: relative;
    display: grid;
    place-items: center;
    color: var(--mn-off);
}
.mn-hot-photo img { width: 100%; height: 100%; object-fit: cover; }
.mn-hot-price {
    position: absolute;
    top: 9px;
    inset-inline-end: 9px;
    padding: 4px 9px;
    border-radius: 999px;
    background: rgba(7, 18, 26, .78);
    backdrop-filter: blur(8px);
    font-family: var(--mn-grotesk);
    font-size: calc(13px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-gold-soft);
}
:root[data-mn-scheme="light"] .mn-hot-price { background: rgba(255, 255, 255, .86); }
.mn-hot-name {
    font-size: calc(15px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
    line-height: 1.3;
}

.mn-wifi {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 18px;
    border-radius: 20px;
    background: var(--mn-raised);
    border: 1px solid var(--mn-hairline);
}
.mn-wifi-head {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
/* screen_home.html draws this glyph stroke="#D9A441" beside #F4F7FA text. It
   inherits currentColor, so without this it comes out near-white. */
.mn-wifi-head svg { color: var(--mn-gold-text); }
.mn-wifi-row { display: flex; gap: 10px; }
.mn-wifi-cell {
    flex: 1;
    min-width: 0;
    padding: 11px 13px;
    border-radius: 12px;
    background: var(--mn-bg);
    border: 1px solid rgba(255, 255, 255, .06);
}
:root[data-mn-scheme="light"] .mn-wifi-cell { border-color: var(--mn-hairline); }
.mn-wifi-cell small {
    display: block;
    font-size: calc(12px * var(--mn-scale, 1));
    color: var(--mn-off);
    margin-bottom: 2px;
}
.mn-wifi-cell code {
    font-family: var(--mn-mono);
    font-size: calc(14px * var(--mn-scale, 1));
    color: var(--mn-ink);
    overflow-wrap: anywhere;
}

.mn-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 11px;
}

.mn-fact {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 15px;
    border-radius: 18px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline);
    color: var(--mn-ink);
    min-width: 0;
    transition: transform .18s ease, border-color .18s ease;
}
a.mn-fact:hover, .mn-fact.is-link:hover {
    border-color: rgba(217, 164, 65, .55);
    transform: translateY(-3px);
    color: var(--mn-ink);
}
.mn-fact-text { display: flex; flex-direction: column; min-width: 0; }
.mn-fact-text b {
    font-size: calc(14px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
}
.mn-fact-text span {
    font-size: calc(13px * var(--mn-scale, 1));
    color: var(--mn-muted-2);
    overflow: hidden;
    text-overflow: ellipsis;
}
.mn-fact-text .mn-fact-hours {
    font-family: var(--mn-grotesk);
    white-space: nowrap;
}
/* All four tiles are drawn stroke="#D9A441" against #F4F7FA text — the tile
   inherits ink, so the glyph has to be told. */
.mn-fact svg { flex: 0 0 auto; color: var(--mn-gold-text); }

.mn-social {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding-top: 6px;
}
.mn-social-label {
    font-family: var(--mn-mono);
    font-size: calc(11px * var(--mn-scale, 1));
    letter-spacing: .2em;
    color: var(--mn-off);
}
/*
   A centred row of second-rank actions that WRAPS, because "call the
   restaurant" is two words in one language and five in another. The footer's
   social icons and the status page's actions are the same row; the gap was
   written twice, at 11 and at 10, for no reason either rule stated.
   .mn-acts adds only the one thing that is its own — see the ORDER section. */
.mn-social-row, .mn-acts { display: flex; gap: 11px; flex-wrap: wrap; justify-content: center; }
.mn-social-row a {
    width: 46px;
    height: 46px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .1);
    display: grid;
    place-items: center;
    color: var(--mn-muted);
}
:root[data-mn-scheme="light"] .mn-social-row a { border-color: var(--mn-hairline-2); }
.mn-social-row a:hover { color: var(--mn-gold-text); border-color: rgba(217, 164, 65, .6); }
.mn-colophon {
    font-family: var(--mn-mono);
    font-size: calc(10px * var(--mn-scale, 1));
    letter-spacing: .12em;
    color: var(--mn-footnote);
}

/*
    The legal row: terms, privacy, accessibility.

    Beside the colophon because that is the only footer the design draws, and
    these links belong in a footer -- not in the tab bar, which has four
    entries and 390px, and not on every screen above the fold.

    Quiet on purpose. They must be findable and must not compete with the menu;
    --mn-muted-2 is the same weight the design gives the hours line.
*/
.mn-legal {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 4px 16px;
}
.mn-legal a {
    font-size: calc(13px * var(--mn-scale, 1));
    color: var(--mn-muted-2);
}
.mn-legal a:hover { color: var(--mn-gold-text); }

/* ------------------------------------------------------------- MENU page */

.mn-menu-bar {
    position: sticky;
    top: 0;
    z-index: 5;
    padding: 14px 18px 12px;
    background: color-mix(in srgb, var(--mn-bg) 86%, transparent);
    backdrop-filter: blur(16px);
    border-bottom: 1px solid rgba(255, 255, 255, .06);
    display: flex;
    flex-direction: column;
    gap: 12px;
}
:root[data-mn-scheme="light"] .mn-menu-bar { border-bottom-color: var(--mn-hairline); }

.mn-search-row { display: flex; align-items: center; gap: 10px; }

.mn-search {
    flex: 1;
    min-width: 0;
    height: 44px;
    border-radius: 999px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline-2);
    display: flex;
    align-items: center;
    gap: 9px;
    padding-inline: 15px;
    color: var(--mn-off);
}
.mn-search input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: none;
    color: var(--mn-ink);
    font-size: calc(15px * var(--mn-scale, 1));
    outline: none;
}
.mn-search input::placeholder { color: var(--mn-off); }
.mn-search svg { flex: 0 0 auto; }

/*
    The field is a real <form method="get">, so Enter reaches the results page
    with no script at all. Everything below is the suggest listbox that sits
    over it when there IS a script — #f-marketing-menu-search asks for the top
    six, debounced, with full keyboard support.

    `position: relative` on the row and not on the field: the listbox is as wide
    as the field plus the language pill's gap would allow, and anchoring it to
    the pill-shaped label would clip it against that label's own radius.
*/
.mn-search-row { position: relative; }

.mn-suggest {
    position: absolute;
    z-index: 6;
    top: calc(100% + 8px);
    inset-inline: 0;
    margin: 0;
    padding: 6px;
    list-style: none;
    border-radius: 18px;
    background: var(--mn-raised);
    border: 1px solid var(--mn-hairline-2);
    box-shadow: 0 24px 50px -22px rgba(0, 0, 0, .85);
    max-height: 292px;
    overflow-y: auto;
}
.mn-suggest-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 11px;
    border-radius: 13px;
    cursor: pointer;
    color: var(--mn-ink-2);
    font-size: calc(15px * var(--mn-scale, 1));
}
.mn-suggest-row svg { flex: 0 0 auto; color: var(--mn-off); }
/* aria-selected is the state a screen reader is told about, so it is the state
   the eye is shown too. Two sources of truth for "which one is highlighted" is
   how a listbox ends up announcing one row and painting another. */
.mn-suggest-row:hover,
.mn-suggest-row[aria-selected="true"] {
    background: var(--mn-card);
    color: var(--mn-ink);
}
.mn-suggest-row[aria-selected="true"] svg { color: var(--mn-gold-text); }
.mn-suggest-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mn-suggest-cat {
    flex: 0 0 auto;
    font-size: calc(12px * var(--mn-scale, 1));
    color: var(--mn-off);
}

.mn-lang {
    height: 44px;
    padding-inline: 13px;
    border-radius: 999px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline-2);
    display: grid;
    place-items: center;
    cursor: pointer;
    font-family: var(--mn-mono);
    font-size: calc(12px * var(--mn-scale, 1));
    color: var(--mn-ink);
    flex: 0 0 auto;
}
.mn-lang:hover { border-color: rgba(217, 164, 65, .7); color: var(--mn-ink); }

.mn-chips {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    margin-inline: -18px;
    padding: 2px 18px 4px;
}
.mn-chip {
    flex: 0 0 auto;
    height: 38px;
    padding-inline: 15px;
    display: flex;
    align-items: center;
    gap: 8px;
    border-radius: 999px;
    cursor: pointer;
    font-size: calc(14.5px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    background: var(--mn-card);
    color: var(--mn-ink-2);
    border: 1px solid var(--mn-hairline-2);
}
.mn-chip img { width: 22px; height: 22px; border-radius: 999px; object-fit: cover; }
.mn-chip:hover { border-color: rgba(217, 164, 65, .55); color: var(--mn-ink); }
.mn-chip.is-active {
    background: var(--mn-gold);
    color: var(--mn-gold-ink);
    border-color: var(--mn-gold-text);
}
.mn-chip.is-active:hover { color: var(--mn-gold-ink); }

.mn-menu-body {
    padding: 16px 18px 30px;
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.mn-banners {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    margin-inline: -18px;
    padding: 0 18px 4px;
}
.mn-banner {
    flex: 0 0 auto;
    width: 270px;
    height: 132px;
    border-radius: 20px;
    overflow: hidden;
    background: var(--mn-photo);
    border: 1px solid var(--mn-hairline);
}
.mn-banner img { width: 100%; height: 100%; object-fit: cover; }

.mn-list-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}
.mn-list-head-title {
    margin: 0;
    font-size: calc(21px * var(--mn-scale, 1));
    font-weight: calc(800 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
.mn-list-count {
    font-family: var(--mn-grotesk);
    font-size: calc(13px * var(--mn-scale, 1));
    color: var(--mn-muted-2);
    flex: 0 0 auto;
}

.mn-dishes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

.mn-dish {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 9px;
    border-radius: 20px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline);
    cursor: pointer;
    color: inherit;
    transition: transform .18s ease, border-color .18s ease;
}
.mn-dish:hover {
    transform: translateY(-4px);
    border-color: rgba(217, 164, 65, .5);
    color: inherit;
}
.mn-dish-photo {
    height: 112px;
    border-radius: 14px;
    overflow: hidden;
    background: var(--mn-raised);
    position: relative;
    display: grid;
    place-items: center;
    color: var(--mn-off);
}
.mn-dish-photo img { width: 100%; height: 100%; object-fit: cover; }
.mn-dish-body {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: 0 3px 4px;
}
.mn-dish-name {
    font-size: calc(15px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
    line-height: 1.3;
}
.mn-dish-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.mn-dish-price {
    font-family: var(--mn-grotesk);
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-gold-text);
}
.mn-dish-add {
    width: 30px;
    height: 30px;
    border-radius: 999px;
    background: var(--mn-gold-wash);
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    color: var(--mn-gold-text);
}

/* A dish outside its window or sold out is dimmed, not deleted — the
   restaurant chooses show / dim / hide and dim is the default, because a
   customer who cannot find yesterday's dish assumes the menu is broken. */
.mn-dish.is-unavailable { opacity: .55; }
.mn-dish.is-unavailable .mn-dish-add { display: none; }


/* ----------------------------------------------------------- SEARCH page */

/*
    #f-marketing-menu-search. The designer drew no search screen, so this is
    built out of the menu's own vocabulary rather than invented: the results are
    .mn-dish cards in the .mn-dishes grid — the reference asks for the same card
    component by name — on the page shell every other listing screen stands on,
    which is .mn-page at the wall's gap (.mn-page.mn-page-wall), under the
    .mn-page-head title block, with .mn-empty.is-panel for the state that names
    the term.

    Only TWO things here are new, and each is a thing the menu grid has no word
    for: the matched run highlighted inside a dish's name, and the line that
    says when an out-of-window dish comes back.

    The term echoed back in the header is not a third. It is printed inside the
    translated sentence — "Nothing for :term" — where no span can reach it, so
    the class that was written to colour it could never have been used and is
    gone.
*/

/* The matched run inside a dish's name. <mark>, so it is in the accessibility
   tree as a highlight rather than being a colour only a sighted reader can
   see; the UA's yellow-on-black is repainted because on this ground it is the
   one thing on the page that looks like a rendering fault. */
.mn-hit {
    background: var(--mn-gold-wash);
    color: var(--mn-gold-soft);
    border-radius: 4px;
    padding-inline: 2px;
}

/* An out-of-window dish is DIMMED and labelled, never hidden: somebody
   searching for the thing they had last week needs to be told it is on at six.
   .mn-dish.is-unavailable already carries the dimming. */
.mn-dish-when {
    font-size: calc(12.5px * var(--mn-scale, 1));
    color: var(--mn-gold-soft);
    line-height: 1.4;
}

/* ------------------------------------------------------------- DISH page */

.mn-dish-hero {
    position: relative;
    height: 330px;
    background: var(--mn-photo);
    display: grid;
    place-items: center;
    color: var(--mn-off);
}
.mn-dish-hero > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.mn-dish-veil {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top,
        var(--mn-bg) 0%,
        color-mix(in srgb, var(--mn-bg) 15%, transparent) 55%,
        rgba(7, 18, 26, .5) 100%);
}
.mn-back {
    position: absolute;
    top: 14px;
    inset-inline-start: 18px;
    width: 44px;
    height: 44px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--mn-bg) 62%, transparent);
    backdrop-filter: blur(14px);
    border: 1px solid var(--mn-glass-line);
    display: grid;
    place-items: center;
    cursor: pointer;
    color: var(--mn-ink);
}
.mn-back:hover { border-color: rgba(217, 164, 65, .7); color: var(--mn-ink); }
/* The chevron points back along the reading direction, so it mirrors. */
[dir="ltr"] .mn-back svg { transform: scaleX(-1); }

.mn-dish-body-page {
    padding: 4px 20px 30px;
    display: flex;
    flex-direction: column;
    gap: 22px;
}
/* screen_dish.html makes the body one flex column at gap:22px with Ingredients,
   Extras, Notes and the buy row as SIBLINGS. Here a <form> wraps the last four,
   so without this rule the form is a single flex child and everything inside it
   stacks flush — Extras sitting on Ingredients, the gold button on the notes
   box. The form is the same column at the same gap. */
.mn-dish-body-page > form {
    display: flex;
    flex-direction: column;
    gap: 22px;
}

.mn-dish-title { display: flex; flex-direction: column; gap: 10px; }
.mn-dish-title-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
}
.mn-dish-title h1 {
    margin: 0;
    font-size: calc(30px * var(--mn-scale, 1));
    font-weight: calc(900 + var(--mn-weight-bump));
    line-height: 1.15;
    color: var(--mn-ink);
    letter-spacing: -.01em;
}
.mn-dish-title-price {
    font-family: var(--mn-grotesk);
    font-size: calc(26px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-gold-text);
    flex: 0 0 auto;
}
.mn-dish-cat {
    font-family: var(--mn-mono);
    font-size: calc(11px * var(--mn-scale, 1));
    letter-spacing: .16em;
    color: var(--mn-gold-text);
}

/* Three blocks, three gaps, counted off screen_dish.html: Ingredients 8,
   Extras 11, Notes 9. One rule for all three is 3px and 1px wrong, which is
   small and is still not what was drawn. */
.mn-field { display: flex; flex-direction: column; gap: 8px; }
.mn-field.is-extras { gap: 11px; }
.mn-field.is-notes { gap: 9px; }
/* The same column as a <fieldset>, which is what a group of radios has to be.
   One arrives with a groove border, 2px of inline margin, ~0.6em of padding
   and min-inline-size:min-content, and every one of those moves the row inside
   it — the same reset .mn-extras carries below, for the same reason. */
fieldset.mn-field { margin: 0; padding: 0; border: 0; min-inline-size: 0; }
fieldset.mn-field > legend { padding: 0; }
.mn-field-label {
    font-size: calc(14px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-muted-2);
}
.mn-prose {
    font-size: calc(16px * var(--mn-scale, 1));
    line-height: 1.7;
    color: var(--mn-ink-2);
    text-wrap: pretty;
}

/*
    A page that is nothing but prose -- terms, privacy, the accessibility
    statement.

    On the ground colour and NOT in a card. A card is a thing among other
    things; this is the only thing on the screen, and putting a thousand words
    of it inside a rounded panel builds a box with no outside.

    62ch is the measure. The app column is already capped at 480px, so on a
    phone this changes nothing and on a laptop it stops the paragraph running
    to a line nobody can track back from.

    The child rules are the operator's own HTML, which arrives as headings,
    paragraphs and lists and carries no classes of its own.
*/
.mn-doc { max-width: 62ch; }
.mn-doc > * { margin: 0; }
.mn-doc > * + * { margin-block-start: 14px; }
.mn-doc h2 {
    font-size: calc(19px * var(--mn-scale, 1));
    font-weight: calc(800 + var(--mn-weight-bump));
    color: var(--mn-ink);
    line-height: 1.35;
}
.mn-doc h3 {
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink-2);
}
.mn-doc h2 + *, .mn-doc h3 + * { margin-block-start: 8px; }
.mn-doc > h2, .mn-doc > h3 { margin-block-start: 26px; }
.mn-doc ul, .mn-doc ol {
    padding-inline-start: 22px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.mn-doc a { text-decoration: underline; text-underline-offset: 3px; }

/* A <fieldset> on the dish page and a <div> for the sizes above it, so the
   reset has to cover both: a fieldset arrives with a groove border, 2px of
   inline margin, ~0.6em of padding and min-inline-size:min-content, and every
   one of those moves the drawn chip row. The element is a fieldset because
   jadtags-cart.js reads a group's cap off fieldset[data-max] — see
   item.blade.php. */
.mn-extras {
    display: flex;
    flex-wrap: wrap;
    gap: 9px;
    margin: 0;
    padding: 0;
    border: 0;
    min-inline-size: 0;
}
/* Shown only when a dish has more than one choice group; otherwise the legend
   carries .mn-sr and the screen is exactly the one drawn. */
.mn-extras-legend {
    padding: 0;
    width: 100%;
    font-size: calc(13px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink-2);
}
.mn-extras-legend span {
    font-family: var(--mn-mono);
    font-size: calc(11px * var(--mn-scale, 1));
    letter-spacing: .08em;
    color: var(--mn-off);
    margin-inline-start: 6px;
}
.mn-extra {
    height: 42px;
    padding-inline: 15px;
    display: flex;
    align-items: center;
    gap: 9px;
    border-radius: 999px;
    cursor: pointer;
    font-size: calc(14.5px * var(--mn-scale, 1));
    font-weight: calc(600 + var(--mn-weight-bump));
    background: var(--mn-card);
    color: var(--mn-ink-2);
    border: 1px solid var(--mn-hairline-2);
    user-select: none;
}
/* The tick itself is invisible — the CHIP is the control, and :has() below
   paints it. :not(.mn-extra-qty) because an extra-component count is also an
   input inside a chip and it has to be typed into. */
.mn-extra input:not(.mn-extra-qty) { position: absolute; opacity: 0; pointer-events: none; }
.mn-extra:hover { border-color: rgba(217, 164, 65, .55); }
.mn-extra:has(input:checked) {
    background: var(--mn-gold);
    color: var(--mn-gold-ink);
    border-color: var(--mn-gold-text);
}
.mn-extra:has(input:focus-visible) { outline: 2px solid var(--mn-gold); outline-offset: 2px; }
.mn-extra:has(input:disabled) { opacity: .45; cursor: not-allowed; }
.mn-extra-price {
    font-family: var(--mn-grotesk);
    font-size: calc(13px * var(--mn-scale, 1));
    opacity: .75;
}
/* "extra cheese x2" — a number, inside the chip, with the browser's own box
   and spinners taken away for the same reason the dish stepper's are. */
.mn-extra-qty {
    width: 42px;
    text-align: center;
    border: 0;
    border-radius: 999px;
    padding: 2px 0;
    background: var(--mn-bg);
    color: inherit;
    font-family: var(--mn-grotesk);
    font-size: calc(14px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    appearance: none;
    -moz-appearance: textfield;
}
.mn-extra-qty::-webkit-inner-spin-button,
.mn-extra-qty::-webkit-outer-spin-button { appearance: none; margin: 0; }
.mn-extra:has(.mn-extra-qty) { cursor: default; }

/* 82px, not the drawn 52px, and they are the same measurement. The design
   draws min-height:52px on a CONTENT-box element with 14px of padding and a
   1px border, so what renders is 52 + 28 + 2. box-sizing below folds the
   padding into the minimum, so the literal 52 would render 30px short. */
.mn-note {
    min-height: 82px;
    padding: 14px 16px;
    border-radius: 14px;
    background: var(--mn-raised);
    border: 1px solid var(--mn-hairline);
    font-size: calc(15px * var(--mn-scale, 1));
    color: var(--mn-ink);
    width: 100%;
    box-sizing: border-box;
    resize: vertical;
    font-family: inherit;
}
.mn-note::placeholder { color: var(--mn-off); }

.mn-buy { display: flex; align-items: center; gap: 14px; }

.mn-stepper {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 5px;
    border-radius: 999px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline-2);
    flex: 0 0 auto;
}
.mn-stepper button {
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 999px;
    background: none;
    display: grid;
    place-items: center;
    cursor: pointer;
    color: var(--mn-ink);
}
.mn-stepper button:hover { background: var(--mn-line); }
.mn-stepper button[disabled] { opacity: .4; cursor: not-allowed; background: none; }
.mn-stepper output, .mn-stepper .mn-qty {
    min-width: 34px;
    text-align: center;
    font-family: var(--mn-grotesk);
    font-size: calc(19px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
/* The design draws bare 19px Space Grotesk between two round buttons. A number
   input arrives with a border, a white ground and a pair of spinner arrows —
   so a control the theme drew as three flat glyphs renders as a boxed field on
   #122231. The input stays a number input because theme.js is progressive and
   the browser's own increment has to keep working with it blocked; only its
   chrome is taken away. `outline: none` and not `outline: 0 !important` —
   :focus-visible above still draws the keyboard ring. */
.mn-stepper .mn-qty {
    border: 0;
    background: none;
    padding: 0;
    appearance: none;
    -moz-appearance: textfield;
}
.mn-stepper .mn-qty:focus { outline: none; }
.mn-stepper .mn-qty::-webkit-inner-spin-button,
.mn-stepper .mn-qty::-webkit-outer-spin-button { appearance: none; margin: 0; }

.mn-buy .mn-cta {
    flex: 1;
    height: 56px;
    font-size: calc(17px * var(--mn-scale, 1));
    box-shadow: 0 12px 32px -14px rgba(217, 164, 65, .7);
}
.mn-buy .mn-cta span:last-child { font-family: var(--mn-grotesk); }

/* ------------------------------------------------------------- CART page */

.mn-page {
    padding: 20px 18px 30px;
    display: flex;
    flex-direction: column;
    gap: 20px;
}

.mn-page-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}
.mn-page-head h1 {
    margin: 0;
    font-size: calc(28px * var(--mn-scale, 1));
    font-weight: calc(900 + var(--mn-weight-bump));
    color: var(--mn-ink);
    letter-spacing: -.015em;
}
.mn-page-count {
    font-family: var(--mn-grotesk);
    font-variant-numeric: tabular-nums;
    font-size: calc(14px * var(--mn-scale, 1));
    color: var(--mn-muted-2);
    flex: 0 0 auto;
}

.mn-empty {
    padding: 56px 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    text-align: center;
}
/*
    The 74px ring. One geometry, two skins.

    An empty state opens with it and so does the confirmation; the second was
    written out again with six of its eight declarations byte-identical to the
    first. Only the three colours and the lift off the heading are the tick's
    own, and those are all it carries — see .mn-order-tick in the ORDER section.
*/
.mn-empty-ring, .mn-order-tick {
    width: 74px;
    height: 74px;
    border-radius: 999px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline);
    display: grid;
    place-items: center;
    color: var(--mn-off);
}
.mn-empty h2 {
    margin: 0;
    font-size: calc(19px * var(--mn-scale, 1));
    font-weight: calc(800 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
.mn-empty p {
    margin: 0;
    font-size: calc(15px * var(--mn-scale, 1));
    color: var(--mn-muted-2);
    max-width: 230px;
    line-height: 1.6;
}
/* screen_cart.html's browseMenu carries no box-shadow. Without resetting it
   here the hero's gold glow arrives through .mn-cta and sits under a button
   the design draws flat. */
.mn-empty .mn-cta { margin-top: 6px; height: 50px; font-size: calc(16px * var(--mn-scale, 1)); box-shadow: none; }

/*
    The empty state as a PANEL.

    screen_wall.html's upload card is where this theme says "a space with
    nothing in it yet": a faint gold wash inside a dashed gold line. A basket
    with nothing in it and a menu with no dishes on it are the same statement,
    and both were a sentence floating on the ground — which reads as a page
    that failed to load rather than a page with nothing to show.

    The ring, the heading and the button above are untouched; this only gives
    them an edge to sit inside.

    ONLY for a screen the designer did not draw. The empty BASKET is a drawn
    screen -- screen_cart.html's cartEmpty, 56px of padding on the bare ground
    with no border and no wash -- so it stays plain .mn-empty. An empty menu
    was never drawn, and that is the one this panel is for.

    THE WASH IS THE TOKEN and not the dark gold spelled out. --mn-gold-wash is
    redefined under :root[data-mn-scheme="light"], and the literal rgba left a
    light-gold dashed border around a dark-gold fill in the theme's own light
    scheme. It fades to transparent rather than to a second alpha because
    there is no second wash token and the token block is not ours to add one
    to; .mn-upload keeps its own .16/.04 because that card IS drawn and its
    alphas are the design.
*/
.mn-empty.is-panel {
    padding: 40px 22px;
    border-radius: 20px;
    background: linear-gradient(100deg, var(--mn-gold-wash), transparent);
    border: 1px dashed var(--mn-gold-line);
}

.mn-lines {
    display: flex;
    flex-direction: column;
    gap: 11px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.mn-line {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px;
    border-radius: 20px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline);
}
.mn-line.is-blocked { border-color: rgba(217, 164, 65, .5); }
.mn-line-photo {
    width: 62px;
    height: 62px;
    border-radius: 14px;
    overflow: hidden;
    background: var(--mn-raised);
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    color: var(--mn-off);
}
.mn-line-photo img { width: 100%; height: 100%; object-fit: cover; }
.mn-line-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.mn-line-name {
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
.mn-line-total {
    font-family: var(--mn-grotesk);
    font-size: calc(15px * var(--mn-scale, 1));
    font-weight: calc(600 + var(--mn-weight-bump));
    color: var(--mn-gold-text);
}
.mn-line-options {
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: calc(13px * var(--mn-scale, 1));
    color: var(--mn-muted-2);
    line-height: 1.5;
}
.mn-line-blocked {
    font-size: calc(13px * var(--mn-scale, 1));
    color: var(--mn-gold-soft);
    line-height: 1.5;
}
.mn-line-note {
    margin-top: 4px;
    width: 100%;
    box-sizing: border-box;
    background: var(--mn-bg);
    border: 1px solid var(--mn-hairline);
    border-radius: 12px;
    padding: 8px 11px;
    color: var(--mn-ink);
    font-size: calc(13px * var(--mn-scale, 1));
    resize: none;
}
.mn-line-note::placeholder { color: var(--mn-off); }

.mn-line-stepper {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 4px;
    border-radius: 999px;
    background: var(--mn-bg);
    border: 1px solid var(--mn-hairline-2);
    flex: 0 0 auto;
}
.mn-line-stepper button {
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: 999px;
    background: none;
    display: grid;
    place-items: center;
    cursor: pointer;
    color: var(--mn-muted);
}
.mn-line-stepper button:hover { color: var(--mn-ink); }
.mn-line-stepper button[disabled] { opacity: .4; cursor: not-allowed; }
.mn-line-stepper output {
    min-width: 24px;
    text-align: center;
    font-family: var(--mn-grotesk);
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
}

/* The three real service types, in a segmented control. The design draws two
   arms; order_settings has three and the branch decides which exist, so this
   is a flex row that reads correctly at one, two or three. */
.mn-service {
    display: flex;
    gap: 4px;
    padding: 5px;
    border-radius: 999px;
    background: var(--mn-raised);
    border: 1px solid var(--mn-hairline);
}
.mn-service-arm {
    flex: 1;
    min-width: 0;
    height: 44px;
    border: 0;
    border-radius: 999px;
    background: none;
    display: grid;
    place-items: center;
    cursor: pointer;
    font-size: calc(15px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-muted);
    padding-inline: 6px;
    text-align: center;
}
.mn-service-arm:hover { color: var(--mn-ink); }
.mn-service-arm.is-active {
    background: var(--mn-gold);
    color: var(--mn-gold-ink);
}
.mn-service-arm.is-active:hover { color: var(--mn-gold-ink); }

/*
    The same segmented control, as radios.

    The cart's arms are links, because that screen re-prices on the server. The
    checkout's are radios inside the form, because a link there would reload
    the page and throw away everything already typed into it. Identical to look
    at, which is the whole point: it is one question asked twice in one
    journey, and an answer that changed shape between the two screens would
    read as two different questions.

    The input is invisible and the ARM is the control — the pattern .mn-extra
    already uses — so no browser tick paints itself inside a gold pill.
*/
label.mn-service-arm { position: relative; }
.mn-service-arm input { position: absolute; opacity: 0; pointer-events: none; }
.mn-service-arm:has(input:checked) {
    background: var(--mn-gold);
    color: var(--mn-gold-ink);
}
.mn-service-arm:has(input:focus-visible) { outline: 2px solid var(--mn-gold); outline-offset: 2px; }

/*
    ...and the block that belongs to the lit arm, WITHOUT the script.

    The server renders every block but the chosen one `hidden`, and the only
    thing that used to take that off was public/js/jadtags-ui.js on `change`.
    With the script blocked -- which on a restaurant's wifi is not rare -- a
    customer tapped "delivery", no address fields appeared, they submitted, and
    CheckoutRequest answered "an address is needed for delivery" about fields
    they had never been shown. The checked radio is the selector, so the page
    can answer its own question.

    `!important` because [hidden] at the top of this file is itself !important,
    and it has to be: without it a class that sets `display` beats the
    browser's own rule and hidden things paint. The script still hides and
    DISABLES the blocks that do not apply, and the two agree -- both show
    exactly the block whose radio is checked.

    Nothing here fires for a branch with one service: there is no radio, the
    single block is never rendered hidden, and it stays visible on its own.
*/
.mn-form:has([data-service-type][value="dine_in"]:checked) [data-when-service="dine_in"],
.mn-form:has([data-service-type][value="delivery"]:checked) [data-when-service="delivery"] {
    display: flex !important;
}

/*
    THE RAISED PANEL: one recipe, three surfaces.

    The totals block, the status track and the week of opening hours are the
    same box -- raised ground inside a hairline at radius 20 -- and it was
    written out three times, so a change to the panel had to be made in three
    places or the three screens drifted apart. Grouped rather than given a new
    class name, because that would mean a second class in the markup of five
    templates for a look none of them has ever asked to opt out of.

    Each of the three then carries only what is its own: its padding, its
    layout and its gap.
*/
.mn-totals, .mn-steps, .mn-hours {
    border-radius: 20px;
    background: var(--mn-raised);
    border: 1px solid var(--mn-hairline);
}

.mn-totals {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 18px;
}
.mn-total-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.mn-total-row > span:first-child {
    font-size: calc(17px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-muted);
}
/* The answer the three order screens exist to show, and the one number on
   them that was not tabular -- so it shifted sideways as it changed while the
   identical total inside the submit button, which carries .mn-amount, did
   not. */
.mn-total-row > span:last-child {
    font-family: var(--mn-grotesk);
    font-variant-numeric: tabular-nums;
    font-size: calc(26px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
/* The lines above the grand total are the arithmetic, not the answer. */
.mn-total-row.is-minor > span { font-size: calc(15px * var(--mn-scale, 1)); font-weight: calc(500 + var(--mn-weight-bump)); }
.mn-total-row.is-minor > span:last-child { font-size: calc(15px * var(--mn-scale, 1)); color: var(--mn-ink-2); }

/*
    The button that ENDS something, as against the one that starts it.

    .mn-cta's 19px and its deeper glow are screen_home.html's hero -- the one
    thing on that page. screen_cart.html draws the basket's "place the order"
    at 18px with a shallower shadow, and the checkout's submit one screen later
    is the same act: two consecutive primary buttons in one journey must not
    differ by a pixel of type. The club form and the preference centre end the
    same way, so they are in it too.
*/
.mn-totals .mn-cta,
.mn-form > .mn-cta { height: 58px; font-size: calc(18px * var(--mn-scale, 1)); box-shadow: 0 12px 32px -14px rgba(217, 164, 65, .7); }

/*
    A receipt: the lines of an order that can no longer be changed.

    INSIDE .mn-totals, because the lines and the arithmetic under them are one
    panel — a separate card for each would put a border between a dish and its
    own price. The gap is 11 where the panel's is 14: a line and the extras
    under it are one thing, and 14 between them reads as two.
*/
.mn-receipt {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 11px;
}
.mn-receipt > li { display: flex; flex-direction: column; gap: 4px; }
.mn-receipt .mn-line-options { padding-inline-start: 16px; }
/* A rule between what was ordered and what it comes to. */
.mn-totals .mn-total-row:last-child {
    padding-block-start: 14px;
    border-block-start: 1px solid var(--mn-hairline);
}

/* How many of it. A badge and not "2×": the glyph sits differently in the two
   directions this theme is drawn in, and a number in its own box does not. */
.mn-line-qty {
    display: inline-block;
    min-width: 20px;
    padding: 1px 7px;
    margin-inline-end: 7px;
    border-radius: 999px;
    background: var(--mn-gold-wash);
    color: var(--mn-gold-soft);
    font-family: var(--mn-grotesk);
    font-variant-numeric: tabular-nums;
    font-size: calc(13px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    text-align: center;
}

.mn-cart-foot {
    display: flex;
    justify-content: center;
    padding-top: 4px;
}
.mn-quiet {
    border: 0;
    background: none;
    color: var(--mn-off);
    font-size: calc(14px * var(--mn-scale, 1));
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
}
.mn-quiet:hover { color: var(--mn-muted); }

/* An honest refusal, in the place the button would have been.
   .jt-notice is here too: it is what the SHIPPED x-menu.flash component emits —
   the soft notice for an unknown table code or a replaced scan token — and it
   is styled in public/css/jadtags.css, which this theme does not load on a page
   it draws itself. Two names, one shape, rather than an unstyled sentence
   floating above the menu. */
.mn-notice,
.jt-notice {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 13px 15px;
    border-radius: 14px;
    background: var(--mn-raised);
    border: 1px solid var(--mn-hairline);
    color: var(--mn-gold-soft);
    font-size: calc(14.5px * var(--mn-scale, 1));
    line-height: 1.5;
    margin: 0;
}
.mn-notice svg, .jt-notice svg { flex: 0 0 auto; }
/* display:flex on a class BEATS the browser's own display:none for [hidden],
   so a notice that starts hidden and is revealed by script — the expired-code
   line on the club's code page — would otherwise be on screen from the first
   paint, telling everybody their code had run out. */
.mn-notice[hidden] { display: none; }

/*
    The toast, under its shipped name — the same decision .jt-notice above is
    here for.

    jadtags-forms.js publishes window.jadtagsToast and jadtags-cart.js uses it
    to confirm a copied order on the confirmation screen. Both scripts are
    loaded on the pages this theme draws; the stylesheet that dresses their
    markup deliberately is not. Without these rules the confirmation is an
    unstyled line of text across the top of a dark page.
*/
.jt-toasts {
    position: fixed;
    inset-block-start: 14px;
    inset-inline: 0;
    z-index: 30;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding-inline: 16px;
    pointer-events: none;
}
.jt-toast {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 9px;
    max-width: 100%;
    padding: 11px 18px;
    border-radius: 999px;
    background: var(--mn-card);
    border: 1px solid var(--mn-gold-line);
    color: var(--mn-ink);
    font-size: calc(14px * var(--mn-scale, 1));
    font-weight: calc(600 + var(--mn-weight-bump));
    box-shadow: 0 18px 40px -20px rgba(0, 0, 0, .75);
    animation: mIn .22s ease-out both;
}
.jt-toast svg { flex: 0 0 auto; color: var(--mn-gold-text); }
.jt-toast.is-leaving { opacity: 0; transition: opacity .18s ease; }

/* ------------------------------------- ORDER: the confirmation and tracking */

/*
    Two screens, one hero, because they carry the same fact: the order number.

    It is the largest thing on either page, and that is not decoration. It is
    three characters long, it is what a waiter asks for across a counter and
    what somebody reads out over a phone in a room with a fryer in it. The
    heading above it is the sentence; the number is the answer.
*/
.mn-order {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
    padding-block: 10px 4px;
}
.mn-order h1 {
    margin: 0;
    font-size: calc(21px * var(--mn-scale, 1));
    font-weight: calc(800 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
/*
    The tick, in this theme's own gold.

    --mn-live is the only other accent in the token list and it belongs to the
    "open now" dot; borrowing it here would make two unrelated things look like
    one, and MIDNIGHT.md's table is the whole palette there is.
*/
/* The geometry is .mn-empty-ring's, grouped with it beside the empty state.
   Only the colours and the lift off the heading are this one's own. */
.mn-order-tick {
    background: var(--mn-gold-wash);
    border-color: var(--mn-gold-line);
    color: var(--mn-gold-text);
    margin-block-end: 4px;
}
.mn-order-num {
    font-family: var(--mn-grotesk);
    font-variant-numeric: tabular-nums;
    font-size: calc(52px * var(--mn-scale, 1));
    font-weight: calc(900 + var(--mn-weight-bump));
    line-height: 1;
    letter-spacing: -.02em;
    color: var(--mn-gold-text);
}

/*
    The four-step machine.

    A track rather than four chips: the question a customer actually has is
    "how far along is it", and four separate badges answer "which one is lit"
    instead. The connector is a ::before on every step but the first, so the
    row is correct at three steps or five and mirrors on its own — there is no
    left or right anywhere in it.
*/
/* The panel is shared -- see .mn-totals. This is only the track inside it. */
.mn-steps {
    list-style: none;
    margin: 0;
    padding: 16px 14px;
    display: flex;
}
.mn-step {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
    position: relative;
    font-size: calc(12.5px * var(--mn-scale, 1));
    line-height: 1.35;
    text-align: center;
    color: var(--mn-off);
}
/* The line INTO this step, from the one before it. */
.mn-step + .mn-step::before {
    content: "";
    position: absolute;
    top: 6px;
    inset-inline-start: -50%;
    inset-inline-end: 50%;
    height: 2px;
    background: var(--mn-line);
}
.mn-step-dot {
    width: 14px;
    height: 14px;
    border-radius: 999px;
    background: var(--mn-card);
    border: 2px solid var(--mn-line);
    box-sizing: border-box;
    position: relative;
    z-index: 1;
    flex: 0 0 auto;
}
.mn-step.is-done { color: var(--mn-ink-2); }
.mn-step.is-done .mn-step-dot { background: var(--mn-gold); border-color: var(--mn-gold-text); }
.mn-step.is-done + .mn-step.is-done::before { background: var(--mn-gold); }
.mn-step.is-now { color: var(--mn-gold-soft); font-weight: calc(700 + var(--mn-weight-bump)); }
.mn-step.is-now .mn-step-dot { box-shadow: 0 0 0 4px var(--mn-gold-wash); }

/*
    Cancelled.

    It REPLACES the track rather than joining it, because it is not a fifth
    step — it is the machine stopping. A track with a fifth dot nobody ever
    reaches reads as an order still on its way.
*/
.mn-state {
    margin: 0;
    padding: 14px 16px;
    border-radius: 16px;
    background: var(--mn-raised);
    border: 1px dashed var(--mn-gold-line);
    text-align: center;
    font-size: calc(15px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-gold-soft);
}

/*
    The cancel window, and how long is left of it.

    The clock is the theme's own countdown — the instant comes from the server,
    so a reload cannot restart it — and the form sits INSIDE the same box, so
    when the script stamps is-expired the button goes with it. A :has() rule
    rather than a second script that knows about buttons.
*/
.mn-cancel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}
.mn-cancel form { margin: 0; }
.mn-cancel:has(.is-expired) form { display: none; }

/* The row of second-rank actions. The centred wrapping row is .mn-social-row's
   and is grouped with it in the FOOTER section; this is the one declaration
   that is this row's own -- its buttons share the width, where the footer's
   icons are fixed circles. */
.mn-acts > * { flex: 1 1 auto; }

/* --------------------------------------- FORMS: the club, the opt-out pages */

/*
    Six screens were drawn. The club form, the code page, the welcome, the
    preference centre and the two unsubscribe pages were not, and neither was a
    content page -- so every shape below is taken from a screen that WAS drawn
    rather than invented.

    The card is the dish page's radius and hairline. The consent row has the
    cart line's proportions. The code cells are the stepper's number treatment
    at the stepper's radius. The sentence under a control that will not move is
    .mn-notice, which already exists in this file to say no honestly.

    ONE thing here is genuinely new, and it is new on purpose. Everywhere else
    in this theme a checkbox is invisible -- .mn-extra hides the input and
    paints the chip gold. That is exactly wrong for a consent box, where the
    whole evidentiary claim is that a person was shown an UNTICKED box and
    ticked it. So these are real controls, sized up and given accent-color, and
    the box is a box.
*/

/*
    The card EXTENDING.md names. --mn-card at radius 20 with a 1px hairline,
    which is what screen_dish.html and screen_home.html both draw.
*/
.mn-card {
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline);
    border-radius: 20px;
    padding: 16px 18px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.mn-card-title {
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(800 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
.mn-card-text {
    font-size: calc(14px * var(--mn-scale, 1));
    line-height: 1.6;
    color: var(--mn-muted-2);
    margin: 0;
}
/* A form inside a card is .mn-form at the card's tighter rhythm. The gap is
   the only thing that is its own -- the other three declarations were a second
   copy of the rule on the next line. */
.mn-card > .mn-form { gap: 10px; }

/* A form is a column of blocks at the page's own rhythm. */
.mn-form { display: flex; flex-direction: column; gap: 16px; margin: 0; }
.mn-form-pair { display: flex; gap: 11px; }
.mn-form-pair > * { flex: 1; min-width: 0; }

/*
    A single-line field, which is .mn-note with one line instead of four.

    16px and not the 15px .mn-note carries: iOS zooms the whole page in on a
    focused input under 16px, and a form that jumps the moment somebody taps
    the first field is a form filled in at 140% with the submit off screen.
*/
.mn-input {
    height: 52px;
    padding: 0 16px;
    border-radius: 14px;
    background: var(--mn-raised);
    border: 1px solid var(--mn-hairline);
    font-size: calc(16px * var(--mn-scale, 1));
    color: var(--mn-ink);
    width: 100%;
    box-sizing: border-box;
    font-family: inherit;
    appearance: none;
}
.mn-input::placeholder { color: var(--mn-off); }
.mn-input:focus { border-color: var(--mn-gold-line); }
/* A date input paints its own clear/calendar glyph nearly black on this
   ground. It is the browser's control and cannot be restyled, only lightened. */
.mn-input::-webkit-calendar-picker-indicator { filter: invert(.75); }

/* The same box with the browser's arrow left alone -- a custom one would be a
   background-image with a physical side, and this theme is drawn both ways. */
select.mn-input { padding-inline-end: 12px; appearance: auto; }

.mn-field-hint {
    font-size: calc(13px * var(--mn-scale, 1));
    line-height: 1.55;
    color: var(--mn-muted-2);
}

/*
    Errors. .mn-notice's shape, because there is no red in this theme's token
    list and inventing one would be inventing a colour the design does not have
    -- gold on the raised ground is how Midnight already says no.
*/
.mn-alert { align-items: flex-start; }
.mn-alert ul {
    margin: 0;
    padding-inline-start: 18px;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

/*
    A consent row: an unticked box and the whole sentence beside it.

    align-items: flex-start, because the sentence is two or three lines and a
    tick centred against a paragraph reads as belonging to the middle line.
    The <label> is the hit area, so the sentence itself is tappable -- a 22px
    box on a phone is not.
*/
.mn-consent,
.mn-choice,
.mn-toggle {
    display: flex;
    gap: 13px;
    padding: 15px 16px;
    border-radius: 16px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline-2);
    cursor: pointer;
}
.mn-consent { align-items: flex-start; }
.mn-choice { align-items: flex-start; }
.mn-toggle { align-items: center; }
.mn-consent:hover, .mn-choice:hover, .mn-toggle:hover { border-color: var(--mn-gold-line); }
.mn-consent:has(input:focus-visible),
.mn-choice:has(input:focus-visible),
.mn-toggle:has(input:focus-visible) { outline: 2px solid var(--mn-gold); outline-offset: 2px; }

.mn-consent input,
.mn-choice input,
.mn-toggle input {
    width: 22px;
    height: 22px;
    flex: 0 0 auto;
    margin: 0;
    accent-color: var(--mn-gold-text);
    cursor: pointer;
}
/* The tick sits on the first line of the sentence rather than above it. */
.mn-consent input, .mn-choice input { margin-block-start: 2px; }

.mn-consent span {
    font-size: calc(14.5px * var(--mn-scale, 1));
    line-height: 1.6;
    color: var(--mn-ink-2);
}

/* The chosen option is the one that is filled. Gold wash rather than solid
   gold: three of these stacked in full gold is a page with no hierarchy. */
/*
    The gold wash means CHOSEN, and the locked row is not chosen -- it is the
    one control on the page that cannot move. It is excluded from the selector
    rather than fought below it: :has() carries the specificity of its most
    specific argument, so `input:checked` makes this (0,2,1) and
    .mn-toggle.is-locked at (0,2,0) loses to it whatever the source order. A
    disabled checkbox still matches :checked.
*/
.mn-choice:has(input:checked),
.mn-toggle:not(.is-locked):has(input:checked) {
    border-color: var(--mn-gold-line);
    background: var(--mn-gold-wash);
}
.mn-choice-body, .mn-toggle-text {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    flex: 1;
}
.mn-choice-body b, .mn-toggle-text b {
    font-size: calc(15.5px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
.mn-choice-body span, .mn-toggle-text span {
    font-size: calc(13.5px * var(--mn-scale, 1));
    line-height: 1.55;
    color: var(--mn-muted-2);
}

/*
    A control that will not move, and the reason it will not.

    Dashed and gold-lined, which is the same vocabulary .mn-upload uses for "a
    panel that is not an ordinary panel". A greyed-out switch with no
    explanation is read as a bug; the whole point of this row is the sentence.
    Not a <label>, because there is nothing to click.
*/
.mn-toggle.is-locked {
    background: var(--mn-raised);
    border: 1px dashed var(--mn-gold-line);
    cursor: default;
}
.mn-toggle.is-locked:hover { border-color: var(--mn-gold-line); }
.mn-toggle.is-locked .mn-toggle-text span { color: var(--mn-gold-soft); }
.mn-toggle.is-locked input { opacity: .5; cursor: not-allowed; }
.mn-toggle.is-locked > svg { flex: 0 0 auto; color: var(--mn-gold-text); }

/* ------------------------------------------------------------ the OTP page */

/*
    One field, six cells.

    The field is the control and the cells are an enhancement over it: with
    JavaScript blocked -- a captive portal, a locked-down phone -- the six cells
    stay hidden and .mn-code is an ordinary code box that submits, autofills
    from an SMS and works. theme.js unhides the cells and turns the real field
    into a hidden input carrying their value.

    display: flex on a [hidden] element WINS over the browser's own
    display: none, so the row below is not defensive tidiness: without it the
    cells are visible on a page with no JavaScript, unlabelled and posting
    nothing.
*/
.mn-otp[hidden] { display: none; }
.mn-otp {
    display: flex;
    gap: 9px;
    /* A verification code reads left to right in every language -- the digits
       arrive in an SMS in that order and are typed in that order. */
    direction: ltr;
}
/*
    ONE BOX, and the two things it is.

    .mn-code is the field a phone with no JavaScript submits; .mn-otp-cell is
    one of the six it becomes once theme.js takes over. They are the same box
    at the same size in the same type, so they are drawn once -- eleven
    declarations were byte-identical, and a change to the code box reaching
    only one of them would leave the enhanced and unenhanced states looking
    like two different screens. Grouped the way .mn-totals/.mn-steps/.mn-hours
    already are.
*/
.mn-otp-cell, .mn-code {
    height: 60px;
    border-radius: 16px;
    background: var(--mn-card);
    border: 1px solid var(--mn-hairline-2);
    color: var(--mn-ink);
    text-align: center;
    font-family: var(--mn-grotesk);
    font-variant-numeric: tabular-nums;
    font-size: calc(24px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    appearance: none;
}
/* The cells' own: six of them share a row, and they carry no padding. */
.mn-otp-cell {
    flex: 1;
    min-width: 0;
    padding: 0;
    -moz-appearance: textfield;
}
.mn-otp-cell::-webkit-inner-spin-button,
.mn-otp-cell::-webkit-outer-spin-button { appearance: none; margin: 0; }
.mn-otp-cell:focus { border-color: var(--mn-gold-text); outline: none; }
.mn-otp-cell:not(:placeholder-shown) { border-color: var(--mn-gold-line); }

/* The field's own: it is the full width of the form, spaced out, and it reads
   left to right the way the cells do. */
.mn-code {
    padding: 0 16px;
    width: 100%;
    box-sizing: border-box;
    direction: ltr;
    letter-spacing: .34em;
    /* letter-spacing puts a gap after the LAST glyph too, which shifts a
       centred string half a gap off centre. */
    text-indent: .34em;
}
.mn-code::placeholder { color: var(--mn-off); letter-spacing: .34em; }

/*
    The countdown, and the sentence it becomes when it runs out.

    Rendered with a real instant in data-mn-until when the controller supplies
    one, and as the plain "it lasts ten minutes" sentence when it does not --
    ten minutes being VerificationCodes::TTL_MINUTES and not a number chosen
    here. A ticking clock started from page load would be a number this screen
    made up.
*/
.mn-countdown {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 0;
    font-size: calc(13.5px * var(--mn-scale, 1));
    color: var(--mn-muted-2);
}
.mn-countdown svg { flex: 0 0 auto; color: var(--mn-off); }
/* A date or a clock set into a sentence. Both are numbers, and EXTENDING.md's
   rule for a number in this theme is grotesk with tabular figures -- the
   preference centre's "paused until" date is the other one. */
.mn-countdown b, .mn-notice b {
    font-family: var(--mn-grotesk);
    font-variant-numeric: tabular-nums;
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink-2);
}
.mn-countdown.is-expired { color: var(--mn-gold-soft); }
.mn-countdown.is-expired svg { color: var(--mn-gold-text); }


/* ----------------------------------------------------------- OFFERS page */

/*
    screen_offers.html, counted off the drawing.

    This screen WAS drawn and this theme was shipped without it: the page
    inherited resources/views/menu/offers.blade.php through the namespace
    fallback and pulled public/css/midnight-promo.css on top of the theme's own
    stylesheet. It rendered, and it was still a seam — a second copy of the
    tokens, a second copy of the two keyframes, and a stylesheet fetched on a
    page the theme claims to draw. The markup is now the theme's, the rules are
    here beside the pages they sit between, and midnight-promo.css keeps the
    popup, which is the one surface it was written for.

    The popup's own rules are NOT duplicated here. It is emitted by the shipped
    x-menu.promo-popup component on every public page, themed or not, and the
    layout links its stylesheet on exactly the condition that component renders.

    THE PRICE SLOTS. The drawing writes each row with an offer price, a
    struck-through old price and a saving chip. Those are three numbers, and
    there is no per-item discount anywhere in this schema — OrderPricer ships
    the subtraction and nothing writes one. So the slots carry what a promotion
    actually has: its headline where the design writes the dish name, its
    sub-headline in the muted line, its CTA label in the chip. A struck-through
    price invented here is a number the restaurant never entered, printed on a
    page customers act on.
*/

/*
    The shell and the title block are .mn-page and .mn-head + .mn-eyebrow, and
    that is the whole of what this screen needed: the drawn container is
    20px 18px 30px at gap 20, the drawn header is 28/900 over a 15px
    --mn-muted-2 line at gap 6, and the drawn small-caps label is 11px mono at
    .2em in --mn-gold. Every one of those was already written down, twice — the
    comment over .mn-head says so in as many words — and this screen wrote a
    third copy of all five.

    .mn-offers survives as a SCOPE and declares nothing of its own except the
    one measurement that really is this screen's: screen_offers.html sets the
    title's leading tighter than the default, because "Today's offers" is the
    page title in this theme most likely to wrap on a 390px phone.
*/
.mn-offers .mn-head h1 { line-height: 1.2; }


.mn-offers-hero {
    position: relative;
    display: block;
    margin: 0;
    height: 180px;
    border-radius: 22px;
    overflow: hidden;
    background: var(--mn-photo);
    border: 1px solid rgba(217, 164, 65, .22);
}
.mn-offers-hero img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Drawn as a scrim so the gold button stays legible on a pale photograph.
   `to top` is physical on purpose: a gradient's axis is not a reading
   direction and must not flip in LTR. */
.mn-offers-hero::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to top, rgba(7, 18, 26, .9), transparent 65%);
}
.mn-offers-hero-cta {
    position: absolute;
    z-index: 1;
    bottom: 14px;
    inset-inline-start: 16px;
    height: 42px;
    padding-inline: 20px;
    box-sizing: content-box;
    border-radius: 999px;
    background: var(--mn-gold);
    color: var(--mn-gold-ink);
    display: flex;
    align-items: center;
    font-size: calc(15px * var(--mn-scale, 1));
    font-weight: calc(800 + var(--mn-weight-bump));
}
.mn-offers-hero:hover .mn-offers-hero-cta { background: var(--mn-gold-hi); }

.mn-offers-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.mn-offer {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 11px;
    border-radius: 20px;
    background: var(--mn-card);
    border: 1px solid rgba(217, 164, 65, .24);
    color: inherit;
    transition: transform .18s ease, border-color .18s ease;
}
/* Only the linked ones lift. A promotion with link_type='none' renders as a
   <div> and must not pretend to be pressable. */
a.mn-offer:hover {
    transform: translateY(-3px);
    border-color: rgba(217, 164, 65, .6);
    color: inherit;
}
.mn-offer-thumb {
    width: 74px;
    height: 74px;
    border-radius: 16px;
    overflow: hidden;
    background: var(--mn-raised);
    flex: 0 0 auto;
}
.mn-offer-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mn-offer-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.mn-offer-name {
    font-size: calc(17px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
/* The drawn row's second line is a price beside a struck-through one, in the
   numeric face. It carries the promotion's sub-headline instead, and keeps the
   face: a sub-headline is very often a time or a number of days. */
.mn-offer-note {
    font-family: var(--mn-grotesk);
    font-size: calc(14px * var(--mn-scale, 1));
    color: var(--mn-off);
}
.mn-offer-chip {
    padding: 6px 11px;
    border-radius: 999px;
    background: var(--mn-gold-wash);
    color: var(--mn-gold-soft);
    font-size: calc(12.5px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    flex: 0 0 auto;
}

/* "More offers" is a REAL link to ?page=2. jadtags-promo.js turns it into an
   append; with the script blocked it is still a working second page. Never
   infinite scroll — it throws away the scroll position on back-navigation,
   which on a phone is the most common thing anybody does after opening an
   offer.

   It wears .mn-ghost and has no class of its own. A paginate link is a
   secondary action, which is one of the exactly two action shapes EXTENDING.md
   names, and a third button height standing beside the CTA's 58 and the
   ghost's 52 is a seam of precisely the kind this work exists to close. The
   search page's "more results" link is the same element for the same reason. */

@media (prefers-reduced-motion: reduce) {
    .mn-offer { transition: none; }
    a.mn-offer:hover { transform: none; }
}

/* ------------------------------------------------------------- WALL page */

/* screen_wall.html sets its container to gap:18px where the cart and the
   offers pages are 20px. Same page shell, one number different. */
.mn-page-wall { gap: 18px; }

/*
    .mn-head is the SAME rule under a name that is not the wall's.

    Every screen in this theme opens 28/900 with a 15px --mn-muted-2 line under
    it at gap 6, and the wall is simply where it was written down first. The
    club form, the code page, the preference centre, the unsubscribe page and a
    content page all open exactly like this -- so they share the declaration
    rather than repeating six of them, and they do not have to call themselves
    the wall to get it.
*/
.mn-wall-head, .mn-head { display: flex; flex-direction: column; gap: 6px; }
.mn-wall-head h1, .mn-head h1 {
    margin: 0;
    font-size: calc(28px * var(--mn-scale, 1));
    font-weight: calc(900 + var(--mn-weight-bump));
    color: var(--mn-ink);
    letter-spacing: -.015em;
}
/* .mn-head-sub is that same line standing ALONE. The search page's "results
   for X" sits under a .mn-page-head rather than inside a .mn-head, and it must
   not borrow a class named after the offers screen to get its 15px. */
.mn-wall-head p, .mn-head p, .mn-head-sub { margin: 0; font-size: calc(15px * var(--mn-scale, 1)); color: var(--mn-muted-2); }
.mn-head p, .mn-head-sub { line-height: 1.6; }

.mn-upload {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 16px 18px;
    border-radius: 20px;
    background: linear-gradient(100deg, rgba(217, 164, 65, .16), rgba(217, 164, 65, .04));
    border: 1px dashed var(--mn-gold-line);
    color: var(--mn-ink);
}
a.mn-upload:hover { border-color: rgba(217, 164, 65, .8); color: var(--mn-ink); }
.mn-upload-ring {
    width: 44px;
    height: 44px;
    border-radius: 14px;
    background: rgba(217, 164, 65, .16);
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    color: var(--mn-gold-soft);
}
.mn-upload-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mn-upload-text b { font-size: calc(16px * var(--mn-scale, 1)); font-weight: calc(800 + var(--mn-weight-bump)); }
.mn-upload-text span { font-size: calc(13.5px * var(--mn-scale, 1)); color: var(--mn-muted); }

.mn-mosaic { columns: 2; column-gap: 11px; }
.mn-mosaic figure,
.mn-mosaic-cell {
    break-inside: avoid;
    margin: 0 0 11px;
    border-radius: 16px;
    overflow: hidden;
    background: var(--mn-photo);
}
.mn-mosaic img { width: 100%; display: block; }

/*
    A cell is a <button>, so it inherits a button's UA styling and has to be
    told it is a block of image. Reset padding and border, keep the focus ring:
    the lightbox is reachable by keyboard precisely because the thing that
    opens it is a control, and a control with no visible focus is one nobody
    can find.
*/
.mn-mosaic-cell {
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    position: relative;
    cursor: zoom-in;
    color: inherit;
    font: inherit;
    text-align: start;
}
.mn-mosaic-cell:focus-visible {
    outline: 2px solid var(--mn-gold);
    outline-offset: 2px;
}

/* The credit sits ON the photograph, over a gradient rather than a flat bar:
   a name has to stay readable over a bright sky and a dark table alike. */
.mn-mosaic-credit {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    padding: 22px 12px 9px;
    font: 500 calc(12px * var(--mn-scale)) / 1.3 var(--mn-sans);
    color: var(--mn-ink);
    background: linear-gradient(to top, rgba(5, 9, 12, .78), rgba(5, 9, 12, 0));
    text-shadow: 0 1px 2px rgba(0, 0, 0, .5);
}

/* ------------------------------------------------------- WALL pager + box */

.mn-pager {
    display: flex;
    justify-content: space-between;
    gap: 10px;
    margin-top: 4px;
}
.mn-pager-link {
    flex: 1;
    padding: 11px 14px;
    border-radius: 13px;
    border: 1px solid var(--mn-line);
    background: var(--mn-card);
    color: var(--mn-ink-2);
    text-align: center;
    text-decoration: none;
    font: 600 calc(13px * var(--mn-scale)) / 1 var(--mn-sans);
}
.mn-pager-link:hover { border-color: var(--mn-gold-line); color: var(--mn-ink); }

/*
    The lightbox is a <dialog>. showModal() gives the focus trap, the Escape
    key and the inert background for free — all three hand-written are three
    more things to get wrong, and the hand-written focus trap is the one people
    get wrong.
*/
.mn-lightbox {
    width: min(96vw, 900px);
    max-height: 92vh;
    padding: 0;
    border: 0;
    border-radius: 18px;
    background: var(--mn-raised);
    color: var(--mn-ink);
    overflow: hidden;
}
.mn-lightbox::backdrop { background: rgba(5, 9, 12, .86); }
.mn-lightbox img {
    display: block;
    width: 100%;
    max-height: 78vh;
    object-fit: contain;
    background: var(--mn-photo);
}
.mn-lightbox-credit {
    margin: 0;
    padding: 11px 14px;
    font: 500 calc(13px * var(--mn-scale)) / 1.4 var(--mn-sans);
    color: var(--mn-muted);
}
.mn-lightbox-credit:empty { display: none; }
.mn-lightbox-close,
.mn-lightbox-nav {
    position: absolute;
    z-index: 2;
    width: 42px;
    height: 42px;
    display: grid;
    place-items: center;
    border: 1px solid var(--mn-glass-line);
    border-radius: 50%;
    background: rgba(5, 9, 12, .62);
    color: var(--mn-ink);
    font-size: calc(22px * var(--mn-scale));
    line-height: 1;
    cursor: pointer;
}
.mn-lightbox-close { top: 10px; inset-inline-end: 10px; }
.mn-lightbox-nav { top: 50%; transform: translateY(-50%); }
.mn-lightbox-nav.is-prev { inset-inline-start: 10px; }
.mn-lightbox-nav.is-next { inset-inline-end: 10px; }
.mn-lightbox-close:focus-visible,
.mn-lightbox-nav:focus-visible { outline: 2px solid var(--mn-gold); outline-offset: 2px; }

/* ------------------------------------------------------- WALL upload form */

/*
    The drop zone is a <label> wrapping a visually-hidden <input type=file>.
    Not a div with a click handler: a label already focuses and activates its
    input from the keyboard, already announces itself to a screen reader, and
    already opens the picker on a tap. Everything a handler would re-implement.
*/
.mn-drop {
    display: grid;
    place-items: center;
    min-height: 220px;
    padding: 18px;
    border: 1.5px dashed var(--mn-line);
    border-radius: 18px;
    background: var(--mn-raised);
    cursor: pointer;
    overflow: hidden;
    position: relative;
}
.mn-drop:hover { border-color: var(--mn-gold-line); }
.mn-drop:focus-within { outline: 2px solid var(--mn-gold); outline-offset: 2px; }
.mn-drop-face {
    display: grid;
    justify-items: center;
    gap: 7px;
    text-align: center;
    color: var(--mn-muted);
    font: 500 calc(13px * var(--mn-scale)) / 1.5 var(--mn-sans);
}
.mn-drop-face b {
    font: 700 calc(15px * var(--mn-scale)) / 1.3 var(--mn-sans);
    color: var(--mn-ink);
}
.mn-drop-preview {
    width: 100%;
    max-height: 340px;
    object-fit: contain;
    border-radius: 12px;
    display: block;
}
.mn-field-note {
    display: block;
    margin-top: 5px;
    font: 400 calc(12px * var(--mn-scale)) / 1.45 var(--mn-sans);
    color: var(--mn-muted-2);
}

/* Disabled until a file is chosen. A button that posts a form the server can
   only refuse teaches the rule by wasting somebody's time. */
.mn-cta[disabled] { opacity: .45; cursor: not-allowed; }

/* ------------------------------------------------------------ HOURS page */

/*
    The week. The designer drew no hours screen; the vocabulary is the home
    screen's fact tile turned into seven rows, on the .mn-page shell every other
    listing page uses.

    Three rules the data forces, and all three are the difference between a
    schedule somebody can act on and one they misread:

      - A CLOSED day says the word. An empty cell reads as data that failed to
        load, and somebody drives out on a Monday.
      - TODAY is marked on the row, not by reordering into a different shape.
      - A window that runs past midnight is ONE row — 23:00 – 02:00 — with the
        far end flagged as the next day. Printed as the evaluator stores it,
        two segments on two weekdays, it reads as a restaurant that closes at
        midnight and reopens at midnight.
*/

/* The live pill from screen_home.html, reused in this page's title block. It
   is a <p> there and a <p> here, and the UA's paragraph margin would push the
   title's baseline out of line with it. */
.mn-page-head .mn-live { margin: 0; }

/* The panel is shared -- see .mn-totals. This is only the week inside it. */
.mn-hours {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px;
    list-style: none;
    margin: 0;
}
.mn-hours-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 11px 12px;
    border-radius: 14px;
}
.mn-hours-row.is-today {
    background: var(--mn-card);
    border: 1px solid var(--mn-gold-line);
    /* The border would otherwise move today's row 2px taller than its
       neighbours and shunt the whole list down by a hairline. */
    margin: -1px;
}
.mn-hours-day {
    font-size: calc(16px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    color: var(--mn-ink-2);
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
}
.mn-hours-row.is-today .mn-hours-day { color: var(--mn-ink); }
.mn-hours-now {
    font-family: var(--mn-mono);
    font-size: calc(10px * var(--mn-scale, 1));
    letter-spacing: .16em;
    color: var(--mn-gold-text);
    flex: 0 0 auto;
}
/* The times, in the numeric face with tabular figures, so seven rows of clock
   times line up under each other instead of dancing by a pixel per digit. */
.mn-hours-times {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 3px;
    text-align: end;
    font-family: var(--mn-grotesk);
    font-variant-numeric: tabular-nums;
    font-size: calc(15px * var(--mn-scale, 1));
    color: var(--mn-ink);
    flex: 0 0 auto;
}
.mn-hours-times.is-shut { color: var(--mn-off); font-family: var(--mn-sans); }
.mn-hours-band { display: block; white-space: nowrap; }
/* "next day" beside 02:00, in words rather than as a superscript asterisk
   nobody reads. Small, because the times are the answer and this is the note. */
.mn-hours-next {
    font-family: var(--mn-sans);
    font-size: calc(11.5px * var(--mn-scale, 1));
    color: var(--mn-muted-2);
    margin-inline-start: 6px;
}

/* Zero assignments means always open, and that is a sentence rather than seven
   rows of 00:00 – 24:00. */
.mn-hours-always {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 18px;
    border-radius: 20px;
    background: var(--mn-gold-wash);
    border: 1px dashed var(--mn-gold-line);
    color: var(--mn-ink-2);
    font-size: calc(15px * var(--mn-scale, 1));
    line-height: 1.6;
}
.mn-hours-always svg { flex: 0 0 auto; color: var(--mn-gold-text); }

/* The timezone, under the table. It is a footnote and it matters: a menu is
   read from another country more often than anybody expects. */
.mn-hours-zone {
    margin: 0;
    text-align: center;
    font-family: var(--mn-mono);
    font-size: calc(10.5px * var(--mn-scale, 1));
    letter-spacing: .12em;
    color: var(--mn-footnote);
}

/* --------------------------------------------------------------- TAB BAR */

.mn-tabs {
    flex: 0 0 auto;
    /*
        Content-box, spelled out, and it is load-bearing.

        The design draws height:78px WITH padding:6px 8px 14px on a
        content-box element, so the bar renders 98px tall. On the seven pages
        this theme does not draw, the layout also links Bootstrap and
        jadtags.css, and both carry a universal `box-sizing: border-box` — a
        zero-specificity rule that wins over any declaration this file does not
        make. Without this line the bar is 78px on the checkout and 98px on the
        menu: the same theme, two heights, depending on which page you came
        from.
    */
    box-sizing: content-box;
    height: 78px;
    padding: 6px 8px 14px;
    display: flex;
    align-items: center;
    background: color-mix(in srgb, var(--mn-bg) 92%, transparent);
    backdrop-filter: blur(18px);
    border-top: 1px solid var(--mn-hairline);
    position: sticky;
    bottom: 0;
    z-index: 6;
    /* The home indicator on a modern phone sits over the last 14px of this
       bar. Without the safe-area inset the cart tab is under it. */
    padding-bottom: max(14px, env(safe-area-inset-bottom));
}
.mn-tab {
    flex: 1;
    min-width: 0;
    height: 56px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    cursor: pointer;
    color: var(--mn-off);
    position: relative;
}
.mn-tab span {
    font-size: calc(11.5px * var(--mn-scale, 1));
    font-weight: calc(600 + var(--mn-weight-bump));
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.mn-tab:hover { color: var(--mn-muted); }
.mn-tab.is-active { color: var(--mn-gold-text); }
.mn-tab-badge {
    position: absolute;
    top: 2px;
    inset-inline-end: 20px;
    min-width: 19px;
    height: 19px;
    padding-inline: 5px;
    border-radius: 999px;
    background: var(--mn-gold);
    color: var(--mn-gold-ink);
    font-family: var(--mn-grotesk);
    font-size: calc(11.5px * var(--mn-scale, 1));
    font-weight: calc(700 + var(--mn-weight-bump));
    display: grid;
    place-items: center;
    /* Content-box, deliberately and explicitly. screen_tab_bar.html draws
       min-width:19px with padding:0 5px, which for one digit is a 29x19 PILL;
       border-box folds the padding into the 19 and renders a circle. Spelled
       out rather than left to the default, because the pages this theme does
       not draw arrive with Bootstrap's universal border-box reset. */
    box-sizing: content-box;
}

/* --------------------------------------------------- overlay: the sheet */

/*
    <dialog>, not a div with a z-index. The browser gives us the focus trap,
    the Escape key, the top layer and the return of focus to wherever it was —
    four things every hand-built overlay eventually loses one of, and losing
    any of them leaves a keyboard user stuck behind a sheet.

    The popup's own panel is not here: it is the shipped x-menu.promo-popup
    component, styled by midnight-promo.css, drawn from the same design file.
*/
.mn-scrim {
    position: fixed;
    inset: 0;
    z-index: 22;
    background: rgba(3, 8, 12, .7);
    backdrop-filter: blur(6px);
    display: flex;
    animation: mIn .25s ease-out both;
    border: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
}
.mn-scrim:not([open]) { display: none; }
.mn-scrim::backdrop { background: transparent; }

/* The sheet rises from the bottom edge, so the scrim aligns to the end
   rather than the centre. */
.mn-scrim.is-sheet { align-items: flex-end; }
.mn-sheet {
    width: 100%;
    padding: 20px 20px 26px;
    padding-bottom: max(26px, env(safe-area-inset-bottom));
    border-radius: 28px 28px 0 0;
    background: var(--mn-card);
    border-top: 1px solid rgba(255, 255, 255, .09);
    display: flex;
    flex-direction: column;
    gap: 14px;
    animation: mSheet .4s cubic-bezier(.2, .7, .2, 1) both;
    box-sizing: border-box;
    max-width: 480px;
    margin-inline: auto;
}
.mn-sheet-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.mn-sheet-head h2 {
    margin: 0;
    font-size: calc(19px * var(--mn-scale, 1));
    font-weight: calc(800 + var(--mn-weight-bump));
    color: var(--mn-ink);
}
.mn-sheet-close {
    width: 36px;
    height: 36px;
    border: 0;
    border-radius: 999px;
    background: var(--mn-bg);
    display: grid;
    place-items: center;
    cursor: pointer;
    color: var(--mn-muted);
    flex: 0 0 auto;
}
.mn-sheet-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}
.mn-a11y {
    height: 52px;
    border-radius: 14px;
    background: var(--mn-bg);
    border: 1px solid var(--mn-hairline);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-size: calc(15px * var(--mn-scale, 1));
    font-weight: calc(600 + var(--mn-weight-bump));
    color: var(--mn-ink);
    cursor: pointer;
    padding-inline: 10px;
    text-align: center;
}
.mn-a11y:hover { border-color: rgba(217, 164, 65, .5); }
/* An on/off setting says which it is. The design draws the buttons only, but
   a toggle that never looks pressed is a toggle nobody believes they pressed. */
.mn-a11y[aria-pressed="true"] {
    background: var(--mn-gold-wash);
    border-color: rgba(217, 164, 65, .4);
    color: var(--mn-gold-soft);
    font-weight: calc(700 + var(--mn-weight-bump));
}
.mn-a11y.is-reset {
    background: var(--mn-gold-wash);
    border-color: rgba(217, 164, 65, .4);
    color: var(--mn-gold-soft);
    font-weight: calc(700 + var(--mn-weight-bump));
}

/* -------------------------------------------- accessibility root settings */

/* Bold text. Applied to the elements the design already weights, so the
   setting deepens the type rather than flattening the hierarchy. */
:root[data-mn-bold="on"] { --mn-weight-bump: 100; }
:root[data-mn-bold="on"] body { font-weight: 500; }

/* Highlighted links. Every real link and every control that navigates, so a
   person who cannot pick a gold word out of grey text can see where the
   targets are. */
:root[data-mn-links="on"] a:not(.mn-tab):not(.mn-cta),
:root[data-mn-links="on"] .mn-tab span {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 3px;
    background: var(--mn-gold-wash);
    box-shadow: 0 0 0 2px var(--mn-gold-wash);
    border-radius: 3px;
}

/* -------------------------------------------------------- the table bar */

/*
    "Ordering for table A3", above every page while a scan is live.

    Styled under the SHIPPED component's class and not an mn- one of its own.
    The layout renders <x-menu.table-bar />, whose markup this work may not
    touch, and it emits .jt-table-bar — so a .mn-table-bar block here would be
    seventy lines matching nothing while the bar rendered as unstyled inline
    text. The rule is the theme's; the name belongs to the component.
*/
.jt-table-bar {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 18px;
    /* Overrides jadtags.css, which is loaded before this file on the pages the
       theme does not draw and gives the bar a rounded card and a 1rem gap. */
    margin: 0;
    border: 0;
    border-radius: 0;
    background: var(--mn-raised);
    border-bottom: 1px solid var(--mn-hairline);
    font-size: calc(13.5px * var(--mn-scale, 1));
    color: var(--mn-ink-2);
}
.jt-table-bar svg { flex: 0 0 auto; color: var(--mn-gold-text); }
.jt-table-bar form { margin: 0; margin-inline-start: auto; }
.jt-table-bar button {
    border: 0;
    background: none;
    padding: 0;
    color: var(--mn-gold-text);
    font-family: inherit;
    font-size: calc(13.5px * var(--mn-scale, 1));
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* The preview bar. Above the tab bar and out of the way of everything the
   design draws: a preview must look like the theme, not like the theme plus a
   banner somebody has to mentally subtract. */
.mn-preview-bar {
    position: fixed;
    inset-inline: 0;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 64px);
    z-index: 40;
    margin: 0 auto;
    inline-size: fit-content;
    max-inline-size: calc(100% - 24px);
    padding: 7px 14px;
    border-radius: 999px;
    background: var(--mn-gold);
    color: var(--mn-gold-ink);
    font: 600 calc(12px * var(--mn-scale)) / 1.3 var(--mn-sans);
    text-align: center;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .25);
}
