/* Neat — design system.
   Paper background, deep-green bar, brass accent. Hand-written custom
   properties: this monolith has no build step, so there is no Tailwind here.

   1. Tokens          8. Cards, rails, tiles
   2. Base            9. Listing rows
   3. Layout         10. Spirit detail
   4. Header         11. Taste, compare
   5. Palette        11b. Scanner
   6. Controls       12. Home extras
   7. Filters        13. Cocktails & pantry
                     13b. My Bar, bottle actions
                     14. Sheets, tabbar, footer
                     15. Utilities, responsive
*/

/* 1. Tokens ------------------------------------------------------------- */

:root {
  --ink: #14211b;
  --paper: #f1f3ee;
  --card: #ffffff;
  --line: #d5dbd3;
  --line-strong: #c3ccc1;
  --muted: #55615a;
  --faint: #7b857e;

  --bar: #0e2a22;
  --bar-2: #143a2f;
  --hero-glow: #1f5242;
  --hero-text: #f2f6f1;
  --hero-muted: #b4c6ba;
  --hero-line: rgba(255, 255, 255, 0.12);
  --hero-line-2: rgba(255, 255, 255, 0.28);
  --hero-field: rgba(255, 255, 255, 0.1);

  --accent: #d9962a;
  --accent-lt: #f2c15a;
  --accent-dk: #b87f22;
  /* White, as the app sets it. Near-black holds more contrast on this gold,
     but the app's filled buttons read as one thing across both, and a gold
     button with dark type looked like a warning next to them. */
  --on-accent: #fff;
  --accent-wash: #fbf1de;
  --accent-ink: #8a5a0e;

  --price: #237a52;
  --price-lt: #5ebf8a;
  --price-wash: #eef5ef;
  --dn: #b24a2c;
  --dn-wash: #f7ece8;

  --art-1: #edf1ea;
  --art-2: #dce4da;
  --star-off: #d8ddd5;
  --track: #e6eae3;

  --shadow-sm: 0 1px 2px rgba(14, 33, 27, 0.06);
  --shadow: 0 1px 2px rgba(14, 33, 27, 0.06), 0 8px 20px -14px rgba(14, 33, 27, 0.35);
  --shadow-lg: 0 18px 34px -18px rgba(14, 33, 27, 0.4);
  --shadow-xl: 0 30px 60px -30px rgba(14, 33, 27, 0.55);

  --r-sm: 8px;
  --r: 14px;
  --r-lg: 18px;
  --r-pill: 999px;

  /* One family, the way the app has it: Inter for display and body alike.
     Display differs by weight and tracking, not by typeface. */
  --f-display: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --f-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  /* The pill itself, and the space the whole floating dock takes: the pill
     plus the paper it hovers on. Anything pinned above the dock measures
     from the second. */
  --tabbar-h: 58px;
  --dock-h: 76px;

  /* Score ramp: red through amber to deep green, cut at the measured
     percentiles (top 2%, 8%, 20%, 50%). A single-hue ramp was too subtle to
     rank a list by; sweeping the hue means two steps apart is unmistakable.
     Every one of these carries white type: they run 4.3:1 to 6.6:1 against
     white, which rules out a bright olive and a bright amber and is why the
     middle of the ramp is deeper than it looks like it wants to be. */
  --g5: #0c6b3d;
  --g4: #1f8a45;
  --g3: #648217;
  --g2: #a26d09;
  --g1: #c1502e;
  --g0: #737d78;

  /* Aliases kept so view-level inline styles written against the previous
     dark theme keep resolving to something sensible. */
  --text: var(--ink);
  --text-soft: #33413a;
  --serif: var(--f-display);
  --sans: var(--f-body);
  --brass: var(--accent);
  --brass-bright: var(--accent-dk);
  --brass-dim: var(--accent);
  --brass-line: rgba(217, 150, 42, 0.55);
  --brass-wash: rgba(217, 150, 42, 0.12);
  --good: var(--price);
  --mid: var(--accent-ink);
  --low: var(--dn);
  --radius: var(--r);
  --radius-sm: var(--r-sm);
  --radius-lg: var(--r-lg);
  --radius-pill: var(--r-pill);
  --ink-950: var(--paper);
  --ink-900: var(--paper);
  --ink-850: var(--card);
  --ink-800: var(--paper);
  --ink-750: var(--track);
  --ink-700: var(--track);
  --ink-600: var(--line-strong);
}

/* 2. Base --------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html { scroll-behavior: smooth; }
html, body { overflow-x: hidden; max-width: 100%; }

body {
  font-family: var(--f-body);
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; text-decoration: none; }
img, svg, canvas { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; background: none; border: 0; }
button { cursor: pointer; }
ul, ol { list-style: none; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

h1, h2, h3, h4 {
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
h1 { font-size: clamp(30px, 4vw, 44px); letter-spacing: -0.03em; line-height: 1.06; }
h2 { font-size: clamp(24px, 2.4vw, 34px); letter-spacing: -0.025em; }
h3 { font-size: 20px; }

.tnum { font-variant-numeric: tabular-nums; }
.muted { color: var(--muted); }
.faint { color: var(--faint); }
.nowrap { white-space: nowrap; }

.eyebrow, .kicker {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-dk);
  margin-bottom: 6px;
}
.eyebrow--brass, .on-dark .eyebrow, .on-dark .kicker { color: var(--accent-lt); }

.lede { font-size: 16.5px; color: var(--muted); max-width: 62ch; }
.prose { color: var(--text-soft); max-width: 68ch; }
.prose p + p { margin-top: 14px; }
.prose h2 { margin: 32px 0 10px; font-size: 22px; }
.prose ul { margin: 12px 0 16px 1.25em; list-style: disc; }
.prose ol { margin: 12px 0 16px 1.25em; list-style: decimal; }
.prose li + li { margin-top: 6px; }
.prose a { color: var(--price); font-weight: 700; }
.prose a:hover { text-decoration: underline; }
.prose .effective {
  margin-top: 28px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--faint);
}

.page-doc {
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}
.page-doc--wide { max-width: 760px; }
.page-doc--center {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.page-doc--center .lede { margin-left: auto; margin-right: auto; }
.page-doc--center .panel { width: 100%; max-width: 520px; text-align: left; }
.page-doc--wide > .page-doc--center { width: 100%; }
.page-doc .prose { max-width: none; }

.link { color: var(--price); font-weight: 700; }
.link:hover { text-decoration: underline; }
.link--icon { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }

/* 3. Layout ------------------------------------------------------------- */

.wrap, .shell { max-width: 1300px; margin: 0 auto; padding: 0 24px; }
.shell--narrow { max-width: 860px; }
.shell.page-doc { max-width: 640px; padding-top: 56px; padding-bottom: 40px; }
.shell.page-doc.page-doc--wide { max-width: 760px; }

.section { margin-top: 52px; }
.section--tight { margin-top: 32px; }

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 20px;
}
.section-head h2 { max-width: 24ch; }
.section-head p { color: var(--muted); font-size: 14.5px; margin-top: 6px; max-width: 62ch; }

.panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 22px;
  box-shadow: var(--shadow);
}
.panel--flush { padding: 0; overflow: hidden; }
.panel__title {
  margin-bottom: 12px;
  font-family: var(--f-body);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.panel__lead { font-size: 14px; color: var(--ink); }
.panel__lead b { font-weight: 800; }
.panel__note { margin-top: 12px; font-size: 12.5px; color: var(--muted); }

/* Contact / support form */
.support .lede { margin: 10px auto 28px; }
.support__status { margin-top: 14px; font-size: 14px; }
.support__status.is-error { color: var(--dn); }
.support__status.is-ok { color: var(--price); }
.support__ok { text-align: center; padding: 28px 12px; }
.support__ok h2 { margin: 8px 0 10px; }
.support__ok[hidden], .support [hidden] { display: none; }
.support__delete { margin-bottom: 20px; }
.support__delete h2 { margin: 4px 0 10px; font-size: 22px; }
.support__delete .steps3 { padding-top: 12px; }
.support__delete .s3 span:not(.s3__n) { line-height: 1.45; }
.delete-account .page-doc--center .lede { margin-bottom: 0; }
.delete-account [hidden] { display: none; }
.delete-account [data-support-page] .support__ok { max-width: none; }

/* Auth: login, signup, forgot / reset password */
.auth .lede { margin: 8px auto 28px; max-width: 36ch; }
.auth .panel { max-width: 420px; padding: 28px 26px; }
.auth .field input { background: var(--card); }
.auth .btn { border-radius: var(--r); }
.auth-error {
  background: var(--dn-wash);
  border: 1px solid var(--dn);
  color: var(--dn);
  border-radius: var(--r);
  padding: 12px 14px;
  margin-bottom: 16px;
  font-size: 14px;
}
.auth-error[hidden],
.auth [hidden] { display: none; }
.auth-oauth {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
}
.auth-oauth:hover { background: var(--paper); border-color: var(--line-strong); }
.auth-oauth svg { width: 20px; height: 20px; flex-shrink: 0; }
.auth-links {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 16px;
  font-size: 14px;
}
.auth-links a,
.auth-foot a { color: var(--accent); font-weight: 600; }
.auth-links a:hover,
.auth-foot a:hover { text-decoration: underline; }
.auth-foot {
  margin-top: 22px;
  text-align: center;
  font-size: 14px;
  color: var(--muted);
}
.auth-ok { text-align: center; padding: 8px 4px; }
.auth-ok h2 { margin: 10px 0 10px; font-size: 22px; }
.auth-hint { margin-top: 8px; font-size: 13px; color: var(--muted); }

.field { display: flex; flex-direction: column; gap: 6px; }
.field + .field { margin-top: 14px; }
.field label { font-size: 13px; font-weight: 700; color: var(--muted); }
.field input,
.field textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper);
  color: var(--ink);
}
.field input::placeholder,
.field textarea::placeholder { color: var(--faint); }
.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--brass-wash);
}
.field textarea { min-height: 140px; resize: vertical; }

.empty {
  background: var(--card);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r);
  padding: 40px 24px;
  text-align: center;
  color: var(--muted);
}
.empty h3 { margin-bottom: 8px; color: var(--ink); }
.empty p { max-width: 46ch; margin-inline: auto; }

.divider-label {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
  font-weight: 700;
}
.divider-label::before, .divider-label::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* 4. Header & subnav ---------------------------------------------------- */

.header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--bar);
  color: var(--hero-text);
  border-bottom: 1px solid var(--hero-line);
}
.header__inner {
  position: relative;
  max-width: 1300px;
  margin: 0 auto;
  padding: 0 24px;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 22px;
  height: 60px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-shrink: 0;
  font-family: var(--f-display);
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--hero-text);
}
/* Sized off its height: the decanter is taller than it is wide. */
.brand__logo {
  display: block;
  width: auto;
  height: 30px;
  flex: 0 0 auto;
}

.searchbar {
  position: relative;
  flex: 1;
  min-width: 0;
  max-width: 520px;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 8px 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--hero-line-2);
  background: var(--hero-field);
  color: var(--hero-muted);
  font-size: 14px;
  text-align: left;
}
.searchbar:hover,
.searchbar:focus-within,
.searchbar.is-open { border-color: var(--hero-text); }
.searchbar > svg { width: 16px; height: 16px; flex-shrink: 0; }
.searchbar input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--hero-text);
  font: inherit;
  outline: none;
}
.searchbar input::placeholder { color: var(--hero-muted); }
/* Only ever shown in the collapsed mobile bar, in place of the input. */
.searchbar__label { display: none; white-space: nowrap; }
.searchbar input::-webkit-search-decoration,
.searchbar input::-webkit-search-cancel-button { -webkit-appearance: none; }
.searchbar__hint {
  margin-left: auto;
  border: 1px solid var(--hero-line-2);
  border-radius: 5px;
  padding: 2px 6px;
  font-size: 11px;
  opacity: 0.75;
  flex-shrink: 0;
}

/* Attached under the header input so typing never leaves this field. */
.searchbar__menu {
  position: absolute;
  left: 0;
  top: calc(100% + 12px);
  z-index: 50;
  width: min(260px, 92vw);
  padding-bottom: 8px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--shadow-xl);
  font-family: var(--f-body);
  font-size: 14px;
  font-weight: 400;
  text-align: left;
}
.searchbar__menu.is-results { width: min(420px, 92vw); }
.searchbar__menu[hidden] { display: none; }
.searchbar__menu::before {
  content: "";
  position: absolute;
  top: -6px;
  left: 22px;
  width: 12px;
  height: 12px;
  background: var(--card);
  border-left: 1px solid var(--line);
  border-top: 1px solid var(--line);
  transform: rotate(45deg);
}
.searchbar__menu-head {
  padding: 14px 16px 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
}
.searchbar__type {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 16px;
  color: var(--muted);
  font-size: 15px;
  font-weight: 500;
}
.searchbar__type:hover,
.searchbar__type.is-active { background: var(--paper); color: var(--ink); }
.searchbar__type svg {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  color: var(--faint);
}

.nav {
  margin-left: auto;
  display: flex;
  gap: 22px;
  font-size: 14px;
  font-weight: 600;
  color: var(--hero-muted);
}
.nav__link:hover { color: var(--hero-text); }
.nav__link.is-current { color: var(--accent-lt); }

/* The tools drawer. Rendered on the dark bar, dropped onto paper. */
.nav__more { position: relative; }
.nav__more summary {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  list-style: none;
}
.nav__more summary::-webkit-details-marker { display: none; }
.nav__more[open] summary { color: var(--hero-text); }
.nav__more[open] summary svg { transform: rotate(180deg); }
.nav__more summary svg { transition: transform 0.15s var(--ease); }
.nav__drawer {
  position: absolute;
  top: calc(100% + 12px);
  right: 0;
  z-index: 40;
  width: 300px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
  box-shadow: var(--shadow-xl);
}
.nav__drawer a {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 10px;
  border-radius: var(--r-sm);
  color: var(--faint);
}
.nav__drawer a:hover { background: var(--paper); }
.nav__drawer span { display: block; font-size: 12.5px; line-height: 1.4; color: var(--muted); }
.nav__drawer strong { display: block; font-size: 14px; font-weight: 700; color: var(--ink); }
.header__spacer { flex: 1; }
.header__actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.header__auth {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: 8px;
}
.header__auth-link {
  color: var(--hero-muted);
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
}
.header__auth-link:hover { color: var(--hero-text); }
.header__auth-cta {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
}
.header__auth-cta:hover { background: var(--accent-dk); color: #fff; }

.icon-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  color: var(--hero-muted);
}
.icon-btn:hover { background: var(--hero-field); color: var(--hero-text); }
.icon-btn svg { width: 20px; height: 20px; }
/* display: grid above outranks the browser's [hidden] rule, so the compare
   door would never actually hide. */
.icon-btn[hidden] { display: none; }
/* The account door. On a wide screen it is only that, so it stays the app's
   circle: initials once it knows a name, the person glyph until then. Below
   the tab bar's breakpoint the same control also opens the menu, and the
   bars beside the face say so — see section 15. */
.icon-btn--menu { display: flex; justify-content: center; }
.icon-btn__bars { display: none; }
.icon-btn__face {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
}
.icon-btn__face.is-mono {
  background: var(--hero-field);
  color: var(--hero-text);
  font-size: 13px;
  font-weight: 700;
}

.count-dot {
  position: absolute;
  top: 2px;
  right: 0;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: var(--r-pill);
  background: var(--accent);
  color: var(--on-accent);
  font-size: 10.5px;
  font-weight: 800;
  line-height: 17px;
  text-align: center;
}

.subnav { background: var(--card); border-bottom: 1px solid var(--line); }
.subnav__inner {
  max-width: 1300px;
  margin: 0 auto;
  padding: 8px 24px;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
}
.subnav__inner::-webkit-scrollbar { display: none; }
.subnav a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: var(--r-pill);
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
}
.subnav a .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--c, var(--line-strong)); }
.subnav a:hover, .subnav a[aria-current="true"] { background: var(--paper); color: var(--ink); }

/* 5. Command palette ---------------------------------------------------- */

.palette-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(14, 33, 27, 0.42);
  backdrop-filter: blur(3px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s var(--ease);
}
.palette-backdrop.is-open { opacity: 1; pointer-events: auto; }

.palette {
  position: fixed;
  top: 72px;
  left: 50%;
  z-index: 91;
  width: min(640px, calc(100vw - 32px));
  max-height: min(70vh, 620px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow-xl);
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -8px);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}
.palette.is-open { opacity: 1; pointer-events: auto; transform: translate(-50%, 0); }
.palette[hidden] { display: none; }

.palette__field {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
}
.palette__field svg { width: 19px; height: 19px; color: var(--muted); flex-shrink: 0; }
.palette__field input { flex: 1; min-width: 0; font-size: 16px; font-weight: 500; outline: none; }
.palette__field input::placeholder { color: var(--faint); font-weight: 400; }
.palette__spin {
  display: none;
  width: 15px;
  height: 15px;
  border: 2px solid var(--track);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
.palette.is-loading .palette__spin { display: block; }
@keyframes spin { to { transform: rotate(360deg); } }

.palette__results { flex: 1; overflow-y: auto; overscroll-behavior: contain; }
.pgroup + .pgroup { border-top: 1px solid var(--line); }
.pgroup__title {
  padding: 8px 16px;
  background: var(--paper);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.presult {
  display: grid;
  grid-template-columns: 38px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 9px 16px;
  border-bottom: 1px solid var(--line);
}
.pgroup .presult:last-child { border-bottom: 0; }
.presult:hover, .presult.is-active { background: var(--paper); }
.presult__thumb {
  display: block;
  width: 38px;
  height: 38px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--art-2) center/cover no-repeat;
}
.presult__main { min-width: 0; }
.presult__name {
  display: block;
  font-size: 14px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.presult__sub {
  display: block;
  font-size: 12.5px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.presult__score {
  flex-shrink: 0;
  flex-direction: column;
  align-items: flex-end;
  gap: 0;
  line-height: 1.15;
}
.presult__score .score__value { font-size: 16px; }
.presult__score .score__count { display: block; font-size: 11px; }

.palette__foot {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 16px;
  border-top: 1px solid var(--line);
  background: var(--paper);
  font-size: 12px;
  color: var(--faint);
}
.kbd {
  display: inline-block;
  min-width: 18px;
  padding: 1px 5px;
  border-radius: 4px;
  border: 1px solid var(--line-strong);
  background: var(--card);
  font-size: 11px;
  text-align: center;
  color: var(--muted);
}

/* 6. Controls: buttons, chips, tags, selects ---------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 42px;
  padding: 10px 18px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease), transform 0.12s var(--ease);
}
.btn:hover { border-color: var(--line-strong); background: var(--paper); }
.btn:active { transform: translateY(1px); }
.btn svg { width: 17px; height: 17px; }

.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
/* Darkens rather than lightens, now that the label is white: the old hover
   went pale and took the type with it. */
.btn--primary:hover { background: var(--accent-dk); border-color: var(--accent-dk); }
.btn--dark { background: var(--ink); border-color: var(--ink); color: #fff; }
.btn--dark:hover { background: var(--bar-2); border-color: var(--bar-2); }
.btn--green { background: var(--price); border-color: var(--price); color: #fff; }
.btn--green:hover { background: #1c6644; border-color: #1c6644; }
.btn--ghost { background: transparent; }
.btn--sm { min-height: 34px; padding: 7px 14px; font-size: 13px; }
.btn--lg { min-height: 48px; padding: 12px 22px; font-size: 15.5px; }
.btn--block { width: 100%; }
.btn[disabled] { opacity: 0.55; pointer-events: none; }

/* On the dark bar and hero panels. */
.on-dark .btn:not(.btn--primary):not(.btn--dark):not(.btn--green) {
  background: transparent;
  border-color: var(--hero-line-2);
  color: var(--hero-text);
}
.on-dark .btn:not(.btn--primary):hover { background: var(--hero-field); border-color: var(--hero-text); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 13px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.chip:hover { border-color: var(--line-strong); color: var(--ink); }
.chip__count { color: var(--faint); font-size: 12px; font-variant-numeric: tabular-nums; }
.chip.is-active { background: var(--ink); border-color: var(--ink); color: #fff; }
.chip.is-active .chip__count { color: rgba(255, 255, 255, 0.7); }
.chip.is-empty { opacity: 0.4; pointer-events: none; }
.chip .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--c, var(--line-strong)); }
.chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
/* Sibling links can run to a dozen entries, which is a wall of chips on a phone. */
@media (max-width: 900px) {
  .chip-row--rail {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    padding-bottom: 2px;
    -webkit-overflow-scrolling: touch;
  }
  .chip-row--rail::-webkit-scrollbar { display: none; }
  .chip-row--rail .chip { flex: 0 0 auto; }
}

.on-dark .chip, .band .chip {
  background: transparent;
  border-color: var(--hero-line-2);
  color: var(--hero-text);
}
.on-dark .chip:hover, .on-dark .chip.is-active, .on-dark .chip[aria-pressed="true"],
.band .chip:hover, .band .chip.is-active, .band .chip[aria-pressed="true"] {
  background: var(--hero-field);
  border-color: var(--hero-text);
  color: var(--hero-text);
}
.on-dark .chip__count, .on-dark .chip small,
.band .chip__count, .band .chip small { color: var(--hero-muted); font-weight: 400; }

.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--r-sm);
  background: var(--track);
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 600;
}
a.tag:hover { background: var(--line); color: var(--ink); }

.select {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 190px;
  padding: 7px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 12px;
  color: var(--muted);
}
.select select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 20px;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
  outline: none;
}
/* The taste bands read as one short word each, so they take the room they
   need rather than the width the sort control wants for "Most reviewed". */
.select--band { min-width: 148px; }
.select::after {
  content: "";
  position: absolute;
  right: 14px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}
.select svg { display: none; }

/* Stars */
.stars { display: inline-flex; gap: 1px; }
.star { width: 13px; height: 13px; fill: var(--star-off); }
.star.on { fill: var(--accent); }
.star.half { fill: url(#half); }
.stars svg { width: 13px; height: 13px; }
.stars .is-off { fill: var(--star-off); color: var(--star-off); }

/* Score, price, badges */
.score { display: inline-flex; align-items: baseline; gap: 4px; }
.score__value { font-family: var(--f-display); font-size: 20px; font-weight: 800; letter-spacing: -0.03em; color: var(--grade, inherit); }
.score__of { font-size: 11.5px; color: var(--faint); }
.score__count { font-size: 11.5px; color: var(--muted); }
.score--none { font-size: 12.5px; color: var(--faint); font-style: italic; }

/* Naming a band is all a caller does; the ramp itself lives in the tokens, so
   a score chip, a scan chip and a cocktail card all land on the same colour. */
.grade--g5 { --grade: var(--g5); }
.grade--g4 { --grade: var(--g4); }
.grade--g3 { --grade: var(--g3); }
.grade--g2 { --grade: var(--g2); }
.grade--g1 { --grade: var(--g1); }
.grade--g0 { --grade: var(--g0); }

/* Score chip, as the app draws it: a brass wash with a star and the number, and
   the grade colour behind white type when a list wants to be ranked by eye. */
.scorechip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-width: 36px;
  padding: 4px 8px;
  border-radius: var(--r-sm);
  background: var(--accent-wash);
  color: var(--accent-dk);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.scorechip svg { width: 12px; height: 12px; fill: currentColor; }
.scorechip--graded { background: var(--grade, var(--g0)); color: #fff; }
.scorechip--none { background: var(--paper); color: var(--faint); font-weight: 600; }
.scorechip__count { display: block; margin-top: 4px; font-size: 11px; color: var(--muted); text-align: center; }

/* A bracket like $100–$300 is wide for a card foot, so it stays on one line and
   gives the score the slack instead of pushing it into a wrap. */
.price { font-weight: 800; font-size: 13.5px; color: var(--price); letter-spacing: 0.02em; white-space: nowrap; }
.critic {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border-radius: var(--r-sm);
  background: var(--accent-wash);
  color: var(--accent-ink);
  font-size: 11.5px;
  font-weight: 800;
}
.badge {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
  padding: 4px 8px;
  border-radius: 6px;
  background: var(--price);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.badge--top { background: var(--accent); color: var(--on-accent); }

.pct {
  width: max-content;
  padding: 3px 8px;
  border-radius: 6px;
  background: var(--accent-wash);
  color: var(--accent-ink);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.pct--mid { background: var(--paper); color: var(--muted); }

.confidence {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--muted);
}
.confidence::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.confidence--high { color: var(--price); border-color: rgba(35, 122, 82, 0.35); background: var(--price-wash); }
.confidence--mid { color: var(--accent-ink); border-color: rgba(217, 150, 42, 0.35); background: var(--accent-wash); }
.confidence--low { color: var(--dn); border-color: rgba(178, 74, 44, 0.3); background: var(--dn-wash); }

.match {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: var(--price-wash);
  border: 1px solid rgba(35, 122, 82, 0.3);
  color: var(--price);
  font-size: 11.5px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* 7. Browse layout & filters -------------------------------------------- */

.browse {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 34px;
  align-items: start;
  padding: 22px 0 56px;
}
.browse__main { min-width: 0; }

.filters { position: sticky; top: 76px; }
.filters .sheet__body { display: flex; flex-direction: column; gap: 12px; }

.fgroup {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px 18px;
}
.fgroup__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 2px 0 8px;
  font-family: var(--f-body);
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.fgroup__head svg { width: 14px; height: 14px; color: var(--faint); transition: transform 0.2s var(--ease); }
.fgroup.is-closed .fgroup__head svg { transform: rotate(-90deg); }
.fgroup.is-closed .fgroup__body { display: none; }
.fgroup__body { display: flex; flex-direction: column; gap: 2px; }
.fgroup__note { font-size: 12px; color: var(--faint); margin-top: 8px; }
.fgroup__more {
  align-self: flex-start;
  margin-top: 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--price);
}
.fgroup__more:hover { text-decoration: underline; }
.fgroup__clear { font-size: 13px; font-weight: 700; color: var(--price); }
.fgroup__clear:hover { text-decoration: underline; }

.opt {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  font-size: 14px;
  color: var(--ink);
  cursor: pointer;
}
.opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.opt__box {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border-radius: 5px;
  border: 1.5px solid var(--line-strong);
  background: var(--card);
  transition: background 0.14s var(--ease), border-color 0.14s var(--ease);
}
.opt__box svg { width: 11px; height: 11px; opacity: 0; color: #fff; }
.opt input:checked + .opt__box { background: var(--bar); border-color: var(--bar); }
.opt input:checked + .opt__box svg { opacity: 1; }
.opt input:focus-visible + .opt__box { outline: 2px solid var(--accent); outline-offset: 2px; }
.opt input[type="radio"] + .opt__box { border-radius: 50%; }
.opt__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.opt__count { margin-left: auto; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.opt em { font-style: normal; color: var(--muted); font-size: 13px; }
.opt b { font-weight: 700; }
.opt.is-empty { opacity: 0.42; }
/* display: flex above outranks the browser's [hidden] rule, so a row held back
   behind "Show 9 more" never actually went anywhere: the whole list showed and
   the button had nothing left to reveal. */
.opt[hidden] { display: none; }

/* A spirit's own styles, kept behind the box that turns them on: eight kinds
   of whiskey are worth reading once whiskey is the question and only noise
   before that. The rule down the left is what says they belong to the row
   above rather than to the list. */
.fsub {
  display: none;
  margin: 2px 0 6px 8px;
  padding-left: 16px;
  border-left: 2px solid var(--line);
}
.opt:has(input:checked) + .fsub,
/* A shared link can arrive with a style set and its spirit not. */
.fsub:has(input:checked) { display: block; }
.fsub .opt { padding: 4px 0; font-size: 13.5px; }
.fsub .opt__box { width: 16px; height: 16px; border-radius: 4px; }
.fsub .fgroup__more { font-size: 12.5px; }
/* Without :has there is nothing to open them with, so they stay open. */
@supports not selector(:has(*)) {
  .fsub { display: block; }
}

/* Dual-handle price range */
.range2 { padding: 4px 0 2px; }
.range2__vals { display: flex; justify-content: space-between; font-size: 14px; font-weight: 700; margin-bottom: 8px; }
.range2__track { position: relative; height: 28px; }
.range2__bar, .range2__fill { position: absolute; top: 12px; height: 4px; border-radius: var(--r-pill); }
.range2__bar { left: 0; right: 0; background: var(--track); }
.range2__fill { background: var(--ink); }
.range2 input[type="range"] {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 28px;
  margin: 0;
  appearance: none;
  -webkit-appearance: none;
  background: none;
  pointer-events: none;
}
.range2 input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--ink);
  border: 4px solid #fff;
  box-shadow: 0 0 0 1px var(--line-strong);
  pointer-events: auto;
  cursor: pointer;
}
.range2 input[type="range"]::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--ink);
  border: 4px solid #fff;
  pointer-events: auto;
  cursor: pointer;
}

/* Number pairs (ABV, age) */
.range { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
.range input[type="number"] {
  width: 100%;
  min-width: 0;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 14px;
  outline: none;
}
.range input:focus { border-color: var(--accent); }
.range span { color: var(--faint); font-size: 13px; }

/* Single slider (rating, taste dials) */
.slider {
  width: 100%;
  height: 22px;
  appearance: none;
  -webkit-appearance: none;
  background: none;
  cursor: pointer;
}
.slider::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--accent) var(--fill, 0%), var(--track) var(--fill, 0%));
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin-top: -7px;
  border-radius: 50%;
  background: var(--ink);
  border: 4px solid #fff;
  box-shadow: 0 0 0 1px var(--line-strong);
}
.slider::-moz-range-track { height: 4px; border-radius: var(--r-pill); background: var(--track); }
.slider::-moz-range-progress { height: 4px; border-radius: var(--r-pill); background: var(--accent); }
.slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--ink);
  border: 4px solid #fff;
}

/* Results toolbar */
.results-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 18px 0 12px;
}
.results-bar__count { font-size: 14px; color: var(--muted); }
.results-bar__count strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.results-bar__spacer { flex: 1; }

/* The app's control pill. Both of these only appear where the filter rail
   does not — see section 15. */
.fpill {
  display: none;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}
.fpill.is-on { border-color: var(--bar); background: var(--bar); color: var(--hero-text); }
.fpill__box {
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border: 1.5px solid var(--faint);
  border-radius: 5px;
  /* The tick is always there; an empty box is what "off" looks like. */
  color: transparent;
}
.fpill.is-on .fpill__box { border-color: var(--hero-text); background: var(--hero-text); color: var(--bar); }
.results-bar__break,
.results-total { display: none; }

.active-filters { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
/* The row is always in the DOM so a filter change can refill it; with nothing
   applied it should take up no space at all. */
.active-filters:empty { display: none; }
.pill-x {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 12.5px;
  font-weight: 600;
}
.pill-x:hover { border-color: var(--line-strong); }
.pill-x--plain { background: none; border-color: transparent; color: var(--price); }
.pill-x--plain:hover { border-color: var(--line); }
.pill-x svg { width: 12px; height: 12px; color: var(--muted); }
.pill-x:hover svg { color: var(--ink); }

/* Listing header: names the page and sizes up the set, nothing more. The
   display serif is for marketing pages; a listing is for reading. */
.listing-head h1 {
  font-family: var(--f-body);
  font-size: clamp(26px, 2.6vw, 34px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.025em;
}
.listing-head__facts {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  margin-top: 10px;
  font-size: 14.5px;
  color: var(--muted);
}
.listing-head__facts span { display: inline-flex; align-items: baseline; gap: 5px; }
.listing-head__facts b { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.listing-head__facts span + span::before {
  content: "·";
  margin-right: 7px;
  color: var(--line-strong);
}
.listing-head__chips { margin-top: 20px; }
.listing-head__chips .eyebrow { color: var(--muted); }

/* Band: the dark header on the bottle page */
.band {
  border-radius: var(--r-lg);
  padding: 26px 28px;
  background: radial-gradient(900px 300px at 80% -20%, var(--hero-glow) 0%, var(--bar) 60%);
  color: var(--hero-text);
  box-shadow: 0 20px 40px -24px rgba(0, 0, 0, 0.6);
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 18px;
  align-items: end;
}
.band h1 { font-size: clamp(26px, 3.4vw, 40px); }
.band h1 small {
  margin-left: 10px;
  font: 15px var(--f-body);
  color: var(--hero-muted);
  letter-spacing: 0;
}
.band p { margin-top: 8px; font-size: 14px; color: var(--hero-muted); max-width: 62ch; }
.band__stats { display: flex; gap: 26px; }
.band__stats div { font-size: 12px; color: var(--hero-muted); }
.band__stats b {
  display: block;
  font-family: var(--f-display);
  font-size: 26px;
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.025em;
  color: #fff;
}
.band__quick { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
.band .breadcrumbs { color: var(--hero-muted); }
.band .breadcrumbs a:hover { color: var(--hero-text); }
.band .breadcrumbs svg { color: var(--hero-line-2); }

.band .btn--ghost { border-color: var(--hero-line-2); color: var(--hero-text); }
.band .btn--ghost:hover { background: var(--hero-field); border-color: var(--hero-text); }
.band__k {
  display: inline-block;
  margin-bottom: 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-lt);
}
.band__k:hover { color: #fff; }

/* Bottle page: one product composition. The hero is not a card — the buy panel
   is the only box in the zone, so it is unambiguously the thing to act on, and
   the identity block takes its hierarchy from type size and whitespace rather
   than from borders and fills. */
.dhero {
  display: grid;
  grid-template-columns: 272px minmax(0, 1fr) 340px;
  gap: 38px;
  align-items: start;
  margin-top: 18px;
  padding-bottom: 34px;
}
.dhero__media { min-width: 0; }
/* The stored frame already cuts the bottle at cap and base, so the art is
   contained, never cropped further: bottles sit off-centre often enough that a
   cover fill slices labels. A shallow portrait frame keeps the column tall
   while the edge wash hides the letterboxing. */
.dhero__art {
  position: relative;
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 5;
  width: 100%;
  min-width: 0;
  overflow: hidden;
}
/* Absolute so a 1050px-tall master cannot inflate the grid row. The frame
   sizes from the identity column (or its own min-height), and the bottle
   fills whatever box that produces. */
.dhero__art img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.dhero__zoom {
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: zoom-in;
}
.dhero__zoom:focus-visible { outline: 2px solid var(--price); outline-offset: -2px; }
.dhero__zoomhint {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 1;
  padding: 5px 9px;
  border-radius: 999px;
  background: rgba(14, 42, 34, 0.82);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  opacity: 0;
  transform: translateY(3px);
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.dhero__zoom:hover .dhero__zoomhint,
.dhero__zoom:focus-visible .dhero__zoomhint { opacity: 1; transform: none; }
.dhero__thumbs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-top: 10px;
  padding: 2px;
}
.dhero__thumb {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  padding: 2px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  cursor: pointer;
}
.dhero__thumb:hover { border-color: var(--muted); }
.dhero__thumb.is-active {
  border-color: var(--price);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--price) 22%, transparent);
}
.dhero__thumb:focus-visible { outline: 2px solid var(--price); outline-offset: 2px; }
.dhero__thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.spirit-lightbox {
  width: min(96vw, 1200px);
  max-width: none;
  height: min(94vh, 1000px);
  max-height: none;
  padding: 0;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 16px;
  background: #f7f8f5;
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.45);
}
.spirit-lightbox::backdrop {
  background: rgba(5, 15, 12, 0.86);
  backdrop-filter: blur(5px);
}
.spirit-lightbox__stage {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  padding: clamp(20px, 4vw, 52px);
}
.spirit-lightbox__stage img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
.spirit-lightbox__close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  padding: 0 0 3px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
}
.spirit-lightbox__close:hover { background: #fff; border-color: var(--muted); }
.spirit-lightbox__close:focus-visible { outline: 2px solid var(--price); outline-offset: 2px; }
.dhero__initial { font-family: var(--f-display); font-size: 60px; font-weight: 800; letter-spacing: -0.04em; color: rgba(20, 33, 27, 0.18); }

.dhero__main { min-width: 0; padding: 4px 0 0; }
/* Producer reads as a quiet label above the name, not a second headline. */
.dhero__brand {
  display: inline-block;
  margin-bottom: 5px;
  font-size: 15px;
  font-weight: 500;
  color: var(--muted);
}
.dhero__brand:hover { color: var(--ink); }
.dhero h1 {
  font-family: var(--f-body);
  font-size: clamp(29px, 3.1vw, 42px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.035em;
}
/* Said once, under the name: the reviews and half the shelves still carry the
   producer's old name, so it is worth confirming this is the same bottle. */
.dhero__former { margin-top: 6px; font-size: 13.5px; color: var(--faint); }

/* Facts: one quiet dot-separated line. Underlines give it texture without
   adding a shape per fact, and it stays on a single line. */
.dhero__facts {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--muted);
}
/* The separator belongs to the fact that follows it, so a wrap never leaves a
   stray dot hanging at the end of a line. It sits outside the anchor so it is
   neither underlined nor clickable. */
.dhero__facts > span:not(:first-child)::before {
  content: "\00b7";
  margin-right: 6px;
  color: var(--line-strong);
}
.dhero__facts a {
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 3px;
}
.dhero__facts a:hover { color: var(--ink); text-decoration-color: currentColor; }

/* Scores sit on the page paper, straight under the name: one big number in
   the verdict colour with the plain-English word beside it, so "is it good?"
   is answered before any digit is parsed. The critic line is a quieter
   second sentence, not a second headline. */
.dscore { margin-top: 14px; --verdict: var(--ink); }
.dscore--good { --verdict: var(--good); }
.dscore--mid  { --verdict: var(--mid); }
.dscore--low  { --verdict: var(--low); }
.dscore__row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 14px;
}
.dscore__num {
  font-size: 50px;
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: -0.045em;
  color: var(--verdict);
}
/* The verdict word is the emotional half of the headline: the serif at near
   the number's size, on the same baseline, so "4.66 Exceptional" reads as one
   statement rather than a number with a caption. */
.dscore__verdict {
  font-family: var(--f-display);
  font-size: 33px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--verdict);
}
.dscore__proof { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; margin-top: 9px; }
.dscore__proof .stars { display: flex; }
.dscore__proof .stars svg, .dscore__proof .star { width: 20px; height: 20px; }
.dscore__reviews {
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 3px;
}
.dscore__reviews:hover { color: var(--ink); text-decoration-color: currentColor; }
/* The phone's shorter version of the same count; see section 22. */
.dscore__round { display: none; }
.dscore__empty { font-size: 15px; font-weight: 600; color: var(--faint); }
/* The critic line stays subordinate but must survive a scan: the number gets
   a small ink tile (Metacritic grammar, instantly read as "critic score") and
   a top-percentile standing earns the verdict green. Both stay small so the
   community headline above keeps the room. */
.dscore__side {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 12px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--muted);
}
.dscore__critic { display: inline-flex; align-items: center; gap: 8px; }
.dscore__badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 27px;
  height: 27px;
  padding: 0 5px;
  border-radius: 7px;
  background: var(--ink);
  color: var(--paper);
  font-size: 14px;
  font-weight: 800;
  letter-spacing: -0.01em;
}
.dscore__standing { color: var(--good); font-weight: 650; }

/* Secondary actions: text and icon, so they never look like the buy button. */
.dhero__acts { display: flex; flex-wrap: wrap; gap: 18px; margin-top: 22px; }
.dhero__acts button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
}
.dhero__acts button:hover { color: var(--ink); }
.dhero__acts button svg { color: var(--faint); }
.dhero__acts button:hover svg { color: var(--accent); }
.dhero__acts button[aria-pressed="true"] { color: var(--accent-ink); }
.dhero__acts button[aria-pressed="true"] svg { color: var(--accent); }

/* Buy panel. Everything in it is one retailer's claim, not ours, so the fine
   print sits with the price rather than somewhere further down the page. */
.buybox {
  align-self: start;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--card);
  box-shadow: var(--shadow);
}
.buybox__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 14px 18px;
  background: var(--bar);
  color: var(--hero-text);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.03em;
}
.buybox__head > span:first-child { display: inline-flex; align-items: center; gap: 8px; }
.buybox__head svg { width: 15px; height: 15px; color: var(--accent-lt); }
.buybox__save {
  padding: 3px 9px;
  border-radius: 6px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.buybox__body { padding: 21px 18px 18px; }
.buybox__price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px; }
.buybox__price b {
  font-size: 38px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.buybox__price s { font-size: 15px; color: var(--faint); }
.buybox__price--none { font-size: 21px; font-weight: 700; color: var(--muted); }
.buybox__sub { margin-top: 8px; font-size: 13.5px; color: var(--muted); }
.buybox__stock {
  margin-top: 8px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--accent-ink);
}
.buybox .btn { margin-top: 18px; }
.buybox__note { margin-top: 13px; font-size: 12.5px; line-height: 1.55; color: var(--faint); }
.buybox__more { margin-top: 14px; border-top: 1px solid var(--line); }
.buybox__more a {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13.5px;
}
.buybox__more a:hover { color: var(--price); }
.buybox__more b { font-variant-numeric: tabular-nums; }
.buybox__tier {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  padding-top: 17px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  color: var(--muted);
}
.buybox__tier b { color: var(--ink); }

/* 8. Cards, rails, tiles ------------------------------------------------ */

.grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.grid > * { content-visibility: auto; contain-intrinsic-size: 320px; }
.grid--wide { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow);
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease), border-color 0.18s var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--c, var(--line-strong)); }

/* The whole card is one target; the title stays a real link for assistive tech
   and the shelf/compare buttons ride above the overlay. Mirrors .row-item. */
.card__link { position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
/* card__actions is already absolute, so it only needs lifting, not positioning. */
.card__name a { position: relative; z-index: 2; }
.card__actions { z-index: 2; }

.card__frame {
  position: relative;
  aspect-ratio: 4 / 3;
  background: linear-gradient(180deg, var(--art-1), var(--art-2));
  background-size: cover;
  background-position: center;
  overflow: hidden;
}

/* Artwork panels pick up a wash of the category colour. */
@supports (background: color-mix(in srgb, red 10%, blue)) {
  .card__frame, .row-item__art, .bottle, .showcard__art {
    background-image: linear-gradient(
      180deg,
      color-mix(in srgb, var(--c, var(--line-strong)) 13%, var(--art-1)),
      color-mix(in srgb, var(--c, var(--line-strong)) 26%, var(--art-2))
    );
  }
}
.card__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
.card__frame img.is-loaded { opacity: 1; }
.card:hover .card__frame img { transform: scale(1.04); }

/* Cutout sources are transparent bottles fitted inside a square preset rather
   than photos filling a frame, so covering a 4:3 panel with one would crop the
   neck and base straight back off. Contain them, and inset a little so the
   bottle sits in the panel instead of butting against it. */
.card__frame--cutout img,
.row-item__art--cutout img,
.showcard__art--cutout img {
  object-fit: contain;
  padding: 8px;
}
.card__frame--empty {
  display: grid;
  place-items: center;
  font-family: var(--f-display);
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--line-strong);
}

.card__rank {
  position: absolute;
  bottom: 6px;
  left: 10px;
  font-family: var(--f-display);
  font-size: 30px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  color: rgba(20, 33, 27, 0.22);
}

.card__body { display: flex; flex-direction: column; gap: 4px; flex: 1; padding: 13px 14px 12px; }
.card__brand {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-dk);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.card__name {
  font-family: var(--f-display);
  font-size: 16.5px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.015em;
}
.card__meta {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12.5px;
  color: var(--muted);
  min-width: 0;
}
.card__meta span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card__dot { color: var(--line-strong); flex-shrink: 0; }
.card__foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px;
  margin-top: auto;
  padding-top: 11px;
  border-top: 1px dashed var(--line);
}

.card__actions {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  gap: 6px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.16s var(--ease), transform 0.16s var(--ease);
}
.card:hover .card__actions, .card:focus-within .card__actions { opacity: 1; transform: none; }
.act {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.94);
  color: var(--muted);
  box-shadow: var(--shadow-sm);
}
.act svg { width: 16px; height: 16px; }
.act:hover { color: var(--ink); border-color: var(--line-strong); }
.act.is-on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.act.is-on svg { fill: currentColor; }

.rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(216px, 1fr);
  gap: 14px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: 8px;
  scrollbar-width: thin;
}
.rail > * { scroll-snap-align: start; }
.rail::-webkit-scrollbar { height: 8px; }
.rail::-webkit-scrollbar-track { background: transparent; }
.rail::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
/* A rail stays a rail on desktop: squeezing eight cards into the content width
   shrinks each one until the type has to be clipped mid-word. */

.tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
.tile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 88px;
  grid-template-areas: "body art";
  align-items: center;
  gap: 10px;
  min-height: 124px;
  overflow: hidden;
  padding: 14px 12px 14px 16px;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow);
  transition: transform 0.18s var(--ease), border-color 0.18s var(--ease);
}
.tile:hover { transform: translateY(-3px); border-color: var(--c, var(--line-strong)); }
.tile__art {
  grid-area: art;
  width: 88px;
  height: 96px;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}
.tile__body { grid-area: body; display: flex; flex-direction: column; min-width: 0; }
.tile__name { font-family: var(--f-display); font-size: 19px; font-weight: 700; letter-spacing: -0.02em; line-height: 1.15; }
.tile__sub { font-size: 12.5px; color: var(--muted); line-height: 1.35; margin-top: 3px; }
.tile__count { font-size: 11.5px; font-weight: 700; color: var(--price); margin-top: 6px; }

.stats { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
.stat {
  padding: 14px 16px;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--card);
}
.stat__value { font-family: var(--f-display); font-size: 24px; font-weight: 800; letter-spacing: -0.03em; }
.stat__label { font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }

/* 9. Listing rows ------------------------------------------------------- */

.list { display: flex; flex-direction: column; gap: 14px; }

.row-item {
  position: relative;
  display: grid;
  grid-template-columns: 208px minmax(0, 1fr) 208px;
  gap: 26px;
  align-items: center;
  padding: 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s var(--ease), box-shadow 0.15s var(--ease), border-color 0.15s var(--ease);
}
.row-item:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: var(--line-strong); }

/* The whole card is one target; the title stays a real link for assistive tech
   and the shelf/compare buttons ride above the overlay. */
.row-item__link { position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
.row-item h3 a, .row-item__acts { position: relative; z-index: 2; }

.row-item__art {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--r);
  background-color: var(--art-1);
  background-image: linear-gradient(180deg, var(--art-1), var(--art-2));
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  overflow: hidden;
}
.row-item__art img { width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.4s var(--ease); }
.row-item__art img.is-loaded { opacity: 1; }
/* A pill rather than the mockup's ghosted numeral: real bottle photos fill the
   panel, so low-contrast ink over them is unreadable. */
.row-item__rank {
  position: absolute;
  left: 10px;
  bottom: 10px;
  padding: 3px 10px;
  border-radius: 8px;
  background: rgba(14, 33, 27, 0.72);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.35;
  font-variant-numeric: tabular-nums;
  color: #fff;
}
.row-item__initial {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  font-family: var(--f-display);
  font-size: 40px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: rgba(20, 33, 27, 0.2);
}

.row-item__info { min-width: 0; padding: 4px 0; }
.row-item__brand {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-dk);
}
/* Body sans rather than the display serif: these are long, unfamiliar bottle
   names and legibility beats flourish in a list. */
.row-item h3 {
  margin: 6px 0 9px;
  font-family: var(--f-body);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.row-item:hover h3 a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 2px; }
.row-item__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 7px;
  font-size: 15px;
  line-height: 1.45;
  color: var(--muted);
}
.row-item__meta .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--c, var(--line-strong)); }
.row-item__info .pct { display: inline-block; margin-top: 10px; }
/* The phone's shorter versions of things this row already says at length: the
   subtitle, the rounded score, the abbreviated count, the badge star. They
   stay in the markup at every width so a crawler reading the mobile page —
   which is the page Google reads — still gets the whole row. */
.row-item__sub,
.row-item__badgestar,
.row-item__round { display: none; }

/* Their own score, in the crowd's units but marked as theirs. Only My Bar
   hands the row a verdict to print, which is the one list that is theirs. */
.row-item__yours {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 9px;
  font-size: 14px;
  font-weight: 700;
  color: var(--accent-dk);
}
/* A duplicate is worth marking; a "×1" on every bottle is not. */
.row-item__qty {
  position: absolute;
  right: 8px;
  bottom: 8px;
  padding: 2px 8px;
  border-radius: 9px;
  background: var(--bar);
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.35;
  color: #fff;
}

.row-item__right {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 14px;
  text-align: right;
}
.row-item__score { display: flex; flex-direction: column; align-items: flex-end; gap: 7px; }
.row-item__score > b {
  font-size: 34px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  /* Falls back to ink for anything that has not named a band. */
  color: var(--grade, inherit);
}
.row-item__scorebits { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.row-item__score .stars svg { width: 17px; height: 17px; }
.row-item__score .star { width: 17px; height: 17px; }
.row-item__price { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.row-item__acts { display: flex; gap: 6px; }

.ring { position: relative; width: 88px; height: 88px; flex-shrink: 0; }
.ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.ring circle { fill: none; stroke-width: 7; }
.ring__track { stroke: var(--track); }
.ring__prog { stroke: var(--ring-color, var(--accent)); stroke-linecap: round; }
/* Sans, like every other number on the site: a score is data, not a headline. */
.ring__value {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 23px;
  font-weight: 800;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.ring__value small { font-size: 11px; font-weight: 600; color: var(--faint); }

.row-item__cnt { font-size: 13.5px; color: var(--muted); }
.pricebtn {
  padding: 9px 20px;
  border-radius: var(--r-pill);
  background: var(--price);
  color: #fff;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: 0.02em;
  text-align: center;
}
/* Solid means we have the listing; a dashed outline means we are guessing from
   the price bracket. The caption saying so is hidden on phones, so the bubble
   itself has to carry the difference. */
.pricebtn--range {
  padding: 7.5px 18.5px;
  border: 1.5px dashed var(--price);
  background: transparent;
  color: var(--price);
  font-size: 15px;
}
.pricebtn--none { background: var(--track); color: var(--muted); font-size: 13.5px; font-weight: 700; }
.pricebtn--sm { padding: 4px 11px; font-size: 13px; }
.row-item__msrp { font-size: 13px; line-height: 1.3; color: var(--muted); }
.row-item__stock {
  font-size: 12px;
  font-weight: 700;
  color: var(--accent-ink);
}

.pagination {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 22px;
  flex-wrap: wrap;
}
.pagination a, .pagination span {
  display: grid;
  place-items: center;
  min-width: 38px;
  height: 38px;
  padding: 0 10px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 14px;
  font-weight: 600;
  color: var(--muted);
}
.pagination a:hover { border-color: var(--line-strong); color: var(--ink); }
.pagination .is-current { background: var(--ink); border-color: var(--ink); color: #fff; }
.pagination .is-gap { border-color: transparent; background: none; }

.filter-fab {
  display: none;
  position: fixed;
  left: 50%;
  bottom: calc(var(--dock-h) + env(safe-area-inset-bottom) + 8px);
  z-index: 50;
  transform: translateX(-50%);
  box-shadow: var(--shadow-lg);
}

/* 10. Spirit detail ----------------------------------------------------- */

.breadcrumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  font-size: 12.5px;
  color: var(--muted);
  padding: 16px 0 0;
}
.breadcrumbs a:hover { color: var(--ink); text-decoration: underline; }
.breadcrumbs svg { width: 12px; height: 12px; color: var(--line-strong); }

.detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 32px;
  align-items: start;
  padding: 20px 0 56px;
}
.detail__aside { position: sticky; top: 82px; display: flex; flex-direction: column; gap: 14px; }

/* Section headings on the bottle page follow its sans hero rather than the
   display serif the marketing pages use. */
.detail h2 {
  font-family: var(--f-body);
  font-size: 23px;
  font-weight: 800;
  letter-spacing: -0.02em;
}
/* About / How it tastes put the h2 straight on the section, not inside
   .section-head, so they need their own gap before the copy. */
.detail .section--tight > h2 { margin-bottom: 16px; }

.bottle {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: linear-gradient(180deg, var(--tint-1, var(--art-1)), var(--tint-2, var(--art-2)));
  box-shadow: var(--shadow);
  min-height: 260px;
}
.bottle__img { width: 100%; height: auto; object-fit: contain; }
.bottle__glow { display: none; }

.speclist { display: grid; grid-template-columns: 92px minmax(0, 1fr); gap: 0 14px; font-size: 14px; }
.speclist dt, .speclist dd { padding: 9px 0; border-bottom: 1px solid var(--line); }
.speclist dt {
  align-self: center;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.speclist dd { font-weight: 600; }
.speclist dt:last-of-type, .speclist dd:last-of-type { border-bottom: 0; }
.speclist a:hover { color: var(--price); text-decoration: underline; }

.scoreblock { display: flex; align-items: center; gap: 12px; }
.scoreblock__label { font-size: 10.5px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.scoreblock__meta { min-width: 0; font-size: 12.5px; color: var(--muted); }
/* Count and sample size wrap as a pair rather than running off the column. */
.scoreblock__evidence { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; }
.scoreblock__note { font-size: 12px; color: var(--faint); }
.scoreblock__note--link {
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: var(--line-strong);
  text-underline-offset: 3px;
}
.scoreblock__note--link:hover { color: var(--ink); }
.scoreblock .ring__value { font-size: 20px; }

.dist { display: flex; flex-direction: column; gap: 6px; }
.dist__row { display: grid; grid-template-columns: 52px minmax(0, 1fr) 46px; gap: 10px; align-items: center; font-size: 12.5px; color: var(--muted); }
.dist__bar { display: block; height: 9px; border-radius: var(--r-pill); background: var(--track); overflow: hidden; }
.dist__fill { display: block; height: 100%; border-radius: var(--r-pill); background: var(--accent); }

.notes { display: flex; flex-direction: column; gap: 9px; }
.note { display: grid; grid-template-columns: 118px minmax(0, 1fr) 40px; gap: 10px; align-items: center; font-size: 13px; }
.note__label { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.note__track { display: block; height: 8px; border-radius: var(--r-pill); background: var(--track); overflow: hidden; }
.note__fill { display: block; height: 100%; border-radius: var(--r-pill); background: linear-gradient(90deg, var(--accent-dk), var(--accent-lt)); }
.note__value { text-align: right; font-variant-numeric: tabular-nums; color: var(--muted); font-size: 12px; }

.radar-wrap {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 260px) minmax(0, 1fr);
  gap: 18px 26px;
  align-items: center;
  padding: 14px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--card);
}
.radar-wrap > :only-child { grid-column: 1 / -1; justify-self: center; }
.radar { width: 100%; height: auto; overflow: visible; }
.radar .grid-line { fill: none; stroke: var(--line); stroke-width: 1; }
.radar .axis-line { stroke: var(--line); stroke-width: 1; }
.radar .axis-label { font-family: var(--f-body); font-size: 10px; font-weight: 700; fill: var(--muted); }
.radar .shape { fill: rgba(217, 150, 42, 0.22); stroke: var(--accent); stroke-width: 2; }
.radar .shape--b { fill: rgba(35, 122, 82, 0.18); stroke: var(--price); }
.radar .point { fill: var(--accent); }

.review {
  padding: 16px 0;
  border-top: 1px solid var(--line);
}
.review:first-child { border-top: 0; padding-top: 4px; }
.review__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.review__who { font-size: 13.5px; font-weight: 700; }
.review__when { font-size: 12px; color: var(--faint); }
.review__body { color: var(--text-soft); font-size: 14.5px; }
.review__body.is-clamped { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.review__more { margin-top: 6px; font-size: 13px; font-weight: 700; color: var(--price); }
.review__more:hover { text-decoration: underline; }
.avatar {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--bar);
  color: var(--accent-lt);
  font-size: 11.5px;
  font-weight: 800;
}

/* 11. Taste, compare ---------------------------------------------------- */

.dial {
  padding: 14px 16px;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--card);
}
.dial__head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.dial__name { font-size: 14px; font-weight: 700; }
.dial__value { font-size: 12.5px; font-weight: 700; color: var(--price); font-variant-numeric: tabular-nums; }

.ctable-wrap { overflow-x: auto; border-radius: var(--r-lg); border: 1px solid var(--line); background: var(--card); box-shadow: var(--shadow); }
.ctable { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.ctable th, .ctable td { padding: 13px 16px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; }
.ctable thead th { background: #f4f6f2; font-size: 11px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.ctable tbody th {
  position: sticky;
  left: 0;
  background: var(--card);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
}
.ctable tr:last-child td, .ctable tr:last-child th { border-bottom: 0; }
.ctable__foot { padding: 12px 16px; background: #f4f6f2; border-top: 1px solid var(--line); font-size: 12px; color: var(--muted); }

.chead { display: flex; flex-direction: column; gap: 8px; min-width: 150px; }
.chead__img {
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--art-2) center/cover no-repeat;
}
.chead__name { font-family: var(--f-display); font-size: 16px; font-weight: 700; letter-spacing: -0.015em; line-height: 1.2; color: var(--ink); }

.tray {
  position: fixed;
  left: 50%;
  bottom: calc(var(--dock-h) + env(safe-area-inset-bottom) + 6px);
  z-index: 45;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: calc(100vw - 24px);
  padding: 10px 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow-lg);
}
.tray[hidden] { display: none; }
.tray__label { font-size: 12px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.tray__items { display: flex; gap: 6px; }
.tray__items img, .tray__thumb {
  width: 38px;
  height: 38px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--art-2) center/cover no-repeat;
  object-fit: cover;
}

@media (min-width: 901px) { .tray { bottom: 18px; } }

.brandgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(224px, 1fr)); gap: 12px; }
.brandcard {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 14px 16px;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow);
  transition: transform 0.15s var(--ease), border-color 0.15s var(--ease);
}
.brandcard:hover { transform: translateY(-2px); border-color: var(--line-strong); }
.brandcard strong { font-family: var(--f-display); font-size: 16.5px; font-weight: 700; letter-spacing: -0.015em; line-height: 1.25; }
.brandcard__sub { font-size: 12px; color: var(--muted); }
.brandcard__score { margin-top: 6px; font-size: 11.5px; color: var(--muted); }
.brandcard__score b {
  font-family: var(--f-display);
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.025em;
  color: var(--ink);
}

/* 11b. Scanner ---------------------------------------------------------- */

.scanhead { max-width: 60ch; margin: 26px 0 22px; }
.scanhead h1 { margin-bottom: 10px; }

.scanbox {
  position: relative;
  padding: 34px 24px 28px;
  border-radius: var(--r-lg);
  border: 1px dashed var(--line-strong);
  background: var(--card);
  box-shadow: var(--shadow);
  text-align: center;
}
.scanbox[hidden] { display: none; }
.scanbox.is-over { border-color: var(--accent); background: var(--accent-wash); }

.scanbox__art {
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  margin: 0 auto 14px;
  border-radius: 50%;
  color: var(--price);
  background: var(--price-wash);
}
.scanbox__sub { max-width: 44ch; margin: 8px auto 0; color: var(--muted); font-size: 14.5px; }
.scanbox__acts { display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; margin-top: 20px; }
.scanbox__drop { margin-top: 14px; font-size: 12.5px; color: var(--faint); }
.scanbox__drop kbd {
  padding: 1px 5px;
  border-radius: 4px;
  border: 1px solid var(--line);
  background: var(--paper);
  font-family: var(--f-body);
  font-size: 11.5px;
}

.scanbox__kinds {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  color: var(--muted);
}
.scanbox__kinds li { display: flex; align-items: center; gap: 7px; }
.scanbox__kinds svg { color: var(--price); flex: none; }

.scanwait {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow);
}
.scanwait[hidden] { display: none; }
.scanwait__shot { flex: none; width: 96px; border-radius: var(--r); overflow: hidden; background: var(--art-2); }
.scanwait__shot img { width: 100%; height: auto; }
.scanwait__body { min-width: 0; }
.scanwait__body b { font-size: 15.5px; }
.scanwait__body p { font-size: 13px; margin-top: 2px; }

.scanwait__bar { height: 4px; margin-top: 12px; border-radius: var(--r-pill); background: var(--track); overflow: hidden; }
.scanwait__bar span {
  display: block;
  width: 38%;
  height: 100%;
  border-radius: inherit;
  background: var(--price);
  animation: scancrawl 1.4s var(--ease) infinite;
}
@keyframes scancrawl {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(320%); }
}

.scanfail {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 16px;
  padding: 14px 16px;
  border-radius: var(--r);
  border: 1px solid var(--line-strong);
  background: var(--dn-wash);
}
.scanfail[hidden] { display: none; }
.scanfail__icon { flex: none; color: var(--dn); }
.scanfail b { font-size: 14.5px; }
.scanfail p { font-size: 13px; }
.scanfail .btn { flex: none; margin-left: auto; }

.scanout:empty { display: none; }
.scanout { margin-top: 26px; }

.scanagain { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; }
.scanagain[hidden] { display: none; }
.scannote { margin-top: 22px; font-size: 12.5px; max-width: 58ch; }

/* The photo they took, with a tag on every bottle we could name. */
.scanshot { margin-bottom: 26px; }
.scanshot__frame {
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: #10231c;
  box-shadow: var(--shadow);
  overflow: hidden;
}
.scanshot__plate { position: relative; }
.scanshot__plate img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.scanshot figcaption { margin-top: 10px; font-size: 12.5px; color: var(--muted); }
.scanshot__hint--dense { display: none; }

/* A single bottle is a thumbnail of what you pointed at, not the result. */
.scanshot--one { max-width: 300px; }
.scanshot--one .scanshot__plate { max-height: 340px; }
.scanshot--one .scanshot__plate img { position: static; height: auto; }

.scanpin {
  position: absolute;
  border-radius: var(--r-sm);
  border: 2px solid rgba(255, 255, 255, 0.85);
  box-shadow: 0 0 0 1px rgba(14, 33, 27, 0.35), inset 0 0 22px rgba(14, 33, 27, 0.25);
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.scanpin:hover, .scanpin:focus-visible, .scanpin.is-lit {
  z-index: 4;
  border-color: var(--accent-lt);
  box-shadow: 0 0 0 1px rgba(14, 33, 27, 0.5), 0 8px 20px -8px rgba(0, 0, 0, 0.6);
}
.scanpin--maybe { border-style: dashed; }
.scanpin--unread { border-color: rgba(255, 255, 255, 0.45); }

/* The score, on the box, at every size.
   The tag below carries the name and the price and is the first thing to go on
   a narrow screen, so the one number worth crossing a room for cannot live in
   it. A count of where the bottle stood on the shelf could: nobody reads a
   back bar to find out which bottle is third from the left. */
.scanpin__score {
  position: absolute;
  top: -10px;
  left: -8px;
  z-index: 2;
  display: grid;
  place-items: center;
  min-width: 34px;
  height: 21px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: var(--grade, var(--g0));
  color: #fff;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  /* Same mount as the menu chips: a pale ring for the dark parts of a photo,
     a shadow for the bright ones, so one badge carries over both. */
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.92), 0 2px 7px rgba(14, 33, 27, 0.45);
}
/* A box against the right edge would hang its badge out of the picture. */
.scanpin--flip .scanpin__score { left: auto; right: -8px; }

/* The same ramp the menu chips use, so a shelf and a drinks list agree on what
   4.2 looks like. The box itself stays white whatever it scored: colour on
   both would leave nothing for the score to stand out against. */
.scanpin--g5 { --grade: var(--g5); }
.scanpin--g4 { --grade: var(--g4); }
.scanpin--g3 { --grade: var(--g3); }
.scanpin--g2 { --grade: var(--g2); }
.scanpin--g1 { --grade: var(--g1); }
.scanpin--g0 { --grade: var(--g0); }

/* The best bottles on the shelf should be the first thing the eye lands on. */
.scanpin--g5 .scanpin__score, .scanpin--g4 .scanpin__score {
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.95), 0 3px 10px rgba(12, 107, 61, 0.55);
}

/* Anchored to a bottom corner of the box: boxes on the right half open
   leftwards, so a tag near the frame edge still reads. */
.scanpin__tag {
  position: absolute;
  bottom: 4px;
  left: 0;
  display: block;
  width: max-content;
  max-width: min(190px, 40vw);
  padding: 5px 8px;
  border-radius: var(--r-sm);
  background: rgba(10, 24, 19, 0.9);
  color: #fff;
  backdrop-filter: blur(3px);
  text-align: left;
}
.scanpin--flip .scanpin__tag { left: auto; right: 0; }

.scanpin__name {
  display: block;
  overflow: hidden;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 1.25;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.scanpin__facts { display: flex; align-items: center; gap: 6px; margin-top: 2px; font-size: 11px; }
.scanpin__facts b { color: var(--accent-lt); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.scanpin__price { color: var(--price-lt); font-weight: 700; }
.scanpin--unread .scanpin__price { color: rgba(255, 255, 255, 0.6); font-weight: 500; }

/* A scanned drinks list: every printed line underlined, with its score sitting
   in the margin beside it. The photo is somebody's menu, so the marks have to
   read over cream paper and over a black bar list alike, which is why they are
   solid ink rather than a wash. */
/* Gutters both sides, sized off the chip, so a score can always hang clear of
   the type whichever margin it belongs to. The padding doubles as a mount, so
   the space reads as deliberate rather than as a stray white strip. */
.scanshot--menu .scanshot__frame {
  --gutter: 56px;
  padding: 12px var(--gutter);
  background: var(--card);
}
/* Rounded on the image, not the plate: the plate must not clip, or it would cut
   the chips off at the very edge they are hanging over. */
.scanshot--menu .scanshot__plate img { border-radius: var(--r-sm); }

/* Making the plate a size container is what lets a chip be sized in terms of the
   photo as displayed. `--pitch` is the spacing between printed lines as a
   percentage of the photo's height, so `calc(var(--pitch) * 1cqh)` is that
   spacing in real pixels, whatever width the photo ended up at. */
.scanshot--menu .scanshot__plate { container-type: size; --pitch: 4; }

/* The element sits exactly on the line of type; the box is drawn by ::before so
   it can stand a few pixels clear of the characters without any arithmetic
   against the percentages the reader gave us. */
.scanline { position: absolute; }
/* Every box is the same brass, whatever the bottle scored: the marks are there
   to show which lines were read, and brass is the one colour that holds up over
   both a cream menu and a blackboard. The score belongs on the chip. */
.scanline::before {
  content: '';
  position: absolute;
  inset: -3px -5px;
  border: 2px solid var(--accent);
  border-radius: 5px;
  background: rgba(217, 150, 42, 0.16);
  transition: background 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.scanline:hover, .scanline:focus-visible, .scanline.is-lit { z-index: 4; }
.scanline:hover::before, .scanline:focus-visible::before, .scanline.is-lit::before {
  background: rgba(217, 150, 42, 0.36);
  box-shadow: 0 0 0 3px rgba(217, 150, 42, 0.28), 0 6px 16px -6px rgba(0, 0, 0, 0.5);
}
/* A name we are not certain of should not look as settled as one we are. */
.scanline--maybe::before { border-style: dashed; }

.scanchip {
  position: absolute;
  top: 50%;
  right: calc(100% + 0.5em);
  transform: translateY(-50%);
  z-index: 2;
  display: block;
  /* Two thirds of the line spacing leaves a clear gap to the chip above and
     below; the clamp keeps it readable on a short list and stops a forty-line
     list from shrinking it into nothing. */
  font-size: clamp(9px, calc(var(--pitch, 4) * 0.66cqh), 15px);
  min-width: 3.1em;
  padding: 0.16em 0.34em;
  border-radius: 0.35em;
  background: var(--grade);
  color: #fff;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  /* A pale ring lifts the chip off a dark menu and the drop shadow lifts it off
     a white one, so the same chip carries on either. */
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.92), 0 2px 7px rgba(14, 33, 27, 0.45);
}
.scanline--right .scanchip { right: auto; left: calc(100% + 0.5em); }

/* The ramp itself lives in the tokens; the scan lines just name a band. Steps
   are told apart by hue rather than by lightness, which holds up when the chips
   sit on a photo that might be a cream page or a blackboard. */
.scanline--g5 { --grade: var(--g5); }
.scanline--g4 { --grade: var(--g4); }
.scanline--g3 { --grade: var(--g3); }
.scanline--g2 { --grade: var(--g2); }
.scanline--g1 { --grade: var(--g1); }
.scanline--g0 { --grade: var(--g0); }

/* The best bottles on the list should be the first thing the eye lands on. */
.scanline--g5 .scanchip, .scanline--g4 .scanchip {
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.95), 0 3px 10px rgba(12, 107, 61, 0.55);
}

/* The controls sit between the photo and the list, close enough to the list to
   read as belonging to it rather than to the picture. */
.scanbar { margin: 22px 0 10px; }
.scanchips { margin-bottom: 16px; }
/* Browse hides this count on a phone because the filter pill carries a total
   of its own. There is no pill here, and the count is how you see a filter
   took. */
.scanbar .results-bar__count { display: inline; }

/* Filtered out rather than gone: the row is still in the list, still sorted,
   and comes straight back when the chip does. */
.scanrow[hidden] { display: none; }

.scanrow__note {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 8px 2px 0;
  font-size: 12.5px;
  color: var(--muted);
}
.scanrow__note > span { display: inline-flex; align-items: center; gap: 6px; }
.scanrow__note svg { flex: none; }
.scanrow__menu b { color: var(--price); }
.scanrow__maybe a { color: var(--price); font-weight: 700; text-decoration: underline; }

.unread {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: var(--r);
  border: 1px dashed var(--line-strong);
  background: var(--card);
}
.unread__num {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: var(--r-pill);
  background: var(--track);
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.unread p { font-size: 13px; color: var(--muted); }
.unread .btn { flex: none; margin-left: auto; }

/* When the scan came back with one thing to say, saying it quietly in 13px
   under a big photo is how someone reads none of it. */
.unread--loud {
  align-items: flex-start;
  gap: 16px;
  padding: 22px 24px;
  border-style: solid;
  border-left: 4px solid var(--accent);
}
.unread--loud > div { flex: 1 1 auto; }
.unread--loud b { display: block; font-size: 20px; line-height: 1.25; margin-bottom: 8px; }
.unread--loud p { font-size: 15.5px; line-height: 1.5; color: var(--text); max-width: 56ch; }
.unread--loud .unread__num { width: 30px; height: 30px; font-size: 13px; }

/* The batches a barcode could mean. Tapping one is the point of the page. */
.unread__pickhead {
  margin: 16px 0 8px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.unread--loud .unread__pickhead { font-size: 12px; }
.unread__picks { list-style: none; margin: 0; display: grid; gap: 8px; }
.unread__picks li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--track);
}
.unread__picks a { font-weight: 700; font-size: 15px; }
.unread__picks .faint { font-variant-numeric: tabular-nums; }

/* A phone cannot fit a dozen tags over a shelf photo. The score badges stay:
   they are the answer, and the list below carries the name and the price. */
@media (max-width: 700px) {
  .scanpin__tag { display: none; }
  .scanpin__score { top: -8px; left: -6px; min-width: 30px; height: 18px; padding: 0 4px; font-size: 10px; }
  .scanpin--flip .scanpin__score { left: auto; right: -6px; }
  /* Menu chips stay: they are the reason to look at the photo at all. */
  .scanshot--menu .scanshot__frame { --gutter: 42px; padding: 8px var(--gutter); }
  .scanline::before { inset: -2px -3px; border-width: 1.5px; border-radius: 4px; }

  /* Except on a list so tightly set that the photo renders barely two hundred
     pixels tall, where the chips would land on top of one another. The boxes
     still show which lines were read, and the list below has every score. */
  .scanshot--dense .scanshot__frame { --gutter: 8px; }
  .scanshot--dense .scanchip { display: none; }
  .scanshot--dense .scanshot__hint { display: none; }
  .scanshot--dense .scanshot__hint--dense { display: inline; }
  .scanshot--one { max-width: 200px; }
  .scanshot--one .scanshot__plate { max-height: 240px; }
  .unread--loud { padding: 18px; gap: 12px; }
  .unread--loud b { font-size: 18px; }
  .unread--loud p { font-size: 14.5px; }
  .unread--loud .btn { margin-left: 0; }
  .scanwait__shot { width: 72px; }
  .scanfail { flex-wrap: wrap; }
  .scanfail .btn { margin-left: 0; }
  .scanbox { padding: 26px 16px 22px; }
  .scanbox__kinds { flex-direction: column; align-items: flex-start; text-align: left; }
}

/* 12. Home ------------------------------------------------------------- */

.hero {
  position: relative;
  padding: 60px 0 46px;
  background: radial-gradient(1200px 520px at 70% -10%, var(--hero-glow) 0%, var(--bar) 58%);
  color: var(--hero-text);
}
.hero h1 {
  max-width: 20ch;
  margin: 14px 0 10px;
  font-weight: 800;
  font-size: clamp(32px, 4.6vw, 56px);
  letter-spacing: -0.035em;
}
.hero h1 em { font-style: normal; color: var(--accent-lt); }
.hero .lede { color: var(--hero-muted); max-width: 58ch; margin-bottom: 30px; }
.hero .eyebrow { color: var(--accent-lt); }

/* 12b. Scan scenes ------------------------------------------------------- */

.scenes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 26px;
}
/* Scanning is a phone errand. On a desktop the hero stays what it was: the
   claim and the bottle finder under it. */
@media (min-width: 901px) {
  .scenes { display: none; }
}
/* A tablet still gets the scenes, at the app's tablet heights — left at phone
   size they stretch into letterbox strips. */
@media (min-width: 600px) and (max-width: 900px) {
  .scene { height: 190px; }
  .scene--lead { height: 260px; }
  .scene__title { font-size: 19px; }
}
.scene {
  position: relative;
  display: block;
  overflow: hidden;
  height: 118px;
  border-radius: var(--r-lg);
  color: #fff;
}
.scene--lead { grid-column: 1 / -1; height: 172px; }
.scene__art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s var(--ease);
}
/* A scrim, not a tint: the copy sits low, so the darkening does too. */
.scene::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(8, 20, 16, 0.1) 30%, rgba(8, 20, 16, 0.86) 100%);
}
.scene__copy {
  position: absolute;
  z-index: 1;
  inset: auto 14px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.scene__kicker {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--accent-lt);
}
.scene__title { font-size: 17px; font-weight: 800; letter-spacing: -0.02em; }
.scene__sub {
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.78);
}
.scene:hover .scene__art { transform: scale(1.04); }
.scene:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* 12c. Your bar & tonight's pour ----------------------------------------- */

.hbpitch {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
  padding: 22px;
  border: 1px dashed var(--line);
  border-radius: var(--r-lg);
  background: var(--card);
}
.hbpitch p { max-width: 62ch; color: var(--muted); }
.hbpitch__btn { gap: 6px; }

.hbcard {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px 22px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--card);
}
.hbstats { display: flex; flex-wrap: wrap; gap: 12px 34px; }
.hbstat { display: flex; flex-direction: column; gap: 2px; }
.hbstat b {
  font-family: var(--f-display);
  font-size: 27px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.05;
}
.hbstat.grade--g0 b, .hbstat.grade--g1 b, .hbstat.grade--g2 b,
.hbstat.grade--g3 b, .hbstat.grade--g4 b, .hbstat.grade--g5 b { color: var(--grade); }
.hbstat span { font-size: 12.5px; color: var(--muted); }

.hbnote {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
  color: var(--ink);
}
.hbnote svg { flex-shrink: 0; color: var(--accent-dk); }
.hbnote--good svg { color: var(--price); }
a.hbnote:hover { color: var(--accent-dk); }
.hbestimate { font-size: 12px; line-height: 1.5; color: var(--muted); }

.pour {
  position: relative;
  display: flex;
  align-items: center;
  margin-top: 14px;
  border-radius: var(--r-lg);
  background: var(--bar);
  color: var(--hero-text);
}
.pour__link {
  display: flex;
  flex: 1;
  min-width: 0;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  color: inherit;
}
.pour__art {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 62px;
  height: 62px;
  border-radius: var(--r);
  background: rgba(255, 255, 255, 0.07);
}
.pour__art img { width: 100%; height: 100%; object-fit: contain; }
.pour__copy { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.pour__kicker {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--accent-lt);
}
.pour__name {
  font-family: var(--f-display);
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.02em;
}
.pour__meta { display: flex; align-items: center; gap: 8px; min-width: 0; }
.pour__badge {
  padding: 2px 7px;
  border-radius: 6px;
  background: var(--grade);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.pour__why {
  overflow: hidden;
  font-size: 12.5px;
  color: var(--hero-muted);
  white-space: nowrap;
  text-overflow: ellipsis;
}
.pour__shuffle {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  margin-right: 8px;
  border-radius: 50%;
  color: var(--hero-muted);
}
.pour__shuffle:hover { background: rgba(255, 255, 255, 0.09); color: var(--hero-text); }

.sentence {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  max-width: 980px;
  padding: 20px 22px;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--shadow-xl);
  font-family: var(--f-display);
  font-size: clamp(19px, 2vw, 26px);
  font-weight: 600;
  letter-spacing: -0.02em;
}
.sentence .pair { display: inline-flex; align-items: center; gap: 10px; }
.sentence .go { margin-left: auto; font-family: var(--f-body); font-size: 15px; padding: 12px 22px; }

.slot { position: relative; }
.slot select, .slot input {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  font-weight: 700;
  line-height: 1.35;
  color: var(--bar);
  background: #e2f0e7;
  border-radius: 8px 8px 2px 2px;
  border-bottom: 2px solid var(--bar);
  padding: 2px 30px 2px 12px;
  cursor: pointer;
  outline: none;
}
.slot input { cursor: text; width: min(8.5em, 52vw); }
.slot input::placeholder { color: #5f7a6c; font-weight: 600; }
.slot select:hover, .slot input:hover { filter: brightness(0.97); }
.slot--select::after {
  content: "";
  position: absolute;
  right: 11px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--bar);
  border-bottom: 2px solid var(--bar);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

/* Combobox menu used by the sentence finder and the header search */
.dd {
  position: absolute;
  left: 0;
  top: calc(100% + 8px);
  z-index: 30;
  width: min(420px, 84vw);
  overflow: hidden;
  border-radius: var(--r);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--shadow-xl);
  font-family: var(--f-body);
  font-size: 14px;
  font-weight: 400;
  text-align: left;
}
.dd[hidden] { display: none; }
.dd.dd--types { width: min(240px, 84vw); }
.dd__row {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  width: 100%;
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  text-align: left;
}
.dd__row:last-child { border-bottom: 0; }
.dd__row:hover, .dd__row.is-active { background: var(--paper); }
.dd__mini {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--art-2) center/cover no-repeat;
}
.dd__mini--cat { background: var(--c, var(--art-2)); border-color: transparent; }
.dd__name { min-width: 0; }
.dd__name b { display: block; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd__name small { display: block; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd__score { font-family: var(--f-display); font-size: 16px; font-weight: 800; letter-spacing: -0.02em; text-align: right; }
.dd__score small { display: block; font: 600 11px/1.25 var(--f-body); color: var(--muted); white-space: nowrap; }
.dd__head {
  padding: 6px 14px;
  background: var(--paper);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.dd__row--type {
  grid-template-columns: 22px minmax(0, 1fr);
  color: var(--muted);
}
.dd__row--type .dd__name b { font-weight: 500; }
.dd__glass {
  display: grid;
  place-items: center;
  color: var(--faint);
}
.dd__glass svg { display: block; }

.hero-stats { display: flex; flex-wrap: wrap; gap: 32px; margin-top: 34px; font-size: 13px; color: var(--hero-muted); }
.hero-stats b {
  display: block;
  font-family: var(--f-display);
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.025em;
  color: var(--hero-text);
}

.hero-search {
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: 620px;
  padding: 8px 8px 8px 16px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--card);
}
.hero-search svg { width: 18px; height: 18px; color: var(--muted); flex-shrink: 0; }
.hero-search input { flex: 1; min-width: 0; font-size: 15px; outline: none; }
.hero-tries { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 14px; }

/* Showcase: what every bottle shows */
.showcase { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: center; }
.steps3 { display: flex; flex-direction: column; gap: 18px; padding-top: 6px; }
.s3 { display: grid; grid-template-columns: 38px minmax(0, 1fr); gap: 14px; align-items: start; }
.s3__n {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--bar);
  color: var(--accent-lt);
  font-family: var(--f-display);
  font-size: 18px;
  font-weight: 800;
}
.s3 b { display: block; font-size: 16.5px; font-weight: 700; margin-bottom: 2px; }
.s3 span:not(.s3__n) { font-size: 14px; color: var(--muted); }

.showcard {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  max-width: 560px;
  justify-self: end;
  overflow: hidden;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow-xl), var(--shadow);
}
.showcard__art {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: linear-gradient(180deg, var(--tint-1, var(--art-1)), var(--tint-2, var(--art-2)));
}
.showcard__art img { width: 100%; height: 100%; object-fit: contain; padding: 12px 8px; }
.showcard__body { display: flex; flex-direction: column; gap: 7px; padding: 18px 20px; }
.showcard__type { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; color: var(--muted); }
.showcard__type .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--c, var(--line-strong)); }
.showcard h3 { font-size: 24px; font-weight: 800; letter-spacing: -0.025em; line-height: 1.1; }
.showcard__nums {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 4px;
  padding: 12px 0;
  border-top: 1px dashed var(--line);
  border-bottom: 1px dashed var(--line);
}
.showcard__score > b { display: block; font-family: var(--f-display); font-size: 48px; font-weight: 800; line-height: 0.9; letter-spacing: -0.04em; }
.showcard__score small { display: block; font-size: 12px; color: var(--muted); }
.showcard__score small b { font-family: var(--f-body); font-size: 12px; font-weight: 800; color: var(--ink); }
.showcard__price { text-align: right; }
.showcard__price small { display: block; font-size: 11px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
.showcard__price b { display: block; font-size: 28px; font-weight: 800; line-height: 1.15; color: var(--price); }
.showcard__price em { font-style: normal; font-size: 12px; color: var(--muted); }
.stars-lg { display: flex; gap: 2px; margin: 6px 0 4px; }
.stars-lg .star, .stars-lg svg { width: 16px; height: 16px; }

/* Scatter */
.tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.tog {
  padding: 7px 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--card);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--muted);
}
.tog:hover { color: var(--ink); }
.tog[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #fff; }

.scat {
  position: relative;
  padding: 16px;
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--card);
  box-shadow: var(--shadow);
}
.scat svg { width: 100%; height: auto; overflow: visible; }
.scat text { font-family: var(--f-body); font-size: 11px; fill: var(--muted); }
.scat .lbl { font-size: 11px; font-weight: 600; fill: var(--ink); }
.scat__tip {
  position: absolute;
  z-index: 5;
  display: none;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  background: var(--ink);
  color: #fff;
  font-size: 12.5px;
  white-space: nowrap;
  pointer-events: none;
}
.scat__tip span { color: var(--accent-lt); font-weight: 700; }

/* Calibration */
.calib {
  padding: 24px;
  border-radius: var(--r-lg);
  background: var(--bar);
  color: var(--hero-text);
}
.calib h3 { font-size: 25px; font-weight: 800; letter-spacing: -0.025em; margin-bottom: 6px; }
.calib p { font-size: 14.5px; color: var(--hero-muted); max-width: 62ch; }
.calib__rows { display: grid; grid-template-columns: 1fr 1fr; gap: 0 22px; margin-top: 16px; }
.crow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--hero-line);
}
.crow b { display: block; font-size: 14px; font-weight: 600; }
.crow small { font-size: 12px; color: var(--hero-muted); }
.crow__st { display: flex; gap: 2px; }
.crow__st button { padding: 2px; line-height: 0; }
.crow__st svg { width: 22px; height: 22px; fill: rgba(255, 255, 255, 0.18); transition: fill 0.1s var(--ease); }
.crow__st svg.on { fill: var(--accent-lt); }
.crow__rv { display: none; min-width: 96px; text-align: right; font-size: 12px; color: var(--hero-muted); }
.crow__rv b { display: inline; font-family: var(--f-display); font-size: 18px; font-weight: 800; letter-spacing: -0.02em; color: var(--hero-text); }
.calib.is-done .crow { grid-template-columns: minmax(0, 1fr) auto auto; }
.calib.is-done .crow__rv { display: block; }
.calib__verdict {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 18px;
  padding: 16px 18px;
  border-radius: var(--r);
  border: 1px solid var(--hero-line-2);
  background: var(--hero-field);
  font-size: 14px;
}
.calib__verdict[hidden] { display: none; }
.calib__big { font-family: var(--f-display); font-size: 34px; font-weight: 800; letter-spacing: -0.03em; line-height: 1; color: var(--accent-lt); }
.calib__big small {
  display: block;
  font: 11px var(--f-body);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--hero-muted);
}
.calib__btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }

/* 13. Cocktails & pantry ------------------------------------------------ */

/* The drinks are punched out against nothing, so the page paints what shows
   through around the glass. See Drinks\ArtBackdrop for why every treatment is
   pale: the knockout takes the stem and foot with the background, and the
   holes it leaves are invisible on paper and gape on anything dark. */
.art {
  position: relative;
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  overflow: hidden;
  border-radius: var(--r-sm);
}
.art img { width: 100%; height: 100%; object-fit: contain; }
.art__glyph { color: var(--faint); }
.art--paper { background: var(--paper); }
.art--card { background: var(--card); }
.art--wash { background: var(--accent-wash); }
/* A disc centred behind the glass gives the drink something to sit against
   without drawing a hard edge anywhere near the cutout. Deliberately wider
   than a short hero frame, so what shows is an arc rather than a circle. */
.art--disc, .art--discCard { position: relative; }
.art--disc { background: var(--paper); }
.art--discCard { background: var(--card); }
.art--disc::before, .art--discCard::before {
  content: "";
  position: absolute;
  width: 78%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--accent-wash);
}
/* A band across the bottom, so the glass reads as standing on something. */
.art--band { background: var(--paper); }
.art--band::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 22%;
  background: var(--line);
}
.art--thumb { width: 56px; height: 56px; }
.art--hero { width: 100%; aspect-ratio: 1.6; border-radius: var(--r-lg); }

/* Two classes deep so the phone's `.shell { padding: 0 16px }` shorthand,
   which comes later in the file, can't flatten the vertical padding. */
.shell.crpage { padding-top: 20px; padding-bottom: 48px; }

.crhead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}
.crhead__text { min-width: 0; }
.crhead h1 { font-size: clamp(28px, 3.2vw, 38px); }
/* Small and quiet: a way to the pantry, not a second call to action. */
.crhead__pantry {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  margin-bottom: 4px;
  padding: 7px 12px;
  border-radius: var(--r-pill);
  background: var(--accent-wash);
  color: var(--accent-dk);
  font-size: 13px;
  font-weight: 700;
}
.crhead__pantry:hover { background: #f6e7c7; }

.crsearch {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding: 0 14px;
  height: 46px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--card);
  color: var(--faint);
}
.crsearch:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--brass-wash); }
.crsearch input {
  flex: 1;
  min-width: 0;
  font-size: 15.5px;
  color: var(--ink);
}
.crsearch input::placeholder { color: var(--faint); }
.crsearch input::-webkit-search-cancel-button { display: none; }
.crsearch__clear { color: var(--faint); }
.crsearch__clear:hover { color: var(--ink); }

.crtabs { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding-top: 12px; }
.crtab {
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--card);
  color: var(--muted);
  font-size: 13.5px;
  font-weight: 700;
}
.crtab:hover { border-color: var(--line-strong); color: var(--ink); }
.crtab.is-on { background: var(--bar); border-color: var(--bar); color: #fff; }
.crtab__count { margin-left: 6px; font-variant-numeric: tabular-nums; opacity: 0.75; }
.crtabs__count { margin-left: auto; font-size: 12.5px; color: var(--faint); }
/* Between "can I pour it" and "did I like it": the same row, two questions. */
.crtabs__split { width: 1px; height: 20px; margin: 0 2px; background: var(--line); }

.crnotice {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--accent-wash);
  color: var(--accent-dk);
}
.crnotice[hidden] { display: none; }
.crnotice p { flex: 1; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.crnotice a { font-weight: 700; color: var(--accent-dk); }
.crnotice a:hover { text-decoration: underline; }
.crnotice button { color: var(--muted); }

/* The first-visit explainer. A sheet, so app.js opens and closes it with the
   rest of them, but its own children throughout: .sheet__* is styled for the
   rate panel's head and grip, and borrowing those would fight this one.

   The enter is deliberately slower than the site's other overlays. This is
   the one panel nobody asked for, so it arrives at reading speed rather than
   at the speed of a control answering a click. The exit is the usual 0.22s —
   a dismissal should feel immediate, and app.js hides the element after
   300ms, which is the ceiling for anything on the way out. */
.crguide {
  position: fixed;
  z-index: 70;
  left: 50%;
  top: 50%;
  width: min(520px, calc(100vw - 32px));
  max-height: min(88vh, 760px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--card);
  box-shadow: 0 30px 70px -30px rgba(14, 33, 27, 0.6);
  opacity: 0;
  transform: translate(-50%, calc(-50% + 26px));
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease);
}
.crguide[hidden] { display: none; }
.crguide.is-open {
  opacity: 1;
  transform: translate(-50%, -50%);
  transition: opacity 0.52s var(--ease), transform 0.52s var(--ease);
}
.crguide__grip { display: none; }

/* The scrim is weighted to the middle to follow the title. The onboarding
   slides darken their foot instead, because that is where their type sits. */
.crguide__hero {
  position: relative;
  display: grid;
  place-items: center;
  height: 190px;
  flex-shrink: 0;
  background: var(--bar);
}
.crguide__hero img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.crguide__hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(4, 16, 12, 0.22),
    rgba(4, 16, 12, 0.62) 50%,
    rgba(4, 16, 12, 0.38)
  );
}
/* Above the scrim. Both are positioned, and ::after is generated last, so
   without this the gradient paints over the type and greys the white out. */
.crguide__title {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 0 24px;
  font-size: 30px;
  line-height: 1.2;
  letter-spacing: -0.8px;
  font-weight: 800;
  text-align: center;
  color: #fff;
}

.crguide__body { overflow-y: auto; overscroll-behavior: contain; padding: 18px 20px 22px; }
.crguide__lead {
  margin: 0 0 16px;
  font-size: 14px;
  line-height: 1.45;
  font-weight: 500;
  color: var(--muted);
}
.crguide__lead strong { font-weight: 700; color: var(--ink); }

.crguide__rows { margin: 0; padding: 0; list-style: none; }
.crguide__rows li { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
/* Replicas, so no pointer and no hover: there is nothing here to click. */
.crguide__rows .crtab { flex-shrink: 0; cursor: default; }
.crguide__says { font-size: 14.5px; font-weight: 600; color: var(--ink); }

.crguide__note {
  margin-top: 4px;
  padding: 12px;
  border-radius: 12px;
  background: var(--paper);
}
.crguide__note p { margin: 0 0 10px; font-size: 13px; line-height: 1.4; color: var(--muted); }
.crguide__note p:last-child { margin-bottom: 0; }
.crguide__note strong { font-weight: 700; color: var(--ink); }
.crguide__note-row { display: flex; align-items: center; gap: 10px; }
.crguide__note-row .crhead__pantry { margin-bottom: 0; cursor: default; }
.crguide__note-row .crhead__pantry:hover { background: var(--accent-wash); }

.crguide__cta {
  width: 100%;
  margin-top: 18px;
  padding: 15px;
  border-radius: 14px;
  background: var(--accent);
  color: #fff;
  font-size: 16px;
  font-weight: 700;
}
.crguide__cta:hover { background: var(--accent-dk); }

@media (max-width: 700px) {
  /* Bottom sheet, as the app draws it on a phone and as the rate sheet does
     here. Opacity stays at 1 so the travel is the whole of the animation. */
  .crguide {
    left: 0;
    top: auto;
    bottom: 0;
    width: 100%;
    max-height: 92vh;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    opacity: 1;
    transform: translateY(100%);
  }
  .crguide.is-open { opacity: 1; transform: none; }
  /* A phone gives the sheet the whole width but far less height, so the photo
     and its headline both come back down to the size the app draws them. */
  .crguide__hero { height: 158px; }
  .crguide__title { padding: 0 20px; font-size: 23px; line-height: 1.26; letter-spacing: -0.5px; }
  .crguide__grip {
    display: block;
    width: 42px;
    height: 4px;
    margin: 8px auto -12px;
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, 0.55);
    position: relative;
    z-index: 1;
  }
  .crguide__body { padding: 16px 16px calc(20px + env(safe-area-inset-bottom)); }
}

.crbases { padding-top: 12px; }
/* Closer to the bases than the bases are to the pills: the two rails are the
   same question asked twice — which bottle, which mood — and read as a pair. */
.crmoods { padding-top: 8px; }
.crpage .results-bar { margin-top: 16px; }

/* One card per row on a phone, exactly as the app draws it; the same card in
   columns once the window has room, rather than a different card. */
.crlist {
  display: grid;
  gap: 1px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--line);
  overflow: hidden;
}
.crock {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  background: var(--card);
  min-width: 0;
}
.crock:hover { background: var(--paper); }
.crock__body { flex: 1; min-width: 0; }
.crock__name {
  display: block;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink);
}
.crock__tags {
  display: block;
  margin-top: 4px;
  font-size: 13px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.crock__ready {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 5px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--price);
}
.crock__missing {
  display: block;
  margin-top: 5px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--accent-dk);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.crock__score { flex-shrink: 0; text-align: center; }
/* Your own marks on a card: a filled heart beside the name, your score under
   the crowd's. Both quiet enough to skim past on a list you are browsing. */
.crock__fav { display: inline-flex; margin-left: 6px; vertical-align: -2px; color: var(--accent-dk); }
.crock__fav svg { fill: currentColor; }
.crock__mine {
  display: block;
  margin-top: 4px;
  font-size: 11.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

.crempty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 56px 24px 64px;
  text-align: center;
}
.crempty__icon {
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
  margin-bottom: 20px;
  border-radius: 50%;
  background: var(--accent-wash);
  color: var(--accent-dk);
}
.crempty__title { margin-bottom: 10px; font-size: 22px; }
.crempty__body { max-width: 46ch; font-size: 15px; line-height: 1.5; color: var(--muted); }
.crempty__btn { margin-top: 28px; min-height: 50px; padding: 0 28px; }

.crlock {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 32px;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--card);
  box-shadow: var(--shadow);
}
.crlock > div { flex: 1; min-width: 240px; }
.crlock__icon {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--accent-wash);
  color: var(--accent-dk);
}
.crlock h2 { margin-bottom: 6px; font-size: 19px; }
.crlock p { font-size: 14px; line-height: 1.5; color: var(--muted); }

/* --- Cocktail detail --- */

.shell.crdetail { padding-top: 20px; padding-bottom: 56px; }
.crdetail__grid { display: grid; gap: 26px; }
.crdetail__back {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 12px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--muted);
}
.crdetail__back:hover { color: var(--ink); }
.crdetail__body h1 { font-size: clamp(26px, 3.4vw, 40px); }
/* Saving a drink, said in a word and sat in the text column where the eye
   already is. One line tall, so the recipe barely moves down for it. */
.crsave { margin: 14px 0 4px; }
.crfav {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 38px;
  padding: 8px 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-pill);
  background: var(--card);
  font-size: 13.5px;
  font-weight: 700;
  color: var(--ink);
}
.crfav:hover { border-color: var(--accent); color: var(--accent-dk); }
.crfav.is-on { background: var(--bar); border-color: var(--bar); color: #fff; }
.crfav.is-on svg { fill: currentColor; }
.crdetail__tags { margin-top: 6px; font-size: 13.5px; color: var(--muted); }
.crdetail__score {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  font-size: 13px;
  color: var(--muted);
}
.crdetail__score b { font-size: 16px; font-weight: 800; color: var(--accent-dk); }

/* Six words stretched over the column read as a banner ad, so it hugs. */
.crbanner {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding: 12px 14px;
  border-radius: 12px;
  font-size: 14.5px;
  font-weight: 700;
}
.crbanner--good { background: #e2efe6; color: var(--price); }
.crbanner--short { background: var(--accent-wash); color: var(--accent-dk); }
.crbanner--locked { background: var(--paper); color: var(--muted); font-weight: 600; }
.crbanner--locked a { font-weight: 800; color: var(--price); }
.crbanner--locked a:hover { text-decoration: underline; }

.crdetail__heading { margin: 26px 0 10px; font-size: 19px; }
/* The rating card is a change of subject — the recipe stops, you are asked
   something — so it gets more air than the headings take, on both sides. */
.crdetail__body .yours { margin: 32px 0 36px; }
/* A recipe is short lines — measures and one-sentence steps. Given the whole
   column they read as lost columns, so the cards keep their own measure. */
.crcard {
  max-width: 620px;
  padding: 6px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
}
.crcard--profile { padding-top: 18px; padding-bottom: 0; }

.ing { padding: 11px 0; }
.ing--divided { border-bottom: 1px solid var(--line); }
.ing__main { display: flex; align-items: center; gap: 10px; }
.ing__mark { display: grid; place-items: center; width: 20px; flex: 0 0 auto; color: var(--accent-dk); }
.ing__dash { width: 6px; height: 5px; border-radius: 3px; background: var(--line); }

.ing__text { flex: 1; font-size: 15px; color: var(--ink); }
/* The number is what the eye scans a recipe for, so it leads in bold. */
.ing__text b { font-weight: 700; color: var(--accent-dk); }
.ing__toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  text-align: left;
  color: var(--accent-dk);
}
/* An empty circle in the shopping colour reads as a problem. A `noted` line
   isn't one, so it stays quiet until it is ticked. */
.ing__toggle.is-quiet:not(.is-on) .ing__mark { color: var(--faint); }
.ing__toggle.is-on .ing__mark { color: var(--price); }
.ing__no { color: var(--dn); }
.ing__hint,
.ing__advice,
.ing__aside { margin: 5px 0 0 30px; }
.ing__hint { font-size: 12.5px; font-weight: 600; color: var(--accent-dk); }
.ing__hint[hidden] { display: none; }
.ing__advice { font-size: 13px; color: var(--muted); }
.ing__advice a { font-weight: 600; color: var(--accent-dk); }
.ing__advice a:hover { text-decoration: underline; }
.ing__aside { font-size: 12.5px; line-height: 1.35; color: var(--faint); }
.ing__aside a:hover { text-decoration: underline; }

.crdetail__note { max-width: 620px; margin-top: 10px; font-size: 13px; line-height: 1.45; color: var(--muted); }
/* Quieter than the shopping list: this one is not asking for anything. */
.crdetail__note--quiet { margin-top: 8px; color: var(--faint); }

.crfact { display: flex; align-items: center; gap: 8px; padding: 11px 0; font-size: 14px; color: var(--ink); }
.crfact svg { flex: 0 0 auto; color: var(--accent-dk); }
/* The published grouping of the method: Prepare, Method, Garnish. */
.crstep-group {
  margin: 12px 0 2px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-dk);
}
.crstep { display: flex; align-items: flex-start; gap: 10px; padding: 9px 0; }
.crstep__n {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin-top: 1px;
  border-radius: 50%;
  background: var(--accent-wash);
  color: var(--accent-dk);
  font-size: 11.5px;
  font-weight: 700;
}
.crstep span:not(.crstep__n) { flex: 1; font-size: 14.5px; line-height: 1.45; }

.crdetail__nutrition { margin-top: 14px; font-size: 13px; color: var(--muted); }
.crdetail__prose { max-width: 620px; margin-bottom: 10px; font-size: 14.5px; line-height: 1.55; }
.crdetail__credits { max-width: 620px; font-size: 13px; color: var(--muted); }

/* The axis is inset so the marker and the 0 and 10 labels, which hang half
   their width past each end, stay off the card's edge. */
.profile { margin-bottom: 18px; padding: 0 11px; }
.profile__ends {
  position: relative;
  display: flex;
  justify-content: space-between;
  margin-bottom: 7px;
}
.profile__end { font-size: 12.5px; font-weight: 600; color: var(--faint); }
/* The end this drink leans towards, so the reading lands before the number. */
.profile__end.is-lean { color: var(--ink); }
.profile__mid {
  position: absolute;
  left: 0;
  right: 0;
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--faint);
}
.profile__axis { position: relative; height: 20px; }
.profile__rail {
  position: absolute;
  left: 0;
  right: 0;
  top: 9px;
  height: 2px;
  border-radius: 1px;
  background: var(--line);
}
.profile__tick {
  position: absolute;
  top: 7px;
  width: 1.5px;
  height: 6px;
  margin-left: -0.75px;
  border-radius: 1px;
  background: var(--line);
}
/* Both ends and the middle stand taller, so the scale reads at a glance. */
.profile__tick.is-major { top: 4px; height: 12px; background: #c3cbc1; }
/* Medium out to the reading: the distance is the point, so it is shaded. */
.profile__span {
  position: absolute;
  top: 8px;
  height: 4px;
  border-radius: 2px;
  background: var(--accent-lt);
}
.profile__knob {
  position: absolute;
  top: 2.5px;
  width: 15px;
  height: 15px;
  margin-left: -7.5px;
  border: 3.5px solid var(--accent-dk);
  border-radius: 50%;
  background: var(--card);
}
.profile__scale { position: relative; height: 14px; margin-top: 1px; }
.profile__num {
  position: absolute;
  width: 22px;
  margin-left: -11px;
  text-align: center;
  font-size: 10.5px;
  line-height: 14px;
  /* Light enough to stay a ruler rather than a row of data, dark enough to
     count off against. */
  color: #aeb8ac;
}
/* The reading itself, and the only number on the row worth reading. */
.profile__num.is-on { font-weight: 700; color: var(--accent-dk); }

/* --- Pantry --- */

.crpantry__lede { margin-top: 12px; font-size: 14px; line-height: 1.5; color: var(--muted); max-width: 68ch; }
.crgroup { margin-top: 24px; }
.crgroup__head {
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--accent-dk);
}
.crgroup__rows {
  display: grid;
  gap: 1px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--line);
  overflow: hidden;
}
.prow { background: var(--card); }
.prow__btn {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 16px;
  text-align: left;
  color: var(--line-strong);
}
.prow__btn:hover { background: var(--paper); }
.prow__btn.is-on { color: var(--price); }
.prow__mark { display: grid; place-items: center; flex: 0 0 auto; }
.prow__body { flex: 1; min-width: 0; }
.prow__name { display: block; font-size: 15px; font-weight: 600; color: var(--ink); }
/* Not owned reads as quieter, not as an error: most of these are fine to skip. */
.prow__btn:not(.is-on) .prow__name { font-weight: 500; color: var(--muted); }
.prow__sub { display: block; margin-top: 2px; font-size: 12px; color: var(--faint); }

/* Columns of the same row, rather than a different card: the list is the
   app's, the density is the desktop's. Cocktails stop at two, because a third
   column buys a screenful of drinks at the price of every tag on it. */
@media (min-width: 900px) {
  .crlist { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .crgroup__rows { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* The width a dropped column gives back, spent on the card. */
  .crock { gap: 16px; padding: 16px 18px; }
  .art--thumb { width: 64px; height: 64px; }
  .crock__tags { margin-top: 5px; }
  /* The art and the readiness banner stay beside the recipe rather than above
     it, so the method is on the first screen. */
  .crdetail__grid { grid-template-columns: minmax(280px, 380px) minmax(0, 1fr); gap: 40px; }
  .crdetail__art { position: sticky; top: 84px; align-self: start; }
  .art--hero { aspect-ratio: 1.2; }
  .crbanner { margin-top: 16px; }
}

@media (min-width: 1200px) {
  /* Pantry goes to three: a name and a count have nothing to lose for it. */
  .crgroup__rows { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .crdetail__grid { grid-template-columns: minmax(320px, 420px) minmax(0, 1fr); }
}

/* 13b. My Bar & bottle actions ------------------------------------------ */

/* Round, dark and 44px: the app's add button, in the corner the title leaves. */
.mybar__add {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bar);
  color: #fff;
}
.mybar__add:hover { background: #143a2e; }

.mybar__tabs { padding-bottom: 4px; }
.mybar__links { display: grid; gap: 10px; margin-top: 14px; }
.mblink {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
  color: var(--faint);
}
.mblink:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.mblink__icon {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--accent-wash);
  color: var(--accent-dk);
}
.mblink__body { flex: 1; min-width: 0; }
.mblink__body strong { display: block; font-size: 15px; font-weight: 700; color: var(--ink); }
.mblink__body span { display: block; margin-top: 2px; font-size: 12.5px; color: var(--muted); }

.mybar__list { margin-top: 16px; }
.mybar__export { margin-top: 28px; }
.crempty__note { margin-top: 14px; font-size: 13px; color: var(--faint); }
.crempty__note[hidden] { display: none; }
.crempty__note a { font-weight: 700; color: var(--accent-dk); }

/* Your own score on a card, in the crowd's units but marked as yours. */
.yours {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 18px;
}
.yours__rate {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--card);
  text-align: left;
}
.yours__rate--set:hover { border-color: var(--line-strong); box-shadow: var(--shadow); }
.yours__title { font-size: 17px; font-weight: 800; letter-spacing: -0.01em; color: var(--ink); }
.yours__ask { font-size: 15px; font-weight: 600; color: var(--ink); }
.yours__score { display: flex; align-items: center; gap: 10px; }
.yours__score b { font-size: 26px; font-weight: 800; letter-spacing: -0.03em; }
.yours__word { font-size: 14px; font-weight: 700; color: var(--price); }
.yours__hint { font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.yours__score-btn { align-self: flex-start; min-height: 46px; padding: 0 18px; }
.yours__chips { display: flex; flex-wrap: wrap; gap: 8px; }
.yours__chips form { display: contents; }
.chip.is-on { background: var(--bar); border-color: var(--bar); color: #fff; }

.yours__qty { display: flex; align-items: center; gap: 12px; }
.yours__qty-label { font-size: 13.5px; font-weight: 700; color: var(--muted); }
.stepper {
  display: flex;
  align-items: center;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--card);
}
.stepper form { display: contents; }
.stepper__btn { display: grid; place-items: center; width: 36px; height: 34px; color: var(--ink); }
.stepper__btn:disabled { color: var(--faint); cursor: default; }
.stepper__n { min-width: 26px; text-align: center; font-size: 14px; font-weight: 700; }

/* A note kept inside the rating card. pre-line because people write these as
   a recipe — a line per measure — and a wall of text is not what they typed. */
.yours__note {
  display: block;
  margin: 2px 0;
  padding: 10px 12px;
  border-left: 2px solid var(--accent);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--paper);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.55;
  color: var(--ink);
  white-space: pre-line;
}

.yours__review {
  padding: 12px 14px;
  border-left: 2px solid var(--accent);
  background: var(--card);
  text-align: left;
}
.yours__review-body { display: block; font-size: 14px; line-height: 1.55; color: var(--ink); }
.yours__review-edit { display: block; margin-top: 6px; font-size: 12.5px; font-weight: 700; color: var(--accent-dk); }

/* 14. Sheets, tabbar, footer -------------------------------------------- */

.sheet-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(14, 33, 27, 0.42);
  backdrop-filter: blur(2px);
}
.sheet-backdrop[hidden] { display: none; }
.sheet__grip { display: none; }
.sheet__head, .sheet__foot { display: none; }

/* .icon-btn is drawn for the dark header, where hover means a white wash and
   near-white ink. A sheet head is a white card, so both of those vanish into
   it — the close door looked like it deleted itself on hover. Restate it in
   the page's own palette for every sheet, not one at a time. */
.sheet__head .icon-btn { color: var(--muted); }
.sheet__head .icon-btn:hover { background: var(--track); color: var(--ink); }

/* The rate sheet is the one sheet that exists on every width: a dialog in the
   middle of a desktop window, the app's bottom sheet on a phone. */
.sheet.rate {
  position: fixed;
  z-index: 70;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -46%);
  width: min(560px, calc(100vw - 32px));
  max-height: min(86vh, 760px);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: 0 30px 70px -30px rgba(14, 33, 27, 0.6);
  opacity: 0;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
}
.sheet.rate[hidden] { display: none; }
.sheet.rate.is-open { opacity: 1; transform: translate(-50%, -50%); }
.sheet.rate .sheet__head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--line);
}
.sheet.rate .sheet__head h3 { font-size: 17px; }
.sheet.rate .sheet__body {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 18px 20px 20px;
}

/* The phone's overflow door, dropped from the icon that opens it, on the same
   white card the desktop tools drawer uses. Above the tab bar's breakpoint the
   header still has its nav and that drawer, so app.js leaves the icon a plain
   link and the rule below keeps the panel out of the way regardless. */
.amenu {
  position: fixed;
  top: 64px;
  right: 12px;
  z-index: 70;
  display: flex;
  flex-direction: column;
  width: min(340px, calc(100vw - 24px));
  max-height: calc(100vh - 76px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--card);
  box-shadow: var(--shadow-xl);
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}
/* display: flex above outranks the browser's [hidden] rule. */
.amenu[hidden] { display: none; }
.amenu.is-open { opacity: 1; transform: none; }

@media (min-width: 901px) {
  .amenu { display: none; }
}

.amenu__head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--line);
}
.amenu__mark {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--bar);
  color: var(--hero-text);
  font-size: 14px;
  font-weight: 700;
}
.amenu__who { display: grid; gap: 1px; min-width: 0; }
.amenu__who strong { font-size: 15px; font-weight: 700; }
.amenu__who span {
  overflow: hidden;
  color: var(--muted);
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.amenu__close {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  margin-left: auto;
  border-radius: 50%;
  color: var(--muted);
}
.amenu__close:hover { background: var(--paper); color: var(--ink); }

.amenu__body {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 16px 16px;
}

.amenu__guest { padding: 16px 0 18px; border-bottom: 1px solid var(--line); }
.amenu__guest-title { font-size: 16px; font-weight: 700; }
.amenu__guest-body { margin: 5px 0 14px; color: var(--muted); font-size: 14px; line-height: 1.5; }

.amenu__group {
  padding: 16px 0 4px;
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

/* Same rows the account page prints, pulled in tighter for a panel. */
.amenu .acct__row { padding: 12px 0; font-size: 15px; }
.amenu .acct__row:last-child { border-bottom: 0; }

.rate__bottle {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
}
.rate__art {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 64px;
  height: 78px;
  padding: 6px;
  border-radius: 10px;
  background: #edf1ea;
  color: var(--faint);
}
/* Fill the box and letterbox inside it, the same way .pour__art and
   .showcard__art do. Sizing by max-width/max-height instead leaves the used
   height to the tag's height attribute, which a percentage max-height does not
   reliably clamp inside a grid area — the bottle then hangs out the bottom. */
.rate__art img { width: 100%; height: 100%; object-fit: contain; }
.rate__id { min-width: 0; }
.rate__brand {
  display: block;
  margin-bottom: 3px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-dk);
}
.rate__name { font-size: 18px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.2; }

.rate__pick {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 22px;
}
.rate__value { font-size: 34px; font-weight: 800; letter-spacing: -0.03em; }
.rate__word { font-size: 14px; font-weight: 700; color: var(--price); }
.rate__slider { display: block; width: 100%; margin: 14px 0 0; accent-color: var(--accent); }
.rate__hint { margin-top: 8px; font-size: 12.5px; color: var(--muted); text-align: center; }

.rate__label {
  display: block;
  margin: 22px 0 8px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.rate__review {
  width: 100%;
  min-height: 120px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
  font: inherit;
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink);
  resize: vertical;
}
.rate__review:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--brass-wash); outline: none; }
.rate__count { margin: 6px 0 22px; font-size: 12px; color: var(--faint); }

/* "How I made it": the note written out as a list, folded away under it.
   Named `mine`, not `pour`, which is already the dark banner on the home
   page. Nothing here is ever drawn on the recipe itself. */
.mine { margin-bottom: 20px; }
.mine__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 700;
  color: var(--accent-dk);
  cursor: pointer;
  list-style: none;
}
.mine__link::-webkit-details-marker { display: none; }
.mine__link::before { content: '▸'; font-size: 11px; }
.mine[open] .mine__link::before { content: '▾'; }
.mine__link:hover { color: var(--ink); }
.mine__aside { margin: 8px 0 10px; font-size: 12.5px; line-height: 1.45; color: var(--faint); }

.mine__rows { display: flex; flex-direction: column; gap: 8px; }
.mine__row { display: flex; align-items: center; gap: 6px; }
.mine__amount, .mine__what {
  min-height: 38px;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  font-size: 13.5px;
  color: var(--ink);
}
.mine__amount { flex: 0 0 auto; width: 118px; }
/* The ingredient names are the long ones, so that select takes what is left. */
.mine__what { flex: 1 1 auto; min-width: 0; }
.mine__drop {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  font-size: 18px;
  line-height: 1;
  color: var(--faint);
}
.mine__drop:hover { background: var(--track); color: var(--dn); }

.mine__find { margin-top: 8px; }
.mine__search {
  width: 100%;
  min-height: 38px;
  padding: 7px 10px;
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  background: var(--card);
  font-size: 13.5px;
}
.mine__hits {
  display: flex;
  flex-direction: column;
  max-height: 220px;
  margin-top: 4px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  box-shadow: var(--shadow);
}
.mine__hit {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  text-align: left;
}
.mine__hit:last-child { border-bottom: 0; }
.mine__hit:hover { background: var(--paper); }
.mine__hit-name { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.mine__hit-note { font-size: 12px; color: var(--muted); }
/* What you own is the answer nine times in ten, so it is marked as such. */
.mine__hit.is-yours .mine__hit-note { color: var(--price); font-weight: 700; }

.mine__add {
  align-self: flex-start;
  margin-top: 10px;
  padding: 7px 12px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-pill);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--muted);
}
.mine__add:hover { border-color: var(--accent); color: var(--accent-dk); }

/* The one question in the sheet that is about other people. */
.mine__share {
  display: flex;
  gap: 9px;
  margin-top: 14px;
  padding-top: 13px;
  border-top: 1px solid var(--line);
  cursor: pointer;
}
.mine__share input[type='checkbox'] { flex: none; width: 16px; height: 16px; margin-top: 2px; }
.mine__share span { font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.mine__share b { display: block; font-size: 13px; color: var(--ink); }

/* Read back on the card, with the score and the note. */
.yours__recipe { display: flex; flex-direction: column; gap: 3px; margin: 2px 0; }
.yours__kicker {
  margin-bottom: 2px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.yours__pour { font-size: 14px; color: var(--ink); }
.yours__pour::before { content: '· '; color: var(--faint); }

/* How members make it: other people's lists, under the printed spec. Plain
   rows rather than cards, because six of these is a page of cards and the
   interesting part is how the measures differ down the column. */
.vers { display: flex; flex-direction: column; gap: 2px; }
.vers__aside { margin: 0 0 10px; font-size: 13px; color: var(--muted); }
.vers__one { padding: 13px 0; border-top: 1px solid var(--line); }
.vers__one:first-of-type { border-top: 0; padding-top: 2px; }
.vers__head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.vers__who { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.vers__pour { margin: 0; padding: 0; list-style: none; }
.vers__pour li {
  display: flex;
  gap: 7px;
  padding: 2px 0;
  font-size: 14px;
  line-height: 1.4;
  color: var(--ink);
}
/* One column of measures, so the eye can run down it and see the ratios. */
.vers__amount { flex: none; min-width: 62px; font-variant-numeric: tabular-nums; color: var(--muted); }
.vers__pour a { color: var(--ink); text-decoration: underline; text-decoration-color: var(--line-strong); }
.vers__pour a:hover { color: var(--accent-dk); text-decoration-color: currentColor; }
.rate__clear { padding: 0 20px 18px; text-align: center; }
.rate__clear button { font-size: 13.5px; font-weight: 700; color: var(--dn); }

@media (max-width: 700px) {
  /* Bottom sheet, so a thumb reaches the slider and the keyboard has room. */
  .sheet.rate {
    left: 0;
    top: auto;
    bottom: 0;
    width: 100%;
    max-height: 92vh;
    transform: translateY(100%);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    opacity: 1;
  }
  .sheet.rate.is-open { transform: none; }
  .sheet.rate .sheet__grip {
    display: block;
    width: 42px;
    height: 4px;
    margin: 8px auto 2px;
    border-radius: var(--r-pill);
    background: var(--line-strong);
  }
  .sheet.rate .sheet__head { padding: 6px 16px 10px; }
  .sheet.rate .sheet__body { padding: 14px 16px calc(18px + env(safe-area-inset-bottom)); }
}

/* The app's dock: a white pill floating on the paper, five slots wide, with
   Scan a dark circle in the middle of the row rather than raised above it. */
.tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 55;
  display: none;
  padding: 8px 12px calc(10px + env(safe-area-inset-bottom));
  background: var(--paper);
}
.tabbar__inner {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  align-items: center;
  height: var(--tabbar-h);
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: var(--card);
  box-shadow: 0 6px 14px rgba(14, 33, 27, 0.12);
}
.tabbar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--faint);
}
.tabbar__item svg { width: 22px; height: 22px; }
.tabbar__item.is-current { font-weight: 700; color: var(--accent-dk); }
.tabbar__item .count-dot { position: static; margin-left: 3px; }
.tabbar__dot {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--bar);
  color: #fff;
}
.tabbar__item--scan svg { width: 18px; height: 18px; }
.tabbar__item--scan.is-current .tabbar__dot { background: var(--accent-dk); }

.footer {
  margin-top: 56px;
  padding: 40px 0 32px;
  background: var(--bar);
  color: var(--hero-muted);
  font-size: 13px;
}
.footer a:hover { color: var(--hero-text); }
.footer__grid { display: flex; justify-content: space-between; gap: 40px; flex-wrap: wrap; }
.footer__grid h5 {
  margin-bottom: 10px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--hero-text);
}
.footer__grid li { margin-bottom: 6px; }
.footer__cols { display: flex; gap: 52px; flex-wrap: wrap; }
.footer__bottom {
  width: 100%;
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px solid var(--hero-line);
  font-size: 12px;
  display: flex;
  justify-content: space-between;
  gap: 12px 28px;
  flex-wrap: wrap;
}
.footer__legal { display: flex; gap: 14px; }
.footer .brand { color: var(--hero-text); }

/* 14a. Account ----------------------------------------------------------- */

.acct { max-width: 640px; }
.acct__email { margin-top: 4px; color: var(--muted); }

.acct__row,
.acct__edit > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 4px;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
  font-size: 16px;
  cursor: pointer;
  list-style: none;
}
.acct__edit > summary::-webkit-details-marker { display: none; }
.acct__row-left { display: flex; align-items: center; gap: 14px; }
.acct__row:hover, .acct__edit > summary:hover { color: var(--accent-dk); }
.acct__row--danger, .acct__row--danger:hover { color: var(--dn); }
.acct__edit[open] > summary svg:last-child { transform: rotate(90deg); }

.acct__form { padding: 18px 4px 22px; border-bottom: 1px solid var(--line); }
.acct__status { margin: 10px 0; font-size: 14px; color: var(--price); }
.acct__status.is-bad { color: var(--dn); }
.acct__delete { margin-top: 26px; }
.acct__delete a { font-size: 14px; font-weight: 600; color: var(--muted); }
.acct__delete a:hover { color: var(--dn); }

/* 14b. The tour ---------------------------------------------------------- */

.tour {
  display: flex;
  flex-direction: column;
  min-height: 78vh;
  padding: 12px 0 22px;
  background: var(--bar);
  color: var(--hero-text);
}
.tour__bar,
.tour__foot {
  width: min(640px, 100%);
  margin: 0 auto;
  padding: 0 24px;
}
.tour__bar { display: flex; align-items: center; justify-content: space-between; }
.tour__brand { display: flex; align-items: center; gap: 7px; color: inherit; }
.tour__brand span { font-size: 19px; font-weight: 800; letter-spacing: -0.03em; }
.tour__skip { font-size: 15px; font-weight: 600; color: var(--hero-muted); }
.tour__skip:hover { color: var(--hero-text); }

.tour__track {
  display: flex;
  /* A column flex item sizes to its content by default, and four side-by-side
     slides would drag the whole page four screens wide. */
  min-width: 0;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.tour__track::-webkit-scrollbar { display: none; }
.tour__slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  padding: 20px 28px 8px;
}
.tour__hero { display: flex; flex-direction: column; align-items: center; }
.tour__kicker {
  margin-bottom: 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--accent-lt);
}
.tour__title {
  margin-bottom: 10px;
  font-size: 29px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.025em;
}
.tour__body { font-size: 15.5px; line-height: 1.5; color: var(--hero-muted); }

.tour__foot { padding-top: 14px; }
.tour__dots { display: flex; justify-content: center; gap: 7px; margin-bottom: 18px; }
.tour__dot {
  width: 7px;
  height: 7px;
  border-radius: 4px;
  background: rgba(242, 246, 241, 0.24);
  transition: width 0.2s var(--ease), background 0.2s var(--ease);
}
.tour__dot.is-on { width: 22px; background: var(--accent); }
/* btn--block is inline-flex, which auto margins cannot centre. */
.tour__cta { display: flex; max-width: 420px; margin: 0 auto; }
.tour__note {
  margin-top: 12px;
  font-size: 12.5px;
  text-align: center;
  color: var(--hero-muted);
  opacity: 0.8;
}

/* Slide 1 — the score. */
.tscore { display: flex; align-items: center; width: 100%; }
.tscore__bottle {
  width: 44%;
  height: auto;
  border-radius: 16px;
  object-fit: cover;
}
.tscore__col { flex: 1; padding-left: 22px; }
.tscore__grade {
  display: inline-block;
  margin-bottom: 10px;
  padding: 4px 9px;
  border-radius: var(--r-pill);
  background: var(--grade);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.4px;
}
.tscore__n {
  display: block;
  font-size: clamp(56px, 16vw, 66px);
  font-weight: 900;
  line-height: 1.05;
  letter-spacing: -0.05em;
  color: var(--accent-lt);
}
.tour .stars { gap: 3px; }
/* On the bar green the paper ramp disappears, so the stars get the hero pair. */
.tour .star { width: 17px; height: 17px; fill: rgba(242, 246, 241, 0.26); }
.tour .star.on, .tour .star.half { fill: var(--accent-lt); }
.tscore__col .stars { margin-top: 4px; }
.tscore__cap {
  display: block;
  margin-top: 14px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 1.1px;
  text-transform: uppercase;
}
.tscore__meta { display: block; margin-top: 3px; font-size: 13px; color: var(--hero-muted); }

/* Slides 2 and 4 share the photo frame. */
.tshot {
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--bar-2);
}
.tshot > img { width: 100%; height: 100%; object-fit: cover; }
.tshot::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(4, 16, 12, 0.1), rgba(4, 16, 12, 0.28) 50%, rgba(4, 16, 12, 0.78));
}
.tchip {
  position: absolute;
  z-index: 1;
  padding: 5px 10px;
  border-radius: var(--r-pill);
  background: var(--grade);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.tsubjects {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 7px;
  margin-top: 16px;
}
.tsubject {
  padding: 7px 10px;
  border: 1px solid rgba(242, 246, 241, 0.2);
  border-radius: var(--r-pill);
  font-size: 12.5px;
  font-weight: 500;
  color: var(--hero-muted);
}

/* Slide 3 — the inventory. */
.tbar {
  width: 100%;
  padding: 12px;
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.06);
}
.tbar__row { display: flex; align-items: center; gap: 12px; padding: 6px 0; }
.tbar__row img { width: 42px; height: 42px; border-radius: 10px; object-fit: cover; }
.tbar__copy { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tbar__copy strong {
  overflow: hidden;
  font-size: 15px;
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.tbar__copy span { font-size: 12.5px; color: var(--hero-muted); }
.tbar__chip {
  padding: 4px 9px;
  border-radius: var(--r-pill);
  background: var(--grade);
  color: #fff;
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.tbar__stats {
  display: flex;
  justify-content: space-between;
  margin-top: 10px;
  padding: 14px 6px 0;
  border-top: 1px solid rgba(242, 246, 241, 0.12);
}
.tbar__stats span { display: flex; flex-direction: column; align-items: center; font-size: 11.5px; color: var(--hero-muted); }
.tbar__stats b { font-size: 19px; font-weight: 800; color: var(--hero-text); }

/* Slide 4 — the cocktails. */
.tcat {
  position: absolute;
  z-index: 1;
  top: 12px;
  left: 12px;
  padding: 6px 11px;
  border-radius: var(--r-pill);
  background: rgba(4, 16, 12, 0.62);
  font-size: 12px;
  font-weight: 700;
}
.tpour { position: absolute; z-index: 1; left: 16px; right: 16px; bottom: 14px; }
.tpour strong { display: block; font-size: 23px; font-weight: 800; letter-spacing: -0.02em; color: #fff; }
.tpour__rating { display: flex; align-items: center; gap: 8px; margin-top: 5px; font-size: 13px; font-weight: 600; }
.tpour__rating .star { width: 14px; height: 14px; }
.tbanner {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  margin-top: 12px;
  padding: 13px 14px;
  border: 1px solid rgba(99, 200, 147, 0.3);
  border-radius: var(--r);
  /* The cocktail list's "you can make this" green, lightened for a dark slide. */
  background: rgba(99, 200, 147, 0.13);
  color: #63c893;
  font-size: 15px;
  font-weight: 700;
}

/* Wide enough to read: the slides stop paging and become a stack. */
@media (min-width: 900px) {
  .tour { padding: 26px 0 40px; }
  .tour__bar, .tour__foot { width: min(1100px, 100%); padding: 0 32px; }
  .tour__track { display: block; overflow: visible; }
  .tour__slide {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    align-items: center;
    gap: 48px;
    width: min(1100px, 100%);
    margin: 0 auto;
    padding: 44px 32px;
  }
  .tour__slide + .tour__slide { border-top: 1px solid rgba(242, 246, 241, 0.1); }
  .tour__slide:nth-child(even) .tour__hero { order: 2; }
  .tour__title { font-size: 38px; }
  .tour__body { font-size: 18px; }
  .tour__dots { display: none; }
  .tour__cta { max-width: 320px; }
}

/* 15. Utilities & responsive -------------------------------------------- */

.row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.row--between { justify-content: space-between; }
.stack { display: flex; flex-direction: column; gap: 18px; }
.stack--sm { gap: 8px; }
.stack--md { gap: 14px; }
.mt-0 { margin-top: 0; }
.mt-sm { margin-top: 8px; }
.mt-md { margin-top: 16px; }
.mt-lg { margin-top: 26px; }
.has-dot { display: inline-flex; align-items: center; gap: 6px; }
.has-dot::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--c, var(--accent)); }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.hide-mobile { display: initial; }
.hide-desktop { display: none; }

/* The sidebar leaves the results column too narrow for three card columns, so
   the score and price drop under the name well before tablet width. */
@media (max-width: 1220px) {
  .row-item { grid-template-columns: 188px minmax(0, 1fr); column-gap: 20px; }
  .row-item__art { grid-row: 1 / span 2; align-self: start; }
  .row-item__right {
    grid-column: 2;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    gap: 12px 18px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--line);
    text-align: left;
  }
  .row-item__score { flex-direction: row; align-items: center; gap: 12px; }
  .row-item__score > b { font-size: 32px; }
  .row-item__scorebits { align-items: flex-start; }
  .row-item__price { flex-direction: row; align-items: center; gap: 12px; }
  .row-item__acts { margin-left: auto; }
}

@media (max-width: 1100px) {
  .browse { grid-template-columns: 262px minmax(0, 1fr); gap: 26px; }
}

@media (max-width: 1024px) {
  .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .detail { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .detail__aside { position: static; }
  /* Three columns is too tight here: the buy panel would sit in a 300px
     sliver while the identity column starves. Drop to Vivino's stack —
     bottle + name, then the offer full-width underneath. */
  .dhero {
    grid-template-columns: minmax(200px, 34%) minmax(0, 1fr);
    align-items: stretch;
    gap: 22px 28px;
    padding-bottom: 28px;
  }
  .dhero .buybox { grid-column: 1 / -1; max-width: none; }
  /* Full width, so the panel becomes a bar: price and button share the first
     line and the small print keeps its own. */
  .dhero .buybox__body {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px 22px;
  }
  .dhero .buybox__sub, .dhero .buybox__stock { margin-top: 0; }
  .dhero .buybox .btn { flex: 1 0 220px; max-width: 340px; margin-top: 0; }
  .dhero .buybox__note, .dhero .buybox__more, .dhero .buybox__tier { flex: 1 0 100%; }
  .dhero__art {
    aspect-ratio: auto;
    min-height: 320px;
    align-self: stretch;
  }
  .dhero__art--cutout { min-height: 380px; }
  .dhero h1 { font-size: 33px; }
  .buybox__body { padding: 20px 16px 18px; }
  .showcase { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .showcard { justify-self: stretch; max-width: none; }
}

@media (max-width: 900px) {
  .browse { grid-template-columns: minmax(0, 1fr); gap: 14px; padding-top: 16px; }
  .nav { display: none; }

  /* Where the tab bar starts, the header stops repeating it: Scan and My Bar
     are tabs, and every auth errand — logging in, signing up, logging out —
     leads the menu behind the icon beside them. That leaves the icon as the
     only thing on the right, which is where the app keeps it, and hands the
     width back to the search bar. */
  .icon-btn--tabbed,
  .header__auth-link,
  .header__auth-cta { display: none; }

  /* Two things in one door: the bars for the menu it opens, the face for
     whose it is. Half of what is behind it is navigation rather than account,
     so the bars lead; the face stays because it is also where you sign in and
     out, and it is how you can tell that you are. */
  .icon-btn--menu {
    gap: 5px;
    width: auto;
    padding: 0 4px 0 9px;
    border: 1px solid var(--hero-line);
    border-radius: var(--r-pill);
  }
  .icon-btn--menu:hover { background: var(--hero-field); }
  .icon-btn__bars { display: grid; place-items: center; }
  .icon-btn__face {
    width: 30px;
    height: 30px;
    background: var(--hero-field);
    color: var(--hero-text);
  }
  .icon-btn__face svg { width: 17px; height: 17px; }
  .icon-btn__face.is-mono { font-size: 12px; }
  .filter-fab { display: inline-flex; }

  /* With the rail gone, the bar carries the doors to it, on the app's two
     lines: the pills, then the total and the sort. The page range goes, since
     it describes a paginator that is a screen and a half further down. */
  .fpill { display: inline-flex; }
  /* The pills sit next to each other rather than at opposite ends: the
     spacer, not the justification, is what pushes the sort right. */
  .results-bar { justify-content: flex-start; gap: 8px 8px; margin: 4px 0 12px; }
  .results-bar__count { display: none; }
  .results-bar__break { display: block; flex-basis: 100%; height: 0; }
  .results-total { display: inline; font-size: 13px; color: var(--muted); }
  .results-bar .select {
    flex-direction: row;
    align-items: center;
    gap: 4px;
    min-width: 0;
    max-width: 220px;
    height: 36px;
    padding: 0 12px;
    border-radius: var(--r-pill);
  }
  .results-bar .select select { font-size: 13.5px; font-weight: 600; }
  .results-total strong { font-weight: 600; color: inherit; font-variant-numeric: tabular-nums; }
  /* Sits on the list, which is what it is counting. */
  .active-filters { margin-bottom: 8px; }
  /* The band opens with the same total, and unlike the one below it that one
     is server-rendered: it still reads 2,278 after a filter has cut the list
     to 40. Below the rail the live copy is close enough to be the only one,
     and the fact that follows it inherits the job of starting the line. */
  /* Scoped, because .listing-head__facts span sets a display of its own. */
  .listing-head__facts .listing-head__sub { display: none; }
  .listing-head__facts .listing-head__sub + span::before { content: none; }

  /* The app fills its active chips rather than outlining them, which is what
     tells them apart from the controls on the line above. */
  .active-filters .pill-x:not(.pill-x--plain) {
    height: 36px;
    padding: 0 12px;
    border-color: var(--bar);
    background: var(--bar);
    color: var(--hero-text);
  }
  .active-filters .pill-x:not(.pill-x--plain):hover { border-color: var(--bar); }
  .active-filters .pill-x:not(.pill-x--plain) svg,
  .active-filters .pill-x:not(.pill-x--plain):hover svg { color: inherit; }
  .active-filters .pill-x--plain { height: 36px; }

  .tabbar { display: block; }
  body { padding-bottom: calc(var(--dock-h) + env(safe-area-inset-bottom)); }
  .hide-mobile { display: none !important; }
  .hide-desktop { display: initial; }

  /* Filters become a bottom sheet */
  .filters {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    z-index: 70;
    display: flex;
    flex-direction: column;
    max-height: 86vh;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    border-top: 1px solid var(--line);
    background: var(--paper);
    box-shadow: 0 -20px 50px -20px rgba(14, 33, 27, 0.5);
    transform: translateY(100%);
    transition: transform 0.24s var(--ease);
  }
  .filters.is-open, .filters:target { transform: none; }
  .filters .sheet__grip {
    display: block;
    width: 42px;
    height: 4px;
    margin: 8px auto 2px;
    border-radius: var(--r-pill);
    background: var(--line-strong);
  }
  .filters .sheet__head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 16px 10px;
    border-bottom: 1px solid var(--line);
  }
  .filters .sheet__head h3 { font-size: 17px; }
  .filters .sheet__body { flex: 1; overflow-y: auto; overscroll-behavior: contain; padding: 12px 16px 16px; }
  .filters .sheet__foot {
    display: flex;
    gap: 10px;
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    border-top: 1px solid var(--line);
    background: var(--card);
  }

  .ring { width: 64px; height: 64px; }
  .ring__value { font-size: 19px; }

  .band { grid-template-columns: minmax(0, 1fr); padding: 20px; }
  .band__stats { gap: 18px; }
  .dhero {
    grid-template-columns: minmax(168px, 38%) minmax(0, 1fr);
    gap: 20px 22px;
    padding-bottom: 26px;
  }
  .dhero__art { min-height: 300px; }
  .dhero__art--cutout { min-height: 360px; }
  .dhero__facts { margin-top: 10px; }
  .dhero__acts { margin-top: 18px; }
  .calib__rows { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 700px) {
  .wrap, .shell { padding: 0 16px; }
  .shell.page-doc { padding-top: 40px; padding-bottom: 32px; }
  .shell.page-doc.page-doc--wide { max-width: 760px; }
  .header__inner { gap: 10px; height: 56px; padding: 0 16px; }
  /* Follows the shorter bar down, so the panel still clears it by 4px. */
  .amenu { top: 60px; max-height: calc(100vh - 72px); }
  .brand { font-size: 20px; }
  .header__auth { margin-left: 2px; gap: 8px; }
  .header__auth-cta { min-height: 30px; padding: 4px 10px; font-size: 12px; }
  .searchbar { max-width: none; }
  .searchbar__hint { display: none; }
  .searchbar__menu { width: min(260px, calc(100vw - 32px)); }
  .searchbar__menu.is-results { width: min(420px, calc(100vw - 32px)); }
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .grid > * { contain-intrinsic-size: 260px; }

  /* The app's listing header: where you are, what you are looking at, and
     then straight into the controls. */
  .listing-head .eyebrow { margin-bottom: 4px; }
  .listing-head h1 { font-size: 28px; }
  /* Three medians wrap to two lines on a phone and push the first bottle off
     the screen to describe a set that is right there to be read. The one
     figure worth keeping, the total, is already live in the bar below, so the
     line goes whole rather than shedding its stalest fact and keeping its
     height. */
  .listing-head__facts { display: none; }
  .browse .results-bar { margin-top: 14px; }
  .tiles, .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .section { margin-top: 38px; }
  .section-head { flex-direction: column; align-items: flex-start; gap: 12px; }
  .section-head h2 { max-width: none; }
  .hero { padding: 38px 0 34px; }
  .hero h1 { font-size: 33px; }
  .hero .lede { font-size: 15px; margin-bottom: 22px; }
  .sentence { padding: 16px; font-size: 20px; border-radius: 16px; }
  .sentence .word { font-size: 18px; }
  .sentence .go { margin-left: 0; width: 100%; margin-top: 4px; }
  .slot input { width: min(11em, 68vw); }
  .slot select, .slot input { padding: 2px 26px 2px 10px; }
  .slot .dd { width: min(320px, 86vw); }
  .hero-stats { gap: 18px; margin-top: 24px; }
  .hero-stats b { font-size: 22px; }
  /* The app's result row. A bordered card that merely shrinks still reads as
     a card, and twenty of them down a phone is a stack of boxes; the app
     gives the same bottles a flat list divided by hairlines, and it is much
     easier to run an eye down. Everything the wide row says beyond a name, a
     subtitle, a score and a price goes quiet here rather than out of the
     markup — see the note in section 9. */
  .list { gap: 0; }
  .row-item {
    /* The right column spans both rows so the badge stays centred against the
       whole row, and display: contents lets the price out of it to sit under
       the subtitle, which is where the app's own card puts it. */
    grid-template-columns: 56px minmax(0, 1fr) auto;
    grid-template-areas:
      "art info score"
      "art price score";
    column-gap: 14px;
    row-gap: 0;
    /* Full width like the app's, so the hairline runs edge to edge. */
    margin: 0 -16px;
    padding: 16px;
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    box-shadow: none;
  }
  .row-item__right { display: contents; }
  .row-item__art { grid-area: art; align-self: center; border-radius: var(--r-sm); }
  .row-item__info { grid-area: info; }
  .row-item__score { grid-area: score; flex-direction: column; align-items: center; gap: 4px; }
  .row-item__scorebits { align-items: center; }
  .row-item__price { grid-area: price; flex-direction: column; align-items: flex-start; gap: 0; }

  .row-item h3 { margin: 0; font-size: 16px; line-height: 1.31; }
  .row-item h3 a {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
  }
  .row-item__sub { display: block; margin-top: 4px; font-size: 13px; color: var(--muted); }
  .row-item__yours { margin-top: 3px; font-size: 12.5px; }
  .row-item__qty {
    right: 2px;
    bottom: 2px;
    padding: 1px 5px;
    border-radius: 8px;
    font-size: 11px;
  }

  /* The badge: one star, one rounded number, on the app's wash rather than
     the grade ramp, because that is what the app prints beside a name. */
  .row-item__score > b {
    display: flex;
    align-items: center;
    gap: 3px;
    min-width: 36px;
    padding: 4px 8px;
    border-radius: var(--r-sm);
    background: var(--accent-wash);
    color: var(--accent-dk);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0;
  }
  .row-item__badgestar { display: flex; }
  .row-item__badgestar svg { width: 11px; height: 11px; }
  .row-item__round { display: inline; }
  .row-item__exact { display: none; }
  .row-item__cnt { font-size: 11px; }

  /* A pill for a price the row is built around; a line for one it merely
     mentions. */
  .pricebtn {
    padding: 0;
    border-radius: 0;
    background: none;
    color: var(--price);
    font-size: 13.5px;
    font-weight: 700;
    letter-spacing: 0;
  }
  .pricebtn--range { border: 0; color: var(--muted); font-weight: 600; }
  .pricebtn--none { display: none; }

  .row-item__brand,
  .row-item__meta,
  .row-item__info .pct,
  .row-item__rank,
  .row-item__art .badge,
  .row-item__score .stars,
  .row-item__msrp,
  .row-item__stock,
  .row-item__acts { display: none; }

  /* My Bar on a phone is the app's screen: the count and the sort over a list
     that runs to both edges. Recently viewed is a desktop indulgence — this
     browser's history, below three lists that are the account's — and on a
     phone it only pushes the bottles off the screen. */
  .mybar__list { margin-top: 12px; }
  .mybar .results-bar__count { display: inline; font-size: 13px; }
  .mybar [data-recent-section] { display: none; }

  /* On a scan the row sits above a note about the same bottle, so it keeps
     the page's margins rather than running past them. Its rank is not a
     ranking either: it is the label on the photo, and without it there is
     nothing tying the row to what the camera saw. */
  .scanrow .row-item { margin: 0; }
  .scanrow .row-item__rank { display: block; padding: 2px 7px; font-size: 11px; }
  .showcard { grid-template-columns: 118px minmax(0, 1fr); }
  .showcard__art img { padding: 10px 6px; }
  .showcard h3 { font-size: 21px; }
  .showcard__score > b { font-size: 40px; }
  .showcard__price b { font-size: 24px; }
  .tile { grid-template-columns: minmax(0, 1fr) 64px; min-height: 108px; padding: 12px 10px 12px 12px; gap: 6px; }
  .tile__art { width: 64px; height: 80px; }
  .tile__name { font-size: 16px; }
  .tile__sub { font-size: 12px; }
  .speclist { grid-template-columns: 82px minmax(0, 1fr); }
  /* Phones get the app's SpiritScreen, in its order: the bottle in a frame of
     its own, then the producer, the name, the verdict, the facts, and what
     you have to say. Two columns at this width left the name in a 140px
     gutter, breaking it over four lines under a score three times its size,
     and dropped everything the identity column could not hold — the actions
     among them — into the same sliver. */
  .dhero {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    margin-top: 12px;
    padding-bottom: 24px;
  }
  .dhero__main { display: block; padding: 0; }
  /* A card the bottle sits in rather than on, as the app draws it. */
  .dhero__art,
  .dhero__art--cutout {
    height: 240px;
    min-height: 0;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--card);
  }
  /* Padding on the image, not the frame: the frame is the image's containing
     block, so insetting it there would move the padding box and change
     nothing. An absolute image cannot be inset by its own offsets either —
     with a width of auto it takes its intrinsic size and hangs out of the
     frame. Border-box sizing shrinks what `contain` has to fit instead. */
  .dhero__art img { padding: 20px 18px; }
  .dhero__thumbs { display: flex; flex-wrap: wrap; }
  .dhero__thumb { width: 52px; }
  /* The producer becomes the app's kicker: small, gold and set in capitals,
     which is also what a listing row prints above a name. */
  .dhero__brand {
    margin-bottom: 4px;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--accent-dk);
  }
  .dhero__id { margin-top: 18px; }
  .dhero h1 { font-size: 26px; line-height: 1.19; }
  /* One quiet line, as the app prints it. Underlining five facts turns a
     sentence into a row of buttons and doubles its visual weight. */
  .dhero__facts { margin-top: 12px; font-size: 14px; }
  .dhero__facts a { text-decoration: none; }

  /* The verdict moves into a panel and the headline number becomes a tile
     beside the word, which is the app's grammar. At 50px the number was the
     loudest thing on a phone screen, louder than the bottle's own name. */
  .dscore {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    margin-top: 14px;
    padding: 14px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--card);
  }
  .dscore__row { grid-column: 1; align-items: center; gap: 4px 9px; }
  /* The measured band rather than the verdict's three, so 3.66 comes out the
     rust the app tiles it with instead of the amber it shares with a 4.1. */
  .dscore__num {
    display: inline-flex;
    align-items: center;
    padding: 4px 9px;
    border-radius: var(--r-sm);
    background: var(--grade, var(--verdict));
    color: #fff;
    font-size: 17px;
    line-height: 1.3;
    letter-spacing: -0.01em;
  }
  .dscore__verdict {
    font-family: var(--f-body);
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0;
    color: var(--ink);
  }
  /* Three lines, as the app stacks them: the score, then the stars, then how
     many people are behind them. */
  .dscore__proof { grid-column: 1; display: block; margin-top: 6px; }
  .dscore__proof .stars svg, .dscore__proof .star { width: 15px; height: 15px; }
  .dscore__reviews {
    display: block;
    margin-top: 6px;
    font-size: 13px;
    text-decoration: none;
  }
  .dscore__exact { display: none; }
  .dscore__round { display: inline; }
  /* Right of the headline and quieter than it, so the tile the critic score
     wears on a desktop would only compete for a column 90px wide. */
  .dscore__side {
    grid-column: 2;
    grid-row: 1 / span 2;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    margin-top: 0;
    padding-left: 10px;
    font-size: 13px;
    text-align: right;
  }
  .dscore__critic { gap: 4px; }
  .dscore__badge {
    min-width: 0;
    height: auto;
    padding: 0;
    border-radius: 0;
    background: none;
    color: inherit;
    font-size: inherit;
    font-weight: inherit;
  }

  /* Your own row is one warm card holding the score, the chips and the count,
     the way the app draws it — not a white card followed by loose controls.
     The inner panel drops its own frame rather than boxing a box. */
  .yours {
    gap: 0;
    margin-top: 16px;
    padding: 20px 20px 22px;
    border: 1px solid var(--accent-lt);
    border-radius: 16px;
    background: var(--accent-wash);
  }
  .yours__rate {
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    gap: 10px;
  }
  .yours__title { font-size: 18px; }
  .yours__ask { font-size: 16px; font-weight: 700; }
  .yours__hint { font-size: 13.5px; line-height: 1.48; }
  .yours__score-btn {
    align-self: stretch;
    min-height: 50px;
    border-radius: 12px;
    font-size: 16px;
  }
  .yours__chips { margin-top: 20px; gap: 10px; }
  .yours .chip { padding: 11px 16px; font-size: 14px; font-weight: 700; color: var(--ink); }
  .yours .chip.is-on { color: #fff; }
  .yours__qty { margin-top: 16px; }
  .yours__qty-label { font-size: 14.5px; font-weight: 600; color: var(--ink); }
  .yours .stepper { border-radius: 10px; }
  .yours .stepper__btn { width: 40px; height: 36px; }
  .yours .stepper__n { font-size: 15.5px; }
  .yours__review { margin-top: 14px; }

  /* The app's section heading, which is a size below the desktop page's. */
  .detail h2 { font-size: 19px; }
  .detail .section--tight > h2 { margin-bottom: 12px; }
  /* The tablet buybox is a horizontal bar (price + button). On a phone that
     pins the size line to the price and leaves no air. Stack it again, with
     the price sitting in the middle of the card. */
  .dhero .buybox { margin-top: 24px; }
  .dhero .buybox__body {
    display: block;
    padding: 28px 18px 24px;
  }
  .dhero .buybox__price { justify-content: center; }
  .dhero .buybox__sub,
  .dhero .buybox__stock {
    margin-top: 12px;
    text-align: center;
  }
  .dhero .buybox .btn {
    flex: none;
    width: 100%;
    max-width: none;
    margin-top: 28px;
  }
  .dhero .buybox__note {
    flex: none;
    margin-top: 22px;
    text-align: center;
  }
  .dhero .buybox__more,
  .dhero .buybox__tier { flex: none; }
  .dhero .buybox__tier {
    justify-content: center;
    margin-top: 22px;
    padding-top: 20px;
  }

  /* The radar needs a 260px circle and a column of labels around it; a phone
     has room for one of those. The app answers the same question with the
     bars alone, label over track, so that is what a phone gets. */
  .radar-wrap {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    padding: 0;
    border: 0;
    background: none;
  }
  .radar { display: none; }
  .notes { gap: 12px; }
  .footer__cols { gap: 26px; }
  .calib { padding: 18px; }
  .calib h3 { font-size: 21px; }
  .calib__verdict { flex-direction: column; align-items: flex-start; gap: 8px; }
  /* Label and value on one line, the bar under both: a note reads as its own
     little chart rather than a name squeezed into a 92px column. Every cell is
     placed by hand — a track spanning both columns cannot share a row with the
     label, so auto-placement drops the value onto a third line of its own. */
  .note {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 5px 10px;
  }
  .note__label { grid-area: 1 / 1; white-space: normal; font-size: 14px; font-weight: 600; color: var(--ink); }
  .note__value { grid-area: 1 / 2; font-size: 13px; color: var(--faint); }
  .note__track { grid-area: 2 / 1 / 3 / -1; height: 7px; background: var(--line); }
  /* The note is still a search for other bottles that lead with it, but it
     reads as the app's label rather than a green link in a row of them; the
     line above the list is what says they can be tapped. */
  .note__label a { color: inherit; font-weight: inherit; }
  .note__fill { background: var(--accent); }
}

@media (max-width: 460px) {
  /* Stays a stretched pill rather than shrinking to a circle: it is the one
     flexible item in the row, so growing it is also what pins the account
     icon and Sign up to the right edge instead of stranding them mid-bar. */
  .searchbar {
    flex: 1;
    min-width: 0;
    height: 40px;
    gap: 8px;
    padding: 0 13px;
    container-type: inline-size;
  }
  .searchbar input, .searchbar__hint { display: none; }
  .searchbar__label { display: block; overflow: hidden; }
  /* The row tightens whenever the compare door is in it. Measured against the
     bar's content box, this is roughly where the glass and the word stop
     fitting side by side, so the word goes rather than clipping to "Sea". */
  @container (max-width: 78px) {
    .searchbar__label { display: none; }
  }
  .searchbar.is-open .searchbar__label { display: none; }
  .searchbar.is-open {
    position: absolute;
    left: 12px;
    right: 12px;
    z-index: 5;
    width: auto;
    max-width: none;
    height: 44px;
    padding: 0 14px;
    justify-content: flex-start;
    border-radius: var(--r-pill);
    background: #fff;
    color: var(--ink);
  }
  .searchbar.is-open > svg { color: var(--muted); }
  .searchbar.is-open input {
    display: block;
    color: var(--ink);
  }
  .searchbar.is-open input::placeholder { color: var(--faint); }

  /* The stack is already the app's; only the frame and the name give ground. */
  .dhero__art,
  .dhero__art--cutout { height: 216px; }
  .dhero h1 { font-size: 24px; }
  .dscore { padding: 12px; }
  .dscore__side { font-size: 12.5px; }
  .yours { padding: 16px 14px 18px; }

  /* The row is already the app's at this width; it does not shrink further. */
  .row-item { column-gap: 12px; }
}

/* iOS Safari zooms the page when a focused field is under 16px. Body type
   is 15.5px and several fields set smaller still. 1em keeps anything already
   larger, like the sentence finder. */
@media (max-width: 900px), (hover: none) and (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="hidden"]):not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="file"]),
  select,
  textarea {
    font-size: max(16px, 1em) !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

@media print {
  .header, .subnav, .tabbar, .footer, .filter-fab, .tray, .palette, .palette-backdrop { display: none !important; }
  body { background: #fff; }
}
