/* EnAffaire for Restaurants - ordering UI
   Generic: nothing here knows about Zio's. Restaurant theming comes from
   CSS custom properties emitted by index.php. */

:root{
  --accent:#b3202c; --accent-dk:#8c1922; --ink:#1c1a19; --ink-2:#57514d;
  --ink-3:#8b837d; --line:#e6e1dc; --bg:#f6f3f0; --card:#fff;
  --ok:#1f7a4d; --shell:1240px; --rad:10px;
  --brand-gold:#B8860B;
  /* Amber "please double-check", deliberately not accent-red: red on this
     page already means "required"/"price" (.rhead .pill, .grp__r .req,
     .warn). A prospect's own working preview needing a glance is a much
     lower-stakes signal than those, and must not read as an error. */
  --warn-bg:#fff6e6; --warn-line:#f0cb7a; --warn-ink:#7a5310;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font:15px/1.5 "Helvetica Neue",Helvetica,Arial,sans-serif;
  color:var(--ink); background:var(--bg); -webkit-font-smoothing:antialiased;
}

/* ---------- blurred flanking panels (desktop only) ------------------- */
.flank{
  position:fixed; top:0; bottom:0; width:calc((100vw - var(--shell))/2);
  overflow:hidden; z-index:0; pointer-events:none;
}
.flank-l{left:0} .flank-r{right:0}
/* When one wide photograph fills both panels, anchor each side to the opposite
   end of the frame so the two flanks read as one scene spanning the page
   instead of the same crop printed twice. */
.flank-l .flank__img{background-position:left center}
.flank-r .flank__img{background-position:right center}
.flank__img{
  position:absolute; inset:-6%;            /* bleed so blur has no hard edge */
  background-size:cover; background-position:center;
  /* NO css blur here on purpose. The blur is baked server-side by
     scene.php?b=1 and the 160px source is upscaled by background-size:cover,
     which reproduces the look exactly. A CSS `filter: blur()` on a layer this
     large - even at 3px - is expensive enough to hang the renderer outright:
     Page.captureScreenshot timed out on this page three times with it on and
     succeeded instantly with it off. Do not add it back. */
  transform:scale(1.1);
}
.flank__veil{position:absolute;inset:0;
  /* Lightened from .52/.66 so the scene reads. It cannot go much further:
     the wordmark is #B8860B gold and the image is a warm orange sunset, so
     the veil is the only thing giving gold-on-orange usable contrast. */
  background:linear-gradient(180deg,rgba(20,14,12,.46),rgba(20,14,12,.60))}
.flank__brand{
  position:absolute; top:17%; left:0; right:0; display:flex; flex-direction:column;
  align-items:center; gap:10px; text-align:center;
  /* LOCAL SCRIM. Gives the lockup its own contrast so the photograph behind it
     can stay sharp - the alternative was darkening or blurring the whole panel,
     which trades the image away to win the text.

     Painted as this element's OWN background, deliberately not a
     `::before{z-index:-1}`: .flank__brand has z-index:auto and therefore makes
     no stacking context, so a negative-z-index child would escape it and land
     behind .flank__veil - and behind the image itself. A background paints
     behind the element's own content, which is exactly the layer we want.

     Ellipse extents keep it tight to the lockup and fully transparent by 82%,
     so it reads as a soft pool rather than a band across the panel.

     text-shadow/box-shadow, never filter:drop-shadow() - filters on these
     fixed panels hang the renderer (see scene.php). */
  padding:36px 16px 30px;
  background:radial-gradient(ellipse 72% 58% at 50% 50%,
      rgba(0,0,0,.60) 0%,
      rgba(0,0,0,.46) 38%,
      rgba(0,0,0,.18) 66%,
      rgba(0,0,0,0)   82%);
}
.flank__brand img{width:46px;height:46px;display:block;border-radius:9px;
  box-shadow:0 2px 10px rgba(0,0,0,.75)}
.flank__brand .wordmark{
  font-family:"Parisienne",cursive; font-size:34px; line-height:1;
  color:var(--brand-gold); text-shadow:0 2px 6px rgba(0,0,0,.85);
}
.flank__brand small{
  display:block; font-size:10px; letter-spacing:.18em; text-transform:uppercase;
  color:rgba(255,255,255,.82); font-family:inherit;
  text-shadow:0 1px 5px rgba(0,0,0,.92);
}

/* ---------- shell ---------------------------------------------------- */
.shell{
  position:relative; z-index:1; max-width:var(--shell); margin:0 auto;
  background:var(--card); min-height:100vh;
  box-shadow:0 0 44px rgba(0,0,0,.30);
}
.rhead{
  padding:22px 26px 16px; border-bottom:1px solid var(--line);
  display:flex; align-items:flex-end; justify-content:space-between; gap:18px; flex-wrap:wrap;
}
.rhead h1{margin:0;font-size:26px;letter-spacing:-.02em}
.rhead .sub{margin:4px 0 0;color:var(--ink-3);font-size:13px}
.rhead .pill{
  font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--accent);
  border:1px solid var(--accent);border-radius:100px;padding:5px 11px;white-space:nowrap;
}
/* Dine-in. FILLED rather than outlined, and carrying the table number, because
   this pill is doing a job the pick-up one is not: it is how a customer who
   just pointed a camera at a sticker confirms - before adding anything to a
   cart - that the code sent them to their own table and not the next one over.
   That confirmation has to be the loudest thing in the header, so it is solid
   accent instead of the quiet outline the pick-up state uses. */
.rhead .pill--table{
  color:#fff;background:var(--accent);border-color:var(--accent);letter-spacing:.1em;
}

/* Language toggle. Sits beside the pick-up pill but reads as a link, not a
   second status chip - the pill states a fact about the order, this one is an
   action. */
.rhead__r{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.langtog{
  font-size:12px;font-weight:700;color:var(--accent);text-decoration:none;
  border-bottom:1px solid currentColor;padding-bottom:1px;white-space:nowrap;
}
.langtog:hover{opacity:.75}

/* ---------- modifier review banner ------------------------------------
   Shown only when the menu carries at least one auto-extracted group
   (groups[].needs_review, computed server-side in index.php). Sits between
   .rhead and .layout so it reads as page-level context, not a per-item
   warning - it is about the menu as a whole, not any one card. */
.modreview{
  margin:16px 26px 0; padding:12px 16px; border-radius:var(--rad);
  background:var(--warn-bg); border:1px solid var(--warn-line);
  color:var(--warn-ink); font-size:13px; line-height:1.5;
  display:flex; gap:10px; align-items:flex-start;
}
.modreview__ico{flex:none; font-size:15px; line-height:1.5}

/* ---------- free-preview-to-paid CTA -----------------------------------
   Shown only on an unclaimed sandbox (?r=try-<token> with no paid_business_id
   yet). Neutral/informational, not a warning - viewing and ordering here are
   already fully free and working; this is an upsell, not an alert. */
.previewcta{
  margin:16px 26px 0; padding:12px 16px; border-radius:var(--rad);
  background:var(--bg); border:1px solid var(--line); color:var(--ink-2);
  font-size:13px; line-height:1.5;
  display:flex; gap:14px; align-items:center; justify-content:space-between; flex-wrap:wrap;
}

/* ---------- hero video ------------------------------------------------
   Lives INSIDE .shell, above .rhead, so it occupies the content column and
   leaves the fixed .flank panels untouched - they are sized off the viewport,
   not off page flow, so nothing here can shift them.

   The height is DERIVED from the width via aspect-ratio, so 560x314 never
   appears as a fixed pixel size. Capping max-width is what keeps it tight:
   600px wide / (560/314) = ~337px tall, so it cannot become a giant video.
   Do NOT add max-height as well - with aspect-ratio it would letterbox the
   embed inside its own box instead of shrinking it. */
.hero{padding:18px 26px 0;display:flex;justify-content:center}
.hero__frame{
  position:relative; width:100%;      /* max-width = the plugin's native width,
                                         set inline so we never upscale it */
  border-radius:12px; overflow:hidden; background:#000;
  box-shadow:0 3px 16px rgba(0,0,0,.16);
}
/* The iframe keeps the plugin's NATIVE pixel size (width/height attributes) and
   is scaled to fit by order.js. Do not put width/height:100% back here - that
   resizes the iframe without resizing Facebook's layout inside it, which is
   exactly what cropped the video on phones. */
.hero__frame iframe{position:absolute;top:0;left:0;border:0;display:block;
  transform-origin:top left}

/* Photo hero. Shares .hero__frame's radius/shadow with the video so the two
   treatments are interchangeable in the same slot. The source is a 600x600
   master, so object-fit:cover crops it to the landscape band - the same crop
   the demo card shows, which is why the page and the card agree. */
.hero__frame--img{background:#efe9e4;aspect-ratio:16/9}
.hero__img{width:100%;height:100%;object-fit:cover;display:block}

.layout{display:grid;grid-template-columns:212px minmax(0,1fr) 320px;gap:0;align-items:start}

/* ---------- category rail ------------------------------------------- */
.rail{position:sticky;top:0;padding:20px 14px 40px;border-right:1px solid var(--line)}
.search{width:100%;padding:9px 11px;border:1px solid var(--line);border-radius:var(--rad);
  font:inherit;font-size:13px;background:#fbf9f8}
.search:focus{outline:2px solid var(--accent);outline-offset:-1px;background:#fff}
.rail ul{list-style:none;margin:16px 0 0;padding:0}
.rail li+li{margin-top:1px}
.rail button{
  width:100%;text-align:left;background:none;border:0;cursor:pointer;font:inherit;
  font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-2);
  padding:9px 10px;border-radius:7px;
}
.rail button:hover{background:#f3efec;color:var(--ink)}
.rail button[aria-current="true"]{background:var(--accent);color:#fff;font-weight:600}

/* ---------- grid ----------------------------------------------------- */
.grid-wrap{padding:20px 24px 60px;min-width:0}
.cat-h{margin:26px 0 0;padding-bottom:9px;border-bottom:1px solid var(--line)}
.cat-h:first-child{margin-top:0}
.cat-h h2{margin:0;font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--accent)}
/* Per-category notice (allergy wording, "naan sold separately"). Deliberately
   readable rather than fine print - it is the kind of text a customer is
   entitled to see before ordering, not a disclaimer to bury. pre-line keeps
   the source's own line breaks without letting it inject markup, since the
   text is written with textContent. */
.cat-h__note{
  margin:7px 0 0;max-width:70ch;
  font-size:12px;line-height:1.5;color:var(--ink-2);
  white-space:pre-line;text-transform:none;letter-spacing:0;
}
.cards{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:14px}
.card{
  display:flex;gap:12px;align-items:flex-start;text-align:left;width:100%;
  background:var(--card);border:1px solid var(--line);border-radius:var(--rad);
  padding:13px;cursor:pointer;font:inherit;transition:border-color .12s,box-shadow .12s;
}
.card:hover{border-color:var(--accent);box-shadow:0 3px 14px rgba(0,0,0,.07)}
.card__b{flex:1;min-width:0}
/* Today's Special. Filled rather than outlined so it reads as a flag at a
   glance and does not compete with the outlined PICK-UP ORDER pill in the
   header; it borrows the same uppercase/letter-spaced idiom but uses the site
   gold rather than the restaurant accent (2026-09-08). */
.card__sp{display:inline-block;margin:0 0 5px;font-size:9.5px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;background:var(--brand-gold);color:#fff;
  border-radius:100px;padding:3px 8px;line-height:1.2}

/* Today's Special: a soft halo that fades in and out, so the flag catches the
   eye while someone scrolls a long menu. Deliberately a glow rather than a
   scale/shake - nothing moves, so it cannot nudge the layout or make the badge
   hard to tap. The colour is the site gold (--brand-gold, the wordmark and
   "Make this your own" gold) rather than the restaurant's own --accent, so
   the flag reads as an EnAffaire marker and is the same on every menu.
   Where color-mix is unsupported the keyframe declarations are simply dropped
   and the badge keeps the flat static halo below - no broken state. */
.card__sp{box-shadow:0 0 6px 1px rgba(0,0,0,.10);
  animation:ea-sp-glow 2.6s ease-in-out infinite}
@keyframes ea-sp-glow{
  0%,100%{box-shadow:0 0 4px 0 color-mix(in srgb, var(--brand-gold) 30%, transparent)}
  50%    {box-shadow:0 0 14px 4px color-mix(in srgb, var(--brand-gold) 65%, transparent)}
}
/* The pulse is decoration. Anyone who has asked their OS for less motion keeps
   the halo and loses the animation. */
@media (prefers-reduced-motion: reduce){
  .card__sp{animation:none;
    box-shadow:0 0 8px 2px color-mix(in srgb, var(--brand-gold) 40%, transparent)}
}
.card__n{margin:0;font-size:14px;font-weight:700;line-height:1.3}
.card__d{margin:5px 0 0;font-size:12.5px;color:var(--ink-2);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.card__d.open{-webkit-line-clamp:unset}
.more{background:none;border:0;padding:0;margin-top:3px;color:var(--accent);
  font:inherit;font-size:11.5px;text-decoration:underline;cursor:pointer}
.card__p{margin:7px 0 0;font-size:13.5px;font-weight:700}
.card__p em{font-style:normal;font-weight:400;color:var(--ink-3);font-size:11.5px}
/* typographic tile - NOT a stock photo (see report) */
.thumb{
  width:74px;height:74px;flex:none;border-radius:8px;display:grid;place-items:center;
  background:linear-gradient(145deg,#f0e9e4,#e2d8d0);color:var(--accent);
  font-size:25px;font-weight:800;letter-spacing:-.03em;
}
.empty-search{padding:40px 4px;color:var(--ink-3);font-size:13.5px}

/* ---------- cart ----------------------------------------------------- */
.cart{position:sticky;top:0;border-left:1px solid var(--line);padding:20px 18px 40px;
  max-height:100vh;overflow-y:auto}
.cart h2{margin:0 0 14px;font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-2)}
.cart__empty{text-align:center;padding:34px 0;color:var(--ink-3)}
.cart__empty svg{width:42px;height:42px;opacity:.35;margin-bottom:10px}
.line{border-bottom:1px solid var(--line);padding:11px 0}
.line__t{display:flex;justify-content:space-between;gap:10px;align-items:baseline}
.line__n{font-size:13.5px;font-weight:700;margin:0}
.line__q{color:var(--ink-3);font-weight:400;font-size:12px}
.line__p{font-size:13px;font-weight:700;white-space:nowrap}
.mods{margin:6px 0 0;font-size:12px;color:var(--ok);line-height:1.45}
.mods.collapsed{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.line__note{margin:5px 0 0;font-size:11.5px;color:var(--ink-3);font-style:italic}
.line__a{margin-top:7px;display:flex;gap:13px}
.line__a button{background:none;border:0;padding:0;font:inherit;font-size:11.5px;
  color:var(--ink-2);text-decoration:underline;cursor:pointer}
.line__a button:hover{color:var(--accent)}
.totals{display:flex;justify-content:space-between;font-size:15px;font-weight:800;margin:15px 0 4px}
.totals--grand{font-size:17px;padding-top:8px;border-top:1px solid var(--line);margin-top:8px}
.co{margin-top:18px;border-top:1px solid var(--line);padding-top:15px}
.co h3{margin:0 0 11px;font-size:11px;letter-spacing:.15em;text-transform:uppercase;color:var(--ink-2)}
.fld{margin-bottom:10px}
.fld label{display:block;font-size:11.5px;color:var(--ink-2);margin-bottom:4px}
.fld input,.fld select{width:100%;padding:8px 10px;border:1px solid var(--line);
  border-radius:7px;font:inherit;font-size:13px;background:#fbf9f8}
.fld input:focus,.fld select:focus{outline:2px solid var(--accent);outline-offset:-1px;background:#fff}
.phone{display:grid;grid-template-columns:88px 1fr;gap:7px}
.pickup-row{display:flex;justify-content:space-between;align-items:baseline;font-size:13px;
  padding:9px 0;border-bottom:1px solid var(--line)}
.paymsg{margin:0 0 10px;padding:.6rem .8rem;border-radius:8px;font-size:12.5px}
.paymsg--ok{background:#e8f5ec;color:#12663a}
.paymsg--err{background:#fdecea;color:#8c231b}
.pickup-row button{background:none;border:0;padding:0;font:inherit;font-size:11.5px;
  color:var(--accent);text-decoration:underline;cursor:pointer}
/* Dine-in variant of the same row. It STATES the table rather than offering a
   control, so it deliberately has no Change affordance beside it: the number
   the kitchen routes by has to be the one on the code that was scanned, never
   something retyped in the cart. The note says where it came from so its being
   uneditable reads as deliberate rather than broken. */
.pickup-row--table{font-size:15px;font-weight:700}
.pickup-row__note{font-size:11px;font-weight:400;color:var(--ink-3);letter-spacing:.02em}
/* Sub-label under an optional field. Small, but it is the whole difference
   between an unexplained email box and one whose purpose is stated. */
.fld__hint{margin:5px 0 0;font-size:11px;line-height:1.45;color:var(--ink-3)}
.btn{width:100%;padding:13px;border:0;border-radius:8px;background:var(--accent);color:#fff;
  font:inherit;font-size:14px;font-weight:700;cursor:pointer;margin-top:14px}
.btn:hover:not(:disabled){background:var(--accent-dk)}
.btn:disabled{background:#d8d2cd;color:#fff;cursor:not-allowed}

/* ---------- modal ---------------------------------------------------- */
.scrim{position:fixed;inset:0;background:rgba(24,18,15,.62);z-index:50;
  display:flex;align-items:flex-start;justify-content:center;padding:26px 16px;overflow-y:auto}
.modal{background:#fff;border-radius:12px;max-width:560px;width:100%;position:relative;
  box-shadow:0 22px 60px rgba(0,0,0,.36)}
.m__h{position:relative;padding:20px 22px 15px;border-bottom:1px solid var(--line);
  display:flex;gap:14px;align-items:flex-start;
  /* clear the absolutely-positioned back/close buttons - without this the
     title runs underneath them on narrow screens */
  padding-right:92px}
/* Item photo across the top of the modal. object-fit:cover matches how every
   other photo in this app is fitted (.thumb--photo, the demo-index card), so a
   tall or square source is cropped rather than squashed.

   aspect-ratio sets the height from the modal's width - 560px wide gives ~315px
   on desktop, against the 62px tile this replaces. The max-height is the mobile
   guard: on a short viewport the ratio alone would push the add-to-cart bar
   below the fold, and dvh (not vh) is what keeps that true while a phone
   browser's URL bar is showing. */
.m__hero{
  display:block;width:100%;aspect-ratio:16/9;
  max-height:min(34dvh,320px);
  object-fit:cover;background:#efe9e4;
  border-radius:12px 12px 0 0;
}
/* The hero costs vertical space, so the scrolling body gives some back. Without
   this the modal can outgrow a phone screen and the Add to cart bar lands off
   the bottom - the one control the whole modal exists to reach. */
.modal--hero .m__b{max-height:min(38dvh,400px)}
.modal--hero .m__h{padding-top:16px}

/* Short viewports - a phone held upright, which is how these get shown on a
   sales call. Measured on a 375x667 iPhone SE the 16/9 hero made the modal
   711px tall against a 667px screen, putting the Add to cart bar exactly on
   the fold. Trimming the hero and the scroll body brings the whole modal back
   inside the screen; the hero is still ~160px, well over twice the 62px
   thumbnail it replaced, so nothing is given up visually. */
@media (max-height:720px){
  .m__hero{max-height:24dvh}
  .modal--hero .m__b{max-height:min(32dvh,400px)}
  .scrim{padding:12px 10px}
}

.m__h h2,.m__h p{overflow-wrap:anywhere}
.m__h .thumb{width:62px;height:62px;font-size:22px}
.m__h h2{margin:0;font-size:19px;line-height:1.25}
.m__h p{margin:5px 0 0;font-size:12.5px;color:var(--ink-2)}
.m__x,.m__back{position:absolute;top:13px;background:#f2eeeb;border:0;width:29px;height:29px;
  border-radius:50%;cursor:pointer;font-size:15px;line-height:1;color:var(--ink-2)}
.m__x{right:13px} .m__back{right:48px}
.m__x:hover,.m__back:hover{background:var(--accent);color:#fff}
.m__b{padding:4px 22px 16px;max-height:min(52vh,470px);overflow-y:auto}
.grp{padding:16px 0;border-bottom:1px solid var(--line)}
.grp:last-child{border-bottom:0}
.grp__n{margin:0;font-size:11.5px;letter-spacing:.15em;text-transform:uppercase;color:var(--accent);font-weight:700}
.grp__r{margin:3px 0 10px;font-size:12px;color:var(--ink-3)}
.grp__r .req{color:var(--accent);font-weight:600}
.opt{display:flex;align-items:center;gap:10px;padding:7px 0;cursor:pointer;font-size:13.5px}
.opt input{width:16px;height:16px;accent-color:var(--accent);flex:none;cursor:pointer}
.opt span{flex:1}
.opt em{font-style:normal;color:var(--ink-2);font-size:12.5px;white-space:nowrap}
.opt.disabled{opacity:.36;cursor:not-allowed}
/* "included" reads as a status, not a price - so it must not borrow the
   price styling sitting in the same slot. */
.opt em.inc{font-size:11px;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3)}
.note-l{display:block;font-size:12.5px;color:var(--ink-2);margin:0 0 6px}
.m__b textarea{width:100%;min-height:58px;padding:9px 10px;border:1px solid var(--line);
  border-radius:8px;font:inherit;font-size:13px;resize:vertical;background:#fbf9f8}
.m__b textarea:focus{outline:2px solid var(--accent);outline-offset:-1px;background:#fff}
.cnt{display:flex;justify-content:space-between;margin-top:5px;font-size:11px;color:var(--ink-3)}
.m__f{display:flex;gap:12px;align-items:center;padding:14px 22px;border-top:1px solid var(--line);
  background:#fbf9f8;border-radius:0 0 12px 12px;position:sticky;bottom:0}
.qty{display:flex;align-items:center;gap:3px;border:1px solid var(--line);border-radius:8px;background:#fff}
.qty button{width:34px;height:38px;border:0;background:none;font-size:17px;cursor:pointer;color:var(--ink-2)}
.qty button:hover:not(:disabled){color:var(--accent)}
.qty button:disabled{opacity:.3;cursor:not-allowed}
.qty span{min-width:26px;text-align:center;font-weight:700;font-size:14px}
.m__f .btn{margin:0;flex:1}
.warn{padding:0 22px 12px;font-size:12px;color:var(--accent)}

/* ---------- owner CTA -------------------------------------------------
   Quiet on purpose: a diner is here to order, not to read our marketing. Small,
   muted, below a hairline at the very end of the menu, and it only gains colour
   on hover. It is NOT in the header and NOT fixed - both would put it in front
   of someone mid-order.

   ⚠ Deliberately carries no @media rule of any kind, so it cannot be lost at a
   breakpoint the way .ea-badge is above 1279px. */
.ownercta{
  margin:30px 0 0; padding:18px 0 24px;
  border-top:1px solid var(--line); text-align:center;
}
.ownercta a{
  display:inline-flex; align-items:center; gap:8px;
  text-decoration:none; color:#7a8593; font-size:13px; line-height:1;
  padding:7px 12px; border-radius:9px;
  transition:color .15s, background-color .15s;
}
.ownercta a:hover, .ownercta a:focus-visible{
  color:var(--accent); background:rgba(24,18,15,.045);
}
.ownercta img{ width:18px; height:18px; border-radius:5px; opacity:.7; display:block; }
.ownercta a:hover img, .ownercta a:focus-visible img{ opacity:1; }

/* ---------- responsive ------------------------------------------------ */
/* ---------- mobile EnAffaire badge -----------------------------------
   Hidden by default: on desktop the .flank panels already carry the lockup,
   and two lockups on one screen is worse than none. */
.ea-badge{display:none}

@media (max-width:1279px){
  .flank{display:none}
  /* padding-top RESERVES the badge's own strip at the top of the card, so the
     badge can never sit over the hero video's Facebook Share control at scroll
     0. Without it a fixed top-right badge lands exactly on the video's
     top-right corner on a phone. */
  .shell{max-width:none;box-shadow:none;padding-top:56px}

  .ea-badge{
    display:inline-flex; align-items:center; gap:8px;
    position:fixed; top:8px; right:10px;
    /* Below .scrim (50) on purpose: an open item modal should cover the badge,
       not have a logo floating over the dialog. */
    z-index:40;
    padding:6px 13px 6px 7px; border-radius:999px;
    background:rgba(255,255,255,.93);
    -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
    border:1px solid rgba(24,18,15,.08);
    box-shadow:0 2px 10px rgba(24,18,15,.17);
    text-decoration:none; line-height:1;
  }
  .ea-badge img{width:30px;height:30px;display:block;border-radius:7px}
  .ea-badge .wordmark{
    font-family:'Parisienne',cursive; color:var(--brand-gold);
    font-size:21px; line-height:1; padding-bottom:3px; white-space:nowrap;
  }
}

/* Very narrow phones: scale the WHOLE lockup down. Never drop the wordmark -
   the standing rule is that the EnAffaire name is never icon-only. */
@media (max-width:360px){
  .ea-badge{padding:5px 10px 5px 6px; gap:6px}
  .ea-badge img{width:26px;height:26px}
  .ea-badge .wordmark{font-size:18px}
}
@media (max-width:1000px){
  .layout{grid-template-columns:1fr}
  .rail{position:static;border-right:0;border-bottom:1px solid var(--line);padding:14px}
  /* WRAP, never a scroll strip. Phones hide overflow scrollbars, so a
     horizontally scrolling pill row gave no hint the later categories existed
     and several were simply unreachable. Wrapping guarantees every category is
     on screen with no affordance to discover. */
  .rail ul{display:flex;flex-wrap:wrap;gap:6px;overflow:visible;margin-top:11px}
  .rail li+li{margin-top:0}
  .rail button{white-space:nowrap;padding:7px 11px;border:1px solid var(--line);
    width:auto;font-size:10px}
  .cart{position:static;border-left:0;border-top:9px solid var(--bg);max-height:none;overflow:visible}
  .grid-wrap{padding:16px 14px 30px}
  .hero{padding:12px 14px 0}
  .rhead{padding:16px 14px 13px}
  .rhead h1{font-size:21px}
  .modreview{margin:12px 14px 0}
  .previewcta{margin:12px 14px 0}
}
@media (max-width:560px){
  .cards{grid-template-columns:1fr}
  .scrim{padding:0}
  .modal{border-radius:0;min-height:100vh}
  .m__f{border-radius:0}
  .m__b{max-height:none}
}

/* ---------- item photos ------------------------------------------------
   .thumb is a 74px grid box centring the initials. With a photo it becomes a
   frame instead: the img fills it and crops, so a 940x627 stock shot and a
   square one both sit correctly. */
.thumb--photo{padding:0;overflow:hidden;background:#efe9e4}
.thumb--photo img{width:100%;height:100%;object-fit:cover;display:block}

/* The demo claim CTA. Same shell as .previewcta - it is the same kind of
   notice in the same slot - with a gold left edge so it reads as EnAffaire
   speaking rather than as another warning from the restaurant's own page.
   Deliberately NOT amber: .modreview directly above it is amber, and two
   amber bars stacked read as two problems. */
.previewcta--claim{
  border-left:3px solid #B8860B;
  background:linear-gradient(90deg,rgba(184,134,11,.06),var(--bg) 42%);
}
.previewcta--claim .btn{
  background:#B8860B; border-color:#B8860B; color:#fff; white-space:nowrap;
  /* On a filled gold pill the inherited link underline reads as a rendering
     mistake rather than as a link affordance. */
  text-decoration:none;
}

/* ---- take-out hours -------------------------------------------------------
   A <details> rather than a modal: open/closed has to be readable at a glance,
   and the full week is a tap away without permanently spending vertical space
   above the food. The dot carries the state redundantly with the word, so it
   still reads for anyone who cannot separate the green from the red. */
.hrs{margin:0 0 14px;border:1px solid var(--line);border-radius:10px;
  background:#fff;overflow:hidden}
.hrs > summary{list-style:none;cursor:pointer;display:flex;align-items:center;
  gap:8px;padding:10px 14px;font-size:.95rem}
.hrs > summary::-webkit-details-marker{display:none}
.hrs__dot{flex:0 0 auto;width:9px;height:9px;border-radius:50%;background:#9aa3af}
.hrs--open .hrs__dot{background:#12a150;box-shadow:0 0 0 3px rgba(18,161,80,.15)}
.hrs--shut .hrs__dot{background:#c1392b;box-shadow:0 0 0 3px rgba(193,57,43,.13)}
.hrs__main{color:#20304a}
.hrs--open .hrs__main{color:#0e7a3c}
.hrs--shut .hrs__main{color:#a32b1f}
.hrs__sub{color:var(--muted)}
.hrs__more{margin-left:auto;font-size:.8rem;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;color:#B8860B}
.hrs[open] .hrs__more{opacity:.55}
.hrs__tbl{width:100%;border-collapse:collapse;font-size:.9rem;
  border-top:1px solid var(--line)}
.hrs__tbl th,.hrs__tbl td{padding:7px 14px;text-align:left;font-weight:400;
  color:var(--muted);vertical-align:top}
.hrs__tbl th{width:9.5em;color:#20304a}
.hrs__tbl tr.is-today th,.hrs__tbl tr.is-today td{background:#fbf7ee;font-weight:700;color:#20304a}
.hrs__tbl td.is-closed{color:#a32b1f}
@media (max-width:520px){
  .hrs__more{display:none}
  .hrs__tbl th{width:7em}
}
/* ── machine-translation disclaimer ───────────────────────────────────
   Louder than .modreview on purpose. .modreview is amber "please check this";
   this is a red-edged alert, because the thing it is warning about is an
   allergen list a machine wrote. It sits above everything else in the column
   and is the only element on the page with this treatment. */
.mtnotice{display:flex;gap:11px;align-items:flex-start;margin:0 0 14px;padding:13px 15px;
  border:1px solid #e3b7b1;border-left:4px solid #c0392b;border-radius:9px;
  background:#fdf3f1;color:#5d2a24;font-size:.93rem;line-height:1.5}
.mtnotice strong{color:#a5281c}
.mtnotice b{font-weight:700}
.mtnotice__ico{flex:0 0 auto;font-size:1.05rem;line-height:1.4;color:#c0392b}
.mtnotice__orig{display:inline-block;margin-top:6px;font-weight:600;color:#a5281c;
  text-decoration:underline;text-underline-offset:2px}
.mtnotice__orig:hover{color:#7d1e15}
@media (max-width:520px){.mtnotice{font-size:.89rem;padding:11px 12px}}

/* Looping video in a card thumbnail (experiment, one item). Same box model as
   .thumb--photo img so the slot is identical whether it holds a photo or a
   loop - nothing reflows if the video is swapped back out for a still. */
.thumb--video video{width:100%;height:100%;object-fit:cover;display:block}

/* ── Live order status (RKP POS DECISIONS 50) ───────────────────────────
   Shown only when the restaurant runs a kitchen display. Three steps, read
   at arm's length on a phone held over a table, so the type does not go
   below 15px and the current step is carried by weight and colour rather
   than by a colour alone. */
.ostat { margin-top: 18px; }
.ostat__steps { list-style: none; margin: 0; padding: 0; }
.ostat__step {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 0; font-size: 15px; color: #6e6a63;
}
.ostat__dot {
  flex: 0 0 auto; width: 12px; height: 12px; border-radius: 50%;
  background: #d8d4cc; box-shadow: inset 0 0 0 1px rgba(0,0,0,.06);
}
.ostat__step.is-done { color: #3e7d4c; }
.ostat__step.is-done .ostat__dot { background: #3e7d4c; }
.ostat__step.is-now { color: #1d1b18; font-weight: 600; }
.ostat__step.is-now .ostat__dot {
  background: #b8860b;
  box-shadow: 0 0 0 4px rgba(184,134,11,.18);
}
/* The "now" step breathes, so a glance tells you it is live rather than a
   static picture of a checklist. Honoured only if the guest has not asked
   for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .ostat__step.is-now .ostat__dot { animation: ostatPulse 1.8s ease-in-out infinite; }
}
@keyframes ostatPulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(184,134,11,.18); }
  50%      { box-shadow: 0 0 0 8px rgba(184,134,11,.06); }
}
.ostat__msg { margin: 10px 0 0; font-size: 15px; color: #4a4640; }

/* ── Call server (RKP POS DECISIONS 50) ─────────────────────────────────
   Sits beside the table pill in the header. Quiet by default: this is a
   safety valve, not a call to action, and a loud button next to the table
   number would get pressed out of curiosity on every scan. */
.callsrv {
  appearance: none; cursor: pointer;
  margin-left: 8px; padding: 7px 14px;
  font: inherit; font-size: 14px; font-weight: 600; line-height: 1;
  color: #5c5851; background: #f2efe9;
  border: 1px solid #ddd8cf; border-radius: 999px;
  min-height: 34px;
}
.callsrv:hover { background: #ebe7df; }
.callsrv:active { transform: translateY(1px); }
.callsrv:focus-visible { outline: 2px solid #b8860b; outline-offset: 2px; }
.callsrv[disabled] { cursor: default; opacity: .85; }
.callsrv--done {
  color: #2f6b3c; background: #e8f2e9; border-color: #cfe3d3;
}

/* ── Dietary preference filters (RKP POS DECISIONS 51) ──────────────────
   PREFERENCE, not allergy — there is deliberately no gluten-free or
   nut-free chip here. Styled as quiet toggles rather than primary buttons:
   most guests are not filtering, and a loud row above the menu would push
   the food itself below the fold on a phone. */
.dietfilters { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 0; }
.dietchip {
  appearance: none; cursor: pointer;
  padding: 6px 13px; min-height: 32px;
  font: inherit; font-size: 14px; line-height: 1;
  color: #5c5851; background: #f4f1eb;
  border: 1px solid #e0dbd2; border-radius: 999px;
}
.dietchip:hover { background: #ede9e1; }
.dietchip:focus-visible { outline: 2px solid #b8860b; outline-offset: 2px; }
.dietchip.is-on {
  color: #22502c; background: #e4efe6; border-color: #bcd8c2; font-weight: 600;
}
