/* ==========================================================================
   DESIGN 2_0 — menu add-ons
   public/css/2_0/menu_addons.css

   Everything the 14.09 merge (cad3019ba, RW_11-09-26_outer_outlets_solve_conflicts
   -> developer) added to menu.ejs / pj_style/menu.scss that the 2_0 batch has
   no markup for.

   WHY A SEPARATE FILE:
   - never in styles.css — that one is replaced wholesale by every new designer
     batch, everything we put there is gone on the next import;
   - the legacy /css/standard/pj_style/menu.css does ship these rules, but it is
     1_0 CSS and its selectors are scoped to #hb_menu_page .hb-main-container,
     which menu_2 does not have (2_0 uses .content). Keeping our own copy makes
     2_0 self-sufficient when that file is finally dropped.

   TOKENS: this file uses the designer's palette (--accent-color, --card-color,
   --background-color, --background-text-color, --secondary-background-text-color,
   --field-border-color), NOT the 1_0 --wo-* namespace. --wo-* is defined per
   site in css/sites/<site>_styles/site_vars.css and is not part of the new
   design, so admin brand colours are not bridged into 2_0 (NEW_DESIGN_BUGS.md
   #24). The old hexes are kept as var() fallbacks.

   Loaded for menu_2 only — see views/index.ejs (design2_page block).

   Contents
     1. is-skeleton — shimmering menu placeholder on the designer's card shell
     2. .geo-modal — one bridge rule for the designer's geo pre-prompt
     3. hb-outlet-outer-*, hb-outlet-elem--disabled, hb-title--city*,
        hb-outlet-data, hb-outer-suggest-* — outer outlets + city + distance
     4. .cat-btn__icon — the category artwork centred in its tile
     5. .mod.is-selected — selected modifier ring drawn above the artwork
     6. .deal-modal-warning — the alert popup: close button inside the card,
        no inner scrollbar
     7. .rewards-loading — the quiet preloader while the rewards are still coming
     8. .hint__spot / .hint__tip — first-visit hint pinned under the modals
     9. .mod-group__req — gap between the min/max hint spans
    10. #hb_menu_page overflow-x: clip on mobile — un-breaks the designer's
        sticky header + categories, which the legacy 1_0 sheet turns into
        non-scrolling scroll containers
    11. .header-address__day — the date is hidden in the address pill
    12. .states-search__placeholder — translated search hint in the city modal
    13. #wo_auth_modal .signin-modal — restore the designer's fonts in the
        sign-in modal (the 1_0 menu.css `#wo_auth_modal *` forces Raleway)
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. MENU SKELETON
   Shown while the geolocation pre-prompt is pending (menu.placeholder).
   Built from the designer's own card classes — card-grid / card / card__img /
   card__body / price-btn — so nothing jumps when the real menu arrives.

   The 30.09 batch reworks this idea (styles.css:9681-9743): there are no fake
   blocks at all — `.app.is-loading` makes the REAL blocks stand in for their own
   skeleton, with a viewport-wide gradient sweeping through them. Not portable to
   us: his menu.html is a static mockup (52 hardcoded cards), while our grid is a
   v-for over menu.list, empty exactly while the placeholder is up
   (menu.js:6339 -> :6420) — there would be nothing to paint, and once the data
   arrives the skeleton is pointless anyway. So only his VISUAL is ported, onto
   our own blocks: same gradient, same 1.6s sweep, every block in step because
   the background is fixed to the viewport.

   Two bugs this also fixes. The old base was `var(--card-color)`, and
   --card-color is #ffffff in every L&L sheet (21.09:63, 30.09:63) — white blocks
   on a white page; and the sheet loads AFTER this file (inline basic_css) with
   equal specificity, so its `.card__img { background: transparent }` (21.09:4680)
   and `.price-btn { background: var(--background-price-color) }` (21.09:4902)
   were the ones that actually won. The placeholder was a transparent image box,
   two invisible lines and a live accent-coloured pill. Hence the
   `.card-grid.is-skeleton` prefix on the paint rule: (0,3,0) beats the sheet's
   single class whatever the order.
   -------------------------------------------------------------------------- */

.is-skeleton .card {
  pointer-events: none;
}

/* The designer's own tokens once his new sheet is installed, literal equivalents
   until then: --shimmer-base is color-mix(--background-text-color 8%,
   --background-color), and color-mix exists in NO live sheet (30.09 only).
   Our names, not his — a --shimmer-base defined here would override his :root. */
.is-skeleton {
  --d2-shimmer-base: var(--shimmer-base, rgba(34, 34, 34, 0.08));
  --d2-shimmer-highlight: var(--shimmer-highlight, var(--background-color, #ffffff));
}

.is-skeleton__img {
  width: 100%;
  padding-top: 66.66%;
  border-radius: 8px;
}

.is-skeleton__line {
  border-radius: 4px;
}

.is-skeleton__title {
  height: 16px;
  width: 85%;
  margin-top: 12px;
}

.is-skeleton__title--short {
  width: 55%;
}

.is-skeleton__btn {
  height: 34px;
  width: 88px;
  border-radius: 17px;
  margin-top: 14px;
}

/* The 30.09 sweep, verbatim from styles.css:9716-9719 and :9690-9693 — a fixed
   200vw x 100vh gradient moved along X, so every block shimmers in step instead
   of each one running its own local shine. `d2-` because the 1_0 placeholder
   already owns the name `wo-mp-shimmer` (css/standard/menu.css:3592). */
.card-grid.is-skeleton .is-skeleton__img,
.card-grid.is-skeleton .is-skeleton__line,
.card-grid.is-skeleton .is-skeleton__btn {
  position: relative;
  overflow: hidden;
  background: linear-gradient(90deg,
      var(--d2-shimmer-base) 40%,
      var(--d2-shimmer-highlight) 50%,
      var(--d2-shimmer-base) 60%) 0 0 / 200vw 100vh fixed;
  animation: d2-shimmer 1.6s linear infinite;
}

@keyframes d2-shimmer {
  from {
    background-position: -150vw 0;
  }

  to {
    background-position: 50vw 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .card-grid.is-skeleton .is-skeleton__img,
  .card-grid.is-skeleton .is-skeleton__line,
  .card-grid.is-skeleton .is-skeleton__btn {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   2. GEOLOCATION PRE-PROMPT — no longer here
   The 21.09 batch ships this dialog (menu.html, "geo-modal" / "geo-btn") and
   styles it in the base sheet, responsive halves included, so the markup in
   menu_2.ejs follows theirs and the hand-rolled geo-perm-* block is gone.
   The one thing the sheet cannot give us: .geo-modal is pointer-events:none
   there, because their gate is mandatory (location-modals.js — "neither modal
   offers a way out"). Ours keeps 1_0's click-outside-to-dismiss, which needs
   the click to land on the overlay rather than pass through to the page.
   .is-open is in the selector on purpose: the base sheet arrives AFTER this
   file (inline basic_css in views/index.ejs), so a plain .geo-modal would lose
   on order; two classes win on specificity.
   -------------------------------------------------------------------------- */

.geo-modal.is-open {
  pointer-events: auto;
}

/* --------------------------------------------------------------------------
   3. OUTER OUTLETS / CITY / DISTANCE
   All of these live inside the outlets map modal (components_2/
   modal_map_outlets.ejs) and mirror the 1_1 port.
   -------------------------------------------------------------------------- */

/* distance line + address/hours block */
.hb-outlet-elem .hb-outlet-data {
  line-height: 17px;
}

.hb-outlet-elem .hb-outlet-data:not(:last-child) {
  padding-bottom: 8px;
}

/* outer outlet: "Available:" label + delivery-service icons */
.hb-outlet-outer-links {
  padding-bottom: 4px;
}

.hb-outlet-outer-label {
  padding-bottom: 4px;
  cursor: default;
}

.hb-outlet-outer-services {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  align-items: center;
}

.hb-outlet-outer-service {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 4px;
}

.hb-outlet-outer-service img {
  display: block;
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.hb-outlet-outer-service-name {
  font-size: 14px;
  line-height: 120%;
  color: var(--background-text-color, #2e3233);
  text-decoration: underline;
  white-space: nowrap;
}

/* outlet we cannot take an order from */
.hb-outlet-elem--disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

/* city name next to "Choose pickup/eat-in" — jumps back to the city step */
.hb-title--city {
  display: inline-block;
}

.hb-title--city-name {
  color: var(--accent-color, #cd222a);
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 4px;
  cursor: pointer;
}

.hb-title--city-name:hover {
  text-decoration-style: solid;
}

/* "Choose delivery service" — the point is outside every own delivery zone */
.hb-outer-suggest {
  width: 100%;
  margin-top: 20px;
}

.hb-outer-suggest-title {
  font-size: 18px;
  line-height: 1.2;
  font-weight: 900;
  color: var(--secondary-background-text-color, #72747A);
  padding-bottom: 12px;
}

.hb-outer-suggest-list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.hb-outer-suggest-service {
  outline: none !important;
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1 0 calc(50% - 6px);
  min-width: 0;
  padding: 12px;
  border: 1px solid rgba(34, 34, 34, 0.08);
  border-radius: 12px;
  text-decoration: none;
  cursor: pointer;
}

.hb-outer-suggest-service img {
  width: 48px;
  height: 48px;
  object-fit: contain;
  flex-shrink: 0;
}

.hb-outer-suggest-name {
  font-size: 14px;
  line-height: 1.2;
  font-weight: 900;
  color: var(--secondary-background-text-color, #72747A);
}

.hb-outer-suggest-service:hover {
  border-color: var(--field-border-color, #7f7f7f);
}

/* "Order here" when the picked outlet cannot take the order. 1_1 ships the
   class with no styling of its own — dim it so it does not look clickable.
   No pointer-events: none — choice_outlet() still runs in 1_1 and must stay
   reachable for the message to make sense. */
.hb-button-company1.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* --------------------------------------------------------------------------
   4. CATEGORY ICON — artwork centred in its tile
   menu_2.ejs:194 (.cat-btn__icon > img)

   The tile is the designer's (styles.css:746): 72x48, aspect-ratio 3/2,
   overflow hidden; he centres with `display: grid; place-items: center` and
   fills it with `img { width: 100%; height: 100%; object-fit: cover }`
   (styles.css:760). That is the look we want, and where his sheet is in play it
   already holds. Where it is not — the tile renders but the artwork keeps its
   natural size, so it hangs off the text baseline and reads as glued to the top
   of the tile — the correction has to live here.

   Specificity is why these two rules are not a no-op: for site 53 the base 2_0
   sheet arrives as the inline `basic_css` (views/index.ejs:105, filled from
   public.site.css in the DB — 240 KB for that site), i.e. AFTER this file, so a
   rule of equal weight loses on order. `.cat-btn .cat-btn__icon*`
   (0,2,0 / 0,2,1) outranks his `.cat-btn__icon*` (0,1,0 / 0,1,1) whatever the
   order is. Same trick as .geo-modal.is-open above.

   The tile geometry is deliberately NOT repeated here: he resizes it per
   breakpoint (48px, 60px, width:100% in the chip row, styles.css:2809/3029/
   3151) and an addon rule of higher weight would freeze the desktop size over
   every one of them.
   -------------------------------------------------------------------------- */

.cat-btn .cat-btn__icon {
  display: flex;
  align-items: center;
  justify-content: center;
}

.cat-btn .cat-btn__icon img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}

/* ==========================================================================
   Location modal on the designer's shell
   components_2/modal_map_outlets_2.ejs

   The shell is theirs (styles.css .events-modal*), the content is ours. These
   rules cover only what their sheet cannot know about:
   - a real map instead of their static basemap,
   - a 4th switch button (events),
   - the 1_0 outlet card, search and sector markup living inside their pane.

   Nothing here is in styles.css: that file is replaced wholesale by every new
   batch.
   ========================================================================== */

/* --- Right pane: the real map ------------------------------------------- */
/* Their delivery mode paints a Nashville crop straight onto the pane
   (styles.css:7905). We have no crop, we have #lp_map. Same specificity,
   later file -> ours wins. */
.events-modal.is-delivery .events-modal__map,
.events-modal__map {
  background-image: none;
}
/* #lp_map is the only hook the map keeps (map.js:8 MAP_ID) — it needs the
   whole pane, and the map lib sizes itself off the element. */
.events-modal__map > #lp_map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* Their spinner is `position: relative` on the pay screen; over the map it has
   to float in the middle of the pane. */
.events-modal__map > .pay-wait__spinner {
  position: absolute;
  left: 50%;
  top: 50%;
  margin: -18px 0 0 -18px;
  z-index: 3;
}
/* The brand strip rides over the map, as it does in 1_0. He drew no filter
   component, so it is his segmented control, un-pilled and scrollable. */
.events-modal__map > .events-switch {
  position: absolute;
  left: 12px;
  right: 12px;
  top: 12px;
  z-index: 2;
  border-radius: 16px;
  overflow-x: auto;
}
.events-modal__map > .events-switch .events-switch__btn {
  flex: 0 0 auto;
}
.events-modal__map > .events-switch .events-switch__btn img {
  width: auto;
  height: 20px;
  max-width: 90px;
}

/* --- Mode switch: 4 buttons, not 2 -------------------------------------- */
/* With the events button added, one row of 460px cannot hold
   "Pickup Order / Eat-in Order / Delivery Order / Events" — go 2x2. */
.events-switch.has-events {
  flex-wrap: wrap;
}
.events-switch.has-events .events-switch__btn {
  flex: 1 1 40%;
}
/* 1_0 injects the type icon as an svg string; their CSS only sizes
   `.events-switch__btn img`. */
.events-switch__icon {
  display: inline-flex;
  flex-shrink: 0;
}
.events-switch__icon svg {
  width: 24px;
  height: 24px;
  display: block;
}
.events-switch__icon:empty {
  display: none;
}

/* --- CTA ---------------------------------------------------------------- */
.events-modal__cta.disabled,
.events-modal__cta:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
/* The class above only PAINTS. 1_0 blocks the click outright — its
   `.hb-button-company1.disabled` carries `pointer-events: none`
   (public/css/standard/menu.css:899). Without that, a tap on the dead
   "Use this address" on the aggregator screen reaches `order_here(true)`, and
   when a `temp_delivery_point` exists but has no `points` that falls through to
   the pickup branch (menu.js:838-852). Scoped to the delivery bar by its own
   handle so the pickup / eat-in CTAs keep exactly today's behaviour. */
.events-modal__bottom[data-delivery-bottom] .events-modal__cta.disabled,
.events-modal__bottom[data-delivery-bottom] .events-modal__cta:disabled {
  pointer-events: none;
}
/* He draws one button per bar; the `.start` screens carry two ("Order here" +
   "Change location", 1_0 menu.ejs:429-441), and his `.events-modal__bottom`
   sets no display of its own, so the stack is ours. Tagged with
   `data-start-bar` rather than `:has()` — this kit still has to render in the
   Safari the app supports. */
.events-modal__bottom[data-start-bar] {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* --- Scroll trap -------------------------------------------------------- */
/* Their `.events-modal` is `pointer-events: none` so the backdrop behind it can
   take the click — which also lets the wheel through, so the site scrolled
   under the modal. Take pointer events back while it is open and move
   "click outside closes" onto the element itself: @click.self on the root in
   modal_map_outlets_2.ejs. */
.events-modal.is-open {
  pointer-events: auto;
}
.events-modal__body {
  overscroll-behavior: contain;
}

/* --- The designer's card: states he never drew -------------------------- */
.event-card--disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.event-card__brand {
  height: 20px;
  width: auto;
  margin-left: 8px;
  vertical-align: middle;
}
.event-card__outer {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.event-card__outer-service {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: var(--radius-pill, 999px);
  background: var(--background-color, #fff);
  box-shadow: inset 0 0 0 1px var(--field-border-color, #7f7f7f);
}
.event-card__outer-service img {
  height: 20px;
  width: auto;
}
.event-card__outer-name {
  font-size: 14px;
  line-height: 1.2;
  font-weight: 900;
}
.event-card__status--closed {
  color: var(--error-color, #cd222a);
}
/* The 21.09 batch drew `.event-card__available` for the aggregators a store is
   on — but read-only, as a row of logos. Ours have to be links (we cannot take
   the order for an outer outlet, so the card hands the user to the service),
   hence the anchor: his `.event-card__available-logos img` sizes the glyph,
   this only makes the anchor hold it. */
.event-card__available-link {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.event-card__available-name {
  font-family: var(--custom-app-font-bold);
  font-weight: 600;
  font-size: 14px;
  line-height: 18px;
  letter-spacing: -0.4px;
  color: var(--card-text-color, #222);
}
/* Their `.dfield` (the 30.09 name; the 21.09 batch called it `.deliver-field`)
   is a column — label over input. `position: relative` is theirs too
   (styles.css:9639); `flex-shrink: 0` is ours.
   NB the `.search-clear` rule under it is DEAD since the 30.09 batch: the field's
   cross is now their own `.dfield__clear`, which the sheet positions itself
   (styles.css:9642), and the only `.search-clear` left in our markup is the store
   search — that one lives in `.events-search`, not in a `.dfield`. Kept rather
   than deleted: it costs nothing and nothing matches it any more. */
.events-modal__pane .dfield {
  position: relative;
  flex-shrink: 0;
}
.events-modal__pane .dfield .search-clear {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
}

/* --- Delivery form ------------------------------------------------------ */
/* `.delivery` is the 30.09 name of the pane the 21.09 batch called
   `.events-deliver`. Previous addresses and address variants ride on his store
   card, which is built for a venue (name + up to 4 rows). Trimmed for a one-line
   address. */
.delivery .events-day__list {
  gap: 8px;
}
.delivery .event-card {
  gap: 4px;
  padding: 10px 12px;
  border-radius: 16px;
}
.delivery .pay-wait__spinner {
  margin: 0 auto;
}

/* NOTE: at <=820px the designer hides `.events-modal__map` (styles.css:5185)
   and turns the card into a bottom sheet. The map instance stays alive in a
   display:none box — fine on load, but a resize across the breakpoint needs a
   map resize trigger. Left as the designer drew it; say the word if the mobile
   map has to stay. */

/* --------------------------------------------------------------------------
   5. MODIFIER CARD — the selected ring stays above the artwork

   The batch marks the chosen modifier with `border-color` + an inset
   `box-shadow` ring. An inset shadow paints *beneath* the element's content,
   so the opaque `.mod__img` (the white/neutral artwork plate) swallows its top
   and sides — the red ring looks half-covered by the image.

   Two things are needed. First, this file is linked BEFORE the inline
   `<style>` that prints the per-site DB CSS (views/index.ejs:97 then :104), and
   the base 2_0 sheet itself arrives from the DB — so a plain `.mod.is-selected`
   here loses the tie to a same-specificity copy of the designer rule and the
   inset shadow comes back. Scope to `#hb_menu_page` (menu_2.ejs:46) so the
   override wins on specificity, whatever else re-declares it.
   Second, draw the ring with an `::after` overlay — a positioned pseudo paints
   above the artwork, so nothing opaque can cover it, and `inset: 0` with a
   11px radius (12px − the 1px it sits inside) keeps it flush with the 1px
   accent border for the designer's 2px selected outline.
   -------------------------------------------------------------------------- */
#hb_menu_page .mod.is-selected {
  border-color: var(--accent-color);
  box-shadow: none;
  position: relative;
}
#hb_menu_page .mod.is-selected::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--accent-color);
  border-radius: 11px;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   6. DEAL-WARNING POPUP (open_modal) — the close button and the inner scroll

   menu.ejs wraps the generic ModalWindow (component markup is not ours to
   change) in `<div :class="modal.modalclass">`, so the block is
   `.deal-modal-warning .wo-modal-block.wo-modal-message`. Two problems:

   a) The `×` is invisible. Two base rules put it OUTSIDE the card:
        - `default_modals.css:23`  left: calc(100% + 18px)
        - `pj_style/menu.css:987`  left: 100%
      Both are harmless by themselves — the block is a fixed overlay spanning
      the viewport, so "100% of the card" still lands inside it. What hides the
      `×` is that the overlay's ancestor is a zero-width absolutely-positioned
      div, so the card sits flush against the left edge and the `×`, offset past
      the card's right edge, falls beyond it and is clipped by `overflow: hidden`
      on the deal modal shell.
      Fix: pin the `×` INSIDE the card on the deal warning. Anchored to the
      card's own corner it is never clipped, and it matches the 21.09 popup
      language (a white circle with the glyph, `default_modals.css:23`).
   b) The card is a scroll box that clips the `×` while itself being a single
      short line — on Windows / older Macs (always-visible scrollbars) that
      draws a scrollbar around a message that does not need one. The popup never
      grows past its 420px, so let it flow instead of scrolling.

   Scoped to `.deal-modal-warning` — every other `.wo-modal-message` caller
   (checkout, profile, ordering) keeps the shared look.
   -------------------------------------------------------------------------- */
.deal-modal-warning .wo-modal-block.wo-modal-message .wo-modal-body .wo-modal-close {
  top: 16px;
  right: 16px;
  left: auto;
  background: none;
}
.deal-modal-warning .wo-modal-block.wo-modal-message .wo-modal-body {
  overflow: visible;
  text-align: left;
}



/* ==========================================================================
   Order hints / warnings above the checkout CTA (menu_2 cart panel)
   --------------------------------------------------------------------------
   The 1_0 set ported from menu.ejs:723-757 (and the orphaned
   components_2/order_block.ejs): the delivery cart hint, the policy checkbox,
   and the locked-order reasons (outlet closed, site off, LP problem, min sum).

   The 21.09 batch draws none of this — its cart is the happy path — so the
   look is ours, in the designer palette (never --wo-*: NEW_DESIGN_BUGS.md #24).
   Markup keeps 1_0 class names, so a later designer pass restyles in place.
   Menu-only sheet: this block never loads on ordering_2.
   ========================================================================== */

.cart-warnings {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 24px;
}

/* Delivery cart hint — icon + text, soft card, like the totals rows. */
.cart-warnings .hb-cart-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 16px;
  background: var(--card-color);
  color: var(--background-text-color);
  font-size: 14px;
  line-height: 18px;
}

.cart-warnings .hb-cart-hint svg {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  color: var(--accent-color);
}

/* Policy checkbox (1_0 .wo-menu-checkbox). */
.cart-warnings .wo-menu-checkbox label {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 14px;
  line-height: 18px;
  color: var(--background-text-color);
  cursor: pointer;
}

.cart-warnings .wo-menu-checkbox input {
  flex: 0 0 auto;
  margin-top: 2px;
  accent-color: var(--accent-color);
}

.cart-warnings .wo-menu-checkbox p {
  margin: 4px 0 0 24px;
  font-size: 13px;
  line-height: 17px;
  color: var(--accent-color);
}

/* Locked-order reason lines (1_0 .hb-order-locked.hb-order-warning). */
.cart-warnings .hb-order-locked {
  padding: 10px 12px;
  border-radius: 16px;
  font-size: 14px;
  line-height: 18px;
}

.cart-warnings .hb-order-locked p {
  margin: 0;
}

/* Accent TEXT only — no tinted surface behind it. Vadim, 07.10: the line was
   unreadable, red on red. `--secondary-accent-color` is #d8233f66, i.e. the
   SAME red at 40%, and the text is `--accent-color` (#d7223e). Measured in the
   live cart before the change: background rgba(216, 35, 63, 0.4) /
   color rgb(215, 34, 62). The reason line is the only cue that the order is
   locked, so the text keeps the accent; the surface goes. */
.cart-warnings .hb-order-warning {
  color: var(--accent-color);
}

/* --------------------------------------------------------------------------
   The checkout CTA in its refused state — the actual block
   1_0 gets this for free: `.hb-button-company1.disabled { pointer-events: none }`
   (css/standard/pj_style/menu.css:1067). The designer's `.cart-panel__cta` has no
   such rule — his refused state is `[aria-disabled='true']` and it only paints
   (styles.css:8548: secondary-accent background + `cursor: default`) — so a
   refused CTA looked dead but still took the click, and unticking the policy box
   above blocked nothing at all.

   Scoped to `#hb_menu_page` on purpose: `.cart-panel__cta` is ALSO the ordering
   page's CTA, and that one belongs to the designer's checkout_addons.css — its
   locked Place-order state must not inherit this. Both carriers are listed
   because both are live in menu_2.ejs: the 1_0-style `.disabled` class and the
   designer's `aria-disabled`. `:disabled` needs no rule — the browser already
   stops the click on its own. */
#hb_menu_page .cart-panel__cta.disabled,
#hb_menu_page .cart-panel__cta[aria-disabled='true'] {
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   7. REWARDS LOADING
   The batch's prototype has no loading state for the rewards block, so this is
   ours, like the skeleton in §1. It takes the exact slot of "No Rewards yet."
   while `d2_rewards_loading` is on (design2_locations_mixin.js), so the section
   does not jump when the cards arrive.
   Deliberately quiet, and it changes NOTHING about the paragraph itself: the
   empty text has no rule in the sheet at all, so both states are a plain <p> and
   inherit the same font and margins. Only the flex row and the ring are added.
   -------------------------------------------------------------------------- */

.rewards-loading {
  display: flex;
  align-items: center;
  gap: 10px;
}

.rewards-loading__spinner {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  border: 2px solid var(--field-border-color);
  border-top-color: var(--accent-color);
  border-radius: 50%;
  animation: d2-spin 0.8s linear infinite;
}

@keyframes d2-spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .rewards-loading__spinner {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   8. FIRST-VISIT HINT — keep the spotlight under the modals
   The batch sheet puts .hint__spot at z-150 and .hint__tip at z-151
   (styles.css:7158 / :7172) — above EVERY overlay we have: cart-backdrop 60,
   cart-panel 70, pos-backdrop 80, pos-modal 90, signin / account / menu / item /
   events backdrops 90, their modals 100, states-backdrop 110, states-modal 120,
   geo-modal 120, toast 120. So the dim swallowed an open item modal, which is
   why the auto-show sat commented out in pj_logic/menu.js. The hint only has to
   dim the page and the header, so pin it just above the header (.site-header
   z-50) and below the first backdrop (cart-backdrop z-60). Scoped to
   #hb_menu_page (1,1,0) because the sheet loads AFTER this file (inline
   basic_css) and would otherwise win at (0,1,0).
   -------------------------------------------------------------------------- */

#hb_menu_page .hint__spot {
  z-index: 55;
}

#hb_menu_page .hint__tip {
  z-index: 56;
}

/* --------------------------------------------------------------------------
   9. .mod-group__req — the sub-line of a modifier group
   PosItemWindow.js builds p.mod-group__req from the chosen-mods span, the
   min/max message (MIN_MAX_MESSAGE, 4 spans, at most one visible) and the
   always-on .mod-group__tap label. Without a gap "max 2" and "Tap to select" ran
   together. margin-right on every span; the last one is reset because the <p>
   sits inside a <button>, whose text is centred, and a trailing margin would
   shift the line. The sheet has no rule for these classes — nothing to outrank,
   except .mod-group__req.is-chosen (accent), which paints the whole line, so the
   tap label needs its own colour back at higher specificity.
   -------------------------------------------------------------------------- */

#hb_menu_page .mod-group__req span {
  margin-right: 4px;
}

#hb_menu_page .mod-group__req span:last-child {
  margin-right: 0;
}

#hb_menu_page .mod-group__req .mod-group__tap {
  color: var(--secondary-background-text-color);
}

/* --------------------------------------------------------------------------
   10. Mobile: the header and the category strip must stay pinned

   Vadim, 07.10: on a phone both the header and the categories disappear as soon
   as the page scrolls. The designer's sheet is NOT at fault — `.site-header` is
   `position: sticky; top: 0; z-index: 50` and `.categories` is
   `position: sticky; top: var(--header-h); z-index: 40` in his <=820 block (both
   present in the site-53 basic_css).

   What kills them is the LEGACY 1_0 sheet, /css/standard/pj_style/menu.css
   (still linked for menu_2 — see knowledge/design2_head_css_order.md). It sets
   `#hb_menu_page { overflow-x: hidden }` in
   `@media (max-width: 767px) and (min-width: 580px)` (menu.css:7436) and in
   `@media (max-width: 579px)` (menu.css:7812). `overflow-x: hidden` makes
   `#hb_menu_page` a scroll container and computes `overflow-y: auto`; it never
   scrolls itself (scrollHeight === clientHeight === 1611), so both sticky
   elements are pinned to a box that does not move with the document.
   Measured at 390x844, scrollY 600: header rect.top -600, categories -520.

   `clip` clips the same overflow but creates NO scroll container, so the sticky
   goes back to the viewport. It is the same substitution menu_2.ejs already
   makes for `.lp-main-block` (its inline style; !important there only because
   `.lp-main-block` is styled by css/style.css). Measured after: header
   rect.top 0 and categories rect.top 64 (=== --header-h) at scrollY 600 and at
   the 767 floor of the scroll.

   Wrapped in the SAME breakpoint the legacy rules use, so desktop is untouched
   (they do not apply there either) — a bare rule would turn `overflow-x:
   visible` into `clip` on desktop too. No !important needed: this sheet loads
   AFTER pj_style/menu.css (views/index.ejs order) at equal specificity (1,0,0).
   Nothing new gets clipped: `.lp-main-block` already carries `overflow-x: clip
   !important` on this page.
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  #hb_menu_page {
    overflow-x: clip;
  }
}

/* --------------------------------------------------------------------------
   11. Address pill: the date is hidden, the opening hours stay

   Vadim, 07.10: `.header-address__day` ("Oct 7,") must not show in the pill.
   It is OUR markup (menu_2.ejs:140 and :155), not the batch's: the designer's
   sheet has no rule for the class at all — 0 hits in the site-53 basic_css and
   0 in public/css — so there is nothing to outrank and no !important is needed.
   `__day` sits inside `.header-address__when`, next to `__hours` (which the
   sheet does style), so hiding only the day leaves the hours line intact.
   Note for the events arm (menu_2.ejs:155) where `__when` holds ONLY the day:
   it then collapses to zero height and only contributes the parent's 2px gap.
   -------------------------------------------------------------------------- */

.header-address__day {
  display: none;
}

/* --------------------------------------------------------------------------
   12. City / state modal — translated search placeholder

   `v-i18n` writes text nodes (public/js/modules/translation.js:78); it cannot
   fill a native `placeholder`, so the hint is a translated overlay span, the
   same trick as the 1_0 `.wo-city-input label`. The designer's sheet styles
   `.states-search input::placeholder` but has no rule for the overlay; the
   span is absolutely positioned where the placeholder used to sit
   (padding 12 + icon 24 + gap 12 = 48px). Loaded for menu_2 only — the city
   modal is included by menu_2.ejs alone (index.ejs gates menu_addons.css on
   the menu template).
   -------------------------------------------------------------------------- */

.states-search {
  position: relative;
}

.states-search__placeholder {
  position: absolute;
  left: 48px;
  top: 50%;
  transform: translateY(-50%);
  pointer-events: none;
  color: var(--secondary-background-text-color);
  font-family: var(--custom-app-font-reg);
  font-size: 16px;
  line-height: 20px;
  letter-spacing: -0.4px;
}

/* --------------------------------------------------------------------------
   13. Sign-in modal — restore the designer's fonts inside #wo_auth_modal

   The 1_0 sheet `standard/pj_style/menu.css` (linked ONLY on menu_2, index.ejs)
   pins every descendant of the auth modal to Raleway:

       #wo_subscription_modal *, #wo_auth_modal * { font-family: Raleway, sans-serif; }

   That ID selector (1,0,0) outranks every one of the designer's class rules
   (0,1,0), so the WHOLE 2_0 `.signin-modal` — title, subtitle, legal, field
   label/input, code boxes, buttons, the country-code panel — rendered in
   Raleway, while titles OUTSIDE the modal (`.section-title` …) kept
   `var(--custom-title-app-font)`. That is why the heading looked wrong on its
   own: the rest of the modal was off too, just less obviously.
   Re-assert the designer's fonts one id deeper (1,1,0) so they win. Order
   matters — same specificity, so the specific rules must come AFTER the generic
   one. Scoped to `.signin-modal` so the 1_0 modal, which shares `#wo_auth_modal`,
   is untouched. Families per public/css/2_0/styles.css: title / code box →
   --custom-title-app-font, buttons → --custom-button-font, code picker →
   --custom-app-font-bold, everything else → --custom-app-font-reg.
   -------------------------------------------------------------------------- */

#wo_auth_modal .signin-modal,
#wo_auth_modal .signin-modal * {
  font-family: var(--custom-app-font-reg);
}

#wo_auth_modal .signin-modal__title,
#wo_auth_modal .signin-code__box {
  font-family: var(--custom-title-app-font);
}

#wo_auth_modal .signin-continue,
#wo_auth_modal .signin-back,
#wo_auth_modal .signin-resend {
  font-family: var(--custom-button-font);
}

#wo_auth_modal .signin-code-pick__code {
  font-family: var(--custom-app-font-bold);
}

