/* ============================================================
   components.css — UI components (layer 5 of 5)
   Mobile-first. Larger-screen layout via min-width breakpoints at the bottom.
   No raw hex here — only semantic tokens + neutral rgba scrims.
   ============================================================ */

/* ---- nav ---- */
.nav { position: sticky; top: 0; z-index: 40; background: rgba(250,249,246,0.9); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); }
.nav__in { display: flex; align-items: center; justify-content: space-between; height: 84px; gap: 16px; max-width: var(--maxw); margin: 0 auto; padding: 0 clamp(20px,5vw,56px); }
/* "Amelia's"-only script wordmark. Its box carries a tall l-ascender + apostrophe,
   so the lettering reads small for a given box height — hence the generous sizing.
   .nav__in is a fixed 84px (92px >=980px), so this never moves the bar. */
.nav__logo { height: 64px; width: auto; }
.nav__brand { display: inline-flex; align-items: center; }
/* The drawer is the ONLY route to these pages at every width (8/5 client call), so it
   is a real panel rather than a phone fallback: it gets a close control, and app.js
   moves focus into it and back to the burger. */
.nav__drawer { position: absolute; top: 100%; left: 0; right: 0; background: var(--cream); border-bottom: 1px solid var(--line); box-shadow: 0 12px 24px rgba(0,0,0,0.07); }
.nav__drawer[hidden] { display: none; }
.nav__drawer-in { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; max-width: var(--maxw); margin: 0 auto; padding: 14px clamp(20px,5vw,56px) 18px; }
.nav__drawer a.lnk { position: relative; display: block; width: 100%; padding: 11px 0; color: var(--ink-2); font-size: 1rem; letter-spacing: 0.02em; font-weight: 500; border-bottom: 1px solid var(--line); }
.nav__drawer a.lnk:last-of-type { border-bottom: 0; }
.nav__drawer a.lnk:hover, .nav__drawer a.lnk:focus-visible { color: var(--ink); }
.nav__drawer a.lnk[aria-current="page"] { color: var(--ink); font-weight: 600; }
.nav__drawer-close { margin-top: 10px; background: none; border: 0; padding: 10px 0; color: var(--text-muted); font-family: var(--font-body); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; cursor: pointer; }
.nav__drawer-close:hover { color: var(--ink); }

/* Both CTAs are hidden on a phone — there they live in .actionbar, so neither ever
   renders twice on one screen. */
.nav__cta { display: none; gap: 10px; align-items: center; }
.nav__burger { display: inline-flex; align-items: center; gap: 2px; background: none; border: 0; cursor: pointer; color: var(--ink); padding: 8px; }
/* Chevron, not the word "Menu": Amelia's HAS a Menu destination and the label would
   collide with it. This buys the expandability signal without a reading word. */
.nav__burger-chev { transition: transform .22s ease; }
.nav__burger[aria-expanded="true"] .nav__burger-chev { transform: rotate(180deg); }
.nav__right { display: flex; align-items: center; gap: 4px; }
/* Instagram joined this row on 2026-08-12 ("I kinda feel like it should just go at the
   top… next to the profile and the cart icon" — "Yeah"), at every width, so it shares
   the icon treatment rather than getting its own. */
.nav__cart, .nav__account, .nav__ig { display: inline-flex; align-items: center; justify-content: center; color: var(--ink); padding: 8px; }
.nav__cart:hover, .nav__account:hover, .nav__ig:hover { color: var(--accent); }
.nav__ig svg { display: block; }

/* ---- sticky bottom action bar (phone) ----
   The two things a visitor came to do, in the thumb zone. Top corners are the
   hard-to-reach zone for one-handed use, which is exactly where a top-bar Order button
   sits on a phone. Hidden from 980px up, where the buttons are in the bar instead. */
.actionbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 45; display: flex; gap: 8px; padding: 10px clamp(12px,4vw,20px) calc(10px + env(safe-area-inset-bottom)); background: rgba(250,249,246,0.94); backdrop-filter: blur(10px); border-top: 1px solid var(--line); }
/* Scoped to .actionbar deliberately. This rule sits ABOVE .btn in this file, so at equal
   specificity .btn wins and every colliding property here (font-size, padding) silently
   never applied. The extra class outranks it regardless of source order. */
.actionbar .actionbar__btn { flex: 1 1 0; min-width: 0; padding: 14px 10px; font-size: 0.82rem; letter-spacing: 0.06em; }
/* Keep the bar from covering the last of the page + the footer. */
body:has(.actionbar) { padding-bottom: 72px; }

/* ---- buttons + arrow links ---- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; font-family: var(--font-body); font-size: 0.78rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase; padding: 12px 22px; border: 1.5px solid var(--ink); color: var(--ink); background: transparent; cursor: pointer; transition: background 0.2s, color 0.2s; border-radius: var(--r); white-space: nowrap; }
.btn:hover { background: var(--ink); color: var(--cream); }
.btn--solid { background: var(--ink); border-color: var(--ink); color: var(--cream); }
.btn--solid:hover { background: var(--ink-deep); border-color: var(--ink-deep); }
.btn--accent { background: var(--accent); border-color: var(--accent); color: var(--cream); }
.btn--lg { padding: 16px 30px; font-size: 0.8rem; }
.btn--sm { padding: 9px 14px; font-size: 0.78rem; }
.btn--block { width: 100%; }
.btn--ghost-light { border-color: var(--white); color: var(--white); }
.btn--ghost-light:hover { background: var(--white); color: var(--ink); }
/* filled light button — the primary action on a DARK surface (cookie bar, dark
   bands). A plain .btn there renders dark-on-dark and washes out. */
.btn--solid-light { background: var(--cream); border-color: var(--cream); color: var(--ink); }
.btn--solid-light:hover { background: var(--white); border-color: var(--white); color: var(--ink); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* A standalone call to action, not an inline link, so it earns a finger-sized row. The
   underline stays tight to the text via the inner span; the padding grows the hit box. */
.link-arrow { display: inline-flex; align-items: center; gap: 9px; padding: 9px 0; font-size: 0.8rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink); border-bottom: 1.5px solid var(--accent); }
.link-arrow svg { transition: transform 0.25s; }
.link-arrow:hover svg { transform: translateX(5px); }

/* ---- heroes / page headers ---- */
.page-hero { position: relative; min-height: clamp(280px,46vh,460px); display: flex; align-items: flex-end; overflow: hidden; background: var(--ink); }
.page-hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.page-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(22,22,16,0.92), rgba(22,22,16,0.55) 55%, rgba(22,22,16,0.22)); }
.page-hero__in { position: relative; z-index: 2; color: var(--white); max-width: var(--maxw); margin: 0 auto; width: 100%; padding: clamp(28px,5vw,56px) clamp(20px,5vw,56px); }
.page-hero h1 { font-size: clamp(2.2rem,5.5vw,4.4rem); color: var(--white); text-shadow: 0 2px 18px rgba(0,0,0,0.45); }
.page-hero p { color: rgba(255,255,255,0.94); max-width: 54ch; margin: 14px 0 0; text-shadow: 0 1px 10px rgba(0,0,0,0.45); }
.page-hero .kicker { color: var(--gold-bright); text-shadow: 0 1px 10px rgba(0,0,0,0.55); }
/* home hero scrim — guarantees text contrast over imagery (min 0.5 dark) */
.home-hero { position: relative; min-height: clamp(440px,80vh,760px); display: flex; align-items: center; background: var(--ink); overflow: hidden; }
.home-hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.home-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to right, rgba(0,0,0,0.62), rgba(0,0,0,0.32)); }
.home-hero__in { position: relative; z-index: 2; color: var(--white); max-width: var(--maxw); margin: 0 auto; width: 100%; padding: clamp(32px,6vw,72px) clamp(20px,5vw,56px); }
.page-head { padding: clamp(30px,4vw,48px) 0 0; }
.page-head h1 { font-size: clamp(2rem,4.6vw,3.4rem); margin: 0; }
.page-head p { color: var(--ink-2); margin: 12px 0 0; max-width: 54ch; }
/* The title sits close to the content it introduces — kill the ~88px section
   gap that made every interior page read as sparse/unfinished (client 7/14). */
.page-head + .section, .page-head + section { padding-top: clamp(10px,1.8vw,20px); }

/* ---- section heads ---- */
.head { max-width: 44ch; margin-bottom: 32px; }
.head h2 { font-size: clamp(1.8rem,4.4vw,3.2rem); }
.head p { color: var(--ink-2); margin: 14px 0 0; }
.head--row { display: flex; flex-direction: column; align-items: flex-start; gap: 16px; max-width: none; }

/* ---- split (image + body), mobile = stacked ---- */
.split { display: grid; grid-template-columns: 1fr; }
.split__media { position: relative; overflow: hidden; height: 52vh; }
.split__media img { width: 100%; height: 100%; object-fit: cover; }
.split__body { display: flex; flex-direction: column; justify-content: center; padding: clamp(32px,7vw,92px) clamp(24px,6vw,80px); }
.split__body h2 { font-size: clamp(1.8rem,4vw,3.1rem); margin: 0 0 18px; }
.split__body p { color: var(--ink-2); }

/* ---- cards / grids (mobile = single column) ---- */
.grid { display: grid; gap: 24px; grid-template-columns: 1fr; }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.card__media { aspect-ratio: 4/3; overflow: hidden; background: var(--bg-soft); }
.card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.9s cubic-bezier(0.2,0.7,0.2,1); }
.card:hover .card__media img { transform: scale(1.04); }
/* Branded tonal panel for cards whose item has no photo yet — identical 4:3
   geometry, deliberately warm (never white/gray, so it never reads as a
   failed load), tone-on-tone script mark. No letters, no icons, no "coming
   soon". Two whisper-apart tints alternate (by item id) so a run of panels
   doesn't wallpaper. */
.card__media--brand { display: grid; place-items: center; background: color-mix(in srgb, var(--taupe) 26%, var(--cream-2)); }
.card__media--brand-alt { background: color-mix(in srgb, var(--taupe) 16%, var(--cream-2)); }
.card__media--brand::after {
  content: "";
  width: 46%;
  aspect-ratio: 1300 / 560; /* the "Amelia's" script wordmark's intrinsic ratio */
  background: color-mix(in srgb, var(--text-muted) 55%, var(--taupe));
  -webkit-mask: url("../brand/amelias-wordmark.svg") center / contain no-repeat;
  mask: url("../brand/amelias-wordmark.svg") center / contain no-repeat;
  opacity: 0.5;
}
.card__body { padding: 18px 20px; }
.card__title { font-family: var(--font-display); font-size: 1.25rem; font-weight: 500; }
.price { font-family: var(--font-display); font-style: italic; color: var(--ink); font-size: 1.15rem; white-space: nowrap; }

/* ---- menu list ---- */
.menu-tabs { display: flex; gap: 6px; flex-wrap: wrap; border-bottom: 1px solid var(--line); margin-bottom: 8px; }
.menu-tab { font-family: var(--font-display); font-size: 1.05rem; padding: 12px 18px; color: var(--sage); border: 0; border-bottom: 2px solid transparent; background: none; cursor: pointer; }
.menu-tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); }
.menu-section { margin-top: 40px; }
.menu-section h3 { font-family: var(--font-display); font-size: 1.5rem; margin: 0 0 6px; }
.menu-section__note { color: var(--sage); font-size: 0.9rem; margin: 0 0 18px; }
.menu-item { display: grid; grid-template-columns: 1fr; gap: 6px 18px; padding: 14px 0; border-bottom: 1px solid var(--line); }
.menu-item__name { font-weight: 600; }
/* Multi-tier prices ("$8 | $12 | $16") must be allowed to wrap at the separators on
   narrow rows, or they overflow the item box. Each "$8.00" has no internal space so it
   never breaks mid-price; only the " | " is a break opportunity. */
.menu-item__price { font-family: var(--font-display); font-style: italic; color: var(--ink); white-space: normal; text-align: right; }
.menu-item__desc { grid-column: 1/-1; color: var(--ink-2); font-size: 0.92rem; max-width: 70ch; }
.menu-item__tags { grid-column: 1/-1; display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.menu-item--soldout { opacity: 0.5; }
.tag { font-size: 0.66rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--olive-ink); border: 1px solid var(--line); border-radius: 999px; padding: 2px 9px; }

/* ---- forms ---- */
.field { margin-bottom: 16px; }
.field label { display: block; font-size: 0.82rem; font-weight: 600; margin-bottom: 6px; color: var(--ink-2); }
.req { color: var(--danger); }
.input, .select, .textarea { width: 100%; font-family: inherit; font-size: 0.98rem; padding: 13px 14px; min-height: 46px; border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white); color: var(--ink); }
.input:focus, .select:focus, .textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }
.field__hint { font-size: 0.82rem; color: var(--sage); margin-top: 5px; }
.field__error { font-size: 0.82rem; color: var(--danger); margin-top: 5px; }
.form-actions { display: flex; gap: 12px; align-items: center; justify-content: flex-end; margin-top: 20px; flex-wrap: wrap; }
.form-actions__left { margin-right: auto; }

/* ---- table ---- */
.tbl { width: 100%; font-size: 0.95rem; }
.tbl th { text-align: left; font-weight: 600; color: var(--sage); font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.06em; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.tbl td { padding: 13px 12px; border-bottom: 1px solid var(--line); font-variant-numeric: tabular-nums; }

/* ---- badges / alerts ---- */
.badge { display: inline-flex; align-items: center; gap: 6px; font-size: 0.72rem; font-weight: 600; padding: 4px 11px; border-radius: 999px; background: var(--bg-soft); color: var(--ink-2); }
.badge--ok { background: var(--c-ok-bg); color: var(--c-ok-ink); }
.badge--warn { background: var(--c-warn-bg); color: var(--c-warn-ink); }
.badge--new { background: var(--c-warn-bg); color: var(--c-warn-ink); }
.badge--danger { background: var(--danger-bg); color: var(--danger); }
.alert { padding: 14px 16px; border-radius: var(--r); border: 1px solid var(--line); background: var(--surface); margin-bottom: 16px; }
.alert--ok { background: var(--c-ok-bg); color: var(--c-ok-ink); border-color: var(--c-ok-ink); }
.alert--warn { background: var(--c-warn-bg); color: var(--c-warn-ink); border-color: var(--c-warn-ink); }
.alert--danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger); }

/* ---- cookie consent ---- */
.cookie-bar { position: fixed; bottom: 0; left: 0; right: 0; z-index: 60; background: var(--ink-deep); color: var(--onink-bright); padding: 16px clamp(20px,5vw,56px); display: flex; gap: 16px; align-items: center; justify-content: center; flex-wrap: wrap; }
/* THE COOKIE BAR STACKS ON TOP OF THE ACTION BAR, IT DOES NOT COVER IT (2026-08-31).
   Both were fixed at bottom:0 and the cookie bar wins on z-index (60 vs 45), so on a
   phone it sat directly over ORDER NOW and RESERVE A TABLE. Measured on staging at
   390x664: the bar wraps to 143px tall and occupies y 521-664, swallowing the whole
   72px action bar — elementFromPoint on the centre of ORDER NOW returned the cookie
   bar's Decline button. Every first-time visitor on a phone had to dismiss a cookie
   notice before they could order, and nothing in the markup said so.
   Found while measuring the Privy overlap; it is a separate bug and predates Privy.
   72px is the action bar's height, the same constant `body:has(.actionbar)` already
   pads with above; the safe-area inset is added because the action bar carries it.
   --privy-lift is the height of Privy's collapsed tab when one is on screen, written by
   app.js — three fixed things end up wanting this corner, and without it the cookie
   bar's own Decline/Accept were half under the tab. It defaults to 0px, so a page with
   no Privy widget is unaffected and the rule still works with the script switched off. */
body:has(.actionbar) .cookie-bar { bottom: calc(72px + var(--privy-lift, 0px) + env(safe-area-inset-bottom)); }

/* ---- footer ---- */
/* Tightened 7/14 (Tim): no brand column, three horizontal columns, and the
   copyright + legal links collapsed onto one line — less vertical footprint. */
.foot { background: var(--ink-deep); color: var(--onink); padding: clamp(24px,3.2vw,40px) 0 18px; }
/* auto-fit: 2 columns on phones (3×~110px overflowed — the email spilled into
   Hours), 3 columns from ~560px; desktop override below keeps 1.6fr 1fr 1fr. */
.foot__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 16px 24px; }
/* Address, phone and email are real links and were 30px tall, under the 44px floor for a
   finger. The hours lines are plain text and only need to sit on the same rhythm. */
.foot__line { margin: 0; padding: 10px 0; color: var(--onink); font-size: 0.92rem; }
.foot__grid a { overflow-wrap: anywhere; }
.foot__more { display: flex; flex-wrap: wrap; gap: 4px 22px; margin-top: 16px; padding-top: 14px; border-top: 1px solid rgba(255,255,255,0.12); }
.foot__more a { font-size: 0.88rem; line-height: 1.3; color: var(--onink); }
.foot__more a:hover { color: var(--white); }
/* DOTS BETWEEN THEM. Stacey, 2026-08-22: "can you separate all the titles with a dot or
   something they all seem to float and run into each other?" She is right and the reason
   is the wrap: this row breaks over three or four lines, and a 22px gap gives the eye no
   edge to cut on, so "Sunday Supper Wine Club Catering" reads as one phrase.

   The dot is generated rather than marked up, so the HTML stays a plain list of links.
   `content: "·" / ""` gives it an EMPTY accessible name, which keeps a screen reader
   from announcing "middle dot" eleven times; the plain `content` above it is the
   fallback for anything that does not support the alt-text syntax. :last-child is not
   enough on its own here, so the dot is suppressed on the final link only. */
.foot__more a:not(:last-child)::after {
  content: "\00B7";
  content: "\00B7" / "";
  margin-left: 11px;
  color: var(--onink-dim);
}
.foot h4 { font-size: 0.7rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--onink-dim); margin: 0 0 10px; font-weight: 600; }
/* THE footer link rule. It is declared after .foot__grid a and .foot__more a at equal
   specificity, so it wins on source order and anything they say about padding is dead.
   Two attempts to fix the tap target above this line did nothing for exactly that reason,
   so the size lives here, once. 15px of text plus 20px of padding clears the 32px floor.  */
.foot a { color: var(--onink); display: block; padding: 10px 0; font-size: 0.92rem; }
.foot a:hover { color: var(--white); }
.foot__base { margin-top: 14px; padding-top: 14px; border-top: 1px solid rgba(255,255,255,0.12); font-size: 0.78rem; color: var(--onink-dim); }
.foot__base a { padding: 9px 0; color: var(--onink-dim); }
.foot__base a:hover { color: var(--white); }

/* ---- home: hero (asymmetric copy | image; mobile = full-bleed overlay) ---- */
.hero { position: relative; display: block; min-height: 86vh; }
.hero__copy { position: relative; z-index: 3; display: flex; flex-direction: column; justify-content: flex-end; min-height: 86vh; margin: 0; padding: 0 clamp(22px,7vw,40px) clamp(40px,9vw,64px); color: var(--white); max-width: 780px; }
.hero h1 { font-size: clamp(2.8rem,6vw,5.2rem); color: var(--white); }
.hero .lede { margin: 24px 0 34px; color: var(--white); text-shadow: 0 1px 12px rgba(0,0,0,0.4); }
.hero__cta { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
.hero__meta { display: flex; gap: 18px; align-items: center; flex-wrap: wrap; margin-top: 30px; font-size: 0.82rem; color: rgba(255,255,255,0.9); }
.open-dot { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; color: var(--white); }
.open-dot::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px rgba(94,96,84,0.22); }
.open-dot--closed::before { background: var(--taupe); box-shadow: none; }
.hero__media { position: absolute; inset: 0; height: 100%; overflow: hidden; }
.hero__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero__media::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(20,21,15,0.86), rgba(20,21,15,0.25) 55%, rgba(20,21,15,0.35)); }
.hero__cap { display: none; }

/* ---- quiet values line ---- */
.values { border-bottom: 1px solid var(--line); background: var(--ivory); }
.values__in { display: flex; justify-content: center; gap: 34px; flex-wrap: wrap; padding: 18px 20px; font-family: var(--font-display); font-style: italic; color: var(--sage); font-size: 1rem; }
.values__in span { color: var(--ink-2); }

.cap { display: block; font-size: 0.66rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--sage); margin-top: 10px; }

/* ---- philosophy band ---- */
.philo { background: var(--ink); color: var(--cream); text-align: center; }
.philo .container { padding-top: clamp(64px,9vw,110px); padding-bottom: clamp(64px,9vw,110px); }
.philo h2 { font-size: clamp(2.1rem,5vw,3.6rem); max-width: 18ch; margin: 0 auto 22px; color: var(--cream); }
.philo p { color: var(--cream-2); max-width: 52ch; margin: 0 auto; font-size: 1.08rem; }

/* ---- our story (B&W heritage) ---- */
.story { background: var(--ink); color: var(--cream); }
.story .container { display: grid; grid-template-columns: 1fr; gap: clamp(32px,6vw,80px); align-items: center; padding-top: clamp(60px,9vw,120px); padding-bottom: clamp(60px,9vw,120px); }
.story img { filter: grayscale(1) contrast(1.02); width: 100%; aspect-ratio: 4/3; max-height: 58vh; object-fit: cover; }
.story h2 { font-size: clamp(2.1rem,4.6vw,3.4rem); margin: 10px 0 22px; color: var(--cream); }
.story p { color: var(--cream-2); max-width: 50ch; margin: 0 0 16px; }
.story .kicker { color: var(--gold); }
.story .link-arrow { color: var(--cream); border-color: var(--gold); margin-top: 14px; }

/* ---- catering 3-cell ---- */
.cater__grid { display: grid; grid-template-columns: 1fr; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.cater__cell { background: var(--cream); padding: clamp(26px,3vw,40px); }
.cater__cell h3 { font-size: 1.45rem; margin: 0 0 12px; }
.cater__cell p { color: var(--ink-2); font-size: 0.95rem; margin: 0 0 18px; }


/* ---- come visit ---- */
.visit { display: grid; grid-template-columns: 1fr; gap: clamp(32px,6vw,72px); align-items: center; }
.visit__info dl { margin: 0; display: grid; grid-template-columns: auto 1fr; gap: 8px 28px; }
.visit__info dt { font-family: var(--font-display); font-style: italic; color: var(--text-muted); }
.visit__info dd { margin: 0; color: var(--ink-2); }
.visit__map { aspect-ratio: 4/3; background: var(--cream-2); border: 1px solid var(--line); object-fit: cover; }
.visit__see { font-family: var(--font-display); font-style: italic; font-size: 1.5rem; color: var(--ink); margin-top: 26px; }
.ulink { border-bottom: 1.5px solid var(--olive); }
/* A .ulink that is the only thing on its line is a control, not prose. */
p > .ulink:only-child, li > .ulink:only-child { display: inline-block; padding: 8px 0; }

/* ============================================================
   Larger-screen layout (mobile-first min-width breakpoints)
   ============================================================ */
@media (min-width: 768px) {
  .menu-item { grid-template-columns: 1fr auto; }
  .grid--2 { grid-template-columns: repeat(2, 1fr); }
  .head--row { flex-direction: row; justify-content: space-between; align-items: flex-end; }
  .rituals { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 980px) {
  .nav__in { height: 92px; gap: 24px; }
  /* hero stays FULL-BLEED on desktop: the photo fills the width, copy overlaid in
     white over a left-darkening scrim (matches the approved home-v3 mockup). */
  .hero { min-height: clamp(620px,86vh,860px); }
  .hero__copy { min-height: clamp(620px,86vh,860px); max-width: 900px; padding: 0 clamp(20px,5vw,72px) clamp(56px,9vw,96px); }
  .hero__media::after { background: linear-gradient(100deg, rgba(20,21,15,0.82) 0%, rgba(20,21,15,0.46) 44%, rgba(20,21,15,0.12) 100%); }
  .hero__cap { display: block; position: absolute; right: 22px; bottom: 18px; z-index: 3; color: var(--white); font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase; text-shadow: 0 1px 10px rgba(0,0,0,0.55); }
  .story .container { grid-template-columns: 0.82fr 1.18fr; }
  .story img { aspect-ratio: 3/4; max-height: none; }
  .visit { grid-template-columns: 1fr 1fr; }
  .nav__logo { height: 74px; }
  .split { grid-template-columns: 1fr 1fr; min-height: clamp(420px,58vh,640px); }
  .split--rev .split__media { order: 2; }
  .split__media { height: auto; }
  .split__media img { position: absolute; inset: 0; }
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
  .foot__grid { grid-template-columns: 1.6fr 1fr 1fr; gap: 36px; }
  .foot__grid > div:first-child { grid-column: auto; }
  .foot__base { flex-direction: row; justify-content: space-between; flex-wrap: wrap; }
}

/* From here up the bar has room for the two CTAs, so they come out of the bottom bar
   and sit beside the wordmark — which is where April asked for them on 8/5. The burger
   STAYS at every width; that is the point of the 8/5 change. */
@media (min-width: 980px) {
  .nav__cta { display: flex; }
  .actionbar { display: none; }
  body:has(.actionbar) { padding-bottom: 0; }
  /* The action bar is gone from here up, so the cookie bar takes the floor back. */
  body:has(.actionbar) .cookie-bar { bottom: 0; }
  .nav__drawer-in { padding-top: 18px; padding-bottom: 24px; }
  /* Two columns once the drawer has width to spare, so nine links do not become a
     long scroll on a laptop. */
  .nav__drawer-in { display: grid; grid-template-columns: 1fr 1fr; column-gap: 48px; align-items: start; }
  .nav__drawer-close { grid-column: 1 / -1; justify-self: start; }
}

/* ===== Mini-cart drawer (menu "Add" → AJAX → slide-in panel) ===== */
.cart-drawer { position: fixed; inset: 0; z-index: 60; }
.cart-drawer[hidden] { display: none; }
.cart-drawer__scrim { position: absolute; inset: 0; background: rgba(20,21,15,0.45); opacity: 0; transition: opacity .25s; }
.cart-drawer.is-open .cart-drawer__scrim { opacity: 1; }
.cart-drawer__panel { position: absolute; top: 0; right: 0; height: 100%; width: min(420px, 92vw); background: var(--cream); border-left: 1px solid var(--line); display: flex; flex-direction: column; transform: translateX(100%); transition: transform .28s cubic-bezier(.2,.7,.2,1); box-shadow: -12px 0 40px rgba(0,0,0,.16); }
.cart-drawer.is-open .cart-drawer__panel { transform: translateX(0); }
.cart-drawer__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 22px; border-bottom: 1px solid var(--line); }
.cart-drawer__title { font-family: var(--font-display); font-size: 1.2rem; }
.cart-drawer__close { width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); color: var(--ink); cursor: pointer; flex: none; }
.cart-drawer__close:hover { background: var(--ink); color: var(--cream); }
.cart-drawer__lines { flex: 1; overflow-y: auto; padding: 6px 22px; }
/* Three columns since 8/25: the photo, the name-and-controls stack, the line total.
   The thumbnail spans both rows so a two-line name does not leave it floating. */
.cart-line { display: grid; grid-template-columns: auto 1fr auto; gap: 8px 14px; padding: 14px 0; border-bottom: 1px solid var(--line); }
.cart-line__img { grid-column: 1; grid-row: 1 / 3; align-self: center; width: 56px; height: 56px; object-fit: cover; border-radius: var(--r); background: var(--cream-2); }
/* The empty frame for a line with no photograph — same footprint, so rows stay aligned. */
.cart-line__img--ph { border: 1px solid var(--line); }
.cart-line__name { font-weight: 600; grid-column: 2; }
.cart-line__controls { grid-column: 2; display: flex; align-items: center; gap: 10px; }
.cart-line__qty { display: inline-flex; align-items: center; border: 1px solid var(--taupe); border-radius: var(--r); background: var(--white); overflow: hidden; }
.cart-line__step { width: 44px; height: 44px; border: 0; background: none; cursor: pointer; font-size: 1.15rem; line-height: 1; color: var(--ink); font-family: inherit; }
.cart-line__step:hover:not(:disabled) { background: var(--cream-2); }
.cart-line__step:disabled { opacity: .4; cursor: not-allowed; }
.cart-line__count { min-width: 32px; text-align: center; font-variant-numeric: tabular-nums; font-weight: 600; font-size: .92rem; }
.cart-line__remove { width: 36px; height: 36px; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); color: var(--ink-2); cursor: pointer; font-size: 1.1rem; line-height: 1; }
.cart-line__remove:hover { border-color: var(--danger); color: var(--danger); }
.cart-line__total { font-family: var(--font-display); font-style: italic; color: var(--ink); white-space: nowrap; grid-column: 3; grid-row: 1 / 3; align-self: center; }
.cart-drawer__empty { padding: 28px 22px; color: var(--ink-2); }
.cart-drawer__foot { border-top: 1px solid var(--line); padding: 18px 22px; }
.cart-drawer__sub { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 14px; font-size: 1.05rem; }
.cart-drawer__sub b { font-family: var(--font-display); font-size: 1.2rem; }
.cart-drawer__actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* nav cart count badge */
.nav__cart { position: relative; }
.cart-count { position: absolute; top: -6px; right: -8px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--danger); color: var(--white); font-size: .66rem; font-weight: 700; display: none; align-items: center; justify-content: center; line-height: 1; }
.cart-count.is-shown { display: inline-flex; }

/* menu row Add button + body link (purchasable items) */
.menu-item__add { grid-column: 3; grid-row: 1; align-self: center; }
.menu-item__add .btn-add { min-width: 44px; min-height: 40px; padding: 0 16px; border: 1.5px solid var(--ink); border-radius: 999px; background: transparent; color: var(--ink); font-family: var(--font-body); font-size: .72rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; cursor: pointer; transition: .18s; }
.menu-item__add .btn-add:hover { background: var(--ink); color: var(--cream); }
@media (prefers-reduced-motion: reduce) { .cart-drawer__panel, .cart-drawer__scrim { transition: none; } }

/* Reservations modal (Task 569): interim Yelp hand-off, centered dialog */
.reserve-modal { position: fixed; inset: 0; z-index: 70; display: flex; align-items: center; justify-content: center; padding: 20px; }
.reserve-modal[hidden] { display: none; }
.reserve-modal__scrim { position: absolute; inset: 0; background: rgba(20,21,15,0.5); opacity: 0; transition: opacity .24s; }
.reserve-modal.is-open .reserve-modal__scrim { opacity: 1; }
.reserve-modal__panel { position: relative; width: min(440px, 100%); background: var(--cream); border: 1px solid var(--line); border-radius: var(--r); box-shadow: 0 24px 60px rgba(0,0,0,.24); padding: clamp(28px,5vw,40px); text-align: center; transform: translateY(12px) scale(.98); opacity: 0; transition: transform .26s cubic-bezier(.2,.7,.2,1), opacity .26s; }
.reserve-modal.is-open .reserve-modal__panel { transform: translateY(0) scale(1); opacity: 1; }
.reserve-modal__close { position: absolute; top: 12px; right: 12px; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); color: var(--ink); cursor: pointer; }
.reserve-modal__close:hover { background: var(--ink); color: var(--cream); }
.reserve-modal__title { font-family: var(--font-display); font-size: 1.5rem; margin: 0 0 10px; }
.reserve-modal__copy { color: var(--ink-2); margin: 0 auto 22px; max-width: 34ch; }
.reserve-modal__cta { display: inline-flex; align-items: center; gap: 10px; }
.reserve-modal__alt { margin: 18px 0 0; font-size: .9rem; color: var(--ink-2); }
@media (prefers-reduced-motion: reduce) { .reserve-modal__panel, .reserve-modal__scrim { transition: none; } }

/* Pickup-or-delivery modal (client 2026-08-20): Order Now asks, delivery hands off to
   Square. Same dialog family as .reserve-modal above - one shape for every hand-off so
   the second one a guest meets is already familiar. */
.order-modal { position: fixed; inset: 0; z-index: 70; display: flex; align-items: center; justify-content: center; padding: 20px; }
.order-modal[hidden] { display: none; }
.order-modal__scrim { position: absolute; inset: 0; background: rgba(20,21,15,0.5); opacity: 0; transition: opacity .24s; }
.order-modal.is-open .order-modal__scrim { opacity: 1; }
.order-modal__panel { position: relative; width: min(440px, 100%); background: var(--cream); border: 1px solid var(--line); border-radius: var(--r); box-shadow: 0 24px 60px rgba(0,0,0,.24); padding: clamp(28px,5vw,40px); text-align: center; transform: translateY(12px) scale(.98); opacity: 0; transition: transform .26s cubic-bezier(.2,.7,.2,1), opacity .26s; }
.order-modal.is-open .order-modal__panel { transform: translateY(0) scale(1); opacity: 1; }
.order-modal__close { position: absolute; top: 12px; right: 12px; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); border-radius: 999px; background: var(--paper); color: var(--ink); cursor: pointer; }
.order-modal__close:hover { background: var(--ink); color: var(--cream); }
/* The title carries the bottom margin now that the explainer line is gone (8/24). */
.order-modal__title { font-family: var(--font-display); font-size: 1.5rem; margin: 0 0 22px; }
/* Two equal choices, side by side where there is room. Below 420px they stack, because
   two buttons plus the dialog padding cannot hold a readable label at 375px. */
.order-modal__choices { display: grid; gap: 10px; }
@media (min-width: 420px) { .order-modal__choices { grid-template-columns: 1fr 1fr; } }
.order-modal__choice { display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }
/* The cart-recovery line (8/25). Quiet by design: it is a safety net under the Delivery
   button, not a third choice, so it sits below the buttons at small type and only
   appears when there is actually something to lose. [hidden] needs the explicit rule
   because the block display below would otherwise beat the UA stylesheet. */
.order-modal__cart { margin: 16px 0 0; font-size: .82rem; color: var(--text-muted); }
.order-modal__cart[hidden] { display: none; }
.order-modal__cart a { color: inherit; text-underline-offset: 3px; }
.order-modal__cart a:hover { color: var(--accent); }
@media (prefers-reduced-motion: reduce) { .order-modal__panel, .order-modal__scrim { transition: none; } }

/* ===== Toasts (public) — bottom-right, translucent colored, auto-dismiss ~5s.
   Distinct class names from the admin toast to avoid any clash. ===== */
.toast-stack { position: fixed; right: 50%; bottom: 16px; transform: translateX(50%); z-index: 200; display: grid; gap: 10px; width: min(92vw, 340px); pointer-events: none; }
@media (min-width: 768px) { .toast-stack { right: 16px; transform: none; } }
.toast-pop { pointer-events: auto; display: flex; align-items: flex-start; gap: 10px; padding: 13px 16px; border-radius: var(--r); color: var(--white); font-size: .9rem; line-height: 1.4; font-weight: 500; box-shadow: 0 12px 34px rgba(20,21,15,.24); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); opacity: 0; transform: translateY(12px); transition: opacity .26s ease, transform .26s cubic-bezier(.2,.7,.2,1); }
.toast-pop.is-in { opacity: 1; transform: none; }
.toast-pop.is-out { opacity: 0; transform: translateY(8px); }
.toast-pop--success { background: color-mix(in srgb, var(--olive-ink) 90%, transparent); }
.toast-pop--info    { background: color-mix(in srgb, var(--ink) 88%, transparent); }
.toast-pop--error   { background: color-mix(in srgb, var(--danger) 92%, transparent); }
.toast-pop__x { margin-left: auto; background: none; border: 0; color: inherit; opacity: .7; cursor: pointer; font-size: 1rem; line-height: 1; padding: 0 0 0 8px; }
.toast-pop__x:hover { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .toast-pop { transition: opacity .2s; transform: none; } .toast-pop.is-in { transform: none; } }

/* The bar CTAs only ever render from 980px up (below that they are in .actionbar), so
   there is always room for the full "Reserve a Table" label. The span survives for the
   1024px-ish band where the wordmark, two buttons and three controls are snug. */
.nav__order, .nav__reserve { white-space: nowrap; }
.nav__reserve-long { display: none; }
@media (min-width: 1120px) {
  .nav__reserve-long { display: inline; }
}

/* ===== Text + Instagram signup pop-up (8/5 client call) =====
   Replaces the Privy pop-up from the old site. <dialog> so focus trapping, Escape and
   the backdrop come from the browser rather than being hand-rolled. */
.signup { width: min(420px, calc(100vw - 32px)); padding: 0; border: 1px solid var(--line); border-radius: var(--r); background: var(--cream); color: var(--ink); box-shadow: 0 24px 60px rgba(0,0,0,0.22); }
.signup::backdrop { background: rgba(20,21,15,0.5); backdrop-filter: blur(2px); }
.signup__in, .signup__done { position: relative; padding: clamp(26px,5vw,36px) clamp(22px,5vw,32px) clamp(22px,4vw,28px); text-align: center; }
.signup__x { position: absolute; top: 8px; right: 10px; width: 40px; height: 40px; border: 0; background: none; color: var(--text-muted); font-size: 1.6rem; line-height: 1; cursor: pointer; }
.signup__x:hover { color: var(--ink); }
.signup__eyebrow { margin: 0 0 4px; color: var(--text-muted); font-size: 0.68rem; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase; }
.signup__h { margin: 0 0 8px; font-size: clamp(1.5rem,5vw,1.9rem); line-height: 1.1; }
.signup__lede { margin: 0 0 18px; color: var(--ink-2); font-size: 0.88rem; line-height: 1.5; }
.signup__label { display: block; margin: 0 0 5px; text-align: left; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2); }
.signup__optional { font-weight: 500; text-transform: none; letter-spacing: 0.02em; color: var(--text-muted); }
.signup__input { width: 100%; margin: 0 0 14px; padding: 13px 14px; border: 1px solid var(--line); border-radius: var(--r); background: var(--paper); color: var(--ink); font-family: var(--font-body); font-size: 1rem; }
.signup__input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.signup__submit { width: 100%; margin-top: 4px; }
.signup__err { margin: 0 0 12px; color: var(--danger-ink, var(--ink)); font-size: 0.82rem; text-align: left; }
.signup__err[hidden] { display: none; }
.signup__ig { margin: 16px 0 0; font-size: 0.84rem; color: var(--ink-2); }
.signup__ig a { text-decoration: underline; text-underline-offset: 3px; }
.signup__fine { margin: 10px 0 0; color: var(--text-muted); font-size: 0.7rem; }
.signup__code { margin: 6px 0 14px; font-family: var(--font-display); font-size: clamp(1.8rem,7vw,2.4rem); letter-spacing: 0.08em; }
.signup__done[hidden] { display: none; }

/* The sticky bar stands down while the page's own CTA row is on screen — otherwise the
   bottom of the homepage shows Order Now / Reserve twice at once, which is the
   repetition the client called out on 7/29. Transform rather than display, so it slides
   rather than blinks, and so it can come back. */
.actionbar { transition: transform .28s cubic-bezier(.2,.7,.2,1), opacity .2s ease; }
.actionbar[data-yield="true"] { transform: translateY(100%); opacity: 0; pointer-events: none; }
/* Same stand-down, driven by Privy's pop-up rather than by the page's own CTA row. A
   SEPARATE attribute from data-yield on purpose: two independent observers write these,
   and sharing one attribute would let each undo the other's decision. See the
   "Privy owns the bottom of the screen too" block in app.js for the measurements. */
.actionbar[data-privy-open="true"] { transform: translateY(100%); opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .actionbar { transition: opacity .2s ease; } }

/* ---- footer spacing corrections (owner, 8/11) ----------------------------------
   Two complaints, one cause. ".foot a" above makes EVERY footer link a block with
   10px of vertical padding — correct for the stacked navigation columns, where each
   link needs its own tap target, but wrong in two places:

     - Contact and Hours are a short run of detail lines, not a menu. Ten pixels top
       and bottom on each put roughly 20px between the phone and the email, and the
       same between Mon-Sat and Sun.
     - The legal line is a SENTENCE — "© … · Privacy · Terms & Refunds". Blocking its
       links broke it onto three lines and stranded a lone middot on one of them.

   Declared here, after the base rules, because they carry equal specificity and the
   later declaration is what decides it. */
.foot__grid a { padding: 4px 0; }
.foot__line { padding: 4px 0; }
.foot__base a { display: inline; padding: 0; }

/* ---- "Coming up", one series, on /sunday-supper and /wine-club -------------
   April, 8/21: each page shows the dates tagged to it. A ruled list rather than
   cards: these are dates being scanned, not things being browsed, and the date
   has to be the first thing the eye lands on. */
.series-up__h { font-size: clamp(1.4rem, 3.4vw, 2rem); margin: 0 0 clamp(16px, 2.2vw, 24px); }
.series-up__list { list-style: none; margin: 0; padding: 0; }
.series-up__item {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px 22px;
  padding: clamp(16px, 2vw, 22px) 0;
  border-top: 1px solid var(--line);
}
.series-up__item:last-child { border-bottom: 1px solid var(--line); }
.series-up__day { display: block; font-family: var(--font-display); text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.95rem; color: var(--ink); }
.series-up__time { display: block; font-size: 0.82rem; color: var(--text-muted); margin-top: 2px; }
.series-up__title { margin: 0; font-size: 1.05rem; }
.series-up__title a { color: var(--ink); text-decoration: none; }
.series-up__title a:hover { text-decoration: underline; text-underline-offset: 3px; }
.series-up__blurb { margin: 4px 0 0; font-size: 0.9rem; line-height: 1.5; color: var(--ink-2); }
.series-up__act { display: flex; align-items: center; gap: 12px; }
.series-up__price { font-size: 0.9rem; color: var(--text-muted); }
@media (min-width: 46em) {
  .series-up__item { grid-template-columns: 150px minmax(0, 1fr) auto; align-items: center; }
}

/* ---- The same programme, every month: say it once, then just list the dates
   (April, 2026-09-02: "Can you update to not show all the same info over and
   over"). Twelve third Wednesdays each carrying the identical title and
   sentence made ~1900px of the page one paragraph printed twelve times.

   The description moves above the list and the rows keep only what differs, so
   a row is now a date. Which is why they go in a grid rather than staying a
   single ruled column: twelve dates stacked one per line is the same wall of
   scrolling with the words taken out, and read across they say "third
   Wednesday, every month" without anybody writing that sentence.

   Column counts are fixed steps, not auto-fill, so a twelve-date list divides
   exactly at every width (6 / 4 / 3 rows) rather than leaving one orphan on a
   last row of seven.

   Only the uniform case gets this; a mixed list falls back to the ruled rows
   above, where each date carries its own words. */
.series-up__lead { max-width: 62ch; margin: -6px 0 clamp(18px, 2.4vw, 28px); }
.series-up__lead-t { margin: 0 0 6px; font-size: 1.05rem; }
.series-up__lead-b { margin: 0; font-size: 0.95rem; line-height: 1.6; color: var(--ink-2); }

.series-up__list--dates {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* The OPENING rule belongs to the list and the closing ones to the cells, which is
     the way round that survives a part-filled last row: the block always opens on a
     full-width line, and the line under the final row stops where the dates stop
     rather than running on under empty grid tracks. */
  border-top: 1px solid var(--line);
}
.series-up__list--dates .series-up__item {
  display: block;
  border-top: 0;
  border-bottom: 1px solid var(--line);
  /* The gutter is padding INSIDE the cell, not a column-gap between cells, so the
     per-cell rules meet and read as one line across the block instead of a row of
     dashes with holes punched in it at every column. */
  padding: 12px clamp(16px, 2.6vw, 36px) 12px 0;
}
.series-up__item--date .series-up__day { font-size: 0.88rem; letter-spacing: 0.06em; }
.series-up__datelink { display: block; color: inherit; text-decoration: none; }
.series-up__datelink:hover .series-up__day,
.series-up__datelink:focus-visible .series-up__day { text-decoration: underline; text-underline-offset: 3px; }
.series-up__item--date .series-up__act { margin-top: 6px; }
@media (min-width: 46em) {
  .series-up__list--dates { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 70em) {
  .series-up__list--dates { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
