/* pub/Components/Design/DesignAreaHead.razor.rz.scp.css */
/* Ported from the prototype's base.css `.area-head` block. Values are token references only — no
   literal colours, sizes or spacings live here (design system §1). */

.area-head[b-srp7bqw9mm] {
    margin-bottom: var(--gap-after-head, 36px);
}

.area-head .t-eyebrow[b-srp7bqw9mm] {
    display: block;
    margin-bottom: var(--gap-eyebrow, 8px);
    font-size: var(--t-cap, .8rem);
    font-weight: 800;
    letter-spacing: var(--track-eyebrow, .22em);
    text-transform: uppercase;
    color: var(--eyebrow, #0E7C7C);
    line-height: var(--lh-heading, 1.15);
}

.area-head-sep[b-srp7bqw9mm] {
    margin-inline: var(--sp-1, 4px);
}

/* The change affordance reads as a link but behaves as the button it is. */
.area-head-change[b-srp7bqw9mm] {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    min-height: var(--touch, 44px);
    font: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    color: var(--accent-fg);
    text-decoration: underline;
    cursor: pointer;
}

.area-head-change:hover[b-srp7bqw9mm] {
    text-decoration: none;
}

.area-head .t-page-title[b-srp7bqw9mm] {
    margin: 0;
    font-size: var(--t-32, 2rem);
    font-weight: 900;
    letter-spacing: var(--track-h1, -.01em);
    line-height: var(--lh-heading, 1.15);
    color: var(--ink-1, #16212C);
}

.area-head .t-display[b-srp7bqw9mm] {
    margin: 0;
    font-size: var(--t-display, clamp(2rem, 6vw, 3.4rem));
    font-weight: 900;
    letter-spacing: var(--track-display, -.02em);
    line-height: var(--lh-display, 1.05);
    color: var(--ink-1, #16212C);
}

.area-head .lede[b-srp7bqw9mm] {
    margin: var(--gap-lede, 12px) 0 0;
    font-size: var(--t-16, 1rem);
    line-height: var(--lh-body, 1.5);
    color: var(--ink-2, #43566A);
    max-width: 56ch;
}
/* pub/Components/Design/DesignButton.razor.rz.scp.css */
/* Ported from the prototype's components.css `.btn` block. One height per row context; the hierarchy
   is carried by exactly one modifier class. */

.btn[b-ndr070a24l] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-icon-text, 8px);
    height: var(--btn-h, 44px);
    padding-inline: var(--sp-5, 24px);
    border: 0;
    border-radius: var(--radius-pill, 999px);
    font-family: inherit;
    font-size: var(--t-16, 1rem);
    font-weight: 700;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: transform var(--dur-fast, 140ms) var(--ease, ease),
                box-shadow var(--dur-fast, 140ms) var(--ease, ease),
                background var(--dur-fast, 140ms) var(--ease, ease);
}

.btn:active[b-ndr070a24l] {
    transform: translateY(1px);
}

.btn-primary[b-ndr070a24l] {
    background: var(--accent-strong, #1F6E9C);
    color: var(--accent-on-strong, #FFFFFF);
    box-shadow: var(--elev-1);
}

.btn-primary:hover[b-ndr070a24l] {
    box-shadow: var(--elev-2);
}

.btn-secondary[b-ndr070a24l] {
    background: var(--surface, #FFFFFF);
    color: var(--accent-fg);
    border: 1px solid var(--hairline-strong, rgba(22, 33, 44, .18));
}

.btn-secondary:hover[b-ndr070a24l] {
    background: var(--surface-2, #F3F7FA);
}

.btn-tertiary[b-ndr070a24l] {
    background: transparent;
    color: var(--accent-fg);
    padding-inline: var(--sp-3, 12px);
}

.btn-tertiary:hover[b-ndr070a24l] {
    background: var(--accent-soft, #E3F0F8);
}

.btn-sm[b-ndr070a24l] {
    height: var(--btn-h-sm, 36px);
    padding-inline: var(--sp-4, 16px);
    font-size: var(--t-14, .875rem);
}

.btn[disabled][b-ndr070a24l] {
    opacity: .48;
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}
/* pub/Components/Design/DesignCard.razor.rz.scp.css */
/* Ported from the prototype's components.css `.card` block plus base.css `.spread`. Token references
   only — no literal colours or spacings (design system §1). */

.card[b-piai096n0w] {
    background: var(--surface, #FFFFFF);
    border: 1px solid var(--hairline, rgba(22, 33, 44, .10));
    border-radius: var(--radius, 12px);
    box-shadow: var(--elev-1);
    padding: var(--sp-5, 24px);
}

.card--flat[b-piai096n0w] {
    box-shadow: none;
}

.spread[b-piai096n0w] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-related, 12px);
}

/* A spread card holds a content column against an action cluster; on a phone the two would each be
   squeezed below their comfortable width, so the row unwinds into a stack instead of scrolling. */
@media (max-width: 519px) {
    .spread[b-piai096n0w] {
        flex-direction: column;
        align-items: stretch;
    }
}
/* pub/Components/Design/DesignChip.razor.rz.scp.css */
/* Ported from the prototype's components.css `.chip` block. A selectable chip keeps a 36px minimum so
   it still clears the one-handed touch floor in a wrapped row. */

.chip[b-6oafagdk0x] {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1, 4px);
    min-height: 32px;
    padding-inline: var(--sp-3, 12px);
    border-radius: var(--radius-pill, 999px);
    font-family: inherit;
    font-size: var(--t-14, .875rem);
    font-weight: 700;
    line-height: 1;
    border: 1px solid var(--hairline-strong, rgba(22, 33, 44, .18));
    background: var(--surface, #FFFFFF);
    color: var(--ink-2, #43566A);
}

/* The two meaning-bearing tones. Their colours are tokens because they flip wholesale between the
   light and dark ramps — a literal here would be unreadable in one of the two themes. */
.chip-include[b-6oafagdk0x] {
    background: var(--chip-include-bg);
    color: var(--chip-include-fg);
    border-color: var(--chip-include-line);
}

.chip-exclude[b-6oafagdk0x] {
    background: var(--chip-exclude-bg);
    color: var(--chip-exclude-fg);
    border-color: var(--chip-exclude-line);
}

.chip-select[b-6oafagdk0x] {
    cursor: pointer;
    user-select: none;
    min-height: 36px;
}

.chip-select.is-on[b-6oafagdk0x] {
    background: var(--accent-soft, #E3F0F8);
    color: var(--accent-fg);
    border-color: var(--accent-fg);
}

.chip-select:focus-visible[b-6oafagdk0x] {
    outline: 2px solid var(--accent-fg);
    outline-offset: 2px;
}
/* pub/Components/Design/DesignComingSoon.razor.rz.scp.css */
/* Ported from the prototype's components.css `.scrim`/`.dialog` block (assets/js/ui.js's dialog()) — the
   SAME treatment DesignKeepMenuPrompt already carries. Every colour is a token, so light/dark both come
   free — no separate dark-mode block needed. */

.scrim[b-2v8jg7uec5] {
    position: fixed;
    inset: 0;
    z-index: 1700;
    display: grid;
    place-items: center;
    padding: var(--sp-5, 24px);
    background: var(--scrim, rgba(22, 33, 44, .45));
}

.dialog[b-2v8jg7uec5] {
    width: min(420px, 100%);
    background: var(--surface, #FFFFFF);
    color: var(--ink-1, #16212C);
    border-radius: var(--radius, 12px);
    box-shadow: var(--elev-4, 0 10px 20px rgba(22, 33, 44, .12), 0 24px 48px -12px rgba(22, 33, 44, .30));
    padding: var(--sp-modal-pad, 24px);
    display: grid;
    gap: var(--sp-4, 16px);
}

.dialog-title[b-2v8jg7uec5] {
    font-size: var(--t-20, 1.25rem);
    font-weight: 800;
}

.dialog .t-body-2[b-2v8jg7uec5] {
    font-size: var(--t-16, 1rem);
    line-height: var(--lh-body, 1.5);
    color: var(--ink-2, #43566A);
}

.dialog-actions[b-2v8jg7uec5] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3, 12px);
    justify-content: flex-end;
}
/* pub/Components/Design/DesignEmptyState.razor.rz.scp.css */
/* Ported from the prototype's components.css `.empty` block. */

.empty[b-3kyjsu9su3] {
    display: grid;
    place-items: center;
    gap: var(--sp-3, 12px);
    text-align: center;
    padding: var(--sp-9, 64px) var(--sp-5, 24px);
    border: 1.5px dashed var(--hairline-strong, rgba(22, 33, 44, .18));
    border-radius: var(--radius, 12px);
    color: var(--ink-3, #5E7183);
}

/* The glyph is DesignIcon's element, so the size override has to cross the scope boundary. */
.empty[b-3kyjsu9su3]  .empty-icon {
    width: 34px;
    height: 34px;
}

.empty .empty-title[b-3kyjsu9su3] {
    font-weight: 800;
    color: var(--ink-2, #43566A);
    font-size: var(--t-16, 1rem);
}

.empty .t-compact[b-3kyjsu9su3] {
    max-width: 40ch;
    font-size: var(--t-14, .875rem);
    line-height: var(--lh-compact, 1.35);
    color: var(--ink-2, #43566A);
}
/* pub/Components/Design/DesignFavoriteRail.razor.rz.scp.css */
/* The prototype's `.rail` (base.css) with a compact `.dish-card`. The rail rules are the same ones
   DishWall carries — scoped CSS gives each component its own copy rather than a shared global that would
   reach into every ym-era screen still on the old vocabulary.

   One departure: the prototype's rail bleeds to the page gutter (a negative `--gutter` margin). This app's
   column is `.patron-shell`, whose padding is 1rem — NARROWER than `--gutter` (20/32/48px), so the bleed
   overhangs the viewport and puts a horizontal scrollbar on the whole page. The rail scrolls inside the
   column instead; measured at 375/768/1280, the cards still align with the content above them. */

.rail[b-afmk54u23v] {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: min(72vw, 260px);
    gap: var(--sp-card-gap, 16px);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    padding-bottom: var(--sp-2, 8px);
    scrollbar-width: thin;
}

.fav-card[b-afmk54u23v] {
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    text-decoration: none;
    border-radius: var(--radius, 12px);
    overflow: hidden;
    background: var(--surface, #FFFFFF);
    border: 1px solid var(--hairline, rgba(22, 33, 44, .10));
    box-shadow: var(--elev-1);
    transition: transform var(--dur, 220ms) var(--ease, ease), box-shadow var(--dur, 220ms) var(--ease, ease);
}

.fav-card:hover[b-afmk54u23v] {
    transform: translateY(-2px);
    box-shadow: var(--elev-3);
}

.fav-card:focus-visible[b-afmk54u23v] {
    outline: 2px solid var(--accent-fg);
    outline-offset: 2px;
}

.fav-card.is-sold-out[b-afmk54u23v] {
    opacity: .6;
}

.fav-card .dish-img[b-afmk54u23v] {
    width: 100%;
    aspect-ratio: 16 / 10;
    object-fit: cover;
    display: block;
}

.fav-card .dish-top[b-afmk54u23v] {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-2, 8px);
}

.fav-body[b-afmk54u23v] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1, 4px);
    flex: 1;
    padding: var(--sp-4, 16px);
}

.t-dish-name[b-afmk54u23v] {
    font-size: var(--t-20, 1.25rem);
    font-weight: 800;
    line-height: var(--lh-heading, 1.15);
    color: var(--ink-1, #16212C);
}

.fav-meta[b-afmk54u23v] {
    display: flex;
    align-items: center;
    gap: var(--sp-icon-text, 6px);
    margin-top: auto;
    padding-top: var(--sp-2, 8px);
    font-size: var(--t-14, .875rem);
    color: var(--ink-3, #5E7183);
}

.fav-meta[b-afmk54u23v]  .fav-star {
    width: 16px;
    height: 16px;
}

@media (min-width: 1280px) {
    .rail[b-afmk54u23v] {
        grid-auto-columns: 350px;
        gap: var(--sp-6, 24px);
    }
}
/* pub/Components/Design/DesignHelpDot.razor.rz.scp.css */
/* Ported from the prototype's components.css `.help-dot` / `.help-pop` blocks. Token references only. */

.help-dot[b-lj6ls0oyp9] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    flex: none;
    margin-inline-start: var(--sp-1, 4px);
    border: 1.5px solid var(--ink-3, #5E7183);
    border-radius: 50%;
    background: transparent;
    color: var(--ink-3, #5E7183);
    font-size: var(--t-cap, .8rem);
    font-weight: 800;
    line-height: 1;
    vertical-align: middle;
    cursor: pointer;
}

.help-dot:hover[b-lj6ls0oyp9], .help-dot[aria-expanded="true"][b-lj6ls0oyp9] {
    border-color: var(--accent-fg);
    color: var(--accent-fg);
}

.help-pop[b-lj6ls0oyp9] {
    display: block;
    margin-top: var(--sp-2, 8px);
    max-width: 300px;
    padding: var(--sp-3, 12px);
    border: 1px solid var(--hairline, rgba(22, 33, 44, .10));
    border-radius: var(--radius, 12px);
    background: var(--surface, #FFFFFF);
    box-shadow: var(--elev-2);
    font-size: var(--t-14, .875rem);
    line-height: var(--lh-body, 1.5);
    color: var(--ink-2, #43566A);
}
/* pub/Components/Design/DesignIcon.razor.rz.scp.css */
/* Ported verbatim from the prototype's components.css `.icon` block — without the stroke/fill pair a
   24×24 line path renders as a filled silhouette. */

.icon[b-ef5cb4pewa] {
    width: 20px;
    height: 20px;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
    flex: none;
}
/* pub/Components/Design/DesignKeepMenuPrompt.razor.rz.scp.css */
/* Ported from the prototype's components.css `.scrim`/`.dialog` block (assets/js/ui.js's dialog()). Every
   colour is a token, so light/dark both come free — no separate dark-mode block needed. */

.scrim[b-e7vcqg8kux] {
    position: fixed;
    inset: 0;
    z-index: 1700;
    display: grid;
    place-items: center;
    padding: var(--sp-5, 24px);
    background: var(--scrim, rgba(22, 33, 44, .45));
}

.dialog[b-e7vcqg8kux] {
    width: min(420px, 100%);
    background: var(--surface, #FFFFFF);
    color: var(--ink-1, #16212C);
    border-radius: var(--radius, 12px);
    box-shadow: var(--elev-4, 0 10px 20px rgba(22, 33, 44, .12), 0 24px 48px -12px rgba(22, 33, 44, .30));
    padding: var(--sp-modal-pad, 24px);
    display: grid;
    gap: var(--sp-4, 16px);
}

.dialog-title[b-e7vcqg8kux] {
    font-size: var(--t-20, 1.25rem);
    font-weight: 800;
}

.dialog .t-body-2[b-e7vcqg8kux] {
    font-size: var(--t-16, 1rem);
    line-height: var(--lh-body, 1.5);
    color: var(--ink-2, #43566A);
}

.dialog .keep-menu-result[b-e7vcqg8kux] {
    color: var(--ink-1, #16212C);
}

.keep-menu-email-field[b-e7vcqg8kux] {
    display: grid;
    gap: var(--sp-label-control, 8px);
}

.keep-menu-email-field .input[b-e7vcqg8kux] {
    min-height: 44px;
    padding: 0 var(--sp-4, 16px);
    border-radius: var(--radius-sm, 8px);
    border: 1px solid var(--hairline-strong, rgba(22, 33, 44, .18));
    background: var(--surface, #FFFFFF);
    color: var(--ink-1, #16212C);
    font: inherit;
}

.keep-menu-error[b-e7vcqg8kux] {
    color: var(--error, #B91C1C);
    margin: 0;
}

.dialog-actions[b-e7vcqg8kux] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3, 12px);
    justify-content: flex-end;
}
/* pub/Components/Design/DesignLinkRow.razor.rz.scp.css */
/* The prototype's `.card.spread` used as a list row. `.card` belongs to DesignCard's scope, so the
   positioning context the stretched link needs has to cross the boundary with ::deep. */

.linkrow[b-05xl6ltich]  .linkrow-card {
    position: relative;
}

.linkrow-logo[b-05xl6ltich] {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-sm, 10px);
    flex: none;
    object-fit: cover;
}

.linkrow-main[b-05xl6ltich] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.linkrow-link[b-05xl6ltich] {
    font-size: var(--t-16, 1rem);
    font-weight: 700;
    line-height: var(--lh-heading, 1.15);
    color: var(--ink-1, #16212C);
    text-decoration: none;
}

/* The whole card is the target — the overlay, not a wrapping anchor, so the row's own controls stay
   real buttons. */
.linkrow-link[b-05xl6ltich]::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--radius, 12px);
}

.linkrow-link:focus-visible[b-05xl6ltich] {
    outline: 2px solid var(--accent-fg);
    outline-offset: 2px;
    border-radius: var(--radius-sm, 8px);
}

.linkrow-meta[b-05xl6ltich] {
    font-size: var(--t-14, .875rem);
    line-height: var(--lh-compact, 1.35);
    color: var(--ink-3, #5E7183);
}

/* Above the overlay, or the row's controls would be un-tappable. */
.linkrow-end[b-05xl6ltich] {
    position: relative;
    z-index: 1;
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--sp-3, 12px);
    color: var(--ink-3, #5E7183);
}

/* The stacked phone layout (DesignCard's `.spread` unwinds below 520px) would leave the chevron
   floating under the title — it only means "onward" beside the row. */
@media (max-width: 519px) {
    .linkrow-end[b-05xl6ltich] {
        justify-content: flex-end;
    }
}
/* pub/Components/Design/DesignMoodCard.razor.rz.scp.css */
/* The prototype's moods row: a `.card.spread` whose content column may shrink but never squeezes the
   action cluster. `.card` itself belongs to DesignCard's scope, so the open-state accent has to cross
   the boundary with ::deep. */

.mood-card[b-ksvmdfj7uz]  .card.is-open {
    border-color: var(--accent-fg);
    box-shadow: var(--elev-2);
}

.mood-main[b-ksvmdfj7uz] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2, 8px);
    min-width: 0;
}

.t-card-title[b-ksvmdfj7uz] {
    font-size: var(--t-20, 1.25rem);
    font-weight: 800;
    line-height: var(--lh-heading, 1.15);
    color: var(--ink-1, #16212C);
}

/* The name is a control, so it carries the button reset and the touch floor — it still has to READ as
   the card's title. */
.mood-open[b-ksvmdfj7uz] {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    min-height: var(--touch, 44px);
    font-family: inherit;
    text-align: start;
    cursor: pointer;
}

.mood-open:focus-visible[b-ksvmdfj7uz] {
    outline: 2px solid var(--accent-fg);
    outline-offset: 2px;
    border-radius: var(--radius-sm, 8px);
}

.t-meta[b-ksvmdfj7uz] {
    font-size: var(--t-14, .875rem);
    line-height: var(--lh-compact, 1.35);
    color: var(--ink-3, #5E7183);
}

.mood-actions[b-ksvmdfj7uz] {
    display: flex;
    flex: none;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-2, 8px);
}
/* pub/Components/Design/DesignOrderLines.razor.rz.scp.css */
/* The order sheet's rhythm, from the prototype's `.area-section` / `.stack`. The line card, its inner
   layout and the chip row are rendered by child components, so they are reached with ::deep — a plain
   selector here only ever matches the elements this component writes itself. */

.order-lines[b-ha1uj8sq0n] {
    margin-top: var(--sp-section, 36px);
}

.order-lines[b-ha1uj8sq0n]  .stack {
    display: flex;
    flex-direction: column;
    gap: var(--sp-related, 12px);
}

/* The prototype tightens the line card: it is a row in a list, not a region of its own. */
.order-lines[b-ha1uj8sq0n]  .order-line {
    padding: var(--sp-3, 12px) var(--sp-4, 16px);
    align-items: flex-start;
}

.order-lines[b-ha1uj8sq0n]  .order-line-main {
    min-width: 0;
}

.order-lines[b-ha1uj8sq0n]  .order-line-name {
    font-size: var(--t-16, 1rem);
    font-weight: 700;
    color: var(--ink-1);
}

.order-lines[b-ha1uj8sq0n]  .order-line-mods {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-1, 4px);
    margin-top: var(--sp-1, 4px);
}

.order-lines[b-ha1uj8sq0n]  .order-line-mod {
    min-height: 24px;
    font-size: var(--t-cap, .75rem);
}

.order-lines[b-ha1uj8sq0n]  .t-price {
    font-size: var(--t-16, 1rem);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--ink-1);
    white-space: nowrap;
}
/* pub/Components/Design/DesignRestRailHead.razor.rz.scp.css */
/* Ported from the prototype's components.css `.rest-rail-head`. Token references only. */

.rest-rail-head[b-6idegzfuuw] {
    display: flex;
    align-items: center;
    gap: var(--sp-3, 12px);
    margin-bottom: var(--gap-caps-head, var(--sp-3, 12px));
}

.rest-rail-head img[b-6idegzfuuw] {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-sm, 10px);
    flex: none;
    object-fit: cover;
}

.rest-rail-head .who[b-6idegzfuuw] {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.rest-rail-head .who .name[b-6idegzfuuw] {
    font-weight: 800;
    font-size: var(--t-16, 1rem);
    color: var(--ink-1, #16212C);
}

.rest-rail-head .who .meta[b-6idegzfuuw] {
    font-size: var(--t-14, .875rem);
    color: var(--ink-3, #5E7183);
}

.rest-rail-actions[b-6idegzfuuw] {
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--sp-2, 8px);
}

/* Desktop: the actions sit NEXT TO the name rather than at the far edge of a wide column — the
   prototype's own note (#6), and the reason the who column stops growing here. */
@media (min-width: 768px) {
    .rest-rail-head .who[b-6idegzfuuw] {
        flex: 0 1 auto;
    }

    .rest-rail-head[b-6idegzfuuw]::after {
        content: "";
        flex: 1;
    }
}
/* pub/Components/Design/DesignSaveBar.razor.rz.scp.css */
/* Ported from the prototype's components.css `.save-bar` block. Token references only — no literal
   colours or spacings (design system §1). */

.save-bar[b-qtflmtmmnp] {
    display: flex;
    align-items: center;
    gap: var(--sp-4, 16px);
    padding: var(--sp-3, 12px) var(--sp-4, 16px);
    background: var(--surface, #FFFFFF);
    border: 1px solid var(--hairline, rgba(22, 33, 44, .10));
    border-radius: var(--radius, 12px);
    box-shadow: var(--elev-1);
    position: sticky;
    z-index: var(--z-rail, 30);
}

/* The top mount clears the app bar it sticks under. The bottom mount sticks to the foot of the viewport:
   this app has no bottom nav bar to clear, so the prototype's --bottomnav-h offset is deliberately dropped
   rather than carried across as a token that resolves to nothing here. */
.save-bar.at-top[b-qtflmtmmnp] {
    top: calc(var(--appbar-h, 56px) + var(--sp-2, 8px));
    margin-bottom: var(--sp-4, 16px);
}

.save-bar.at-bottom[b-qtflmtmmnp] {
    bottom: var(--sp-2, 8px);
    margin-top: var(--sp-6, 32px);
}

.save-bar .last-saved[b-qtflmtmmnp] {
    font-size: var(--t-14, .875rem);
    color: var(--ink-3);
}

/* The unsaved mark is the warning ramp, not a new colour: "you have something pending" is the same
   meaning the removable/held tone already carries elsewhere, and it tracks the theme. */
.save-bar .dirty-dot[b-qtflmtmmnp] {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--removable);
    display: none;
    flex: none;
}

.save-bar.is-dirty .dirty-dot[b-qtflmtmmnp] {
    display: block;
}

.save-bar .save-notice[b-qtflmtmmnp] {
    color: var(--unverified);
    font-size: var(--t-14, .875rem);
    font-weight: 700;
}

.save-bar .spacer[b-qtflmtmmnp] {
    flex: 1;
}

/* On a phone the stamp and the button fight for one row; the stamp wraps under rather than truncating,
   because "last saved when" is the sentence the bar exists to say. */
@media (max-width: 519px) {
    .save-bar[b-qtflmtmmnp] {
        flex-wrap: wrap;
        gap: var(--sp-2, 8px);
    }

    .save-bar .last-saved[b-qtflmtmmnp] {
        flex: 1 0 100%;
        order: -1;
    }
}
/* pub/Components/Design/DesignSectionHead.razor.rz.scp.css */
/* Ported from the prototype's base.css `.section-head` block. */

.section-head[b-aizx9c2sco] {
    display: flex;
    align-items: center;
    gap: var(--sp-icon-text, 8px);
    margin-bottom: var(--gap-caps-head, 14px);
}

.section-head .t-section[b-aizx9c2sco] {
    margin: 0;
    font-size: var(--t-14, .875rem);
    font-weight: 800;
    letter-spacing: var(--track-caps-head, .14em);
    text-transform: uppercase;
    color: var(--eyebrow, #0E7C7C);
    line-height: var(--lh-heading, 1.15);
}

.section-head .count[b-aizx9c2sco] {
    font-size: var(--t-14, .875rem);
    color: var(--ink-3, #5E7183);
    font-weight: 600;
}

.section-head .spacer[b-aizx9c2sco] {
    flex: 1;
}
/* pub/Components/Design/DesignSheetShell.razor.rz.scp.css */
/* F-616 — ported verbatim from the prototype's components.css .sheet-host/.sheet/.sheet-grab/.sheet-close
   block (assets/js/ui.js's sheet()) plus .icon-btn and .t-subsection (base.css) for the close button and
   title. Every color/spacing/motion value is a token, so light/dark and reduced-motion both come free — no
   separate dark-mode block needed. z-index sits above every other overlay this app already renders (dialogs
   up to 80, DesignKeepMenuPrompt's own scrim at 1700) is deliberately NOT required here: the sheet's own
   scrim already fully occludes the page beneath it, so its stacking only has to clear ordinary page chrome
   (highest here: 80) — 1600 leaves headroom below the keep-menu prompt, which must always win if the two
   ever coincide. */

.sheet-host[b-otnq7quv4r] {
    position: fixed;
    inset: 0;
    z-index: 1600;
    background: var(--scrim, rgba(22, 33, 44, .45));
    animation: fade-in-b-otnq7quv4r var(--dur-fast, 140ms) var(--ease, cubic-bezier(.2, .7, .3, 1));
}

/* AlwaysMounted consumers (the QR menu drawer) never unmount the shell — Open only toggles this state via
   CSS, exactly as the pre-F-616 .filter-drawer's own is-open toggle did. A mount-on-open consumer (the wall's
   SearchFilterSheet) never renders this class at all: it is only ever mounted already-open (see the shell's
   own @if(AlwaysMounted || Open)), so the rule below never applies to it. */
.sheet-host:not(.is-open)[b-otnq7quv4r] {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.sheet[b-otnq7quv4r] {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    max-height: 88dvh;
    overflow: auto;
    background: var(--surface, #FFFFFF);
    color: var(--ink-1, #16212C);
    border-radius: var(--radius, 12px) var(--radius, 12px) 0 0;
    border-top: 1px solid var(--hairline, rgba(22, 33, 44, .10));
    box-shadow: var(--elev-4, 0 10px 20px rgba(22, 33, 44, .12), 0 24px 48px -12px rgba(22, 33, 44, .30));
    padding: var(--sp-modal-pad, 24px);
    animation: sheet-in-b-otnq7quv4r var(--dur-slow, 420ms) var(--ease, cubic-bezier(.2, .7, .3, 1));
}
@keyframes sheet-in-b-otnq7quv4r {
    from { transform: translateY(24%); opacity: .6; }
}
@keyframes fade-in-b-otnq7quv4r {
    from { opacity: 0; }
}

@media (min-width: 768px) {
    .sheet[b-otnq7quv4r] {
        inset-inline: auto 0;
        inset-block: 0;
        bottom: auto;
        height: 100dvh;
        max-height: none;
        width: min(92vw, 460px);
        border-radius: 0;
        border-inline-start: 1px solid var(--hairline, rgba(22, 33, 44, .10));
        animation: drawer-in-b-otnq7quv4r var(--dur-slow, 420ms) var(--ease, cubic-bezier(.2, .7, .3, 1));
    }
    @keyframes drawer-in-b-otnq7quv4r {
        from { transform: translateX(calc(12% * var(--flip, 1))); opacity: .6; }
    }
}

.sheet-grab[b-otnq7quv4r] {
    width: 40px;
    height: 4px;
    border-radius: 2px;
    background: var(--hairline-strong, rgba(22, 33, 44, .18));
    margin: -8px auto var(--sp-4, 16px);
}
@media (min-width: 768px) {
    .sheet-grab[b-otnq7quv4r] { display: none; }
}

/* universal Close on non-decision panels — same effect as tapping the scrim */
.sheet .sheet-close[b-otnq7quv4r] {
    position: absolute;
    top: 10px;
    inset-inline-end: 10px;
    z-index: 2;
    background: var(--surface, #FFFFFF);
    border: 1px solid var(--hairline, rgba(22, 33, 44, .10));
    box-shadow: var(--elev-1, 0 2px 6px rgba(22, 33, 44, .12));
}

/* icon-only button (44px target) — components.css's shared .icon-btn, ported here since this app has not
   otherwise adopted it. */
.icon-btn[b-otnq7quv4r] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--touch, 44px);
    height: var(--touch, 44px);
    border-radius: 50%;
    color: var(--ink-2, #43566A);
}
.icon-btn:hover[b-otnq7quv4r] {
    background: var(--surface-2, #F3F7FA);
    color: var(--ink-1, #16212C);
}

/* base.css's .t-subsection — the sheet's own title typography. */
.t-subsection[b-otnq7quv4r] {
    font-size: var(--t-24, 1.5rem);
    font-weight: 800;
    line-height: var(--lh-heading, 1.2);
    color: var(--ink-1, #16212C);
    margin: 0 0 var(--sp-4, 16px);
}

@media (prefers-reduced-motion: reduce) {
    .sheet-host[b-otnq7quv4r], .sheet[b-otnq7quv4r] { animation: none; }
}
/* pub/Components/Design/DesignStepper.razor.rz.scp.css */
/* Ported from the prototype's components.css `.stepper` block. The connector between two dots is the
   `::before` rail on each step, which is why the dot has to sit above it (z-index) on an opaque surface —
   without that the rail draws straight through the ring. */

.stepper[b-2hpzzl25uc] {
    display: flex;
    flex-direction: column;
    gap: 0;
    list-style: none;
    margin: 0;
    padding: 0;
}

.step[b-2hpzzl25uc] {
    display: flex;
    gap: var(--sp-4, 16px);
    position: relative;
    padding-bottom: var(--sp-5, 24px);
}

.step:last-child[b-2hpzzl25uc] {
    padding-bottom: 0;
}

.step .dot[b-2hpzzl25uc] {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    flex: none;
    display: grid;
    place-items: center;
    border: 2px solid var(--hairline-strong);
    background: var(--surface);
    color: var(--ink-3);
    z-index: 1;
}

.step .dot .dot-tick[b-2hpzzl25uc] {
    width: 14px;
    height: 14px;
}

.step[b-2hpzzl25uc]::before {
    content: "";
    position: absolute;
    inset-inline-start: 12px;
    top: 26px;
    bottom: 0;
    width: 2px;
    background: var(--hairline-strong);
}

.step:last-child[b-2hpzzl25uc]::before {
    display: none;
}

.step.is-done .dot[b-2hpzzl25uc] {
    border-color: var(--success);
    background: var(--safe-soft);
    color: var(--success);
}

.step.is-done[b-2hpzzl25uc]::before {
    background: var(--success);
}

.step.is-current .dot[b-2hpzzl25uc] {
    border-color: var(--accent-fg);
    color: var(--accent-fg);
    box-shadow: 0 0 0 4px var(--accent-soft);
}

.step .step-body[b-2hpzzl25uc] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.step .step-body .step-label[b-2hpzzl25uc] {
    font-size: var(--t-16, 1rem);
    font-weight: 700;
    color: var(--ink-1);
}

/* A step still ahead is quieter than the two behind it — the guest's eye should land on "where am I". */
.step:not(.is-done):not(.is-current) .step-body .step-label[b-2hpzzl25uc] {
    color: var(--ink-3);
    font-weight: 600;
}

.step .step-body .when[b-2hpzzl25uc] {
    font-size: var(--t-14, .875rem);
    color: var(--ink-3);
}
/* pub/Components/Design/DesignTermChips.razor.rz.scp.css */
/* Ported from the prototype's base.css `.row-wrap`. The chips carry their own colour; this only
   governs how they flow. */

.row-wrap[b-wzuiq68is5] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2, 8px);
}
/* pub/Components/Design/DishWall.razor.rz.scp.css */
/* Ported from the prototype's base.css `.area-section` + `.rail` blocks. Horizontal scroll is a
   first-class interaction here, not an overflow accident: the rail snaps, contains its overscroll,
   and bleeds to the page gutter so the first and last card align with the content above them.

   The breakpoints are the design system's two (768 / 1280) — the same pair base.css uses for
   `.grid-cards`; a third would be a new regime nothing else on the surface shares. */

.area-section[b-l7jcejspul] {
    margin-top: var(--sp-section, 36px);
}

.area-section:first-of-type[b-l7jcejspul] {
    margin-top: 0;
}

.rail[b-l7jcejspul] {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: min(72vw, 300px);
    gap: var(--sp-card-gap, 16px);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter, 20px);
    padding-bottom: var(--sp-2, 8px);
    margin-inline: calc(-1 * var(--gutter, 20px));
    padding-inline: var(--gutter, 20px);
    scrollbar-width: thin;
}

/* The cards are their own components, so the snap rule has to cross the scope boundary. */
.rail[b-l7jcejspul] >  * {
    scroll-snap-align: start;
}

@media (min-width: 1280px) {
    .rail[b-l7jcejspul] {
        grid-auto-columns: 350px;
        gap: var(--sp-6, 24px);
    }
}

/* NEW.2b: desktop-only prev/next chevrons so a mouse user can page a rail without shift-scrolling.
   Below 1280px the rail is touch/scroll-snap only — the same regime .rail already switches on above —
   so the buttons stay hidden rather than fighting for space with the narrower card layout. */
.rail-wrap[b-l7jcejspul] {
    position: relative;
}

.rail-nav[b-l7jcejspul] {
    display: none;
}

@media (min-width: 1280px) {
    .rail-nav[b-l7jcejspul] {
        display: flex;
        align-items: center;
        justify-content: center;
        position: absolute;
        top: 50%;
        z-index: 1;
        width: 40px;
        height: 40px;
        border: 1px solid var(--line);
        border-radius: 50%;
        background: var(--card, #fff);
        box-shadow: var(--elev-1);
        color: var(--ink);
        cursor: pointer;
        transform: translateY(-50%);
    }

    .rail-nav svg[b-l7jcejspul] {
        width: 20px;
        height: 20px;
        stroke: currentColor;
        stroke-width: 1.8;
        stroke-linecap: round;
        stroke-linejoin: round;
        fill: none;
    }

    .rail-nav--prev[b-l7jcejspul] {
        left: -20px;
    }

    .rail-nav--next[b-l7jcejspul] {
        right: -20px;
    }
}
/* pub/Components/Design/RailHero.razor.rz.scp.css */
/* Ported from the prototype's components.css `.rail-hero` block (the party-mode vote button is dropped —
   out of this surface's scope). Values are token references only. */

.rail-hero[b-3imlcu77n7] {
    position: relative;
    border-radius: var(--radius, 12px);
    overflow: hidden;
    box-shadow: var(--elev-1);
    margin-bottom: var(--gap-caps-head, 16px);
    min-height: 96px;
    display: flex;
    align-items: flex-end;
}

.rail-hero .hero-img[b-3imlcu77n7] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.rail-hero .hero-veil[b-3imlcu77n7] {
    position: relative;
    width: 100%;
    display: flex;
    align-items: center;
    gap: var(--sp-3, 12px);
    padding: var(--sp-5, 24px) var(--sp-4, 16px) var(--sp-3, 12px);
    background: linear-gradient(transparent, rgba(8, 14, 20, .82));
    color: #fff;
}

.rail-hero--band .hero-veil[b-3imlcu77n7] {
    background: none;
    padding-block: var(--sp-4, 16px);
}

.rail-hero .hero-logo[b-3imlcu77n7] {
    width: 44px;
    height: 44px;
    border-radius: 11px;
    flex: none;
    object-fit: cover;
}

.rail-hero .hero-who[b-3imlcu77n7] {
    flex: 1;
    min-width: 0;
}

.rail-hero .hero-name[b-3imlcu77n7] {
    font-weight: 900;
    font-size: var(--t-20, 1.25rem);
    line-height: var(--lh-heading, 1.15);
    color: inherit;
}

.rail-hero .hero-tag[b-3imlcu77n7] {
    font-size: var(--t-14, .875rem);
    opacity: .85;
}

.rail-hero .hero-meta[b-3imlcu77n7] {
    font-size: var(--t-cap, .8rem);
    opacity: .75;
    margin-top: 2px;
}

/* The CTA is its own component (DesignButton) — its rendered markup carries ITS OWN scope, not this
   component's, so reaching the extra `.hero-cta` skin needs ::deep (same pattern DishWall.razor.css uses
   to reach the WallDishCard rail children). */
.hero-veil[b-3imlcu77n7]  .hero-cta {
    background: rgba(255, 255, 255, .94);
    flex: none;
}

@media (min-width: 768px) {
    .rail-hero .hero-who[b-3imlcu77n7] {
        flex: 0 1 auto;
    }

    .rail-hero .hero-veil[b-3imlcu77n7]::after {
        content: "";
        flex: 1;
    }
}
/* pub/Components/Design/WallDishCard.razor.rz.scp.css */
/* Ported from the prototype's components.css `.dish-card` block. The card is one control, so the button
   reset lives here too. NEW.8: `.dish-img` reserves its aspect ratio whether or not the element renders,
   so a dish with no photo never shifts layout, and a dish whose photo loads late never shifts it either. */

.dish-card[b-vri59bwkvm] {
    position: relative;
    display: flex;
    flex-direction: column;
    width: 100%;
    text-align: start;
    text-decoration: none;
    cursor: pointer;
    font-family: inherit;
    border-radius: var(--radius, 12px);
    overflow: hidden;
    background: var(--surface, #FFFFFF);
    border: 1px solid var(--hairline, rgba(22, 33, 44, .10));
    box-shadow: var(--elev-1);
    transition: transform var(--dur, 220ms) var(--ease, ease), box-shadow var(--dur, 220ms) var(--ease, ease);
}

.dish-card:hover[b-vri59bwkvm] {
    transform: translateY(-2px);
    box-shadow: var(--elev-3);
}

.dish-card:focus-visible[b-vri59bwkvm] {
    outline: 2px solid var(--accent-fg);
    outline-offset: 2px;
}

.dish-img[b-vri59bwkvm] {
    aspect-ratio: 4 / 3;
    width: 100%;
    object-fit: cover;
    background: var(--surface-2, #F3F7FA);
}

.dish-body[b-vri59bwkvm] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-1, 4px);
    flex: 1;
    padding: var(--sp-4, 16px);
}

.dish-top[b-vri59bwkvm] {
    display: flex;
    justify-content: space-between;
    gap: var(--sp-3, 12px);
    align-items: baseline;
}

.t-dish-name[b-vri59bwkvm] {
    font-size: var(--t-20, 1.25rem);
    font-weight: 800;
    line-height: var(--lh-heading, 1.15);
    color: var(--ink-1, #16212C);
}

.t-price[b-vri59bwkvm] {
    font-size: var(--t-16, 1rem);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--ink-1, #16212C);
}

.dish-meta[b-vri59bwkvm] {
    font-size: var(--t-14, .875rem);
    color: var(--ink-3, #5E7183);
}

/* Two lines, then it clamps — the detail view is one tap away and owns the full copy. */
.dish-desc-clamp[b-vri59bwkvm] {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: var(--t-14, .875rem);
    color: var(--ink-2, #43566A);
    line-height: var(--lh-compact, 1.35);
}

/* The safety line sits at the BOTTOM of every card, so it lands in the same place on each one. */
.dish-badges[b-vri59bwkvm] {
    display: flex;
    gap: var(--sp-1, 4px);
    flex-wrap: wrap;
    margin-top: auto;
    padding-top: var(--sp-2, 8px);
}

.verdict[b-vri59bwkvm] {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1, 4px);
    min-height: 26px;
    padding-inline: var(--sp-2, 8px);
    border-radius: var(--radius-sm, 8px);
    font-size: var(--t-cap, .8rem);
    font-weight: 800;
    letter-spacing: .04em;
}

.verdict-safe[b-vri59bwkvm] {
    background: var(--safe-soft, #E8F5EC);
    color: var(--safe);
}

.verdict-modifiable[b-vri59bwkvm] {
    background: var(--removable-soft, #F9EFE2);
    color: var(--removable);
}

.dish-must-request[b-vri59bwkvm] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-1, 4px);
    padding-top: var(--sp-1, 4px);
    font-size: var(--t-14, .875rem);
}

.must-request-lead[b-vri59bwkvm] {
    font-weight: 800;
    color: var(--removable);
}

.must-request-chip[b-vri59bwkvm] {
    padding: 2px var(--sp-2, 8px);
    border-radius: var(--radius-pill, 999px);
    background: var(--removable-soft, #F9EFE2);
    color: var(--removable);
    font-weight: 700;
}
/* pub/Components/Design/WallExclusionsCard.razor.rz.scp.css */
/* F-606 NEW.2 — the prototype's inline `style="margin-top:var(--sp-4)"` on the CTA row and
   `style="flex:1"` on the button, lifted into a scoped sheet rather than repeated inline. */
.wall-exclusions-actions[b-01m84uk8hq] {
    margin-top: var(--sp-4);
}

.wall-exclusions-show[b-01m84uk8hq] {
    flex: 1;
}
/* pub/Components/PatronIdentityPicker.razor.rz.scp.css */
/* The identity tiles, from the prototype's `#icon-picker` override of `.chip` — a square big enough to read
   as a person's mark. Token references only; no literal colours. */

.identity-picker[b-hy5e9gjthi] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-3, 12px);
}

.identity-tile[b-hy5e9gjthi] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 56px;
    min-height: 56px;
    padding: 0 var(--sp-2, 8px);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-sm, 8px);
    background: var(--surface);
    color: var(--ink-1);
    font: inherit;
    font-size: var(--t-16, 1rem);
    font-weight: 800;
    cursor: pointer;
    transition: border-color var(--dur-fast, .15s) var(--ease, ease), box-shadow var(--dur-fast, .15s) var(--ease, ease);
}

.identity-tile:hover[b-hy5e9gjthi] {
    border-color: var(--accent-fg);
}

/* The chosen mark is carried by BOTH the border and the ring: colour alone would leave the choice invisible
   to anyone who cannot see the accent against the surface. */
.identity-tile.is-on[b-hy5e9gjthi] {
    border-color: var(--accent-fg);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

.identity-tile:focus-visible[b-hy5e9gjthi],
.identity-tile:focus-within[b-hy5e9gjthi] {
    outline: 2px solid var(--accent-fg);
    outline-offset: 2px;
}

.identity-glyph[b-hy5e9gjthi] {
    font-size: 26px;
    line-height: 1;
}

.identity-photo[b-hy5e9gjthi] {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    object-fit: cover;
}

/* The input stays in the accessibility tree (it is the real control) but is not drawn — the tile is.
   `::deep` because InputFile is a COMPONENT: the scope attribute lands on this label, never on the <input>
   the component renders, so a plain `.identity-file` rule matches nothing and the browser's own
   "Choose File" widget shows through the tile. */
.identity-upload[b-hy5e9gjthi]  .identity-file {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.identity-error[b-hy5e9gjthi] {
    margin-top: var(--sp-2, 8px);
    color: var(--unverified);
    font-weight: 700;
}
/* pub/Components/PatronPhoneField.razor.rz.scp.css */
/* NEW.1: the patron-family phone field, following Account.razor.css's `.field`/`.input`/`.t-label` idiom —
   a country select beside the number input, both at the same touch-target metrics as the rest of the form. */

.phone-field[b-n4yhasdgtt] {
    display: flex;
    gap: var(--sp-2, 8px);
    align-items: flex-end;
}

.phone-field-code[b-n4yhasdgtt],
.phone-field-number[b-n4yhasdgtt] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2, 8px);
}

.phone-field-code[b-n4yhasdgtt] {
    flex: 0 0 auto;
    width: 96px;
}

.phone-field-number[b-n4yhasdgtt] {
    flex: 1 1 auto;
}

.phone-field .t-label[b-n4yhasdgtt] {
    font-size: var(--t-14, .875rem);
    font-weight: 700;
    color: var(--ink-2);
}

.phone-field .input[b-n4yhasdgtt] {
    min-height: var(--touch, 44px);
    padding: 10px var(--sp-4, 16px);
    border-radius: var(--radius-sm, 8px);
    border: 1px solid var(--hairline-strong);
    background: var(--surface);
    color: var(--ink-1);
    font: inherit;
    transition: border-color var(--dur-fast, .15s) var(--ease, ease), box-shadow var(--dur-fast, .15s) var(--ease, ease);
}

.phone-field .input:focus[b-n4yhasdgtt] {
    outline: none;
    border-color: var(--accent-fg);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
/* pub/Components/UpdateAvailablePill.razor.rz.scp.css */
/* F-619 — ported from the prototype's own .toast-host/.toast (assets/css/components.css), token-for-token, so
   both themes and reduced-motion come free the same way DesignSheetShell's port does. Sits well below every
   sheet/dialog in this app (highest overlay z-index here is DesignKeepMenuPrompt's 1700) so an overlay always
   wins if the two ever coincide — the pill is a passive affordance, never something to fight a dialog over. */

.update-pill-host[b-e9878nbj8k] {
    position: fixed;
    z-index: 200;
    bottom: calc(var(--bottomnav-h, 60px) + var(--sp-4, 16px));
    inset-inline: 0;
    display: flex;
    justify-content: center;
    pointer-events: none;
}

/* .toast is a read-only announcement in the prototype; this ONE instance is tappable, so it adds a pointer
   cursor and a hover state without touching the shared visual shape. */
.update-pill[b-e9878nbj8k] {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: var(--sp-icon-text, 8px);
    max-width: min(92vw, 460px);
    padding: var(--sp-3, 12px) var(--sp-4, 16px);
    border: none;
    border-radius: var(--radius, 12px);
    background: var(--ink-1, #16212C);
    color: var(--bg, #F8FBFC);
    font-family: inherit;
    font-size: var(--t-14, .875rem);
    font-weight: 600;
    cursor: pointer;
    box-shadow: var(--elev-3, 0 6px 12px rgba(22, 33, 44, .09), 0 24px 48px -20px rgba(22, 33, 44, .30));
    animation: update-pill-in-b-e9878nbj8k var(--dur, 220ms) var(--ease, cubic-bezier(.2, .7, .3, 1));
}

.update-pill:hover[b-e9878nbj8k] {
    filter: brightness(1.1);
}

@keyframes update-pill-in-b-e9878nbj8k {
    from { opacity: 0; transform: translateY(8px); }
}

@media (prefers-reduced-motion: reduce) {
    .update-pill[b-e9878nbj8k] { animation: none; }
}
/* pub/Components/WallSearchFab.razor.rz.scp.css */
/* NEW.3 (owner ruling 2026-08-17): Search & Filter is a FIXED top-right FAB everywhere, not pinned
   in flow — floats over the wall content at every width, both themes — token references only (design
   system fidelity), so a theme switch needs no override here. Visually mirrors Menu.razor's
   .menu-filter-fab (same shape, same 44px touch target) but shares no class or file with it.
   z-index 30 sits above ordinary page content (wall rows, chips) but below every drawer/overlay
   surface in app.css (.patron-appbar 40, .filter-drawer 41, .cart-drawer 46, .dislike-drawer 56,
   modals 50-80) — the FAB never floats over a drawer or dialog once one opens. Right offset adds the
   safe-area inset so the FAB clears a notch/rounded corner on mobile. */

/* F-616 (owner devtools spec, 2026-08-19): the prototype's own .filter-fab positioning, verbatim —
   BELOW the app bar (top: appbar height + sp-3), inset at the content gutter, on the rail z-layer.
   The previous top:8px pinned the fab AT the viewport top, where the app bar's guest pill rendered
   OVER it (elementFromPoint returned the pill's avatar at the fab's center) — present, on-screen,
   and completely occluded. Positioning below the app bar removes the occlusion by construction.
   Safe-area insets are kept additively; the prototype's source has no env() but a notch still must
   not clip the control. */
.wall-fab-rail[b-37pucb8maj] {
    position: fixed;
    top: calc(var(--appbar-h, 56px) + var(--sp-3, 12px) + env(safe-area-inset-top, 0px));
    inset-inline-end: calc(var(--gutter, 20px) + env(safe-area-inset-right, 0px));
    z-index: var(--z-rail, 30);
    display: flex;
    justify-content: flex-end;
    pointer-events: none;
}

/* NEW.4 (wall-fidelity, owner 2026-08-16): the prototype's `.filter-fab` composes with `.btn-secondary`
   (components.css) — surface fill, accent-fg text, a hairline border — not a filled primary pill. */
.wall-search-fab[b-37pucb8maj] {
    pointer-events: auto;
    display: inline-flex;
    align-items: center;
    gap: var(--sp-icon-text, 8px);
    min-height: var(--btn-h, 44px);
    padding-inline: var(--sp-5, 24px);
    border: 1px solid var(--hairline-strong, rgba(22, 33, 44, .18));
    border-radius: var(--radius-pill, 999px);
    background: var(--surface, #FFFFFF);
    color: var(--accent-fg, #1F6E9C);
    font-family: inherit;
    font-size: var(--t-16, 1rem);
    font-weight: 700;
    cursor: pointer;
    box-shadow: var(--elev-2, 0 4px 12px rgba(0, 0, 0, .2));
}

.wall-search-fab:hover[b-37pucb8maj] {
    background: var(--surface-2, #F3F7FA);
    box-shadow: var(--elev-3, var(--elev-2, 0 6px 16px rgba(0, 0, 0, .24)));
}
/* pub/Layout/MainLayout.razor.rz.scp.css */
/* NEW.7 (owner ruling 2026-08-14 evening): the router's FocusOnNavigate now targets #route-focus-sink
   instead of the page heading (App.razor), so no browser/accessibility-mode focus ring on the
   heading is possible after navigation. .visually-hidden is the standard sr-only pattern (also
   defined in the design system's base.css, which this host does not load) — clip: rect(0 0 0 0)
   clips the sink's own outline too, but #route-focus-sink:focus below makes the "never visible"
   guarantee explicit rather than relying on that side effect. h1:focus stays suppressed
   belt-and-braces, reaching every page's heading through @Body via ::deep, for any residual
   direct-focus path. */
.visually-hidden[b-p1517t1r9m] {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

#route-focus-sink:focus[b-p1517t1r9m] {
    outline: none;
}

[b-p1517t1r9m] h1:focus {
    outline: none;
}
/* pub/Pages/Account.razor.rz.scp.css */
/* The account surface's form and rhythm, from the prototype's `.form-grid--2` / `.field` / `.input` and
   `.area-section` / `.stack`. No width or gutter here: `.patron-shell` (app.css) is the app's ONE column, and
   a second max-width inside it would centre a narrower column inside a centred column. */

.account-form[b-r0jke5ta88] {
    margin-top: var(--sp-4, 16px);
}

/* Two columns where there is room for two. The prototype's grid is fixed at two from its own breakpoint up;
   here the columns are asked for by minimum width instead, so the identity picker (the widest field, a row of
   56px tiles) is never squeezed into a half column that wraps it three deep. */
.form-grid[b-r0jke5ta88] {
    display: grid;
    gap: var(--sp-4, 16px);
    grid-template-columns: 1fr;
}

@media (min-width: 620px) {
    .form-grid[b-r0jke5ta88] {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* The picker spans the row: it is a group of controls, not a single input beside one. */
    .form-grid .field:last-child[b-r0jke5ta88] {
        grid-column: 1 / -1;
    }
}

.field[b-r0jke5ta88] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2, 8px);
}

.field .t-label[b-r0jke5ta88] {
    font-size: var(--t-14, .875rem);
    font-weight: 700;
    color: var(--ink-2);
}

.field .t-helper[b-r0jke5ta88] {
    margin: 0;
    font-size: var(--t-14, .875rem);
    color: var(--ink-3);
}

.input[b-r0jke5ta88] {
    min-height: var(--touch, 44px);
    padding: 10px var(--sp-4, 16px);
    border-radius: var(--radius-sm, 8px);
    border: 1px solid var(--hairline-strong);
    background: var(--surface);
    color: var(--ink-1);
    font: inherit;
    transition: border-color var(--dur-fast, .15s) var(--ease, ease), box-shadow var(--dur-fast, .15s) var(--ease, ease);
}

.input:focus[b-r0jke5ta88] {
    outline: none;
    border-color: var(--accent-fg);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

.area-section[b-r0jke5ta88] {
    margin-top: var(--sp-section, 36px);
}

.stack[b-r0jke5ta88] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-related, 12px);
}

/* The guest branch stands where the head would, rather than against the app bar (the empty block is a
   component root, so it carries no margin of the page's own). */
.account-page[b-r0jke5ta88]  .empty {
    margin-top: var(--sp-section, 36px);
}
/* pub/Pages/Home.razor.rz.scp.css */
/* F-606 NEW.1 (wall-fidelity, lift-verbatim): the prototype's `#wall { margin-top: var(--sp-6) }`
   inline rule, lifted into a scoped sheet rather than repeated inline. */
#wall[b-puqeatv56x] {
    margin-top: var(--sp-6);
}
/* pub/Pages/Moods.razor.rz.scp.css */
/* The moods surface's own column + rhythm, from the prototype's `.area-wrap` / `.area-section` / `.stack`.
   Scoped rather than added to app.css: these names are generic enough that a global rule would reach into
   every ym-era screen still on the old vocabulary. */

/* No width or gutter here on purpose: `.patron-shell` (app.css) is the app's ONE column, and a second
   max-width inside it would centre a narrower column inside a centred column. */
.area-section[b-tb6eawmtt8] {
    margin-top: var(--sp-section, 36px);
}

.stack[b-tb6eawmtt8] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-related, 12px);
}

/* NEW.7: the anonymous/example-moods lead-in — quiet metadata copy, not a heading. */
.moods-examples-lead[b-tb6eawmtt8] {
    font-size: var(--t-14, .875rem);
    color: var(--ink-3, #5E7183);
    margin: 0 0 var(--sp-2, 8px);
}

/* F-626 NEW.2 — moods.html's own `.row-wrap` (components.css), the popular-nearby chip row's wrapper. */
.row-wrap[b-tb6eawmtt8] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2, 8px);
}

/* The Parties card: the prototype makes the whole row one `<a>`; this one is a `<button>` instead (there is
   no parties route to link to — it opens the Coming-soon dialog), reset to fill the card exactly as the
   anchor did. */
.moods-parties-trigger[b-tb6eawmtt8] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-related, 12px);
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    text-align: start;
    color: inherit;
    cursor: pointer;
}

.moods-parties-trigger:focus-visible[b-tb6eawmtt8] {
    outline: 2px solid var(--accent-fg);
    outline-offset: 2px;
    border-radius: var(--radius-sm, 8px);
}

.moods-parties-label[b-tb6eawmtt8] {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2, 8px);
    font-weight: 700;
}

/* The editor beneath the list keeps the design-system surface, but its internals are still the shared
   ym-era zone — restyling that whole chip-field family is its own increment. */
.moods-page[b-tb6eawmtt8]  .ym-zone-moods.is-embedded {
    background: var(--surface, #FFFFFF);
    border: 1px solid var(--hairline, rgba(22, 33, 44, .10));
    border-radius: var(--radius, 12px);
    box-shadow: var(--elev-1);
    padding: var(--sp-5, 24px);
    margin: 0;
}
/* pub/Pages/Orders.razor.rz.scp.css */
/* The orders entry's rhythm and its one form, from the prototype's `.field` / `.input-row` / `.area-section`.
   No width or gutter here: `.patron-shell` (app.css) is the app's ONE column, and a second max-width inside
   it would centre a narrower column inside a centred column. */

.orders-lookup[b-hz1boyguqx] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-3, 12px);
}

.orders-lookup .t-label[b-hz1boyguqx] {
    font-size: var(--t-14, .875rem);
    font-weight: 700;
    color: var(--ink-2);
}

.orders-lookup .input-row[b-hz1boyguqx] {
    display: flex;
    gap: var(--sp-2, 8px);
}

.orders-lookup .input[b-hz1boyguqx] {
    flex: 1;
    min-width: 0;
    min-height: var(--touch, 44px);
    padding: 10px var(--sp-4, 16px);
    border-radius: var(--radius-sm, 8px);
    border: 1px solid var(--hairline-strong);
    background: var(--surface);
    color: var(--ink-1);
    font: inherit;
    transition: border-color var(--dur-fast, .15s) var(--ease, ease), box-shadow var(--dur-fast, .15s) var(--ease, ease);
}

.orders-lookup .input:focus[b-hz1boyguqx] {
    outline: none;
    border-color: var(--accent-fg);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

.area-section[b-hz1boyguqx] {
    margin-top: var(--sp-section, 36px);
}

/* The empty state stands where the recents section would — without this it butts against the lookup row
   (the empty block is a component root, so it carries no margin of the page's own). */
.orders-page[b-hz1boyguqx]  .empty {
    margin-top: var(--sp-section, 36px);
}

.stack[b-hz1boyguqx] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-related, 12px);
}

.order-row-actions[b-hz1boyguqx] {
    display: flex;
    align-items: center;
    gap: var(--sp-3, 12px);
}

.order-row-reveal[b-hz1boyguqx] {
    min-height: var(--touch, 44px);
    padding: 6px var(--sp-3, 12px);
    border-radius: var(--radius-sm, 8px);
    border: 1px solid var(--hairline-strong);
    background: var(--surface);
    color: var(--ink-1);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.order-row-goto[b-hz1boyguqx] {
    color: var(--accent-fg);
    font-weight: 600;
    text-decoration: underline;
}

.order-row-details[b-hz1boyguqx] {
    color: var(--ink-2);
    text-decoration: underline;
}

.order-row-qr[b-hz1boyguqx] {
    margin-top: var(--sp-2, 8px);
}
/* pub/Pages/OrderStatus.razor.rz.scp.css */
/* The order-detail surface's own chrome, moved off app.css onto the design system's tokens (W1b NEW.4).
   No width or gutter here: `.patron-shell` (app.css) is the app's ONE column.

   The regions that are DesignCards and the actions that are DesignButtons are reached with ::deep — their
   root element belongs to the component, so a plain selector in this sheet never matches it. */

.order-status-back[b-xfzcmebtwl] {
    display: inline-flex;
    align-items: center;
    min-height: var(--touch, 44px);
    color: var(--accent-fg);
    font-weight: 700;
    font-size: var(--t-14, .875rem);
    text-decoration: none;
}

.order-status-back:hover[b-xfzcmebtwl] {
    text-decoration: underline;
}

/* An unknown reference lands on the standard empty state, which stands clear of the back link. */
.order-status[b-xfzcmebtwl]  .empty {
    margin-top: var(--sp-5, 24px);
}

/* The headline verdict, in the app's one badge shape. The tokens are the shared verdict ramp rather than
   six hand-picked hexes, so the badge tracks the theme (F-136 measured the old pairs on light only). */
.order-status-badge[b-xfzcmebtwl] {
    display: inline-flex;
    align-items: center;
    margin-top: var(--sp-2, 8px);
    padding: 4px 10px;
    border-radius: 999px;
    font-size: var(--t-14, .875rem);
    font-weight: 800;
    white-space: nowrap;
}

.order-status-badge.is-requested[b-xfzcmebtwl] { background: var(--unverified-soft); color: var(--unverified); }
.order-status-badge.is-accepted[b-xfzcmebtwl] { background: var(--safe-soft); color: var(--safe); }
/* Prep track (F-169): downstream of accepted, so it warms toward "ready" rather than repeating the green. */
.order-status-badge.is-in-kitchen[b-xfzcmebtwl] { background: var(--removable-soft); color: var(--removable); }
.order-status-badge.is-ready[b-xfzcmebtwl] { background: var(--safe-soft); color: var(--safe); }
.order-status-badge.is-rejected[b-xfzcmebtwl] { background: var(--unsafe-soft); color: var(--unsafe); }
.order-status-badge.is-needs-edit[b-xfzcmebtwl] { background: var(--removable-soft); color: var(--removable); }

.order-status-line[b-xfzcmebtwl] {
    margin: var(--sp-3, 12px) 0 0;
    color: var(--ink-2);
    font-size: var(--t-16, 1rem);
    line-height: var(--lh-body, 1.55);
    max-width: 56ch;
}

.order-status[b-xfzcmebtwl]  .order-status-progress {
    margin-top: var(--sp-5, 24px);
}

/* The prototype's halt bar: an order that cannot move again states it instead of drawing a rail. */
.order-status-halt[b-xfzcmebtwl] {
    display: flex;
    align-items: center;
    gap: var(--sp-icon-text, 8px);
    margin-top: var(--sp-5, 24px);
    padding: var(--sp-2, 8px) var(--sp-3, 12px);
    border-radius: var(--radius-sm, 8px);
    background: var(--unsafe-soft);
    color: var(--unsafe);
    font-size: var(--t-14, .875rem);
    font-weight: 700;
}

.order-status-total[b-xfzcmebtwl] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-related, 12px);
    margin-top: var(--sp-5, 24px);
}

.order-status-total .t-label[b-xfzcmebtwl] {
    font-size: var(--t-14, .875rem);
    font-weight: 700;
    color: var(--ink-2);
}

.order-status-total .t-price[b-xfzcmebtwl] {
    font-size: var(--t-24, 1.5rem);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--ink-1);
}

.order-status[b-xfzcmebtwl]  .order-status-qr,
.order-status[b-xfzcmebtwl]  .order-status-loyalty,
.order-status[b-xfzcmebtwl]  .order-status-giftcard {
    margin-top: var(--sp-section, 36px);
}

.order-status-qr-title[b-xfzcmebtwl],
.order-status-loyalty-title[b-xfzcmebtwl],
.order-status-giftcard-title[b-xfzcmebtwl] {
    margin: 0;
    font-size: var(--t-16, 1rem);
    font-weight: 800;
    color: var(--ink-1);
}

.order-status-qr-img[b-xfzcmebtwl] {
    display: block;
    margin: var(--sp-4, 16px) 0;
    border-radius: var(--radius-sm, 8px);
    background: #fff;
}

.order-status-qr-hint[b-xfzcmebtwl],
.order-status-giftcard-hint[b-xfzcmebtwl],
.order-status-loyalty-note[b-xfzcmebtwl],
.order-status-loyalty-hint[b-xfzcmebtwl] {
    margin: var(--sp-2, 8px) 0 0;
    color: var(--ink-2);
    font-size: var(--t-14, .875rem);
    line-height: var(--lh-body, 1.55);
}

/* The field + its action stack full-width on a phone and sit inline once there is room. */
.order-status-loyalty-row[b-xfzcmebtwl],
.order-status-giftcard-row[b-xfzcmebtwl] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2, 8px);
    margin-top: var(--sp-3, 12px);
}

.order-status-loyalty-email[b-xfzcmebtwl],
.order-status-giftcard-input[b-xfzcmebtwl] {
    flex: 1 1 12rem;
    min-width: 0;
    min-height: var(--touch, 44px);
    padding: 10px var(--sp-4, 16px);
    border-radius: var(--radius-sm, 8px);
    border: 1px solid var(--hairline-strong);
    background: var(--surface);
    color: var(--ink-1);
    font: inherit;
}

.order-status-giftcard-input[b-xfzcmebtwl] {
    text-transform: uppercase;
}

.order-status-loyalty-email:focus[b-xfzcmebtwl],
.order-status-giftcard-input:focus[b-xfzcmebtwl] {
    outline: none;
    border-color: var(--accent-fg);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

.order-status-loyalty-result[b-xfzcmebtwl],
.order-status-giftcard-result[b-xfzcmebtwl] {
    margin: var(--sp-3, 12px) 0 0;
    font-size: var(--t-14, .875rem);
    font-weight: 700;
}

.order-status-loyalty-result.is-ok[b-xfzcmebtwl],
.order-status-giftcard-result.is-ok[b-xfzcmebtwl] { color: var(--safe); }

.order-status-loyalty-result.is-error[b-xfzcmebtwl],
.order-status-giftcard-result.is-error[b-xfzcmebtwl] { color: var(--unsafe); }

.order-status[b-xfzcmebtwl]  .order-status-refresh {
    margin-top: var(--sp-section, 36px);
}
/* pub/Pages/Preferences.razor.rz.scp.css */
/* The exclusions surface's rhythm, from the prototype's `.area-section`. No width or gutter here:
   `.patron-shell` (app.css) is the app's ONE column. */

.area-section[b-rtix3gpshs] {
    margin-top: var(--sp-section, 36px);
}

.t-helper[b-rtix3gpshs] {
    margin: 0 0 var(--sp-3, 12px);
    font-size: var(--t-14, .875rem);
    line-height: var(--lh-compact, 1.35);
    color: var(--ink-3, #5E7183);
}

.prefs-applynote[b-rtix3gpshs] {
    margin: var(--sp-3, 12px) 0 0;
}

/* The guest note is a quiet aside, not another content card. */
.prefs-guestnote[b-rtix3gpshs] {
    margin-top: var(--sp-section, 36px);
}

.t-compact[b-rtix3gpshs] {
    font-size: var(--t-14, .875rem);
    line-height: var(--lh-compact, 1.35);
    color: var(--ink-2, #43566A);
}

.prefs-saved[b-rtix3gpshs] {
    margin: var(--sp-4, 16px) 0 0;
    padding: var(--sp-3, 12px) var(--sp-4, 16px);
    border-radius: var(--radius-sm, 8px);
    background: var(--safe-soft, var(--surface-2, #F3F7FA));
    color: var(--safe, #1E7A4B);
    font-weight: 700;
}
/* pub/Pages/Saved.razor.rz.scp.css */
/* The saved surface's rhythm, from the prototype's `.area-section`. No width or gutter here:
   `.patron-shell` (app.css) is the app's ONE column, and a second max-width inside it would centre a
   narrower column inside a centred column. */

.area-section[b-6hzvh64t2u] {
    margin-top: var(--sp-section, 36px);
}

/* The adjacent surface (the automatic list) is a quiet way onward, not a page action. */
.saved-cross[b-6hzvh64t2u] {
    margin: var(--sp-section, 36px) 0 0;
}

.saved-cross a[b-6hzvh64t2u] {
    display: inline-flex;
    align-items: center;
    min-height: var(--touch, 44px);
    color: var(--accent-fg);
    font-weight: 700;
    text-decoration: none;
}

.saved-cross a:hover[b-6hzvh64t2u] {
    text-decoration: underline;
}
/* pub/Pages/Visited.razor.rz.scp.css */
/* The visited surface's rhythm, from the prototype's `.area-section` / `.stack`. No width or gutter here:
   `.patron-shell` (app.css) is the app's ONE column. */

.stack[b-c4nsnwgoft] {
    display: flex;
    flex-direction: column;
    gap: var(--sp-related, 12px);
    margin-top: var(--sp-section, 36px);
}

/* A row already promoted states it rather than offering the action again. */
.visited-done[b-c4nsnwgoft] {
    font-size: var(--t-14, .875rem);
    font-weight: 700;
    color: var(--safe, #1E7A4B);
}

.visited-cross[b-c4nsnwgoft] {
    margin: var(--sp-section, 36px) 0 0;
}

.visited-cross a[b-c4nsnwgoft] {
    display: inline-flex;
    align-items: center;
    min-height: var(--touch, 44px);
    color: var(--accent-fg);
    font-weight: 700;
    text-decoration: none;
}

.visited-cross a:hover[b-c4nsnwgoft] {
    text-decoration: underline;
}
