/* Fairfield Flavor — styles */

:root {
  --bg: #faf6f0;
  --bg-elev: #ffffff;
  --bg-sunk: #f1ece3;
  --ink: #1c1813;
  --ink-2: #5f584e;
  --ink-3: #938a7d;
  --line: #e7e0d5;
  --line-2: #d8d0c2;
  --accent: #c2410c;
  --accent-soft: #fdece2;
  --accent-ink: #9a3308;
  --open: #157f4a;
  --open-soft: #e2f4ea;
  --shut: #a4362f;
  --shut-soft: #fbe9e7;
  --warn-ink: #8a5a06;
  --warn-soft: #fdf4e3;
  --warn-line: #ecd9a8;
  --geo: #1d4ed8;
  --geo-soft: #eaf0fe;
  --shadow-sm: 0 1px 2px rgba(26, 24, 21, .05), 0 1px 3px rgba(26, 24, 21, .04);
  --shadow-md: 0 4px 6px -2px rgba(26, 24, 21, .06), 0 12px 24px -8px rgba(26, 24, 21, .14);
  --shadow-lg: 0 20px 48px -12px rgba(26, 24, 21, .28);
  --r: 18px;
  --r-sm: 11px;
  --maxw: 1280px;
  --header-h: 132px;
  --sans: ui-sans-serif, -apple-system, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif;
  /* ui-serif resolves to New York on Apple platforms — an editorial voice with no download. */
  --serif: ui-serif, "New York", "Iowan Old Style", Palatino, Georgia, serif;
}

html[data-theme="dark"] {
  --bg: #14120e;
  --bg-elev: #201d17;
  --bg-sunk: #100e0b;
  --ink: #f4f1ea;
  --ink-2: #b7ae9f;
  --ink-3: #8b8274;
  --line: #322e26;
  --line-2: #423d33;
  --accent: #fb923c;
  --accent-soft: #35211284;
  --accent-ink: #fdba74;
  --open: #4ade80;
  --open-soft: #16301f8c;
  --shut: #fca5a5;
  --shut-soft: #3a1a1a8c;
  --warn-ink: #fcd34d;
  --warn-soft: #33280c8c;
  --warn-line: #5c4a16;
  --geo: #7dabff;
  --geo-soft: #16203a8c;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-md: 0 4px 8px rgba(0, 0, 0, .4), 0 16px 32px -12px rgba(0, 0, 0, .55);
  --shadow-lg: 0 24px 56px -12px rgba(0, 0, 0, .7);
}

* { box-sizing: border-box; }

/* Author `display` rules (.grid, .active-row) otherwise beat the UA [hidden] rule. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--sans);
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

svg { width: 1em; height: 1em; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

a { color: var(--accent-ink); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--bg-elev); padding: .7rem 1rem; border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }

/* ---------- hero ---------- */

.hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  background:
    radial-gradient(120% 140% at 12% -10%, color-mix(in srgb, var(--accent) 13%, transparent), transparent 62%),
    radial-gradient(90% 120% at 92% 0%, color-mix(in srgb, #d9a03c 16%, transparent), transparent 60%),
    var(--bg);
}
.hero-inner {
  position: relative; z-index: 1;
  max-width: var(--maxw); margin: 0 auto;
  padding: clamp(1.7rem, 3.6vw, 2.6rem) 1.25rem clamp(1.3rem, 2.2vw, 1.7rem);
}
.hero-eyebrow {
  margin: 0 0 .7rem; font: 600 .76rem var(--sans);
  letter-spacing: .16em; text-transform: uppercase; color: var(--accent-ink);
}
.hero-title {
  margin: 0; font-family: var(--serif); font-weight: 600;
  font-size: clamp(2.1rem, 5vw, 3.3rem); line-height: 1.02;
  letter-spacing: -.026em; color: var(--ink);
}
/* One line on roomy screens, stacked on phones. */
@media (min-width: 620px) { .hero-title br { display: none; }
  .hero-title em { margin-left: .28em; } }
.hero-title em {
  font-style: italic;
  background: linear-gradient(96deg, var(--accent), #e0863f 60%, #d9a03c);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero-sub {
  margin: .75rem 0 0; max-width: 46ch;
  font-size: .97rem; line-height: 1.5; color: var(--ink-2);
}
.hero-sub strong { color: var(--ink); font-variant-numeric: tabular-nums; }

.hero-quick { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.1rem; }
.qbtn {
  font: 600 .85rem var(--sans); color: var(--ink);
  background: var(--bg-elev);
  border: 1px solid var(--line-2); border-radius: 999px;
  padding: .55rem 1.05rem; cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: transform .16s cubic-bezier(.2,.7,.3,1), box-shadow .16s, background .16s, color .16s;
}
.qbtn:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
/* The one hero button that opens a different view rather than filtering the list.
   It is set in caps to read as a door rather than a filter, and caps want a little
   tracking to stay legible at this size. */
.qbtn-wide { letter-spacing: .04em; }

.qbtn.is-on {
  background: var(--ink); border-color: var(--ink); color: var(--bg);
}

/* Soft warm bloom behind the headline. */
.hero-glow {
  position: absolute; inset: auto -10% -70% 40%;
  height: 300px; pointer-events: none;
  background: radial-gradient(50% 50% at 50% 50%, color-mix(in srgb, var(--accent) 22%, transparent), transparent 70%);
  filter: blur(48px); opacity: .55;
}
html[data-theme="dark"] .hero-glow { opacity: .34; }

/* ---------- header ---------- */

.topbar {
  position: sticky; top: 0; z-index: 60;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(1.6) blur(14px);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 1px solid var(--line);
}

.topbar-inner {
  max-width: var(--maxw); margin: 0 auto;
  padding: .8rem 1.25rem .55rem;
  display: flex; align-items: center; gap: 1rem;
}

.brand { display: flex; align-items: center; gap: .6rem; flex: 0 0 auto; }
.brand-mark {
  width: 38px; height: 38px; border-radius: 11px;
  box-shadow: var(--shadow-sm);
  /* icons/icon.svg is a full-bleed square, so the radius does the rounding —
     same mark, same crop as the home-screen icon. */
}
.brand-text { display: flex; flex-direction: column; line-height: 1.1; }
.brand-text strong { font-size: 1.03rem; letter-spacing: -.017em; }
.brand-text small { color: var(--ink-3); font-size: .735rem; margin-top: 2px; }

.search { position: relative; flex: 1 1 auto; max-width: 560px; }
.search-icon {
  position: absolute; left: .82rem; top: 50%; transform: translateY(-50%);
  font-size: 1.05rem; color: var(--ink-3); pointer-events: none;
}
#q {
  width: 100%; font: inherit; font-size: .92rem; color: var(--ink);
  padding: .68rem 4.3rem .68rem 2.5rem;
  background: var(--bg-elev);
  border: 1px solid var(--line-2); border-radius: 11px;
  box-shadow: var(--shadow-sm);
  transition: border-color .15s, box-shadow .15s;
}
#q::placeholder { color: var(--ink-3); }
#q:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3.5px var(--accent-soft);
}
#q::-webkit-search-cancel-button { display: none; }
.q-clear {
  position: absolute; right: 2.35rem; top: 50%; transform: translateY(-50%);
  width: 22px; height: 22px; border: 0; border-radius: 50%;
  background: var(--bg-sunk); color: var(--ink-2);
  font-size: 1.05rem; line-height: 1; cursor: pointer;
}
.q-clear:hover { background: var(--line-2); color: var(--ink); }
.slash-hint {
  position: absolute; right: .6rem; top: 50%; transform: translateY(-50%);
  font: 600 .68rem var(--sans); color: var(--ink-3);
  border: 1px solid var(--line-2); border-bottom-width: 2px;
  border-radius: 5px; padding: 1px 5px; background: var(--bg);
}
.search:focus-within .slash-hint { opacity: 0; }

.topbar-actions { display: flex; gap: .45rem; margin-left: auto; flex: 0 0 auto; }

.icon-btn {
  display: inline-flex; align-items: center; gap: .4rem;
  font: 600 .82rem var(--sans); color: var(--ink-2);
  background: var(--bg-elev); border: 1px solid var(--line-2);
  border-radius: 10px; padding: .55rem .75rem; cursor: pointer;
  box-shadow: var(--shadow-sm); transition: .15s;
}
.icon-btn:hover { color: var(--ink); border-color: var(--ink-3); transform: translateY(-1px); }
.icon-btn svg { font-size: 1.05rem; }
.icon-btn.square { padding: .55rem; }

.ico-moon { display: none; }
html[data-theme="dark"] .ico-sun { display: none; }
html[data-theme="dark"] .ico-moon { display: block; }

/* ---------- filters ---------- */

.filters { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem .7rem; }

.filter-row { display: flex; align-items: center; gap: .5rem; }
.filter-row.secondary { margin-top: .55rem; flex-wrap: wrap; }
.spacer { flex: 1 1 auto; }

.chips { display: flex; gap: .4rem; overflow-x: auto; padding-bottom: 2px; scrollbar-width: none; }
.chips::-webkit-scrollbar { display: none; }

.chip {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .38rem;
  font: 600 .82rem var(--sans); color: var(--ink-2);
  background: transparent; border: 1px solid var(--line-2);
  border-radius: 999px; padding: .4rem .8rem; cursor: pointer;
  white-space: nowrap; transition: .14s;
}
.chip:hover { color: var(--ink); border-color: var(--ink-3); }
.chip .n { font-weight: 500; color: var(--ink-3); font-size: .76rem; font-variant-numeric: tabular-nums; }
.chip.is-on {
  background: var(--ink); border-color: var(--ink); color: var(--bg);
}
.chip.is-on .n { color: color-mix(in srgb, var(--bg) 70%, transparent); }

.toggle {
  display: inline-flex; align-items: center; gap: .42rem;
  font: 600 .82rem var(--sans); color: var(--ink-2);
  background: var(--bg-elev); border: 1px solid var(--line-2);
  border-radius: 999px; padding: .44rem .8rem; cursor: pointer; transition: .14s;
}
.toggle:hover { color: var(--ink); border-color: var(--ink-3); }
.toggle .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--ink-3); box-shadow: 0 0 0 3px transparent; transition: .2s;
}
.toggle[aria-pressed="true"] {
  background: var(--open-soft); border-color: color-mix(in srgb, var(--open) 45%, transparent); color: var(--open);
}
.toggle[aria-pressed="true"] .dot { background: var(--open); box-shadow: 0 0 0 3px color-mix(in srgb, var(--open) 22%, transparent); }
#saved-only[aria-pressed="true"] {
  background: var(--accent-soft); border-color: color-mix(in srgb, var(--accent) 45%, transparent); color: var(--accent-ink);
}
#saved-only[aria-pressed="true"] .heart-ico { fill: currentColor; }
.heart-ico { font-size: 1rem; }

/* Near me */
.toggle.near .near-ico { font-size: 1rem; }
.toggle.near[aria-pressed="true"] {
  background: var(--geo-soft); border-color: color-mix(in srgb, var(--geo) 45%, transparent);
  color: var(--geo);
}
.toggle.near[data-state="asking"] { color: var(--ink-3); cursor: progress; }
.toggle.near[data-state="asking"] .near-ico { animation: spin 1.1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.toggle.near:disabled { opacity: .75; }

.linkish {
  border: 0; background: none; padding: 0 0 0 .5rem; cursor: pointer;
  font: 600 .8rem var(--sans); color: var(--geo);
  text-decoration: underline; text-underline-offset: 3px;
}
.linkish:hover { filter: brightness(1.15); }

.geo-problem {
  margin: 0 0 1.1rem; padding: .95rem 1.1rem;
  background: var(--geo-soft); border: 1px solid color-mix(in srgb, var(--geo) 28%, transparent);
  border-radius: var(--r);
}
.geo-problem p { margin: 0 0 .8rem; font-size: .87rem; line-height: 1.55; color: var(--ink); }
.geo-problem code {
  font-size: .85em; background: var(--bg-sunk); border: 1px solid var(--line);
  border-radius: 5px; padding: .08em .35em;
}
.geo-problem-actions { display: flex; flex-wrap: wrap; gap: .5rem; }

.pick-banner {
  display: flex; align-items: center; gap: .9rem; flex-wrap: wrap;
  margin: 0 0 1.1rem; padding: .8rem 1.1rem;
  background: var(--geo-soft); border: 1px dashed color-mix(in srgb, var(--geo) 50%, transparent);
  border-radius: var(--r); font-size: .87rem; font-weight: 600; color: var(--ink);
}
.pick-banner .btn { margin-left: auto; padding: .45rem .8rem; font-size: .8rem; }
body.is-picking #map { cursor: crosshair; }
body.is-picking .leaflet-marker-icon { cursor: crosshair; }

.you-dot {
  width: 22px; height: 22px; border-radius: 50%;
  background: color-mix(in srgb, var(--geo) 28%, transparent);
  display: grid; place-items: center;
}
.you-dot span {
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--geo); border: 2.5px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .45);
}

.d-away { color: var(--geo); font-weight: 600; white-space: nowrap; }

/* Small pill links inside a detail row. Only the Reviews row uses these now — the
   maps hand-off moved to the Directions button, which asks which app you want. */
.pill-links { display: flex; gap: .5rem; margin-top: .3rem; flex-wrap: wrap; }
.pill-links a {
  font: 600 .755rem var(--sans); color: var(--accent-ink);
  text-decoration: none; white-space: nowrap;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  border-radius: 999px; padding: .18rem .55rem;
  transition: border-color .15s, transform .15s;
}
.pill-links a:hover { border-color: var(--accent); transform: translateY(-1px); }
.mini-count { font-variant-numeric: tabular-nums; opacity: .75; font-weight: 500; }

.select {
  display: inline-flex; align-items: center; gap: .4rem;
  background: var(--bg-elev); border: 1px solid var(--line-2);
  border-radius: 999px; padding: .3rem .35rem .3rem .75rem;
}
.select > span { font: 600 .74rem var(--sans); color: var(--ink-3); text-transform: uppercase; letter-spacing: .045em; }
.select select {
  font: 600 .82rem var(--sans); color: var(--ink);
  background: transparent; border: 0; padding: .16rem 1.2rem .16rem .2rem; cursor: pointer;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right .55rem center, right .3rem center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
.select select:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
.select:has(select:not([data-default])) { border-color: var(--accent); }

.viewswitch {
  display: inline-flex; background: var(--bg-sunk);
  border: 1px solid var(--line); border-radius: 999px; padding: 3px;
}
.vs-btn {
  display: inline-flex; align-items: center; gap: .35rem;
  font: 600 .8rem var(--sans); color: var(--ink-2);
  background: transparent; border: 0; border-radius: 999px;
  padding: .35rem .8rem; cursor: pointer; transition: .15s;
}
.vs-btn.is-on { background: var(--bg-elev); color: var(--ink); box-shadow: var(--shadow-sm); }

.active-row { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .6rem; align-items: center; }
.active-label { font: 600 .74rem var(--sans); color: var(--ink-3); text-transform: uppercase; letter-spacing: .045em; }
.pill {
  display: inline-flex; align-items: center; gap: .35rem;
  font: 600 .78rem var(--sans);
  background: var(--accent-soft); color: var(--accent-ink);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 999px; padding: .25rem .3rem .25rem .65rem;
}
.pill button {
  border: 0; background: transparent; color: inherit; cursor: pointer;
  font-size: 1rem; line-height: 1; padding: 0 .25rem; opacity: .7;
}
.pill button:hover { opacity: 1; }
.clear-all {
  font: 600 .78rem var(--sans); color: var(--ink-2);
  background: none; border: 0; cursor: pointer; text-decoration: underline;
  text-decoration-color: var(--line-2); text-underline-offset: 3px;
}
.clear-all:hover { color: var(--ink); }

/* ---------- results ---------- */

main { max-width: var(--maxw); margin: 0 auto; padding: 1.1rem 1.25rem 3rem; }

.statusline { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; margin: 0 0 .9rem; }
.count { margin: 0; font-size: .85rem; color: var(--ink-2); }
.count strong { color: var(--ink); font-variant-numeric: tabular-nums; }
/* Honest small print about how far a menu search can see. Set apart so it reads as a
   caveat on the count rather than part of it. */
.count-note {
  display: block; margin-top: .18rem;
  font-size: .76rem; color: var(--ink-3);
}
.geo-note { margin: 0; font-size: .8rem; color: var(--ink-3); }

.grid {
  display: grid; gap: .85rem;
  grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
}

.card {
  position: relative; display: flex; flex-direction: column;
  background: var(--bg-elev); border: 1px solid transparent;
  border-radius: var(--r); padding: 1.05rem 1.05rem .35rem;
  box-shadow: var(--shadow-sm); cursor: pointer;
  transition: transform .18s cubic-bezier(.2,.7,.3,1), box-shadow .18s, border-color .18s;
  animation: cardIn .42s cubic-bezier(.2,.7,.3,1) both;
  animation-delay: var(--delay, 0ms);
}
html[data-theme="dark"] .card { border-color: var(--line); }

@keyframes cardIn {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
}

/* A wash of the place's own cuisine colour, revealed on hover. */
.card::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(160deg, hsl(var(--h, 30) calc(var(--sat, 1) * 80%) 60% / .09), transparent 55%);
  opacity: 0; transition: opacity .2s; pointer-events: none;
}
.card:hover::before { opacity: 1; }
.card:hover {
  transform: translateY(-4px);
  box-shadow: 0 2px 4px hsl(var(--h, 30) calc(var(--sat, 1) * 40%) 30% / .07),
              0 18px 34px -12px hsl(var(--h, 30) calc(var(--sat, 1) * 45%) 32% / .26);
  border-color: hsl(var(--h, 30) calc(var(--sat, 1) * 55%) 62% / .38);
}
.card:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.card-body { display: flex; align-items: flex-start; gap: .85rem; }

.tile {
  flex: 0 0 auto; width: 58px; height: 58px; border-radius: 16px;
  display: grid; place-items: center; font-size: 1.6rem; line-height: 1;
  background:
    radial-gradient(120% 120% at 28% 18%,
      hsl(var(--h, 30) calc(var(--sat, 1) * 88%) calc(72% - var(--sat, 1) * 2%)),
      hsl(var(--h, 30) calc(var(--sat, 1) * 72%) calc(54% - var(--sat, 1) * 2%)) 62%,
      hsl(calc(var(--h, 30) - 16) calc(var(--sat, 1) * 68%) 46%));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4),
              0 5px 12px -5px hsl(var(--h, 30) calc(var(--sat, 1) * 60%) 38% / .5);
  transition: transform .22s cubic-bezier(.2,.7,.3,1);
}
.tile { position: relative; overflow: hidden; }
.tile-glyph { filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .28)); }
/* A real storefront photo covers the generated tile. If the file is missing or
   fails to decode the <img> removes itself and the glyph shows through. */
.tile img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; border-radius: inherit;
  /* Same upward bias as the detail banner, for the same reason: the fascia is what
     identifies the place, and centring the crop loses it. */
  object-position: center 28%;
}
.card:hover .tile { transform: scale(1.06) rotate(-3deg); }

.card-text { flex: 1 1 auto; min-width: 0; }
.card.is-flash { animation: flash 1.5s ease-out; }
@keyframes flash {
  0%, 40% { box-shadow: 0 0 0 3px var(--accent), var(--shadow-md); }
  100% { box-shadow: 0 0 0 0 transparent, var(--shadow-sm); }
}

.card h3 {
  margin: 0 0 .2rem; font-family: var(--serif); font-weight: 600;
  font-size: 1.2rem; letter-spacing: -.016em; line-height: 1.2;
  overflow-wrap: anywhere;
}
.card-kinds {
  margin: 0; font-size: .82rem; color: var(--ink-2); line-height: 1.4;
}
.card-kinds i { font-style: normal; color: var(--line-2); padding: 0 .3rem; }
.card-kinds b {
  font-weight: 700; color: var(--accent-ink);
  box-shadow: inset 0 -.42em 0 var(--accent-soft);
}
/* The dish that explains a search hit. Quiet, because it is a footnote to the result
   rather than part of the place's identity — it only ever appears mid-search. */
.card-menu {
  margin: .3rem 0 0; font-size: .78rem; color: var(--ink-2); line-height: 1.35;
}
.card-menu span {
  font: 700 .62rem/1 var(--sans); letter-spacing: .06em; text-transform: uppercase;
  color: var(--accent-ink); background: var(--accent-soft);
  border-radius: 4px; padding: .18em .32em; margin-right: .38em;
  vertical-align: .06em;
}
.card-where {
  margin: .3rem 0 0; font-size: .79rem; color: var(--ink-3); line-height: 1.4;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
.fav {
  flex: 0 0 auto; width: 30px; height: 30px; margin: -3px -4px 0 0;
  display: grid; place-items: center;
  border: 0; border-radius: 8px; background: transparent;
  color: var(--ink-3); cursor: pointer; font-size: 1.15rem; transition: .15s;
}
.fav:hover { background: var(--accent-soft); color: var(--accent); }
.fav[aria-pressed="true"] { color: var(--accent); }
.fav[aria-pressed="true"] svg { fill: currentColor; }

.card-sub {
  margin: .4rem 0 0; display: flex; align-items: center; gap: .45rem;
  font-size: .8rem; color: var(--ink-2); flex-wrap: wrap;
}
.cat {
  font-weight: 600; font-size: .68rem; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-2); background: var(--bg-sunk);
  border-radius: 5px; padding: .17rem .4rem;
}
.sep { color: var(--line-2); }

/* Only "open" earns a filled pill — everything else is quiet text, so a screen of
   cards reads as a few green highlights instead of 168 coloured boxes. */
.status {
  display: inline-flex; align-items: center; gap: .38rem;
  font: 600 .755rem var(--sans); border-radius: 999px; padding: .22rem .1rem;
}
.status::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: 0 0 auto;
}
.status.open {
  color: var(--open); background: var(--open-soft); padding: .22rem .6rem .22rem .5rem;
}
.status.open::before { animation: livePulse 2.4s ease-in-out infinite; }
@keyframes livePulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--open) 55%, transparent); }
  60% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--open) 0%, transparent); }
}
.status.soon {
  color: var(--accent-ink); background: var(--accent-soft); padding: .22rem .6rem .22rem .5rem;
}
.status.shut { color: var(--ink-3); }
.status.unknown { color: var(--ink-3); }
.status.unknown::before { opacity: .5; }

.tags { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .65rem; }
.tag {
  font: 500 .755rem var(--sans); color: var(--ink-2);
  border: 1px solid var(--line); border-radius: 6px; padding: .16rem .42rem;
  background: transparent;
  /* Each tag filters the list, so it needs to read as pressable rather than as a label. */
  -webkit-appearance: none; appearance: none;
  cursor: pointer; line-height: inherit;
}
.tag:hover { border-color: var(--accent); color: var(--accent-ink); }
.tag:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tag.is-match { border-color: var(--accent); color: var(--accent-ink); background: var(--accent-soft); }

.stale {
  display: inline-flex; align-items: center; gap: .3rem;
  font: 600 .72rem var(--sans); color: var(--warn-ink);
  cursor: help; white-space: nowrap;
}
.stale::before {
  content: "!"; display: grid; place-items: center;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--warn-soft); border: 1px solid var(--warn-line);
  font-size: .62rem; font-weight: 800;
}

.fresh-box { margin-top: 1.3rem; display: grid; gap: .5rem; }
.fresh-box p { margin: 0; font-size: .8rem; line-height: 1.55; }
.fresh-ok { color: var(--ink-3); }
.fresh-note {
  color: var(--ink-2); background: var(--bg-sunk);
  border-left: 3px solid var(--line-2); border-radius: 0 6px 6px 0; padding: .5rem .65rem;
}
.fresh-warn {
  color: var(--warn-ink); background: var(--warn-soft);
  border: 1px solid var(--warn-line); border-radius: var(--r-sm); padding: .65rem .75rem;
}
.fresh-warn a { color: inherit; font-weight: 600; }
.fresh-good {
  color: var(--open); background: var(--open-soft);
  border: 1px solid color-mix(in srgb, var(--open) 32%, transparent);
  border-radius: var(--r-sm); padding: .65rem .75rem;
}

.card-foot {
  margin-top: auto; padding: .7rem 0; display: flex; align-items: center;
  gap: .45rem .55rem; flex-wrap: wrap; font-size: .78rem; color: var(--ink-3);
  border-top: 1px solid var(--line);
}
/* Space above the rule without collapsing the auto margin that pins it down. */
.card-body { padding-bottom: .95rem; }
.dist {
  flex: 0 0 auto; margin-left: auto; font-weight: 600; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.perks { display: flex; gap: .3rem; flex: 0 0 auto; }
.perk { font-size: .82rem; }

/* ---------- empty / footer ---------- */

.empty { text-align: center; padding: 4rem 1rem; }
.empty-art { font-size: 2.6rem; }
.empty h2 { margin: .7rem 0 .3rem; font-size: 1.25rem; letter-spacing: -.02em; }
.empty p { margin: 0 0 1.2rem; color: var(--ink-2); font-size: .9rem; }

.btn {
  font: 600 .86rem var(--sans); border-radius: 10px; padding: .6rem 1rem;
  border: 1px solid var(--line-2); background: var(--bg-elev); color: var(--ink);
  cursor: pointer; transition: .15s; text-decoration: none; display: inline-flex;
  align-items: center; gap: .4rem; justify-content: center;
}
.btn:hover { border-color: var(--ink-3); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { filter: brightness(1.08); }
html[data-theme="dark"] .btn.primary { color: #201404; }

.foot {
  max-width: var(--maxw); margin: 0 auto; padding: 1.6rem 1.25rem 3rem;
  border-top: 1px solid var(--line); font-size: .8rem; color: var(--ink-3);
}
.foot p { margin: 0 0 .5rem; }
.foot strong { color: var(--ink-2); font-variant-numeric: tabular-nums; }

/* ---------- map ---------- */

.mapwrap {
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
  box-shadow: var(--shadow-sm); background: var(--bg-sunk);
}
#map { height: clamp(420px, calc(100vh - var(--header-h) - 140px), 780px); }

.leaflet-container { font: inherit; background: var(--bg-sunk); }
.leaflet-popup-content-wrapper {
  border-radius: var(--r-sm); background: var(--bg-elev); color: var(--ink);
  box-shadow: var(--shadow-md); border: 1px solid var(--line);
}
.leaflet-popup-tip { background: var(--bg-elev); border: 1px solid var(--line); }
.leaflet-popup-content { margin: .7rem .85rem; font-size: .85rem; line-height: 1.45; }
.leaflet-popup-close-button { color: var(--ink-3) !important; }
.leaflet-bar a, .leaflet-control-attribution {
  background: var(--bg-elev) !important; color: var(--ink-2) !important; border-color: var(--line) !important;
}
.leaflet-control-attribution a { color: var(--ink-2) !important; }

.pop-name { font-weight: 700; font-size: .95rem; letter-spacing: -.01em; display: block; }
.pop-sub { color: var(--ink-3); font-size: .78rem; }
.pop-open { margin-top: .3rem; display: inline-block; }
.pop-btn {
  display: inline-block; margin-top: .55rem; font: 600 .78rem var(--sans);
  color: var(--accent-ink); background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 7px; padding: .3rem .6rem; cursor: pointer;
}

.pin {
  width: 26px; height: 26px; border-radius: 50% 50% 50% 4px;
  transform: rotate(45deg);
  background: linear-gradient(150deg, hsl(var(--h, 30) calc(var(--sat, 1) * 85%) 64%), hsl(var(--h, 30) calc(var(--sat, 1) * 72%) 48%));
  border: 2.5px solid var(--bg-elev);
  box-shadow: 0 2px 6px rgba(0,0,0,.35);
  display: grid; place-items: center;
}
.pin span { transform: rotate(-45deg); font-size: .78rem; line-height: 1; }
.pin.shut { background: var(--ink-3); filter: saturate(.25); }

.cluster {
  width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--ink); color: var(--bg);
  border: 3px solid var(--bg-elev);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .35);
  font: 700 .82rem var(--sans); font-variant-numeric: tabular-nums;
}
.marker-cluster { background: transparent; }
.marker-cluster div { background: transparent; }
.pin.sel { background: var(--ink); width: 32px; height: 32px; z-index: 500; }

/* ---------- drawer ---------- */

.scrim {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(20, 18, 15, .45); backdrop-filter: blur(2px);
  animation: fade .18s ease-out;
}
@keyframes fade { from { opacity: 0; } }

.drawer {
  position: fixed; z-index: 100; top: 0; right: 0; bottom: 0; width: min(440px, 100vw);
  background: var(--bg-elev); border-left: 1px solid var(--line);
  box-shadow: var(--shadow-lg); overflow-y: auto;
  animation: slide .24s cubic-bezier(.2,.8,.25,1);
}
@keyframes slide { from { transform: translateX(102%); } }

/* Sits on the colour band, so it needs its own contrast rather than theme colours. */
.d-close {
  position: absolute; top: .7rem; right: .8rem; z-index: 3;
  width: 34px; height: 34px; border-radius: 50%;
  border: 0; background: rgba(20, 16, 12, .34); color: #fff;
  font-size: 1.35rem; line-height: 1; cursor: pointer;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  transition: background .15s, transform .15s;
}
.d-close:hover { background: rgba(20, 16, 12, .55); transform: scale(1.06); }
.d-close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Colour band carrying the same cuisine hue as the card you came from. */
.d-banner {
  height: 116px; display: grid; place-items: center;
  background:
    radial-gradient(120% 150% at 22% 12%,
      hsl(var(--h, 30) calc(var(--sat, 1) * 86%) 70%),
      hsl(var(--h, 30) calc(var(--sat, 1) * 72%) 52%) 58%,
      hsl(calc(var(--h, 30) - 18) calc(var(--sat, 1) * 66%) 42%));
  position: relative; overflow: hidden;
}
.d-banner::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to bottom, transparent 55%, color-mix(in srgb, var(--bg-elev) 92%, transparent));
}
#d-glyph {
  font-size: 3.1rem; line-height: 1;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, .3));
}
/* With a storefront photo the band grows and shows the picture instead. */
#d-photo { display: none; }
.d-banner.has-photo { height: 210px; }
.d-banner.has-photo #d-glyph { display: none; }
.d-banner.has-photo #d-photo {
  display: block; position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  /* The band is far wider than it is tall, so a photo loses most of its height to
     the crop. Centring it cut the fascia off shots where the sign sits high — Bar
     Bagel lost its name entirely. Signage is nearly always in the upper third of a
     storefront picture, so bias the window upwards. Not hard to the top: that would
     fill portrait shots with sky. */
  object-position: center 28%;
}
.d-banner.has-photo::after {
  background: linear-gradient(to bottom, rgba(0, 0, 0, .16) 0%, transparent 38%,
              color-mix(in srgb, var(--bg-elev) 88%, transparent));
}
/* ---------- storefront photo, full size ---------- */

/* Only the photographed banner behaves like a control. */
.d-banner[role="button"] { cursor: zoom-in; }
.d-zoom { display: none; }
.d-banner[role="button"] .d-zoom {
  display: grid; place-items: center;
  position: absolute; right: .7rem; bottom: .7rem; z-index: 2;
  width: 30px; height: 30px; border-radius: 50%;
  background: rgba(0, 0, 0, .45); color: #fff;
  backdrop-filter: blur(3px);
  opacity: .85; transition: opacity .16s, transform .16s;
}
.d-zoom svg { width: 15px; height: 15px; stroke-width: 2; }
.d-banner[role="button"]:hover .d-zoom { opacity: 1; transform: scale(1.08); }
.d-banner[role="button"]:focus-visible {
  outline: 3px solid var(--accent); outline-offset: -3px;
}

.lightbox {
  position: fixed; inset: 0; z-index: 300;
  display: grid; place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(10, 8, 6, .92);
  backdrop-filter: blur(6px);
  animation: fade .18s ease-out;
  cursor: zoom-out;
  /* The whole overlay is a swipe target, so hand every touch to the script rather
     than letting the browser start a scroll or a pinch first. */
  touch-action: none;
  transition: opacity .26s ease;
}
@keyframes fade { from { opacity: 0; } }
.lb-figure {
  margin: 0; display: flex; flex-direction: column; gap: .8rem; align-items: center;
  /* No percentage max-height here. It used to carry one, which meant a tall photo's
     size depended on resolving a percentage against the grid area and then flex-
     shrinking the image to fit — and Safari resolves that differently from Chrome,
     collapsing portrait photos to a thumbnail. The image constrains itself against
     the viewport instead, and this box just wraps whatever comes out. */
  min-height: 0;
  transition: transform .26s cubic-bezier(.2, .8, .3, 1);
}
/* While a finger is on it the position comes from the script frame by frame; the
   transition is only there to carry it home when the swipe falls short. */
.lb-figure.is-dragging { transition: none; }
#lb-img {
  display: block; cursor: default;
  /* Both limits are measured against the viewport, never against the parent. The
     old max-width of 100% pointed at the figure, whose own width comes from this
     image — a circle the browser has to break, and Safari broke it small. The 8rem
     and 2rem leave room for the caption and the overlay's padding. */
  max-width: min(1400px, calc(100vw - 2rem));
  max-height: calc(100vh - 8rem);
  max-height: calc(100dvh - 8rem);   /* ignored where dvh is unknown; mobile chrome-safe */
  width: auto; height: auto;
  /* Never let the column flex shrink it below the size those limits produced. */
  flex: 0 0 auto;
  border-radius: var(--r-sm);
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, .8);
}
#lb-caption {
  color: #f4f1ea; font: 600 .92rem var(--sans); text-align: center;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}
.lb-close {
  position: absolute; top: 1rem; right: 1rem; z-index: 1;
  width: 42px; height: 42px; border-radius: 50%;
  border: 0; cursor: pointer;
  background: rgba(255, 255, 255, .14); color: #fff;
  font-size: 1.6rem; line-height: 1;
  backdrop-filter: blur(4px);
}
.lb-close:hover { background: rgba(255, 255, 255, .26); }
.lb-close:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  .lightbox { animation: none; }
  .d-banner[role="button"]:hover .d-zoom { transform: none; }
}

/* ---------- pull to refresh ---------- */

/* Added to an iPad home screen, the site opens standalone: no address bar, and so
   none of Safari's own pull-to-refresh, which lives on that bar. This puts the
   gesture back. The travel is driven from JS frame by frame while the finger is
   down, so the transition is only switched on for the snap home. */
.ptr {
  position: fixed; top: 0; left: 50%; z-index: 200;
  display: grid; place-items: center;
  width: 38px; height: 38px; margin-left: -19px;
  border-radius: 50%;
  background: var(--bg-elev); color: var(--ink-2);
  box-shadow: var(--shadow-md);
  opacity: 0; pointer-events: none;
  transform: translateY(-46px);
}
.ptr svg {
  width: 19px; height: 19px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.ptr.is-settling { transition: transform .3s cubic-bezier(.2, .8, .3, 1), opacity .3s ease; }
/* Pulled far enough that letting go will reload. */
.ptr.is-ready { color: var(--accent); }
.ptr.is-busy svg { animation: ptr-spin .7s linear infinite; }
@keyframes ptr-spin { to { transform: rotate(360deg); } }

@media (display-mode: standalone) {
  /* Kill the rubber-band at the top so the indicator is the only thing that moves
     during a pull. Scoped to the home-screen app — in an ordinary browser tab the
     bounce belongs to the browser and shouldn't be taken away. */
  html { overscroll-behavior-y: contain; }
}

.menu-btn { text-decoration: none; }

/* Transcribed menu, set like a printed one rather than shown as a photograph */
.menu-box { margin-top: 1.6rem; }
.menu-box h3 {
  margin: 0 0 .7rem; font: 600 .74rem var(--sans); letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-3);
}
.menu-body {
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--bg-sunk); padding: .1rem 1rem .9rem;
}
.ms + .ms { border-top: 1px dashed var(--line-2); margin-top: .9rem; padding-top: .9rem; }
.ms h4 {
  margin: .9rem 0 .6rem; font-family: var(--serif); font-weight: 600;
  font-size: 1.02rem; letter-spacing: -.01em; color: var(--ink);
  display: flex; align-items: baseline; gap: .5rem;
}
.ms-note {
  font: 500 .72rem var(--sans); color: var(--ink-3);
  letter-spacing: .02em; text-transform: none;
}
.mi-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .62rem; }

.mi-head { display: flex; align-items: baseline; gap: .35rem; }
.mi-name { font: 600 .855rem var(--sans); color: var(--ink); }
.mi-raw {
  font-style: normal; font-size: .72em; font-weight: 700; margin-left: .28em;
  vertical-align: super; cursor: help;
  color: var(--ink-3);
}
/* Leader dots, the way a printed menu runs the eye across to the price. */
.mi-dots {
  flex: 1 1 auto; height: .55em;
  border-bottom: 1.5px dotted var(--line-2);
  transform: translateY(-.15em);
}
.mi-price {
  font: 600 .855rem var(--sans); color: var(--accent-ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mi-desc { margin: .12rem 0 0; font-size: .795rem; line-height: 1.45; color: var(--ink-2); max-width: 46ch; }
.mi-extra { margin: .15rem 0 0; font-size: .755rem; color: var(--ink-3); font-style: italic; }
.ms-footer {
  margin: .75rem 0 0; font-size: .765rem; line-height: 1.5; color: var(--ink-3);
  border-top: 1px solid var(--line); padding-top: .55rem;
}

.menu-note { margin: .6rem 0 0; font-size: .755rem; color: var(--ink-3); line-height: 1.5; }
.menu-link { margin: .45rem 0 0; font-size: .82rem; }
.menu-link a { font-weight: 600; }

.d-body { padding: 1.1rem 1.5rem 2.5rem; }
.d-kicker {
  margin: 0 0 .35rem; font: 600 .72rem var(--sans); letter-spacing: .07em;
  text-transform: uppercase; color: var(--accent-ink);
}
#d-name {
  margin: 0 0 .6rem; font-family: var(--serif); font-weight: 600;
  font-size: 1.72rem; letter-spacing: -.022em; line-height: 1.12;
}
.d-status { margin-bottom: .75rem; }

.d-meta { margin-top: 1.1rem; display: grid; gap: .5rem; font-size: .875rem; }
.d-row { display: flex; gap: .6rem; align-items: flex-start; color: var(--ink-2); }
.d-row svg { flex: 0 0 auto; font-size: 1.05rem; margin-top: 1px; color: var(--ink-3); }
.d-row a { color: var(--accent-ink); text-decoration: none; overflow-wrap: anywhere; }
.d-row a:hover { text-decoration: underline; }
/* Warm rather than alarming — it is a thing to know before you set off, not an error. */
.d-row.cash-only { color: var(--warn-ink); }
.d-row.cash-only svg { color: var(--warn-ink); }

.d-actions { margin-top: 1.2rem; display: grid; grid-template-columns: 1fr 1fr; gap: .5rem; }
.d-actions .btn { padding: .65rem .8rem; font-size: .84rem; }
.d-actions .btn.wide { grid-column: 1 / -1; }

.hours-box { margin-top: 1.5rem; }
.hours-box h3, .d-minimap-title {
  margin: 0 0 .5rem; font: 600 .74rem var(--sans); letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-3);
}
.hours { width: 100%; border-collapse: collapse; font-size: .85rem; }
.hours th, .hours td { padding: .38rem .1rem; text-align: left; font-weight: 500; }
.hours th { color: var(--ink-2); width: 6.2rem; }
.hours td { color: var(--ink); font-variant-numeric: tabular-nums; }
.hours tr + tr { border-top: 1px dashed var(--line); }
.hours tr.today th, .hours tr.today td { color: var(--accent-ink); font-weight: 700; }
.hours td.off { color: var(--ink-3); }
.no-hours { font-size: .85rem; color: var(--ink-3); margin: 0; line-height: 1.55; }

.d-minimap { margin-top: 1.5rem; }
.d-minimap-link {
  display: block; text-decoration: none; width: 100%;
  /* It became a <button> when it stopped going straight to Google, so reset the
     chrome a button brings with it: background, border, padding and centring. */
  -webkit-appearance: none; appearance: none;
  background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.d-minimap-inner {
  display: block;
  height: 190px; border-radius: var(--r-sm); overflow: hidden;
  border: 1px solid var(--line); background: var(--bg-sunk);
  transition: border-color .16s, box-shadow .16s;
}
/* The map is a picture inside a link — let every click reach the anchor.
   Leaflet puts .leaflet-container on the element it initialises into, which here
   IS .d-minimap-inner, so this has to match the same element, not a descendant. */
.d-minimap-inner, .d-minimap-inner * { pointer-events: none; }
.d-minimap-link:hover .d-minimap-inner,
.d-minimap-link:focus-visible .d-minimap-inner {
  border-color: var(--accent); box-shadow: 0 0 0 3.5px var(--accent-soft);
}
/* The cue sits in the heading, above the link, so hover is tracked on the shared
   parent rather than with a sibling selector. */
.d-minimap-cta { float: right; color: var(--accent-ink); font-weight: 600; }
.d-minimap:hover .d-minimap-cta { text-decoration: underline; }
.d-osm { margin: 1.4rem 0 0; font-size: .74rem; color: var(--ink-3); }
.d-osm a { color: var(--ink-3); }

/* ---------- toast ---------- */

.toast {
  position: fixed; z-index: 200; left: 50%; bottom: 1.6rem; transform: translateX(-50%);
  background: var(--ink); color: var(--bg);
  font: 600 .85rem var(--sans); padding: .7rem 1.1rem; border-radius: 10px;
  box-shadow: var(--shadow-lg); animation: pop .22s cubic-bezier(.2,.8,.25,1);
  max-width: calc(100vw - 2rem); text-align: center;
}
@keyframes pop { from { opacity: 0; transform: translate(-50%, 12px); } }

/* ---------- responsive ---------- */

@media (max-width: 900px) {
  .topbar-inner { flex-wrap: wrap; padding-bottom: .5rem; }
  .search { order: 3; flex-basis: 100%; max-width: none; }
  .topbar-actions { margin-left: auto; }
  .slash-hint { display: none; }
  #q { padding-right: 2.6rem; }
  .q-clear { right: .6rem; }
}

@media (max-width: 620px) {
  /* The filter block is too tall to pin on a phone — let the header scroll away. */
  .topbar { position: static; }
  .brand-text small { display: none; }
  .icon-btn span { display: none; }
  .icon-btn { padding: .55rem; }
  .filter-row.secondary { gap: .4rem; }
  .select { padding-left: .6rem; flex: 1 1 calc(50% - .25rem); min-width: 0; justify-content: space-between; }
  .select select { flex: 1 1 auto; min-width: 0; }
  .select > span { display: none; }
  .toggle { flex: 1 1 calc(50% - .25rem); justify-content: center; }
  .viewswitch { flex: 1 1 100%; }
  .vs-btn { flex: 1 1 50%; justify-content: center; }
  .spacer { display: none; }
  .grid { grid-template-columns: 1fr; }
  main { padding-left: 1rem; padding-right: 1rem; }
  .filters, .topbar-inner { padding-left: 1rem; padding-right: 1rem; }
  .drawer { width: 100vw; }
  #map { height: calc(100vh - 260px); }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  html { scroll-behavior: auto; }
  /* The one exception. A spinner is a progress indicator, not decoration — near-zero
     duration would leave it juddering in place while the page reloads behind it. */
  .ptr.is-busy svg { animation-duration: .7s !important; }
}

/* ---------------------------------------------------------------- *
   Directions chooser

   One button asked which map app to use, so this is what it asks in. Sized and
   centred like the lightbox, but a small sheet rather than a full-bleed overlay —
   it is a three-way question, not a picture.
 * ---------------------------------------------------------------- */
.mapchoice {
  position: fixed; inset: 0; z-index: 320;
  display: grid; place-items: center;
  padding: clamp(1rem, 5vw, 3rem);
  background: rgba(10, 8, 6, .55);
  backdrop-filter: blur(3px);
  animation: fade .16s ease-out;
}
.mc-sheet {
  width: min(21rem, 100%);
  background: var(--bg-card, var(--bg)); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-md, 14px);
  box-shadow: 0 24px 60px -18px rgba(0, 0, 0, .55);
  padding: 1.1rem 1.1rem .9rem;
}
.mc-title {
  margin: 0 0 .85rem; font: 700 .95rem/1.35 var(--sans); color: var(--ink);
}
.mc-title span { color: var(--ink-2); font-weight: 600; }
.mc-apps { display: grid; gap: .45rem; }
.mc-app {
  display: flex; align-items: center; justify-content: space-between;
  font: 600 .9rem var(--sans); color: var(--ink); text-decoration: none;
  border: 1px solid var(--line); border-radius: 10px;
  padding: .62rem .8rem; background: var(--bg-sunk, transparent);
  transition: border-color .15s, background .15s;
}
.mc-app span { color: var(--ink-3); font-weight: 400; }
.mc-app:hover { border-color: var(--accent); background: var(--accent-soft); }
.mc-app:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.mc-cancel {
  display: block; width: 100%; margin-top: .7rem;
  font: 600 .85rem var(--sans); color: var(--ink-2);
  background: none; border: 0; padding: .5rem; cursor: pointer; border-radius: 8px;
}
.mc-cancel:hover { color: var(--ink); background: var(--bg-sunk); }
.mc-cancel:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (prefers-reduced-motion: reduce) { .mapchoice { animation: none; } }

/* ---------------------------------------------------------------- *
   Happy hour
   The badge only appears while one is actually running, so it can afford to be
   loud. The panel line is quieter — it is there whether or not the clock agrees,
   because someone planning Thursday wants to read Thursday.
 * ---------------------------------------------------------------- */
.hh-badge {
  display: inline-block; margin: .3rem 0 0;
  font: 700 .68rem/1 var(--sans); letter-spacing: .04em; text-transform: uppercase;
  color: var(--warn-ink); background: var(--warn-soft);
  border: 1px solid var(--warn-line); border-radius: 999px; padding: .24em .5em;
}
.hh-live { color: var(--warn-ink); font-weight: 700; }
.hh-what { display: block; margin-top: .15rem; color: var(--ink-2); font-size: .82rem; line-height: 1.4; }

/* Brunch wears the same badge as happy hour in a different colour, so the two read as
   the same kind of fact — something that is on right now — rather than two inventions. */
.hh-badge.hh-brunch { color: var(--open); background: var(--open-soft); border-color: color-mix(in srgb, var(--open) 30%, transparent); }

/* ---------------------------------------------------------------- *
   Happy hour schedule
   A timetable, not a card grid: the time is the left-hand column and everything
   lines up against it, so the eye can run down the hour rather than hunt.
 * ---------------------------------------------------------------- */
.schedule { max-width: var(--maxw); margin: 0 auto; padding: 0 1.25rem 3rem; }
.sd-tabs { display: flex; flex-wrap: wrap; gap: .4rem; margin: .2rem 0 1.4rem; }
.sd-tab {
  display: inline-flex; align-items: baseline; gap: .38rem;
  font: 600 .85rem var(--sans); color: var(--ink);
  background: var(--bg-elev); border: 1px solid var(--line-2); border-radius: 999px;
  padding: .5rem .9rem; cursor: pointer; box-shadow: var(--shadow-sm);
  transition: transform .16s cubic-bezier(.2,.7,.3,1), box-shadow .16s, background .16s, color .16s;
}
.sd-tab span { font-size: .74rem; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.sd-tab:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.sd-tab.is-on { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.sd-tab.is-on span { color: var(--bg); opacity: .7; }

.sd-heading { margin: 0 0 .9rem; font: 600 1.35rem var(--serif); letter-spacing: -.01em; }
.sd-heading.sd-sub { margin-top: 2rem; font-size: 1.05rem; color: var(--ink-2); }
.sd-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.sd-row {
  display: grid; grid-template-columns: 10.5rem 1fr; gap: 1rem; align-items: start;
  background: var(--bg-elev); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: .85rem 1rem; cursor: pointer;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.sd-row:hover { border-color: var(--accent); box-shadow: var(--shadow-md); transform: translateY(-1px); }
.sd-row:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sd-when {
  font: 700 .88rem var(--sans); color: var(--accent-ink);
  font-variant-numeric: tabular-nums; line-height: 1.5;
}
.sd-when-none { color: var(--ink-3); }
.sd-body { display: block; line-height: 1.45; }
.sd-body b { font-size: .98rem; }
.sd-live {
  margin-left: .5rem; font: 700 .64rem/1 var(--sans); letter-spacing: .05em; text-transform: uppercase;
  color: var(--warn-ink); background: var(--warn-soft); border: 1px solid var(--warn-line);
  border-radius: 999px; padding: .22em .48em; vertical-align: .1em;
}
.sd-what { display: block; margin-top: .18rem; font-size: .84rem; color: var(--ink-2); }
.sd-where { display: block; margin-top: .12rem; font-size: .78rem; color: var(--ink-3); }
.sd-none { color: var(--ink-2); font-size: .95rem; }
.sd-foot { margin-top: 1.6rem; font-size: .8rem; color: var(--ink-3); }
@media (max-width: 560px) {
  .sd-row { grid-template-columns: 1fr; gap: .3rem; }
  .sd-when { font-size: .82rem; }
}
