/*
 * The editorial client's one stylesheet — the fork's ui/public/styles.css, grown since.
 *
 * It is one frame and a layer per drink (PR 25). The frame is everything a drink does not
 * change: the type, the geometry, the motion, the anatomy of a card or a dialog, and the
 * six tokens in the first `:root` below. A layer is what a drink does change, and it is
 * all tokens: one flat, complete block per drink and appearance,
 *
 *   :root[data-drink="wine"][data-theme="morning" | "evening" | "dark"]
 *
 * each at specificity (0,3,0) and each declaring every palette token, so no block leans
 * on another and source order decides nothing. js/theme.js stamps `data-drink` and
 * `data-theme` on <html> before this file is fetched, so the first paint is already in
 * the reader's drink and appearance; a root with no `data-drink` shares wine's morning
 * block, which is what a page with no script gets. Tokens are named for their role, never
 * for a drink — `--accent`, not `--wine` — because beer's accent is not a wine colour. The
 * names are listed in docs/ui/design-notes.md, and test/contrast.test.js and
 * scripts/contrast-audit.js measure every block they find.
 *
 * A token that is an alias (`--x: var(--y)`) resolves on the element that declares it,
 * so an alias declared on `:root` would not follow a drink set lower in the tree. That is
 * why `data-drink` lives on <html>, and why no old name is kept as an alias of a new one.
 *
 * The fork's `@import url("/css/fonts.css")` is gone: the shell links fonts.css directly,
 * ahead of this file, so the @font-face rules are declared once and an import does not
 * serialise a second round trip behind this one.
 */

/* The frame: what every drink shares. */
:root {
  --serif: "Newsreader", Georgia, serif;
  --sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "DM Mono", monospace;
  /*
   * The type floor, and the step above it.
   *
   * Everything a reader is meant to read — eyebrows, captions, meta lines, chip and tab
   * labels, fine print — is at least `--t-fine`. The sheet used to spell that out as 149
   * literals between 6px and 10.5px, each one a separate decision, and the ones on a
   * phone were the smallest of them. They are one token now, so the floor is one edit
   * and nothing can drift under it by accident.
   *
   * The eyebrows that grew kept their *ratio* of tracking to size: every letter-spacing
   * in a rule this floor lifted is expressed in `em` rather than px, so an eyebrow still
   * reads as an eyebrow at the larger size instead of flattening into a label.
   *
   * One thing is deliberately allowed under the floor: the hero's wax stamp, which is
   * `aria-hidden` ornament drawn inside a 105px circle and is not read by anyone.
   */
  --t-fine: 11px;
  --t-small: 12px;
  --ease: cubic-bezier(0.22, 0.68, 0, 1);
  font-family: var(--sans);
  color: var(--ink);
  background: var(--paper);
  /* The layer's texture on the page ground (`none` for a drink without one, which is both
     drinks today). The root and `body` both start at 0,0, so their two patterns would line
     up, and the canvas under a short page carries it too. */
  background-image: var(--ground-texture);
  font-synthesis: style;
}
/*
 * Wine, morning. A root with no `data-drink` shares it: the page before any script has
 * run. Only a root with no drink at all: under another drink's stamp this block is not on
 * the page, so none of wine's own tokens (its five dots) leaks into beer's layer, and a
 * wine row drawn there falls back to the layer's `--muted`, as a can under wine does. It
 * also means a `data-drink` with no blocks of its own gets no palette at all, which is why
 * theme.js stamps only a drink `papers` names.
 */
:root:not([data-drink]), :root[data-drink="wine"][data-theme="morning"] {
  /* The page and its text. */
  --paper: #f7f5ed;
  --ink: #302b25;
  --muted: #655e54;
  --line: #ded9ce;
  /* Grounds: the raised one (fields, dialogs, cards), the neutral one, the three tints a
     style, a card or a status is drawn on, and the translucent wash over a photograph. */
  --white: #fffcf6;
  --surface: #edece1;
  --tint-1: #efdfd7;
  --tint-2: #e3e7d9;
  --tint-3: #eee5ce;
  --glass: #fffcf6d9;
  /* The accent (primary button, active chip, links, the save heart), its hover, and the
     ink that goes on it. `--orange` is the focus ring. */
  --accent: #632d3d;
  --accent-strong: #482332;
  --button-text: #fffcf6;
  --orange: #a64d30;
  /* The slab: the one surface that is deep in every appearance (the hero stamp, the palate
     banner, the tasting night's unmasked, winner and host cards), and the inks it brings,
     because --ink would vanish on it. The light button on it keeps its own pair. */
  --slab: #632d3d;
  --on-slab: #fff5ee;
  --on-slab-soft: #fff5eecc;
  --on-slab-quiet: #fff5eeb3;
  --on-slab-line: #fff5ee80;
  --on-slab-wash: #fff5ee1f;
  --on-slab-flower: #c68f86;
  --on-slab-eyebrow: #e0c1b9;
  --on-slab-copy: #e0c8c4;
  --on-slab-note: #dec4bd;
  --slab-button-ink: #632d3d;
  --slab-button-ink-strong: #482332;
  --slab-button-hover: #fff;
  --stamp-edge: #b69894;
  /* Edges warmer than --line: the outline button, a text link's underline, and the upload
     zone's dashes and its link. */
  --edge-button: #b9a9a7;
  --edge-link: #b9a79b;
  --edge-drop: #aa968a;
  --edge-drop-link: #b79d92;
  /* Shadows and the dialog's backdrop, tinted to the layer rather than black. */
  --shadow-note: #29160d0d;
  --shadow-dialog: #1d10183b;
  --shadow-toast: #24151620;
  --shadow-nav: #30201405;
  --shadow-bottle: #21141d24;
  --backdrop: #241c2385;
  --backdrop-solid: #241c23e8;
  /* One dot per style; the style rules below hand each one to `--style-dot`. Each dot clears
     WCAG's non-text 3:1 on --white and --paper in its own appearance: W1's one set of five
     did not (white, rosé and sparkling were 2.1–2.6:1 in the light, red 2.1:1 in the dark),
     so each appearance moves the ones that failed the smallest OKLCH lightness step that
     clears, hue and chroma kept, and leaves every dot that passed at W1's value: red and
     dessert here and in the evening, white, rosé, sparkling and dessert in the dark. The
     gate is the only rule, so in the light appearances white, rosé and sparkling end at
     one lightness and are told apart by hue alone, as white and sparkling always were. */
  --dot-red: #9d3745;
  --dot-white: #9f8d4b;
  --dot-rose: #bd7d78;
  --dot-spark: #9b8e4e;
  --dot-dessert: #a46537;
  /* The mood orb, and the grading of the hero photograph. */
  --orb: #cfb96e;
  --orb-light: #fff4d6;
  --orb-deep: #cfb96e;
  --orb-stop: 67%;
  --hero-filter: saturate(.78) brightness(1.07);
  /* The appearance dialog's four previews, which picture this drink's palettes. */
  --preview-ink: #593749;
  --preview-auto-from: #f2ead1;
  --preview-auto-to: #dbb5a5;
  --preview-morning-from: #fff6da;
  --preview-morning-to: #dce1c7;
  --preview-evening-from: #f8dfc8;
  --preview-evening-to: #d2a49c;
  --preview-dark-from: #514050;
  --preview-dark-to: #221b26;
  --preview-dark-ink: #f1d4dc;
  /* The texture tokens every drink declares, which the frame reads (beer draws its own with
     them). Wine's draw the frame as it was before there were layers: a plain page, the
     thin pale ellipse turned behind a card's bottle, the journal drawings at 0.35, a
     plain slab and a 12px corner on the card art. Wine draws no ledger rule and no label
     on its slab: `--meta-rule` and `--slab-label` are declared for the shared set and
     nothing reads them. */
  --ground-texture: none;
  --art-ring-inset: auto -30px -130px 15px;
  --art-ring-width: auto;
  --art-ring-height: 300px;
  --art-ring-edge: 1px solid #ffffff55;
  --art-ring-halo: none;
  --art-ring-turn: rotate(-30deg);
  --art-ring-forced: block;
  --meta-rule: transparent;
  --slab-label: transparent;
  --drawing-opacity: 0.35;
  --slab-texture: none;
  --slab-texture-ink: transparent;
  --slab-texture-size: auto;
  --art-radius: 12px;
}
/* Wine, evening: a familiar journal, with light that follows the reader's day. */
:root[data-drink="wine"][data-theme="evening"] {
  --paper: #f4e7df;
  --ink: #3d2b2e;
  --muted: #684d48;
  --line: #dfc9be;
  --white: #f9eee7;
  --surface: #ecdbd0;
  --tint-1: #e9cfc5;
  --tint-2: #dfdfca;
  --tint-3: #ebd6b9;
  --glass: #f9eee7ed;
  --accent: #793e50;
  --accent-strong: #613041;
  --button-text: #fffcf6;
  --orange: #a64d30;
  --slab: #683748;
  --on-slab: #fff5ee;
  --on-slab-soft: #fff5eecc;
  --on-slab-quiet: #fff5eeb3;
  --on-slab-line: #fff5ee80;
  --on-slab-wash: #fff5ee1f;
  --on-slab-flower: #c68f86;
  --on-slab-eyebrow: #e0c1b9;
  --on-slab-copy: #e0c8c4;
  --on-slab-note: #dec4bd;
  --slab-button-ink: #632d3d;
  --slab-button-ink-strong: #482332;
  --slab-button-hover: #fff;
  --stamp-edge: #b69894;
  --edge-button: #b9a9a7;
  --edge-link: #b9a79b;
  --edge-drop: #aa968a;
  --edge-drop-link: #b79d92;
  --shadow-note: #29160d0d;
  --shadow-dialog: #1d10183b;
  --shadow-toast: #24151620;
  --shadow-nav: #30201405;
  --shadow-bottle: #21141d24;
  --backdrop: #241c2385;
  --backdrop-solid: #241c23e8;
  --dot-red: #9d3745;
  --dot-white: #978543;
  --dot-rose: #b47670;
  --dot-spark: #938646;
  --dot-dessert: #a46537;
  --orb: #cb8069;
  --orb-light: #fff4d6;
  --orb-deep: #cb8069;
  --orb-stop: 67%;
  --hero-filter: saturate(.85) sepia(.12) brightness(.95);
  --preview-ink: #593749;
  --preview-auto-from: #f2ead1;
  --preview-auto-to: #dbb5a5;
  --preview-morning-from: #fff6da;
  --preview-morning-to: #dce1c7;
  --preview-evening-from: #f8dfc8;
  --preview-evening-to: #d2a49c;
  --preview-dark-from: #514050;
  --preview-dark-to: #221b26;
  --preview-dark-ink: #f1d4dc;
  --ground-texture: none;
  --art-ring-inset: auto -30px -130px 15px;
  --art-ring-width: auto;
  --art-ring-height: 300px;
  --art-ring-edge: 1px solid #ffffff55;
  --art-ring-halo: none;
  --art-ring-turn: rotate(-30deg);
  --art-ring-forced: block;
  --meta-rule: transparent;
  --slab-label: transparent;
  --drawing-opacity: 0.35;
  --slab-texture: none;
  --slab-texture-ink: transparent;
  --slab-texture-size: auto;
  --art-radius: 12px;
}
/* Wine, dark. */
:root[data-drink="wine"][data-theme="dark"] {
  --paper: #211b24;
  --ink: #f1e7e3;
  --muted: #c5b2b9;
  --line: #52414e;
  --white: #302632;
  --surface: #302b33;
  --tint-1: #49333b;
  --tint-2: #333b35;
  --tint-3: #453b30;
  --glass: #302632ed;
  --accent: #e5b0be;
  --accent-strong: #f1c4cf;
  --button-text: #291c25;
  --orange: #e8a280;
  --slab: #51313f;
  --on-slab: #fff5ee;
  --on-slab-soft: #fff5eecc;
  --on-slab-quiet: #fff5eeb3;
  --on-slab-line: #fff5ee80;
  --on-slab-wash: #fff5ee1f;
  --on-slab-flower: #c68f86;
  --on-slab-eyebrow: #e0c1b9;
  --on-slab-copy: #e0c8c4;
  --on-slab-note: #dec4bd;
  --slab-button-ink: #632d3d;
  --slab-button-ink-strong: #482332;
  --slab-button-hover: #fff;
  --stamp-edge: #b69894;
  --edge-button: #b9a9a7;
  --edge-link: #b9a79b;
  --edge-drop: #aa968a;
  --edge-drop-link: #b79d92;
  --shadow-note: #29160d0d;
  --shadow-dialog: #1d10183b;
  --shadow-toast: #24151620;
  --shadow-nav: #30201405;
  --shadow-bottle: #21141d24;
  --backdrop: #241c2385;
  --backdrop-solid: #241c23e8;
  --dot-red: #b9505c;
  --dot-white: #baa865;
  --dot-rose: #ce8d87;
  --dot-spark: #b8ab6a;
  --dot-dessert: #a46537;
  --orb: #c0a9cd;
  --orb-light: #eee2f8;
  --orb-deep: #786781;
  --orb-stop: 75%;
  --hero-filter: saturate(.68) brightness(.73);
  --preview-ink: #593749;
  --preview-auto-from: #f2ead1;
  --preview-auto-to: #dbb5a5;
  --preview-morning-from: #fff6da;
  --preview-morning-to: #dce1c7;
  --preview-evening-from: #f8dfc8;
  --preview-evening-to: #d2a49c;
  --preview-dark-from: #514050;
  --preview-dark-to: #221b26;
  --preview-dark-ink: #f1d4dc;
  --ground-texture: none;
  --art-ring-inset: auto -30px -130px 15px;
  --art-ring-width: auto;
  --art-ring-height: 300px;
  --art-ring-edge: 1px solid #ffffff55;
  --art-ring-halo: none;
  --art-ring-turn: rotate(-30deg);
  --art-ring-forced: block;
  --meta-rule: transparent;
  --slab-label: transparent;
  --drawing-opacity: 0.35;
  --slab-texture: none;
  --slab-texture-ink: transparent;
  --slab-texture-size: auto;
  --art-radius: 12px;
}

/* Beer, morning: the bottle-shop fridge door (B2 "Can shelf"). Cool white, near-ink
   hairlines, a cobalt slab under a halftone dot, one flat colour per family. The shared
   set first, in wine's order; then beer's own art colours (the dots, the five family
   grounds, the can bodies, their bands and the lid), which its family rules hand out. */
:root[data-drink="beer"][data-theme="morning"] {
  --paper: #f6f6f1;
  --ink: #161a17;
  --muted: #4f5651;
  --line: #2a2f2b;
  --white: #ffffff;
  --surface: #e9ebe3;
  --tint-1: #ffe1c2;
  --tint-2: #d9f0d6;
  --tint-3: #fff0b3;
  --glass: #ffffffd9;
  --accent: #165e2f;
  --accent-strong: #135229;
  --button-text: #f6f6f1;
  --orange: #c1401c;
  --slab: #1d3a8a;
  --on-slab: #fff5ee;
  --on-slab-soft: #fff5eee0;
  --on-slab-quiet: #fff5eed1;
  --on-slab-line: #fff5ee80;
  --on-slab-wash: #fff5ee1f;
  --on-slab-eyebrow: #fff5eed1;
  --on-slab-copy: #fff5eee0;
  --on-slab-note: #fff5eed1;
  --on-slab-flower: #ffc93c;
  --slab-button-ink: #1d3a8a;
  --slab-button-ink-strong: #172e6e;
  --slab-button-hover: #fff;
  --stamp-edge: #ffc93c;
  --edge-button: #2a2f2b;
  --edge-link: #4f5651;
  --edge-drop: #2a2f2b;
  --edge-drop-link: #4f5651;
  --shadow-note: #161a170d;
  --shadow-dialog: #161a173b;
  --shadow-toast: #161a1720;
  --shadow-nav: #161a1705;
  --shadow-bottle: transparent;
  --backdrop: #161a1785;
  --backdrop-solid: #161a17e8;
  --orb: #ffc93c;
  --orb-light: #fff4d6;
  --orb-deep: #ffc93c;
  --orb-stop: 67%;
  --hero-filter: saturate(1) brightness(1);
  --preview-ink: #1d3a8a;
  --preview-auto-from: #fff0b3;
  --preview-auto-to: #f9d9b8;
  --preview-morning-from: #fff0b3;
  --preview-morning-to: #d9f0d6;
  --preview-evening-from: #f7e4a6;
  --preview-evening-to: #f9d9b8;
  --preview-dark-from: #1a2f7a;
  --preview-dark-to: #121412;
  --preview-dark-ink: #f2f1ea;
  --ground-texture: none;
  --art-ring-inset: auto -38px -74px auto;
  --art-ring-width: 236px;
  --art-ring-height: 236px;
  --art-ring-edge: 1.5px solid transparent;
  --art-ring-halo: none;
  --art-ring-turn: none;
  --art-ring-forced: none;
  --meta-rule: transparent;
  --drawing-opacity: 0.35;
  --slab-label: transparent;
  --slab-texture: radial-gradient(var(--slab-texture-ink) 1px, transparent 1.6px);
  --slab-texture-ink: #ffffff24;
  --slab-texture-size: 6px 6px;
  --art-radius: 6px;
  --dot-pale_lager: #9f893e;
  --dot-hybrid: #9e8d4a;
  --dot-dark_lager: #a85a24;
  --dot-bock: #8a4318;
  --dot-wheat: #9e894e;
  --dot-pale_ale: #b98427;
  --dot-ipa: #bf7f1c;
  --dot-hazy_ipa: #b68336;
  --dot-brown_amber: #a24d1d;
  --dot-porter_stout: #231611;
  --dot-strong_ale: #6f3212;
  --dot-belgian_pale: #a68838;
  --dot-belgian_dark: #43200f;
  --dot-sour: #d9636e;
  --ground-straw: #fff0b3;
  --ground-amber: #f7c9a1;
  --ground-gold: #ffdfa6;
  --ground-dark: #ccc8c1;
  --ground-sour: #ffd3dd;
  --can-pale_lager: #f1cf5e;
  --can-hybrid: #efd670;
  --can-dark_lager: #a85a24;
  --can-bock: #8a4318;
  --can-wheat: #efcf76;
  --can-pale_ale: #e2a12f;
  --can-ipa: #de9420;
  --can-hazy_ipa: #f0ad47;
  --can-brown_amber: #a24d1d;
  --can-porter_stout: #231611;
  --can-strong_ale: #6f3212;
  --can-belgian_pale: #e7bd4e;
  --can-belgian_dark: #43200f;
  --can-sour: #d9636e;
  --can-band-pale_lager: #b59b47;
  --can-band-hybrid: #b3a154;
  --can-band-dark_lager: #7e441b;
  --can-band-bock: #683212;
  --can-band-wheat: #b39b59;
  --can-band-pale_ale: #aa7923;
  --can-band-ipa: #a76f18;
  --can-band-hazy_ipa: #b48235;
  --can-band-brown_amber: #7a3a16;
  --can-band-porter_stout: #1a110d;
  --can-band-strong_ale: #53260e;
  --can-band-belgian_pale: #ad8e3b;
  --can-band-belgian_dark: #32180b;
  --can-band-sour: #a34a53;
  --can-lid: #c5c6c5;
}
/* Beer, evening: warm paper, a rust accent and a bottle-green slab. */
:root[data-drink="beer"][data-theme="evening"] {
  --paper: #f4ecdc;
  --ink: #1c1a15;
  --muted: #55503f;
  --line: #2c2820;
  --white: #fdf7ea;
  --surface: #e9dfc9;
  --tint-1: #f9d9b8;
  --tint-2: #dfe8c6;
  --tint-3: #f7e4a6;
  --glass: #fdf7eadf;
  --accent: #943814;
  --accent-strong: #7e2f11;
  --button-text: #fdf7ea;
  --orange: #1f793e;
  --slab: #123f3f;
  --on-slab: #fff5ee;
  --on-slab-soft: #fff5eee0;
  --on-slab-quiet: #fff5eed1;
  --on-slab-line: #fff5ee80;
  --on-slab-wash: #fff5ee1f;
  --on-slab-eyebrow: #fff5eed1;
  --on-slab-copy: #fff5eee0;
  --on-slab-note: #fff5eed1;
  --on-slab-flower: #ff8a3d;
  --slab-button-ink: #123f3f;
  --slab-button-ink-strong: #0e3232;
  --slab-button-hover: #fff;
  --stamp-edge: #ff8a3d;
  --edge-button: #2c2820;
  --edge-link: #55503f;
  --edge-drop: #2c2820;
  --edge-drop-link: #55503f;
  --shadow-note: #1c1a150d;
  --shadow-dialog: #1c1a153b;
  --shadow-toast: #1c1a1520;
  --shadow-nav: #1c1a1505;
  --shadow-bottle: transparent;
  --backdrop: #1c1a1585;
  --backdrop-solid: #1c1a15e8;
  --orb: #ff8a3d;
  --orb-light: #fff4d6;
  --orb-deep: #ff8a3d;
  --orb-stop: 67%;
  --hero-filter: saturate(.95) sepia(.1) brightness(.97);
  --preview-ink: #1d3a8a;
  --preview-auto-from: #fff0b3;
  --preview-auto-to: #f9d9b8;
  --preview-morning-from: #fff0b3;
  --preview-morning-to: #d9f0d6;
  --preview-evening-from: #f7e4a6;
  --preview-evening-to: #f9d9b8;
  --preview-dark-from: #1a2f7a;
  --preview-dark-to: #121412;
  --preview-dark-ink: #f2f1ea;
  --ground-texture: none;
  --art-ring-inset: auto -38px -74px auto;
  --art-ring-width: 236px;
  --art-ring-height: 236px;
  --art-ring-edge: 1.5px solid transparent;
  --art-ring-halo: none;
  --art-ring-turn: none;
  --art-ring-forced: none;
  --meta-rule: transparent;
  --drawing-opacity: 0.35;
  --slab-label: transparent;
  --slab-texture: radial-gradient(var(--slab-texture-ink) 1px, transparent 1.6px);
  --slab-texture-ink: #ffffff24;
  --slab-texture-size: 6px 6px;
  --art-radius: 6px;
  --dot-pale_lager: #9a843c;
  --dot-hybrid: #948545;
  --dot-dark_lager: #a85a24;
  --dot-bock: #8a4318;
  --dot-wheat: #99844c;
  --dot-pale_ale: #b07e25;
  --dot-ipa: #b6791a;
  --dot-hazy_ipa: #ad7d33;
  --dot-brown_amber: #a24d1d;
  --dot-porter_stout: #231611;
  --dot-strong_ale: #6f3212;
  --dot-belgian_pale: #a28437;
  --dot-belgian_dark: #43200f;
  --dot-sour: #d5616c;
  --ground-straw: #f7e4a6;
  --ground-amber: #efc09a;
  --ground-gold: #f9d4a0;
  --ground-dark: #ccc0b1;
  --ground-sour: #f7cdcf;
  --can-pale_lager: #f1cf5e;
  --can-hybrid: #efd670;
  --can-dark_lager: #a85a24;
  --can-bock: #8a4318;
  --can-wheat: #efcf76;
  --can-pale_ale: #e2a12f;
  --can-ipa: #de9420;
  --can-hazy_ipa: #f0ad47;
  --can-brown_amber: #a24d1d;
  --can-porter_stout: #231611;
  --can-strong_ale: #6f3212;
  --can-belgian_pale: #e7bd4e;
  --can-belgian_dark: #43200f;
  --can-sour: #d9636e;
  --can-band-pale_lager: #b59b47;
  --can-band-hybrid: #b3a154;
  --can-band-dark_lager: #7e441b;
  --can-band-bock: #683212;
  --can-band-wheat: #b39b59;
  --can-band-pale_ale: #aa7923;
  --can-band-ipa: #a76f18;
  --can-band-hazy_ipa: #b48235;
  --can-band-brown_amber: #7a3a16;
  --can-band-porter_stout: #1a110d;
  --can-band-strong_ale: #53260e;
  --can-band-belgian_pale: #ad8e3b;
  --can-band-belgian_dark: #32180b;
  --can-band-sour: #a34a53;
  --can-lid: #c6c6c5;
}
/* Beer, dark: charcoal, a mint accent, the cobalt slab kept; the family grounds drop to
   deep tints and the can carries the colour. */
:root[data-drink="beer"][data-theme="dark"] {
  --paper: #121412;
  --ink: #f2f1ea;
  --muted: #b9b8ae;
  --line: #3c403c;
  --white: #1e211e;
  --surface: #1b1e1b;
  --tint-1: #4a2f1a;
  --tint-2: #22391f;
  --tint-3: #3d3410;
  --glass: #1e211eed;
  --accent: #8fe08a;
  --accent-strong: #b3f0ad;
  --button-text: #121412;
  --orange: #ffb054;
  --slab: #1a2f7a;
  --on-slab: #fff5ee;
  --on-slab-soft: #fff5eee0;
  --on-slab-quiet: #fff5eed1;
  --on-slab-line: #fff5ee80;
  --on-slab-wash: #fff5ee1f;
  --on-slab-eyebrow: #fff5eed1;
  --on-slab-copy: #fff5eee0;
  --on-slab-note: #fff5eed1;
  --on-slab-flower: #ffd23f;
  --slab-button-ink: #1a2f7a;
  --slab-button-ink-strong: #152662;
  --slab-button-hover: #fff;
  --stamp-edge: #ffd23f;
  --edge-button: #7a7f79;
  --edge-link: #8f948d;
  --edge-drop: #7a7f79;
  --edge-drop-link: #8f948d;
  --shadow-note: #0608060d;
  --shadow-dialog: #0608063b;
  --shadow-toast: #06080620;
  --shadow-nav: #06080605;
  --shadow-bottle: transparent;
  --backdrop: #06080685;
  --backdrop-solid: #060806e8;
  --orb: #ffd23f;
  --orb-light: #fff4d6;
  --orb-deep: #ffd23f;
  --orb-stop: 67%;
  --hero-filter: saturate(.8) brightness(.8);
  --preview-ink: #1d3a8a;
  --preview-auto-from: #fff0b3;
  --preview-auto-to: #f9d9b8;
  --preview-morning-from: #fff0b3;
  --preview-morning-to: #d9f0d6;
  --preview-evening-from: #f7e4a6;
  --preview-evening-to: #f9d9b8;
  --preview-dark-from: #1a2f7a;
  --preview-dark-to: #121412;
  --preview-dark-ink: #f2f1ea;
  --ground-texture: none;
  --art-ring-inset: auto -38px -74px auto;
  --art-ring-width: 236px;
  --art-ring-height: 236px;
  --art-ring-edge: 1.5px solid transparent;
  --art-ring-halo: none;
  --art-ring-turn: none;
  --art-ring-forced: none;
  --meta-rule: transparent;
  --drawing-opacity: 0.35;
  --slab-label: transparent;
  --slab-texture: radial-gradient(var(--slab-texture-ink) 1px, transparent 1.6px);
  --slab-texture-ink: #ffffff24;
  --slab-texture-size: 6px 6px;
  --art-radius: 6px;
  --dot-pale_lager: #f1cf5e;
  --dot-hybrid: #efd670;
  --dot-dark_lager: #a85a24;
  --dot-bock: #995c37;
  --dot-wheat: #efcf76;
  --dot-pale_ale: #e2a12f;
  --dot-ipa: #de9420;
  --dot-hazy_ipa: #f0ad47;
  --dot-brown_amber: #a65426;
  --dot-porter_stout: #726a67;
  --dot-strong_ale: #906149;
  --dot-belgian_pale: #e7bd4e;
  --dot-belgian_dark: #80685c;
  --dot-sour: #d9636e;
  --ground-straw: #4a4014;
  --ground-amber: #422a18;
  --ground-gold: #4a3410;
  --ground-dark: #26282a;
  --ground-sour: #4a2430;
  --can-pale_lager: #f1cf5e;
  --can-hybrid: #efd670;
  --can-dark_lager: #a85a24;
  --can-bock: #8a4318;
  --can-wheat: #efcf76;
  --can-pale_ale: #e2a12f;
  --can-ipa: #de9420;
  --can-hazy_ipa: #f0ad47;
  --can-brown_amber: #a24d1d;
  --can-porter_stout: #231611;
  --can-strong_ale: #6f3212;
  --can-belgian_pale: #e7bd4e;
  --can-belgian_dark: #43200f;
  --can-sour: #d9636e;
  --can-band-pale_lager: #f6e096;
  --can-band-hybrid: #f5e4a2;
  --can-band-dark_lager: #c69471;
  --can-band-bock: #b38569;
  --can-band-wheat: #f5e0a6;
  --can-band-pale_ale: #ecc278;
  --can-band-ipa: #eab96e;
  --can-band-hazy_ipa: #f5ca87;
  --can-band-brown_amber: #c38b6c;
  --can-band-porter_stout: #706864;
  --can-band-strong_ale: #a17a65;
  --can-band-belgian_pale: #efd48c;
  --can-band-belgian_dark: #856e63;
  --can-band-sour: #e69aa1;
  --can-lid: #f5f4ee;
}

/*
 * Wine's styles.
 *
 * A style hands whatever is drawn in it two tokens: `--style-dot`, the dot beside its
 * name, and `--style-ground`, the tint its card, detail panel, glass tile or reveal card is
 * drawn on. Those pieces read the two tokens and never a style by name, so a drink's layer
 * brings its own styles as one rule each, beside its palettes. Each piece declares its own
 * default before it reads the token (`.wine-dot`, `.wine-art`, `.detail-art`, and
 * tasting.css's `.glass-tile` and `.reveal-card`), so a style no rule names draws as it
 * always has: a red dot, a neutral card, a rose detail panel — and a token never leaks
 * into a piece from the card around it. These rules are (0,2,0), one class above the
 * pieces they dress, as the category rules they replace were.
 */
:is(.wine-dot, .wine-art, .detail-art, .glass-tile, .reveal-card).red {
  --style-dot: var(--dot-red, var(--muted));
  --style-ground: var(--tint-1, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .glass-tile, .reveal-card).white {
  --style-dot: var(--dot-white, var(--muted));
  --style-ground: var(--tint-2, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .glass-tile, .reveal-card).rose {
  --style-dot: var(--dot-rose, var(--muted));
  --style-ground: var(--tint-1, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .glass-tile, .reveal-card).spark {
  --style-dot: var(--dot-spark, var(--muted));
  --style-ground: var(--tint-3, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .glass-tile, .reveal-card).dessert {
  --style-dot: var(--dot-dessert, var(--muted));
  --style-ground: var(--tint-3, var(--surface));
}
/*
 * Beer's families.
 *
 * The same mechanism as wine's styles, keyed by the family a beer row carries as its
 * `cat` (`KINDS.beer` in shared/catalog.js): one rule per family hands the pieces the dot
 * beside its name, the ground its card and detail panel are drawn on (five grounds, one per
 * group: straw, amber, gold, dark and sour), and the three colours of its can. Every token
 * is read with a fallback, so a beer row drawn under another drink's layer — a beer on a
 * list scanned from a wine page, since Discover stays wine and theme.js reads the drink
 * from the address alone — draws a grey dot, a neutral card and a grey can rather than
 * nothing; a wine row under beer's layer falls back the same way, its dot `--muted`. The
 * tasting night's pieces are left out: a tasting is always wine.
 */
:is(.wine-dot, .wine-art, .detail-art, .can-art).pale_lager {
  --style-dot: var(--dot-pale_lager, var(--muted));
  --style-ground: var(--ground-straw, var(--surface));
  --can-body: var(--can-pale_lager, var(--muted));
  --can-band: var(--can-band-pale_lager, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).hybrid {
  --style-dot: var(--dot-hybrid, var(--muted));
  --style-ground: var(--ground-straw, var(--surface));
  --can-body: var(--can-hybrid, var(--muted));
  --can-band: var(--can-band-hybrid, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).dark_lager {
  --style-dot: var(--dot-dark_lager, var(--muted));
  --style-ground: var(--ground-amber, var(--surface));
  --can-body: var(--can-dark_lager, var(--muted));
  --can-band: var(--can-band-dark_lager, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).bock {
  --style-dot: var(--dot-bock, var(--muted));
  --style-ground: var(--ground-amber, var(--surface));
  --can-body: var(--can-bock, var(--muted));
  --can-band: var(--can-band-bock, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).wheat {
  --style-dot: var(--dot-wheat, var(--muted));
  --style-ground: var(--ground-straw, var(--surface));
  --can-body: var(--can-wheat, var(--muted));
  --can-band: var(--can-band-wheat, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).pale_ale {
  --style-dot: var(--dot-pale_ale, var(--muted));
  --style-ground: var(--ground-gold, var(--surface));
  --can-body: var(--can-pale_ale, var(--muted));
  --can-band: var(--can-band-pale_ale, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).ipa {
  --style-dot: var(--dot-ipa, var(--muted));
  --style-ground: var(--ground-gold, var(--surface));
  --can-body: var(--can-ipa, var(--muted));
  --can-band: var(--can-band-ipa, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).hazy_ipa {
  --style-dot: var(--dot-hazy_ipa, var(--muted));
  --style-ground: var(--ground-gold, var(--surface));
  --can-body: var(--can-hazy_ipa, var(--muted));
  --can-band: var(--can-band-hazy_ipa, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).brown_amber {
  --style-dot: var(--dot-brown_amber, var(--muted));
  --style-ground: var(--ground-amber, var(--surface));
  --can-body: var(--can-brown_amber, var(--muted));
  --can-band: var(--can-band-brown_amber, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).porter_stout {
  --style-dot: var(--dot-porter_stout, var(--muted));
  --style-ground: var(--ground-dark, var(--surface));
  --can-body: var(--can-porter_stout, var(--muted));
  --can-band: var(--can-band-porter_stout, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).strong_ale {
  --style-dot: var(--dot-strong_ale, var(--muted));
  --style-ground: var(--ground-dark, var(--surface));
  --can-body: var(--can-strong_ale, var(--muted));
  --can-band: var(--can-band-strong_ale, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).belgian_pale {
  --style-dot: var(--dot-belgian_pale, var(--muted));
  --style-ground: var(--ground-gold, var(--surface));
  --can-body: var(--can-belgian_pale, var(--muted));
  --can-band: var(--can-band-belgian_pale, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).belgian_dark {
  --style-dot: var(--dot-belgian_dark, var(--muted));
  --style-ground: var(--ground-dark, var(--surface));
  --can-body: var(--can-belgian_dark, var(--muted));
  --can-band: var(--can-band-belgian_dark, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
:is(.wine-dot, .wine-art, .detail-art, .can-art).sour {
  --style-dot: var(--dot-sour, var(--muted));
  --style-ground: var(--ground-sour, var(--surface));
  --can-body: var(--can-sour, var(--muted));
  --can-band: var(--can-band-sour, var(--ink));
  --can-cap: var(--can-lid, var(--surface));
}
* {
  box-sizing: border-box;
}
body {
  margin: 0;
}
button,
input,
select,
textarea {
  font: inherit;
}
button,
a,
input,
select,
textarea {
  -webkit-tap-highlight-color: transparent;
}
button {
  cursor: pointer;
}
button,
a {
  touch-action: manipulation;
}
button {
  color: inherit;
}
a {
  color: inherit;
  text-decoration: none;
}
/*
 * Disabled is not the exception people think it is. "Lock in your score" is disabled
 * until a glass has been scored, so the resting state of the rate screen *is* this rule,
 * and at 0.55 the button read 2.9:1 against the page and its own label 3.3:1 against it —
 * a primary call to action nobody could read. 0.8 is the lowest value at which the button
 * still clears 3:1 as a shape and its label 4.5:1 as text on every ground in all three
 * appearances — the evening palette is the one that decides it; scripts/contrast-audit.js
 * measures both and fails if it stops being true.
 */
button:disabled {
  cursor: wait;
  opacity: 0.8;
}
button {
  border: 0;
  background: none;
}
/*
 * Where the keyboard is. One ring for the whole app, and no rule below is allowed to
 * take it away — `outline: none` on a focusable thing is how the previous client lost it
 * on every text field in the product.
 *
 * The ring is drawn 5px *outside* the control, so what it has to contrast with is the
 * surface around the control rather than the control itself: that is why --orange works
 * on a wine-red button. scripts/contrast-audit.js measures it against every ground, in
 * all three appearances.
 */
button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: 3px solid var(--orange);
  outline-offset: 5px;
}
/* The exception is the app's own deep-plum surfaces, where a burnt orange ring on a
   bordeaux ground is a ring nobody can see. There the ring takes the near-white ink the
   surface already carries. (tasting.css does the same for its three plum cards.) */
.palate-banner :is(a, button, input, select, textarea):focus-visible {
  outline-color: var(--on-slab);
}
h1,
h2,
h3,
p {
  margin: 0;
}
h1,
h2,
h3 {
  font-weight: 400;
}
em {
  font-family: var(--serif);
  font-weight: 400;
}
p {
  line-height: 1.65;
}
svg {
  flex-shrink: 0;
}
.icon {
  display: inline-block;
  vertical-align: middle;
  width: 21px;
  height: 21px;
}
.page-width {
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: 64px;
}
.eyebrow {
  font: var(--t-fine)/1.5 var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.subtle,
.fine-print {
  color: var(--muted);
  font-size: var(--t-small);
  line-height: 1.65;
}
.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;
}
/* The same thing under the name the rest of the world writes. Both are shipped because
   the client already says `sr-only` in a dozen places and a second name is cheaper than
   a rename that touches every screen; new markup should reach for this one. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* Two lines, then an ellipsis — for the strings that used to be clipped at one with no
   way to read the rest: a Discover reason, an explanation line, a long wine name. The
   element it goes on must not also be `white-space: nowrap`. */
.clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
}
.skip-link {
  position: fixed;
  top: -80px;
  left: 24px;
  z-index: 100;
  padding: 16px;
  background: var(--accent);
  /* `white` here, until the audit learned to read a named colour and measured it: in the
     dark appearance `--accent` is #e5b0be, a pale pink, and white on it is 1.86:1 — the one
     control the whole keyboard pass exists for, unreadable at night. `--button-text` is
     the token that already means "the ink that goes on a wine ground"; it is #291c25 in
     the dark palette and near-white in the other two, and it is measured on `--accent` in
     all three. Was 10.64 / 8.02 / 1.86:1; now 10.39 / 7.83 / 8.77:1. */
  color: var(--button-text);
}
.skip-link:focus {
  top: 12px;
}
/*
 * The drawn ornaments (components.js): the rosette, a six-petal printer's flower kin to
 * the wordmark's fleuron, at two optical sizes. A small one is an icon in a `.mark-slot`
 * (the match tag, the lobby note, the footer); a large one is a `.mark` on a 100-unit
 * square (the hero stamp, the palate banners, the palate page). Both are drawn in
 * `currentColor`, so each role below keeps the colour token it always had, and each sizes
 * a box rather than a glyph, so no platform can swap an emoji in for it.
 */
.mark-slot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.mark-slot > .icon,
.mark {
  display: block;
}
.initial-load {
  padding: 80px;
  text-align: center;
}
.site-header {
  height: 102px;
  max-width: 1440px;
  margin: auto;
  padding: 0 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  border-bottom: 1px solid var(--line);
}
.wordmark {
  display: flex;
  align-items: center;
  white-space: nowrap;
  font-size: 35px;
  letter-spacing: -2.5px;
  font-weight: 500;
}
.brand-flower {
  font-size: 30px;
  color: var(--accent);
  margin: 0 4px 0 7px;
  letter-spacing: -4px;
}
.brand-period {
  color: var(--accent);
}
.desktop-nav {
  display: flex;
  align-items: center;
  gap: 30px;
  height: 100%;
  font-size: 12px;
}
.desktop-nav > a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 7px;
  height: 100%;
  color: var(--muted);
  transition: color 0.2s;
}
.desktop-nav > a:hover,
.desktop-nav > a[aria-current] {
  color: var(--accent);
}
.desktop-nav > a[aria-current]:after {
  content: "";
  position: absolute;
  bottom: 24px;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--accent);
}
/* The place's name in both navs: My Cellar, or whatever the reader calls it, up to the
   40 characters the server keeps. A long name ends in an ellipsis rather than pushing the
   header's other links aside or widening the phone nav's column. The whole name is
   still the link's text, so a screen reader reads all of it. The phone's cellar item
   gets `min-width: 0` so its grid column can be narrower than an unbroken name. */
.nav-place {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.desktop-nav .nav-place {
  max-width: 14em;
}
.mobile-nav > a[data-nav="cellar"] {
  min-width: 0;
}
.mobile-nav .nav-place {
  max-width: 100%;
}
.nav-count[hidden] { display: none; }
.nav-count {
  font-size: var(--t-fine);
  background: var(--line);
  border-radius: 50%;
  height: 18px;
  min-width: 18px;
  display: grid;
  place-items: center;
}
.header-actions {
  display: flex;
  align-items: center;
  gap: 15px;
}
.button {
  border-radius: 50px;
  min-height: 51px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 17px;
  padding: 14px 23px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.35;
  background: var(--accent);
  color: var(--button-text);
  border: 1px solid transparent;
  transition:
    background 0.2s,
    transform 0.2s;
  white-space: normal;
}
.button:hover {
  background: var(--accent-strong);
  transform: translateY(-2px);
}
.button .icon {
  width: 18px;
  height: 18px;
}
.button-small {
  min-height: 44px;
  padding: 10px 18px;
  font-size: var(--t-fine);
  gap: 10px;
}
.button-quiet {
  color: var(--ink);
  background: none;
  padding-inline: 8px;
}
.button-quiet:hover {
  color: var(--accent);
  background: none;
}
.button-outline {
  color: var(--accent);
  background: none;
  border: 1px solid var(--edge-button);
}
.button-outline:hover {
  color: var(--button-text);
  background: var(--accent);
}
.button-light {
  color: var(--accent);
  background: var(--paper);
}
.button-light:hover {
  color: var(--accent);
  /* `#fff` here was a white the dark appearance could not move: a pale pink label on a
     white button, 1.9:1, on the one control the palate banner offers. */
  background: var(--white);
}
/* 44px, which is the floor for anything a thumb has to find: the dialog's close button,
   the bottle stepper, and the header's two toggles. (The save heart on a card sets its
   own smaller size below — it is 30px on a phone, and growing it would take taps from
   the card it sits on.) */
.icon-button {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  flex-shrink: 0;
  transition:
    background 0.2s,
    color 0.2s;
}
.icon-button:hover {
  background: var(--surface);
}
/* The account button. The disc stays 36px, which is the proportion the header wants
   beside the two 44px toggles; the box a thumb has to find is 44px. */
.avatar {
  position: relative;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--surface);
  color: var(--accent);
  font-size: 12px;
}
.avatar:before {
  content: "";
  position: absolute;
  inset: -4px;
}
.avatar .icon {
  width: 16px;
  height: 16px;
}
.mobile-nav {
  display: none;
}
.hero {
  display: grid;
  grid-template-columns: 1.08fr 1fr;
  gap: 36px;
  align-items: center;
  padding-top: 59px;
  padding-bottom: 56px;
  min-height: 610px;
}
.hero-copy {
  padding-bottom: 10px;
  position: relative;
  z-index: 1;
}
.hero .eyebrow {
  margin-bottom: 28px;
  font-size: var(--t-fine);
  letter-spacing: 0.144em;
  display: flex;
  align-items: center;
  gap: 9px;
}
/* The sun sits in a 24px row, the height the eyebrow always had: the glyph it replaced set
   the row at 16px × 1.5, and the h1 and everything under it hang from that line. */
.tiny-sun {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: var(--orange);
}
.tiny-sun > .icon {
  width: 16px;
  height: 16px;
}
.hero h1 {
  font-size: clamp(55px, 6.25vw, 90px);
  line-height: 1.05;
  letter-spacing: -5px;
  white-space: nowrap;
}
.hero h1 em {
  color: var(--accent);
  letter-spacing: -3.8px;
  display: inline-block;
  line-height: 1.12;
}
.hero-description {
  margin-top: 25px;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.9;
  max-width: 380px;
}
.hero-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 28px;
}
/* The sentence box: Explore's search shell, in the hero's column and without its
   bottom margin, so the examples and the hint sit under it as one group. */
.hero-finder {
  margin: 24px 0 0;
  max-width: 430px;
}
.hero-finder .search-form,
.hero-finder {
  margin-bottom: 0;
}
.hero-finder-examples {
  margin-top: 10px;
}
.hero-finder-hint {
  margin-top: 9px;
  max-width: 400px;
}
.hero-footnote {
  display: flex;
  gap: 13px;
  align-items: center;
  margin-top: 43px;
  font-size: var(--t-fine);
  color: var(--muted);
}
.hero-footnote strong {
  font-weight: 400;
  color: var(--ink);
}
.small-glasses {
  display: flex;
  padding-left: 5px;
}
.small-glasses .icon {
  width: 25px;
  height: 25px;
  border: 1px solid var(--paper);
  border-radius: 50%;
  padding: 4px;
  margin-left: -5px;
  /* The three washes these glasses are drawn on were three literals — gold, rose and
     sage, the same three a category tile uses — so in the dark appearance they stayed
     pale while the wine-red mark on them turned pink: 1.3:1, an icon nobody could make
     out. They are the tokens they always meant. */
  background: var(--tint-3);
  color: var(--accent);
  transform: rotate(-9deg);
}
.small-glasses .icon:nth-child(2) {
  background: var(--tint-1);
  transform: rotate(8deg);
}
.small-glasses .icon:nth-child(3) {
  background: var(--tint-2);
}
.hero-visual {
  position: relative;
  height: 460px;
  min-width: 0;
}
.hero-visual > :is(img, svg) {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 52% center;
  border-radius: 130px 3px 3px 3px;
}
.photo-note {
  position: absolute;
  bottom: 28px;
  left: 25px;
  display: flex;
  gap: 26px;
  align-items: center;
  padding: 18px 20px;
  background: rgba(255, 252, 240, 0.86);
  backdrop-filter: blur(14px);
  color: #47362b;
  transform: rotate(-4deg);
  box-shadow: 0 4px 22px var(--shadow-note);
}
.photo-note > span {
  font-size: 19px;
  line-height: 1.25;
  letter-spacing: -0.5px;
}
.photo-note em {
  font-size: 24px;
}
.photo-note > .icon {
  width: 32px;
  height: 32px;
  stroke-width: 1;
}
.hero-stamp {
  position: absolute;
  top: -24px;
  right: -20px;
  height: 105px;
  width: 105px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 5px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--paper);
  transform: rotate(13deg);
  border: 5px double var(--stamp-edge);
}
.hero-stamp > span {
  font: 8px var(--mono);
  letter-spacing: 1.4px;
}
/* The seal's device: the large rosette, a slightly heavier line beside the double ring. */
.hero-stamp .mark {
  width: 43px;
  height: 43px;
  stroke-width: 3.25;
}
.photo-index {
  position: absolute;
  right: 0;
  bottom: -21px;
  font: var(--t-fine) var(--mono);
  letter-spacing: 0.138em;
  color: var(--muted);
}
.intent-strip {
  display: grid;
  grid-template-columns: 0.63fr 1.18fr 1.15fr 1.15fr;
  padding-block: 28px;
  border-block: 1px solid var(--line);
  gap: 25px;
}
.intent-strip > p {
  font-size: 16px;
  line-height: 1.3;
  letter-spacing: -0.3px;
}
.intent-strip > p em {
  font-size: 23px;
}
.intent-strip > :is(a, button) {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  padding-left: 23px;
  border-left: 1px solid var(--line);
  font-size: 12px;
}
.intent-strip > :is(a, button) > span:nth-child(2) {
  flex: 1;
}
.intent-strip > :is(a, button) small {
  display: block;
  font-size: var(--t-fine);
  color: var(--muted);
  margin-top: 6px;
  line-height: 1.5;
}
.intent-strip > :is(a, button) > .icon {
  width: 17px;
  height: 17px;
}
.intent-icon {
  color: var(--accent);
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
}
.intent-icon > .icon {
  width: 27px;
  height: 27px;
}
.intent-strip :is(a, button):hover .icon {
  transform: translate(2px, -2px);
}
/* Three of the four tiles start a journey rather than going anywhere, so they are
   buttons. The shared rule above dresses them; a button's centred text is the one thing
   it does not fix, and the pressed one is underlined as well as coloured. */
.intent-strip > button {
  text-align: left;
}
.intent-strip > button[aria-pressed="true"] > span:nth-child(2) {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.section-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 28px;
}
.section-heading .eyebrow {
  margin-bottom: 12px;
  font-size: var(--t-fine);
}
.section-heading h2 {
  font-size: 38px;
  letter-spacing: -1.3px;
  line-height: 1.15;
}
.section-heading h2 em {
  font-size: 44px;
  color: var(--accent);
}
/* An underlined phrase that is really a button — "Save these details", "Start over",
   "See all". The rule is the chip's: the underline stays where the design put it, and an
   invisible ::before takes the box a thumb has to find to 44px tall. */
.text-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: var(--t-fine);
  padding: 6px 0;
  border-bottom: 1px solid var(--edge-link);
  line-height: 1.5;
}
.text-link:before {
  content: "";
  position: absolute;
  inset: -8px 0;
}
.text-link .icon {
  width: 17px;
  height: 17px;
}
.text-link:hover {
  color: var(--accent);
}
.discovery-section {
  padding-top: 67px;
  padding-bottom: 65px;
}
.discovery-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Five criteria chips and "Start over" are more than one phone row: without this the
     row pushes the document wider than the screen. */
  flex-wrap: wrap;
  gap: 20px;
  margin-bottom: 27px;
}
.discovery-controls > .subtle {
  font-size: var(--t-fine);
  max-width: 260px;
  text-align: right;
}
/* The guided finder: one step at a time above the wines, and a second tier below them.
   The four containers it paints into carry nothing of their own, so an empty one takes up
   no space at all. */
.finder-panel {
  display: grid;
  gap: 14px;
  margin-bottom: 26px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--line);
}
.finder-panel h3,
.finder-also h3,
.finder-also h4,
.finder-kind-title {
  font: 27px/1.2 var(--serif);
  letter-spacing: -0.6px;
}
/* Wine's heading, when a dish is answered with beer as well: above wine's cards, as
   beer's is above its own in the section below (PR 19). */
#recommendations > .finder-kind-title {
  margin-bottom: 18px;
}
.finder-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
}
.finder-panel .chip,
.finder-criteria .chip {
  min-height: 44px;
  white-space: normal;
}
.finder-criteria .chip .icon {
  width: 13px;
  height: 13px;
}
.finder-status {
  display: grid;
  gap: 6px;
  margin-bottom: 22px;
}
.finder-also {
  display: grid;
  gap: 18px;
  margin-top: 44px;
  padding-top: 28px;
  border-top: 1px solid var(--line);
}
/* The grape field is one row of the panel's own grid, so it drops the search shell's
   bottom margin the way the hero's copy of it does. */
.finder-inline {
  margin-bottom: 0;
}
#finder-more:empty {
  display: none;
  margin: 0;
}
/* 8px between chips along a row, 12px between rows — because a chip's hit box is 6px
   taller than the pill at each end (`.chip:before` below) and 8px of air between two
   wrapped rows left 4px of every boundary claimed by both. The later chip hit-tests on
   top, so a thumb aimed at the last chip of a row could select the first chip of the next
   one. 12px is exactly the two pseudo-elements meeting, and no more: the rows sit 4px
   further apart than the design drew them, which is the visible half of this. */
.chips {
  display: flex;
  gap: 8px;
  row-gap: 12px;
  flex-wrap: wrap;
}
/*
 * A chip is drawn at 35px because that is the proportion the design wants beside a
 * heading — but 35px is not a target. The pill keeps its ink and its border exactly
 * where they are, and an invisible ::before extends what a thumb can hit to 45px,
 * vertically only, so a chip never steals a tap from whatever is beside it in the row.
 */
.chip {
  position: relative;
  display: inline-flex;
  gap: 7px;
  align-items: center;
  justify-content: center;
  min-height: 35px;
  padding: 9px 15px;
  border-radius: 30px;
  border: 1px solid var(--line);
  font-size: var(--t-fine);
  line-height: 1.3;
  transition: all 0.2s;
  white-space: nowrap;
}
/* The box a thumb has to find, which is not the box the ink is in: the pill keeps the
   34px (35px above 700px) the design gave it and this invisible rectangle takes the hit
   area to 44px. `inset` is measured against the chip's *padding* box, which its 1px
   border is outside of — so the number owed is (44 - height + 2 borders) / 2, and -5px
   left every chip in the app 2px short of the floor it was written to reach. */
.chip:before {
  content: "";
  position: absolute;
  inset: -6px 0;
}
.chip:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.chip.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--button-text);
}
.wine-dot {
  width: 7px;
  height: 7px;
  display: inline-block;
  border-radius: 50%;
  --style-dot: var(--dot-red, var(--muted));
  background: var(--style-dot);
  flex-shrink: 0;
}
.wine-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 24px;
}
.wine-card {
  min-width: 0;
}
.wine-art {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  --style-ground: var(--surface);
  background: var(--style-ground);
  height: 305px;
  border-radius: 3px;
}
/* The hairline ring behind a card's bottle: all of it the layer's (`--art-ring-*`). Wine's
   is the thin pale ellipse turned -30deg the card has always carried; a drink that draws
   none declares a transparent edge, no halo, and `--art-ring-forced: none`. */
.wine-art:after {
  content: "";
  position: absolute;
  inset: var(--art-ring-inset);
  width: var(--art-ring-width);
  height: var(--art-ring-height);
  border: var(--art-ring-edge);
  box-shadow: var(--art-ring-halo);
  border-radius: 50%;
  z-index: -1;
  transform: var(--art-ring-turn);
}
.wine-type {
  position: absolute;
  top: 17px;
  left: 15px;
  display: flex;
  align-items: center;
  gap: 6px;
  font: var(--t-fine) var(--mono);
  text-transform: uppercase;
  letter-spacing: 0.087em;
}
.save-button {
  position: absolute;
  top: 8px;
  right: 9px;
  z-index: 1;
  width: 34px;
  height: 34px;
  border: 1px solid #ffffff70;
  background: var(--glass);
  backdrop-filter: blur(8px);
}
.save-button .icon {
  width: 15px;
  height: 15px;
}
.save-button:hover {
  background: var(--white);
}
.is-saved .icon {
  fill: var(--accent);
  stroke: var(--accent);
}
.bottle-link {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 35px 15px 0;
}
.bottle {
  height: 100%;
  max-width: 100%;
  transition: transform 0.7s var(--ease);
}
.wine-art .bottle {
  height: 260px;
  transform: rotate(-8deg);
}
.wine-card:nth-child(even) .bottle {
  transform: rotate(8deg);
}
.wine-card:hover .bottle {
  transform: rotate(0) translateY(-5px);
}
.wine-card-info {
  padding-top: 17px;
}
.wine-card-info > .eyebrow {
  font-size: var(--t-fine);
  letter-spacing: 0.113em;
  color: var(--muted);
  min-height: 12px;
  line-height: 1.65;
  /* This line is the reason the bottle is in front of the reader — "Same Cabernet
     Sauvignon · Warm Mediterranean climate" — and it was clipped at one line with no
     title and no way to read the rest. Two lines, then the ellipsis. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
}
.wine-name {
  display: flex;
  align-items: baseline;
  text-align: left;
  justify-content: space-between;
  gap: 10px;
  font-family: var(--serif);
  font-size: 23px;
  font-weight: 400;
  line-height: 1.18;
  width: 100%;
  margin: 8px 0;
  padding: 0;
}
.wine-name .icon {
  width: 14px;
  height: 14px;
  align-self: flex-start;
  margin-top: 5px;
}
.wine-name:hover {
  color: var(--accent);
}
.wine-meta {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  color: var(--muted);
  font-size: var(--t-fine);
  line-height: 1.6;
}
.wine-meta .price {
  white-space: nowrap;
  color: var(--ink);
  font-size: var(--t-fine);
}
.price small {
  font-size: var(--t-fine);
  color: var(--muted);
}
.match-tag {
  position: absolute;
  bottom: 12px;
  left: 12px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: var(--glass);
  border-radius: 20px;
  padding: 6px 9px;
  font-size: var(--t-fine);
  color: var(--accent);
}
/* 12px, filled so it holds at fine-print size, the way .your-rating fills its star. */
.match-tag .mark-slot > .icon {
  width: 12px;
  height: 12px;
  fill: currentColor;
  stroke-width: 1;
}
.your-rating {
  font-size: var(--t-fine);
  color: var(--accent);
  margin-top: 10px;
  display: flex;
  align-items: center;
  gap: 5px;
}
.your-rating .icon {
  width: 12px;
  height: 12px;
  fill: currentColor;
}
.palate-banner {
  position: relative;
  background: var(--accent);
  color: var(--paper);
  margin-inline: auto;
  max-width: 1312px;
  padding: 42px 46px;
  display: grid;
  grid-template-columns: 150px 1fr auto;
  align-items: center;
  gap: 40px;
  border-radius: 3px;
  overflow: hidden;
}
.palate-mark .mark {
  width: 155px;
  height: 155px;
  color: var(--on-slab-flower);
}
.palate-banner .eyebrow {
  font-size: var(--t-fine);
  color: var(--on-slab-eyebrow);
}
.palate-banner h2 {
  font-size: 36px;
  line-height: 1.1;
  letter-spacing: -1px;
  margin: 13px 0;
}
.palate-banner h2 em {
  font-size: 43px;
}
.palate-banner p:not(.eyebrow) {
  font-size: var(--t-fine);
  color: var(--on-slab-copy);
  line-height: 1.7;
}
.banner-action {
  display: flex;
  flex-direction: column;
  gap: 15px;
  align-items: center;
}
.banner-action > span {
  font-size: var(--t-fine);
  color: var(--on-slab-note);
}
.journal {
  padding-top: 69px;
  padding-bottom: 74px;
}
.journal-aside {
  font-size: var(--t-fine);
  color: var(--muted);
}
.journal-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.journal-card {
  position: relative;
  min-height: 244px;
  background: var(--surface);
  padding: 25px;
  text-align: left;
  overflow: hidden;
  border-radius: 3px;
  transition: transform 0.3s;
}
/* The journal card is an <article>; this button is the whole card's click target so
   the heading inside stays a heading (extra-a11y-headings-and-block-content-inside-buttons). */
.journal-open {
  position: absolute;
  inset: 0;
  z-index: 2;
}
.journal-card:hover {
  transform: translateY(-4px);
}
.journal-card:nth-child(2) {
  background: var(--tint-1);
}
.journal-card:nth-child(3) {
  background: var(--tint-2);
}
.journal-number {
  font: var(--t-fine) var(--mono);
  letter-spacing: 0.15em;
  position: relative;
  z-index: 1;
}
.journal-card h3 {
  font-size: 29px;
  letter-spacing: -0.7px;
  line-height: 1.05;
  margin-top: 28px;
  position: relative;
  z-index: 1;
}
.journal-card h3 em {
  font-size: 36px;
}
.journal-card > span:last-of-type {
  display: flex;
  gap: 12px;
  align-items: center;
  font-size: var(--t-fine);
  margin-top: 23px;
  position: relative;
  z-index: 1;
}
.journal-card > span .icon {
  width: 17px;
  height: 17px;
}
.journal-drawing {
  position: absolute;
  right: 12px;
  bottom: 40px;
  opacity: var(--drawing-opacity);
  transform: rotate(14deg);
}
.journal-drawing > .icon {
  width: 100px;
  height: 130px;
  stroke-width: 0.5;
}
.pair-drawing {
  font-family: var(--serif);
  font-size: 170px;
  bottom: 0;
  right: -10px;
  line-height: 1;
}
.label-drawing {
  right: 0;
  transform: rotate(-16deg);
}
.site-footer {
  max-width: 1312px;
  margin: 0 auto;
  border-top: 1px solid var(--line);
  padding: 32px 0 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
}
.site-footer .wordmark {
  font-size: 26px;
}
.site-footer .brand-flower {
  font-size: 23px;
}
.site-footer p {
  font-size: 12px;
  color: var(--muted);
}
.site-footer p em {
  color: var(--ink);
  font-size: 17px;
}
.site-footer > span {
  display: flex;
  gap: 15px;
  align-items: center;
  font: var(--t-fine) var(--mono);
  letter-spacing: 0.125em;
}
/* The rosette is drawn at 24px (20 on a phone) in the 28px (21px) line the glyph it replaced
   set, so the motto's row, and the footer under it, keep their height. */
.site-footer .mark-slot {
  min-height: 28px;
  color: var(--accent);
}
.site-footer .mark-slot > .icon {
  width: 24px;
  height: 24px;
}
.inner-page {
  padding-top: 63px;
  padding-bottom: 85px;
  min-height: calc(100vh - 225px);
}
.page-heading {
  margin-bottom: 40px;
}
.page-heading .eyebrow {
  color: var(--muted);
  margin-bottom: 25px;
}
.page-heading h1 {
  font-size: 68px;
  letter-spacing: -3.2px;
  line-height: 1.02;
}
.page-heading h1 em {
  color: var(--accent);
  font-size: 74px;
}
.page-heading > p:last-child,
.page-heading > div > p:last-child {
  margin-top: 20px;
  color: var(--muted);
  font-size: 13px;
  max-width: 530px;
}
.heading-with-action {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 35px;
}
.search-form {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 12px 14px 12px 22px;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--white);
  margin-bottom: 30px;
}
.search-form > .icon {
  color: var(--accent);
}
.search-form input {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  border: 0;
  background: none;
  padding: 12px 0;
  color: var(--ink);
  outline-offset: 0;
}
.browse-tools {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}
.sort-control {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--t-fine);
  color: var(--muted);
  white-space: nowrap;
}
.sort-control select {
  background: none;
  border: 0;
  font-size: var(--t-fine);
  max-width: 130px;
  color: var(--ink);
  padding: 10px 0;
  /* A bare select is as tall as its own text; this is the sort control of a browse
     screen, tapped on a phone with one thumb. The label beside it does not move. */
  min-height: 44px;
}
.results-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 24px 0;
}
.results-meta > p {
  font-size: var(--t-fine);
  color: var(--muted);
}
.results-meta > .text-link {
  font-size: var(--t-fine);
  border: 0;
}
.results-meta > .text-link .icon {
  width: 13px;
  height: 13px;
}
.inner-page .wine-grid {
  row-gap: 37px;
}
.load-more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-top: 40px;
}
.load-more > span {
  font-size: var(--t-fine);
  color: var(--muted);
}
.empty-state {
  text-align: center;
  padding: 65px 30px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 3px;
}
.empty-state > .icon {
  width: 44px;
  height: 44px;
  stroke: var(--accent);
  stroke-width: 1;
  margin-bottom: 20px;
}
.empty-state h2 {
  font-family: var(--serif);
  font-size: 34px;
  line-height: 1.2;
}
.empty-state p {
  font-size: 13px;
  max-width: 440px;
  margin: 15px auto 23px;
  color: var(--muted);
}
.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 50px;
  gap: 20px;
  background: var(--tint-1);
  text-align: center;
  font-size: 13px;
}
.skeleton-card > div {
  height: 305px;
  background: var(--surface);
  border-radius: 3px;
}
.skeleton-card > span {
  display: block;
  background: var(--surface);
  height: 15px;
  margin-top: 15px;
  width: 80%;
}
.skeleton-card > span:last-child {
  width: 50%;
  height: 10px;
}
.skeleton-card {
  animation: breathe 1.8s ease-in-out infinite;
}
.collection-summary {
  display: flex;
  gap: 32px;
  align-items: center;
  padding: 25px 0;
  border-block: 1px solid var(--line);
  font-size: 12px;
  color: var(--muted);
}
.collection-summary strong {
  font-size: 28px;
  font-family: var(--serif);
  color: var(--accent);
  font-weight: 400;
  margin-right: 8px;
}
.collection-storage {
  margin-left: auto;
  font-size: var(--t-fine);
  display: flex;
  align-items: center;
  gap: 7px;
}
.collection-storage > .icon {
  width: 14px;
  height: 14px;
}
.inline-link {
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 0;
  color: var(--accent);
  font-size: inherit;
}
.collection-tabs {
  display: flex;
  gap: 25px;
  margin: 23px 0;
}
.text-tab {
  font-size: 12px;
  padding: 10px 0;
  color: var(--muted);
  border-bottom: 2px solid transparent;
}
.text-tab.active {
  color: var(--accent);
  border-color: var(--accent);
}
/* The switch between kinds of drink, at the top of Explore and My Cellar (core.js,
   `kindSwitch`). It is drawn only once a second kind is served, so nothing on a wine-only
   page uses these rules. It is a segmented row of links, one per kind. It is the frame's
   anatomy, not a drink's: every colour is a token, so each layer paints it. Each segment
   is 44px tall because it is a whole target, not a pill that needs a larger hit box. The
   current kind wears the accent, like an active chip. */
.kind-switch {
  display: inline-flex;
  margin-bottom: 26px;
  border: 1px solid var(--line);
  border-radius: 30px;
  padding: 3px;
  gap: 3px;
  background: var(--white);
}
.kind-switch > a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 88px;
  padding: 0 20px;
  border-radius: 30px;
  font-size: var(--t-small);
  color: var(--muted);
  transition: color 0.2s, background-color 0.2s;
}
.kind-switch > a:hover {
  color: var(--accent);
}
.kind-switch > a[aria-current] {
  background: var(--accent);
  color: var(--button-text);
}
.palate-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  margin-top: 50px;
}
.taste-profile {
  padding: 35px;
  background: var(--surface);
  border-radius: 3px;
}
.taste-profile h2 {
  font-size: 37px;
  letter-spacing: -1.3px;
  line-height: 1.2;
  margin: 26px 0 20px;
}
.taste-profile h2 em {
  color: var(--accent);
}
.taste-profile > p:not(.eyebrow) {
  font-size: 13px;
  color: var(--muted);
  max-width: 360px;
}
.palate-stats {
  display: flex;
  gap: 30px;
  border-block: 1px solid var(--line);
  padding: 25px 0;
  margin: 32px 0;
}
.palate-stats > div {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.palate-stats strong {
  font: 43px var(--serif);
  color: var(--accent);
}
.palate-stats span {
  font: var(--t-fine) var(--mono);
  letter-spacing: 0.087em;
}
.structure-panel {
  padding: 15px 0;
}
.structure-panel > .eyebrow {
  margin-bottom: 28px;
}
.structure-row {
  margin-bottom: 21px;
}
.structure-row > div:first-child {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 12px;
  margin-bottom: 11px;
}
.structure-row strong {
  font-weight: 400;
}
.structure-row > div:first-child > span {
  font-size: var(--t-fine);
  color: var(--muted);
}
.structure-track {
  height: 5px;
  background: var(--line);
  border-radius: 10px;
  overflow: hidden;
}
.structure-track > span {
  height: 100%;
  display: block;
  background: var(--accent);
  border-radius: 10px;
  transition: width 0.5s;
}
.structure-labels {
  display: flex;
  justify-content: space-between;
  font-size: var(--t-fine);
  color: var(--muted);
  margin-top: 7px;
}
.structure-panel > .fine-print {
  font-size: var(--t-fine);
  max-width: 400px;
  margin-top: 25px;
}
.palate-bottom {
  margin-top: 60px;
  border-block: 1px solid var(--line);
  padding-block: 28px;
  display: flex;
  gap: 25px;
  align-items: center;
}
/* Drawn at 60px but laid out at 50: the negative margins keep the heading's column where
   the old glyph (60px type, a 50px advance) put it. */
.palate-bottom > .mark {
  width: 60px;
  height: 60px;
  margin-inline: -5px;
  color: var(--accent);
  stroke-width: 2.75;
  flex: none;
}
.palate-bottom > div {
  flex: 1;
}
.palate-bottom h2 {
  font: 30px var(--serif);
}
.palate-bottom p {
  color: var(--muted);
  font-size: 12px;
  margin-top: 7px;
}
dialog {
  background: var(--paper);
  color: var(--ink);
  border: 1px solid #ffffff50;
  max-width: min(620px, calc(100vw - 32px));
  max-height: calc(100dvh - 64px);
  width: 100%;
  padding: 0;
  border-radius: 7px;
  box-shadow: 0 24px 120px var(--shadow-dialog);
  overflow: auto;
  overscroll-behavior: contain;
}
dialog[open] {
  animation: dialog-in 0.3s var(--ease);
}
dialog::backdrop {
  background: var(--backdrop);
  backdrop-filter: blur(6px);
}
body:has(dialog[open]) {
  overflow: hidden;
}
.dialog-close {
  position: absolute;
  right: 14px;
  top: 14px;
  background: var(--glass);
  z-index: 3;
}
.dialog-padding {
  padding: 48px;
}
.dialog-padding > .eyebrow {
  font-size: var(--t-fine);
  color: var(--muted);
  margin-bottom: 25px;
}
.dialog-padding h2 {
  font-size: 45px;
  line-height: 1.07;
  letter-spacing: -1.5px;
}
.dialog-padding h2 em {
  font-size: 49px;
  color: var(--accent);
}
.dialog-padding > p:not(.eyebrow) {
  font-size: 13px;
  color: var(--muted);
  margin-top: 20px;
}
.dialog-padding > .button {
  margin-top: 25px;
}
.dialog-padding .wine-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.dialog-padding form {
  margin-top: 25px;
}
.dialog-padding form label {
  display: block;
  font-size: 12px;
  margin-bottom: 9px;
}
input[type="email"],
input[type="url"],
.place-form input,
textarea {
  width: 100%;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 14px;
  color: var(--ink);
  font-size: 13px;
  line-height: 1.6;
}
textarea {
  resize: vertical;
  min-height: 105px;
}
input::placeholder,
textarea::placeholder {
  color: var(--muted);
}
.dialog-padding form > .button {
  margin-top: 18px;
  width: 100%;
}
.dialog-padding form > p {
  margin-top: 15px;
  font-size: 12px;
  color: var(--muted);
}
.dialog-padding .fine-print {
  font-size: var(--t-fine);
}
.wine-dialog {
  max-width: min(950px, calc(100vw - 40px));
}
.detail-layout {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
}
.detail-art {
  padding: 40px 25px;
  --style-ground: var(--tint-1, var(--surface));
  background: var(--style-ground);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: sticky;
  top: 0;
  align-self: start;
  height: 690px;
  max-height: calc(100dvh - 66px);
}
.detail-art .bottle {
  height: 430px;
  width: 205px;
  transform: rotate(-6deg);
  flex: 1;
  min-height: 180px;
  margin: 28px 0;
}
.detail-art > .fine-print {
  font-size: var(--t-fine);
}
.detail-copy {
  padding: 50px 36px 35px;
  min-width: 0;
}
.detail-copy > .eyebrow {
  color: var(--muted);
  font-size: var(--t-fine);
}
.detail-copy h2 {
  font-family: var(--serif);
  font-size: 43px;
  line-height: 1.05;
  letter-spacing: -1px;
  margin: 19px 0 13px;
}
.detail-grape {
  font-size: 12px;
  color: var(--muted);
}
/*
 * What the bottle is made of, when a shop has published the proportions. A figure line,
 * so it is set in the mono face the app uses for every other number a shop gave us, and
 * it sits directly under the varietal it is the detail of.
 */
.detail-blend {
  margin: 5px 0 0;
  font: var(--t-fine)/1.5 var(--mono);
  color: var(--muted);
}
.detail-tags {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  margin-top: 22px;
}
.detail-tags > span {
  font-size: var(--t-fine);
  border: 1px solid var(--line);
  padding: 6px 9px;
  border-radius: 20px;
}
.detail-intro {
  font-size: 12px;
  color: var(--muted);
  margin-top: 20px;
}
.pairing-note {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 22px 0;
  padding: 17px 0;
  border-block: 1px solid var(--line);
}
.pairing-note > .icon {
  color: var(--accent);
}
.pairing-note strong {
  font-size: var(--t-fine);
  font-weight: 500;
}
.pairing-note p {
  font-size: var(--t-fine);
  color: var(--muted);
  margin-top: 5px;
}
.detail-save {
  width: 100%;
  margin-top: 24px;
}
.rating-block {
  margin: 27px 0 23px;
}
.rating-block > label {
  font-size: 12px;
}
.rating-stars {
  display: flex;
  align-items: center;
  margin-top: 9px;
  /* 2px between the stars; 8px between *lines*, which is only ever the readout once it has
     wrapped under them. Five 44px stars and "3 / 5 · your rating" stop fitting on one line
     somewhere around 410px, and below that the caption used to land hard against the star
     row with no air at all — it read as something that had fallen off the end rather than
     as a line of its own. `row-gap` is the whole fix because it is worth nothing until the
     row wraps: the design keeps its inline caption wherever there is room for one, and the
     phone gets a deliberate second line, aligned under the stars, without a new
     breakpoint deciding on the layout's behalf where "a phone" begins. */
  gap: 8px 2px;
  flex-wrap: wrap;
}
/* The control most likely to be tapped in a dim room with one hand. The star inside is
   still 25px and still sits where it did — only the box around it grows to the 44px
   floor, and the row's 2px gap keeps five of them inside a 320px screen. */
.star-button {
  padding: 7px 5px;
  min-height: 44px;
  min-width: 44px;
  /* The unchosen star. It was #b7aa95, a pale beige that sat at 1.9:1 on the dialog it is
     drawn in — a control whose whole job is to show you how many of five are filled, with
     the empty ones invisible. The audit proposed another literal; --muted is the token
     that already means "quiet, and still legible in this appearance", it is measured on
     every ground in all three palettes, and unlike a literal it cannot be right in the
     morning and wrong at night. */
  color: var(--muted);
}
.star-button .icon {
  width: 25px;
  height: 25px;
  stroke-width: 1;
}
.star-button.selected,
.star-button:hover {
  color: var(--accent);
}
.star-button.selected .icon {
  fill: var(--accent);
}
.rating-stars > span {
  font-size: var(--t-fine);
  color: var(--muted);
  margin-left: 9px;
}
.notes-label {
  display: block;
  font-size: var(--t-fine);
  margin-bottom: 10px;
}
/* 10px, not 8. `.text-link:before` reaches exactly 8px above the link to make the box a
   thumb has to find 44px tall, and the notes field above it ended exactly 8px away — so
   the top edge of the link's hit area and the bottom edge of the textarea were the same
   line, and a tap meant for the last line of a note could save it instead. The pseudo
   cannot shrink without dropping under the floor (the link's own box is 29px), so the air
   grows instead: 2px of clearance, and 2px is all the design gives up. */
.notes-save {
  margin-top: 10px;
  font-size: var(--t-fine);
}
.similar-link {
  display: flex;
  margin-top: 26px;
  width: max-content;
  font-size: 12px;
}
.scan-mode {
  display: flex;
  gap: 9px;
  margin: 24px 0;
}
.upload-zone {
  position: relative;
  border: 1px dashed var(--edge-drop);
  background: var(--surface);
  border-radius: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  text-align: center;
  padding: 28px 20px;
  gap: 10px;
  cursor: pointer;
}
.upload-zone > .icon {
  width: 38px;
  height: 38px;
  color: var(--accent);
  margin-bottom: 5px;
}
.upload-zone strong {
  font-size: 13px;
  font-weight: 500;
}
.upload-zone > span {
  font-size: var(--t-fine);
  color: var(--muted);
}
.upload-zone input {
  position: absolute;
  inset: 0;
  opacity: 0;
  width: 100%;
  height: 100%;
  cursor: pointer;
}
.upload-zone:focus-within {
  outline: 3px solid var(--orange);
  outline-offset: 4px;
}
.upload-zone .upload-cta {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: var(--t-fine);
  color: var(--accent);
  border-bottom: 1px solid var(--edge-drop-link);
  padding-bottom: 5px;
  margin-top: 5px;
}
.upload-cta .icon {
  width: 15px;
  height: 15px;
}
#scan-progress {
  font-size: var(--t-fine);
  color: var(--accent);
  line-height: 1.7;
  margin-top: 15px;
}
.or-divider {
  margin: 24px 0;
  display: flex;
  align-items: center;
  gap: 10px;
  font: var(--t-fine) var(--mono);
  letter-spacing: 0.125em;
  color: var(--muted);
}
.or-divider:before,
.or-divider:after {
  content: "";
  height: 1px;
  background: var(--line);
  flex: 1;
}
/*
 * The three ways into a wine list that a bottle label has no use for: the file upload, the
 * address of the page, and the PDF links found on it. Hidden off the dialog's own
 * `data-scan-mode` rather than by a class the JS toggles, so the mode has one source of
 * truth and label mode looks exactly as it did before any of this existed.
 */
.list-only {
  display: grid;
  gap: 18px;
  margin-top: 18px;
}
dialog[data-scan-mode="list"] .label-only,
dialog[data-scan-mode="label"] .list-only {
  display: none;
}
/*
 * A barcode is not words, so barcode mode hides everything that reads them — the photo
 * that goes to the OCR, both modes' own ways in, and the words box — and shows its own
 * camera, picture and number field instead. Off the same attribute, for the same reason.
 */
.barcode-only {
  display: none;
}
dialog[data-scan-mode="barcode"] .barcode-only {
  display: grid;
  gap: 18px;
}
dialog[data-scan-mode="barcode"] .words-only,
dialog[data-scan-mode="barcode"] .label-only,
dialog[data-scan-mode="barcode"] .list-only {
  display: none;
}
.barcode-only .or-divider {
  margin: 6px 0;
}
.barcode-only .fine-print {
  margin-top: 9px;
}
/* `.dialog-padding form` opens with 25px of air; inside `.list-only` the grid gap is it. */
.dialog-padding .scan-url {
  margin-top: 0;
}
.scan-url label {
  display: block;
  font-size: 12px;
  margin-bottom: 9px;
}
.scan-url-row {
  display: flex;
  gap: 10px;
  align-items: stretch;
}
.scan-url-row input {
  flex: 1;
  min-width: 0;
}
.scan-url-row .button {
  white-space: nowrap;
}
/*
 * An address and a button do not share a phone's width: below this the field is unusably
 * short and the button's label wraps. The dialog's own breakpoints are 700 and 380, and
 * neither is where this row gives up — it is the two children, not the dialog.
 */
@media (max-width: 480px) {
  .scan-url-row {
    flex-direction: column;
  }
  .scan-url-row .button {
    width: 100%;
  }
}
.scan-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.scan-links:empty {
  display: none;
}
.scan-links-note {
  flex: 0 0 100%;
  font-size: var(--t-fine);
  color: var(--muted);
}
.scan-summary,
.scan-ambiguous,
.scan-unmatched {
  font-size: 12px;
  color: var(--muted);
}
#scan-results > .scan-ambiguous {
  margin: 18px 0 12px;
}
#scan-results > .scan-unmatched {
  margin: 22px 0 0;
}
#scan-results h4 {
  font: 20px var(--serif);
  margin-top: 22px;
}
#scan-results {
  margin-top: 28px;
}
#scan-results > h3 {
  font: 30px var(--serif);
}
#scan-results > p {
  font-size: 12px;
  color: var(--muted);
  margin: 10px 0 22px;
}
.scan-modal {
  max-width: min(700px, calc(100vw - 32px));
}
.form-error {
  color: var(--accent) !important;
}
.wide-dialog {
  max-width: min(1080px, calc(100vw - 32px));
}
.wide-dialog .wine-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: 28px;
}
.wide-dialog .wine-art {
  height: 245px;
}
.wide-dialog .bottle {
  height: 220px;
}
#similar-results > p {
  font-size: 12px;
  color: var(--muted);
  margin-top: 20px;
}
.guide .guide-intro {
  font-size: 15px;
}
.guide section {
  display: flex;
  gap: 20px;
  margin-top: 28px;
  padding-top: 22px;
  border-top: 1px solid var(--line);
}
.guide section > span {
  font: 12px var(--mono);
  color: var(--accent);
  padding-top: 3px;
}
.guide h3 {
  font: 25px var(--serif);
  margin-bottom: 8px;
}
.guide section p {
  font-size: 12px;
  color: var(--muted);
}
.toast {
  position: fixed;
  bottom: 30px;
  left: 50%;
  transform: translate(-50%, 20px);
  background: var(--ink);
  color: var(--paper);
  border-radius: 8px;
  max-width: min(480px, 90vw);
  padding: 15px 23px;
  font-size: 12px;
  line-height: 1.6;
  text-align: center;
  box-shadow: 0 5px 30px var(--shadow-toast);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 0.25s,
    transform 0.25s;
  z-index: 20;
}
.toast.visible {
  opacity: 1;
  transform: translate(-50%, 0);
}
/*
 * <main> takes focus programmatically on every navigation so a screen reader starts at
 * the new screen. That move is silent — the reader did not ask for it and a ring around
 * the whole page would be noise. A reader who *did* ask, by taking the skip link, gets
 * one: :focus-visible only matches when the focus came from the keyboard.
 */
#main:focus {
  outline: none;
}
#main:focus-visible {
  outline: 3px solid var(--orange);
  outline-offset: -3px;
}
.hero-copy,
.hero-visual,
.page-heading {
  animation: rise-in 0.8s var(--ease) both;
}
.hero-visual {
  animation-delay: 0.1s;
}
@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes dialog-in {
  from {
    opacity: 0;
    transform: translateY(15px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
@keyframes breathe {
  50% {
    opacity: 0.5;
  }
}
@media (min-width: 1441px) {
  .palate-banner,
  .site-footer {
    max-width: 1312px;
  }
  .hero h1 {
    font-size: 90px;
  }
}
@media (max-width: 1200px) {
  .page-width {
    padding-inline: 40px;
  }
  .site-header {
    padding-inline: 40px;
    gap: 20px;
  }
  .desktop-nav {
    gap: 20px;
  }
  .hero {
    gap: 25px;
    min-height: 560px;
  }
  .hero h1 {
    font-size: clamp(55px, 6.3vw, 77px);
    letter-spacing: -3.7px;
  }
  .hero h1 em {
    letter-spacing: -3px;
  }
  .hero-visual {
    height: 410px;
  }
  .hero-actions {
    gap: 7px;
  }
  .hero-actions .button {
    padding-inline: 17px;
    font-size: var(--t-fine);
    gap: 10px;
  }
  .hero-actions .button-quiet {
    padding-inline: 4px;
  }
  .hero-footnote {
    font-size: var(--t-fine);
  }
  .intent-strip {
    gap: 16px;
  }
  .intent-strip > :is(a, button) {
    padding-left: 14px;
    gap: 7px;
  }
  .intent-strip > :is(a, button) small {
    font-size: var(--t-fine);
  }
  .intent-strip > :is(a, button) > span:nth-child(2) {
    font-size: var(--t-fine);
  }
  .intent-icon {
    width: 28px;
  }
  .intent-strip > :is(a, button) > .icon {
    width: 14px;
  }
  .wine-grid {
    gap: 19px;
  }
  .wine-art {
    height: 280px;
  }
  .wine-art .bottle {
    height: 235px;
  }
  .wine-name {
    font-size: 22px;
  }
  .palate-banner {
    margin-inline: 40px;
    padding: 38px;
    grid-template-columns: 100px 1fr auto;
    gap: 25px;
  }
  .palate-mark .mark {
    width: 115px;
    height: 115px;
  }
  .palate-banner h2 {
    font-size: 31px;
  }
  .palate-banner h2 em {
    font-size: 38px;
  }
  .banner-action .button {
    font-size: var(--t-fine);
    padding-inline: 18px;
    gap: 10px;
  }
  .site-footer {
    margin-inline: 40px;
  }
  .journal-card {
    padding: 22px;
  }
  .journal-card h3 {
    font-size: 26px;
  }
  .journal-card h3 em {
    font-size: 33px;
  }
  /* The frame dims the layer's drawing where the card narrows and the drawing crowds the
     title: 5/7 and 3/7 of the token, the ratios the frame's old literals (0.25 and 0.15
     against 0.35) held. A drink sets the ink once and every width follows it. */
  .journal-drawing {
    right: -10px;
    opacity: calc(var(--drawing-opacity) * 5 / 7);
  }
  .discovery-controls > .subtle {
    max-width: 200px;
    font-size: var(--t-fine);
  }
  .chip {
    padding-inline: 12px;
  }
  .header-actions {
    gap: 9px;
  }
}
@media (max-width: 960px) {
  .desktop-nav {
    gap: 18px;
    font-size: var(--t-fine);
  }
  .header-scan {
    display: none;
  }
  .site-header {
    height: 86px;
  }
  .hero {
    padding-top: 47px;
    padding-bottom: 43px;
    min-height: 490px;
    gap: 18px;
  }
  .hero h1 {
    font-size: clamp(44px, 6.3vw, 65px);
    letter-spacing: -3px;
  }
  .hero h1 em {
    letter-spacing: -2.7px;
  }
  .hero .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.129em;
    gap: 5px;
    margin-bottom: 20px;
  }
  .hero-description {
    font-size: var(--t-fine);
    margin-top: 18px;
  }
  .hero-visual {
    height: 355px;
  }
  .hero-visual > :is(img, svg) {
    border-top-left-radius: 90px;
  }
  .hero-actions {
    flex-wrap: wrap;
    margin-top: 20px;
    gap: 7px;
  }
  .hero-actions .button {
    min-height: 44px;
    font-size: var(--t-fine);
    padding-inline: 15px;
  }
  .hero-actions .button-quiet {
    min-height: 33px;
    padding-inline: 5px;
  }
  .hero-footnote {
    margin-top: 23px;
    max-width: 285px;
    line-height: 1.5;
  }
  .hero-stamp {
    width: 82px;
    height: 82px;
    top: -19px;
    right: -13px;
    gap: 3px;
    border-width: 4px;
  }
  .hero-stamp > span {
    font-size: 6px;
  }
  .hero-stamp .mark {
    width: 34px;
    height: 34px;
  }
  .photo-note {
    bottom: 22px;
    left: 17px;
    padding: 13px 15px;
    gap: 17px;
  }
  .photo-note > span {
    font-size: 16px;
  }
  .photo-note em {
    font-size: 21px;
  }
  .intent-strip {
    grid-template-columns: repeat(3, 1fr);
    padding-block: 23px;
    gap: 15px;
  }
  .intent-strip > p {
    grid-column: 1/-1;
    display: flex;
    gap: 5px;
    align-items: baseline;
    font-size: 15px;
  }
  .intent-strip > p br {
    display: none;
  }
  .intent-strip > p em {
    font-size: 20px;
  }
  .intent-strip > :nth-child(2) {
    border: 0;
    padding-left: 0;
  }
  .intent-strip > :is(a, button) small {
    font-size: var(--t-fine);
  }
  .intent-strip > :is(a, button) {
    padding-left: 12px;
  }
  .section-heading h2 {
    font-size: 33px;
  }
  .section-heading h2 em {
    font-size: 39px;
  }
  .wine-grid {
    gap: 18px;
  }
  .wine-art {
    height: 230px;
  }
  .wine-art .bottle {
    height: 205px;
  }
  .wine-name {
    font-size: 20px;
  }
  .wine-type {
    font-size: var(--t-fine);
    left: 10px;
    top: 15px;
  }
  .wine-card-info > .eyebrow {
    font-size: var(--t-fine);
  }
  .wine-meta {
    flex-wrap: wrap;
    gap: 3px;
    font-size: var(--t-fine);
  }
  .save-button {
    width: 30px;
    height: 30px;
    top: 8px;
    right: 6px;
  }
  .save-button .icon {
    width: 13px;
    height: 13px;
  }
  .discovery-controls {
    align-items: flex-start;
    flex-direction: column;
    gap: 13px;
  }
  .discovery-controls > .subtle {
    max-width: none;
    text-align: left;
  }
  .palate-banner {
    grid-template-columns: 80px 1fr;
    gap: 25px;
    padding: 32px;
  }
  .palate-mark .mark {
    width: 90px;
    height: 90px;
  }
  .banner-action {
    grid-column: 2;
    align-items: flex-start;
    margin-top: 0;
    gap: 10px;
  }
  .palate-banner h2 {
    font-size: 33px;
  }
  .journal-grid {
    gap: 16px;
  }
  .journal-card {
    padding: 20px;
    min-height: 230px;
  }
  .journal-card h3 {
    font-size: 25px;
  }
  .journal-card h3 em {
    font-size: 31px;
  }
  .journal-card > span:last-of-type {
    font-size: var(--t-fine);
    gap: 7px;
  }
  .journal-number {
    font-size: var(--t-fine);
  }
  .journal-drawing {
    opacity: calc(var(--drawing-opacity) * 3 / 7);
  }
  .browse-tools {
    align-items: flex-start;
    flex-direction: column;
    gap: 10px;
  }
  .page-heading h1 {
    font-size: 59px;
  }
  .page-heading h1 em {
    font-size: 65px;
  }
  .palate-layout {
    gap: 30px;
  }
  .taste-profile {
    padding: 27px;
  }
  .taste-profile h2 {
    font-size: 32px;
  }
  .palate-stats {
    gap: 22px;
  }
  .palate-stats span {
    font-size: var(--t-fine);
  }
  .palate-bottom h2 {
    font-size: 26px;
  }
  .palate-bottom .button {
    font-size: var(--t-fine);
  }
  .collection-summary {
    gap: 24px;
  }
  .collection-storage {
    font-size: var(--t-fine);
    max-width: 210px;
    flex-wrap: wrap;
  }
  .wide-dialog .wine-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 700px) {
  .page-width {
    padding-inline: 24px;
  }
  .site-header {
    padding-inline: 24px;
    height: 78px;
    border-bottom: 1px solid var(--line);
  }
  .wordmark {
    font-size: 31px;
  }
  .brand-flower {
    font-size: 27px;
  }
  .desktop-nav {
    display: none;
  }
  .header-actions {
    gap: 8px;
  }
  .header-scan {
    display: inline-flex;
    font-size: var(--t-fine);
    padding-inline: 13px;
    /* 37px in a 78px header: the phone's one visible call to action, and the only
       control in it that was under the floor. */
    min-height: 44px;
    gap: 7px;
  }
  .header-scan .icon {
    width: 15px;
    height: 15px;
  }
  .search-toggle {
    display: none;
  }
  .avatar {
    width: 32px;
    height: 32px;
  }
  .avatar:before {
    inset: -6px;
  }
  .hero {
    grid-template-columns: 1fr;
    gap: 40px;
    padding-top: 39px;
    padding-bottom: 47px;
  }
  .hero-copy {
    padding: 0;
  }
  .hero .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.125em;
    margin-bottom: 20px;
  }
  .hero h1 {
    font-size: clamp(47px, 10.3vw, 72px);
    letter-spacing: -3px;
    line-height: 1.02;
  }
  .hero h1 em {
    font-size: 1.055em;
    letter-spacing: -2.5px;
    line-height: 1.15;
  }
  .hero-description {
    font-size: 12px;
    line-height: 1.8;
    margin-top: 18px;
    max-width: 350px;
  }
  .hero-actions {
    flex-wrap: nowrap;
    gap: 12px;
    margin-top: 23px;
  }
  .hero-actions .button {
    font-size: var(--t-fine);
    min-height: 46px;
    padding: 13px 16px;
    gap: 12px;
  }
  .hero-actions .button-quiet {
    padding-inline: 0;
    gap: 7px;
  }
  .hero-actions .button .icon {
    width: 16px;
    height: 16px;
  }
  .hero-footnote {
    margin-top: 23px;
    font-size: var(--t-fine);
    max-width: none;
  }
  .hero-visual {
    height: 340px;
    max-width: 100%;
  }
  .hero-visual > :is(img, svg) {
    border-top-left-radius: 100px;
    object-position: center 53%;
  }
  .hero-stamp {
    right: -6px;
    top: -17px;
    width: 87px;
    height: 87px;
  }
  .hero-stamp > span {
    font-size: 7px;
  }
  .hero-stamp .mark {
    width: 37px;
    height: 37px;
  }
  .photo-note {
    left: 20px;
    bottom: 25px;
    gap: 24px;
    padding: 16px 19px;
  }
  .photo-note > span {
    font-size: 20px;
  }
  .photo-note em {
    font-size: 25px;
  }
  .photo-index {
    font-size: var(--t-fine);
    bottom: -20px;
  }
  .intent-strip {
    grid-template-columns: 1fr;
    padding-block: 24px;
    gap: 0;
  }
  .intent-strip > p {
    font-size: 17px;
    gap: 5px;
    margin-bottom: 17px;
  }
  .intent-strip > p em {
    font-size: 24px;
  }
  .intent-strip > :is(a, button) {
    border-left: 0;
    padding: 17px 0;
    gap: 14px;
    align-items: center;
    border-bottom: 1px solid var(--line);
  }
  .intent-strip > :last-child {
    border-bottom: 0;
    padding-bottom: 4px;
  }
  .intent-strip > :is(a, button) > span:nth-child(2) {
    font-size: 12px;
  }
  .intent-strip > :is(a, button) small {
    font-size: var(--t-fine);
    margin-top: 4px;
  }
  .intent-strip > :is(a, button) > .icon {
    width: 18px;
    height: 18px;
  }
  .intent-icon {
    width: 32px;
  }
  .intent-icon .icon {
    width: 25px;
    height: 25px;
  }
  .discovery-section {
    padding-top: 43px;
    padding-bottom: 44px;
  }
  .section-heading {
    gap: 15px;
    align-items: flex-start;
    margin-bottom: 24px;
  }
  .section-heading h2 {
    font-size: 30px;
    letter-spacing: -1px;
  }
  .section-heading h2 em {
    font-size: 35px;
  }
  .section-heading .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.143em;
    margin-bottom: 10px;
  }
  .section-heading > .text-link {
    font-size: var(--t-fine);
    gap: 7px;
    white-space: nowrap;
    margin-top: 22px;
  }
  .section-heading > .text-link .icon {
    width: 14px;
    height: 14px;
  }
  .discovery-section .section-heading {
    flex-direction: column;
    gap: 10px;
  }
  .discovery-section .section-heading > .text-link {
    margin-top: 0;
  }
  .discovery-controls {
    gap: 13px;
    margin-bottom: 21px;
  }
  .finder-panel h3,
  .finder-also h3,
  .finder-also h4,
  .finder-kind-title {
    font-size: 22px;
  }
  /* Tighter along the row on a phone, and the same 12px between rows: the pill loses a
     pixel of height here (34px) but the hit box is still the pill plus 6px at each end. */
  .chips {
    gap: 6px;
    row-gap: 12px;
    flex-wrap: wrap;
  }
  .chip {
    font-size: var(--t-fine);
    min-height: 34px;
    padding: 8px 12px;
  }
  .wine-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 27px 15px;
  }
  .wine-art {
    height: 245px;
  }
  .wine-art .bottle {
    height: 217px;
  }
  .wine-name {
    font-size: 22px;
    line-height: 1.12;
    gap: 6px;
    margin-top: 7px;
  }
  .wine-name .icon {
    width: 12px;
    height: 12px;
  }
  .wine-card-info {
    padding-top: 13px;
  }
  .wine-card-info > .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.086em;
  }
  .wine-meta {
    font-size: var(--t-fine);
    line-height: 1.5;
    gap: 5px;
  }
  .wine-type {
    font-size: var(--t-fine);
    letter-spacing: 0.086em;
    top: 14px;
  }
  .wine-dot {
    width: 6px;
    height: 6px;
  }
  .save-button {
    width: 32px;
    height: 32px;
    right: 7px;
    top: 7px;
  }
  .save-button .icon {
    width: 14px;
    height: 14px;
  }
  .bottle-link {
    padding-inline: 5px;
  }
  .wine-meta .price {
    font-size: var(--t-fine);
  }
  .match-tag {
    bottom: 10px;
    left: 10px;
    font-size: var(--t-fine);
  }
  .palate-banner {
    margin-inline: 24px;
    padding: 30px 27px;
    grid-template-columns: 1fr;
    gap: 19px;
  }
  .palate-mark {
    position: absolute;
    right: -25px;
    top: 20px;
    opacity: 0.25;
    transform: rotate(20deg);
  }
  .palate-mark .mark {
    width: 145px;
    height: 145px;
  }
  .palate-banner > div:not(.palate-mark) {
    position: relative;
    z-index: 1;
  }
  .palate-banner .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.143em;
  }
  .palate-banner h2 {
    font-size: 30px;
    line-height: 1.1;
    margin: 18px 0;
  }
  .palate-banner h2 em {
    font-size: 38px;
  }
  .palate-banner p:not(.eyebrow) {
    font-size: var(--t-fine);
  }
  .banner-action {
    grid-column: auto;
    gap: 12px;
  }
  .banner-action .button {
    font-size: var(--t-fine);
    padding-inline: 18px;
  }
  .banner-action > span {
    font-size: var(--t-fine);
    margin-left: 10px;
  }
  .journal {
    padding-top: 43px;
    padding-bottom: 45px;
  }
  .journal-aside {
    display: none;
  }
  .journal-grid {
    grid-template-columns: 1fr;
    gap: 13px;
  }
  .journal-card {
    padding: 24px;
    min-height: 211px;
  }
  .journal-number {
    font-size: var(--t-fine);
  }
  .journal-card h3 {
    font-size: 29px;
    margin-top: 21px;
  }
  .journal-card h3 em {
    font-size: 37px;
  }
  .journal-card > span:last-of-type {
    font-size: var(--t-fine);
    margin-top: 18px;
  }
  /* A phone card is tall enough to draw a little heavier than the layer's ink: 38/35 of the
     token, the ratio the frame's old literal (0.38 against 0.35) held. */
  .journal-drawing {
    opacity: calc(var(--drawing-opacity) * 38 / 35);
    right: 28px;
    bottom: 30px;
  }
  .journal-drawing > .icon {
    width: 100px;
    height: 120px;
  }
  .pair-drawing {
    right: 20px;
    bottom: 0;
    font-size: 175px;
    opacity: 0.25;
  }
  .label-drawing {
    right: 19px;
    opacity: 0.3;
  }
  .site-footer {
    margin-inline: 24px;
    padding-top: 26px;
    padding-bottom: 115px;
    gap: 14px;
    flex-wrap: wrap;
  }
  .site-footer .wordmark {
    font-size: 25px;
  }
  .site-footer p {
    font-size: var(--t-fine);
    text-align: right;
    flex: 1;
  }
  .site-footer p em {
    font-size: 14px;
    display: block;
  }
  .site-footer > span {
    width: 100%;
    font-size: var(--t-fine);
    justify-content: space-between;
    border-top: 1px solid var(--line);
    padding-top: 15px;
    margin-top: 5px;
  }
  .site-footer .mark-slot {
    min-height: 21px;
  }
  .site-footer .mark-slot > .icon {
    width: 20px;
    height: 20px;
  }
  .mobile-nav {
    position: fixed;
    z-index: 5;
    bottom: 0;
    left: 0;
    right: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    border-top: 1px solid var(--line);
    background: var(--glass);
    backdrop-filter: blur(18px);
    padding: 10px 12px calc(9px + env(safe-area-inset-bottom));
    box-shadow: 0 -5px 20px var(--shadow-nav);
  }
  .mobile-nav > a {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    color: var(--muted);
    font-size: var(--t-fine);
    min-height: 44px;
    justify-content: center;
    border-radius: 5px;
  }
  .mobile-nav > a .icon {
    width: 19px;
    height: 19px;
    stroke-width: 1.4;
  }
  .mobile-nav > a[aria-current] {
    color: var(--accent);
    background: var(--surface);
  }
  .mobile-nav > a[aria-current] .icon {
    stroke-width: 2;
  }
  .inner-page {
    padding-top: 39px;
    padding-bottom: 45px;
    min-height: 65vh;
  }
  .page-heading {
    margin-bottom: 30px;
  }
  .page-heading .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.171em;
    margin-bottom: 20px;
  }
  .page-heading h1 {
    font-size: 47px;
    letter-spacing: -2.3px;
  }
  .page-heading h1 em {
    font-size: 52px;
  }
  .page-heading > p:last-child,
  .page-heading > div > p:last-child {
    font-size: 12px;
    margin-top: 18px;
  }
  .heading-with-action {
    flex-direction: column;
    align-items: flex-start;
    gap: 22px;
  }
  .heading-with-action > .button {
    font-size: var(--t-fine);
    min-height: 43px;
  }
  .search-form {
    gap: 12px;
    padding: 10px 12px;
    margin-bottom: 20px;
  }
  .search-form input {
    font-size: 12px;
    padding: 9px 0;
  }
  .search-form > .icon {
    width: 17px;
    height: 17px;
  }
  .search-form .button {
    padding: 10px;
    min-height: 36px;
    font-size: var(--t-fine);
  }
  .search-form .button .icon {
    display: none;
  }
  .browse-tools {
    gap: 12px;
  }
  .sort-control {
    font-size: var(--t-fine);
  }
  .results-meta {
    margin: 15px 0 22px;
    gap: 15px;
  }
  .results-meta > p {
    font-size: var(--t-fine);
  }
  .results-meta .text-link {
    font-size: var(--t-fine);
  }
  .inner-page .wine-grid {
    row-gap: 29px;
  }
  .empty-state {
    padding: 42px 22px;
  }
  .empty-state h2 {
    font-size: 30px;
  }
  .empty-state p {
    font-size: 12px;
  }
  .collection-summary {
    flex-wrap: wrap;
    gap: 15px 27px;
    padding-block: 20px;
  }
  .collection-summary > span {
    font-size: var(--t-fine);
  }
  .collection-summary strong {
    font-size: 26px;
  }
  .collection-summary .collection-storage {
    margin-left: 0;
    max-width: none;
    width: 100%;
    font-size: var(--t-fine);
    gap: 5px;
  }
  .collection-tabs {
    gap: 22px;
    margin: 18px 0;
  }
  .text-tab {
    font-size: var(--t-fine);
  }
  .palate-layout {
    grid-template-columns: 1fr;
    gap: 24px;
    margin-top: 28px;
  }
  .taste-profile {
    padding: 27px;
  }
  .taste-profile .eyebrow {
    font-size: var(--t-fine);
  }
  .taste-profile h2 {
    font-size: 35px;
    margin-top: 22px;
  }
  .palate-stats {
    gap: 34px;
  }
  .palate-stats span {
    font-size: var(--t-fine);
  }
  .taste-profile .button {
    font-size: var(--t-fine);
    min-height: 43px;
  }
  .structure-panel {
    padding: 15px 4px;
  }
  .structure-panel > .eyebrow {
    font-size: var(--t-fine);
  }
  .structure-row {
    margin-bottom: 25px;
  }
  .palate-bottom {
    margin-top: 20px;
    gap: 18px;
    flex-wrap: wrap;
  }
  .palate-bottom > .mark {
    width: 42px;
    height: 42px;
    margin-inline: -3.5px;
  }
  .palate-bottom h2 {
    font-size: 27px;
  }
  .palate-bottom p {
    font-size: var(--t-fine);
  }
  .palate-bottom > .button {
    margin-top: 5px;
  }
  .toast {
    bottom: 90px;
    font-size: var(--t-fine);
    width: max-content;
    max-width: calc(100vw - 32px);
    padding: 13px 18px;
  }
  dialog {
    max-width: calc(100vw - 20px);
    max-height: calc(100dvh - 32px);
    border-radius: 7px;
  }
  .dialog-padding {
    padding: 45px 25px 30px;
  }
  .dialog-padding > .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.143em;
    margin-bottom: 22px;
  }
  .dialog-padding h2 {
    font-size: 37px;
  }
  .dialog-padding h2 em {
    font-size: 43px;
  }
  .dialog-padding > p:not(.eyebrow) {
    font-size: 12px;
  }
  .dialog-close {
    right: 8px;
    top: 8px;
  }
  .wine-dialog {
    max-width: calc(100vw - 20px);
  }
  .detail-layout {
    grid-template-columns: 1fr;
  }
  .detail-art {
    position: relative;
    height: 295px;
    padding: 22px;
    max-height: none;
  }
  .detail-art .bottle {
    height: 235px;
    width: 135px;
    min-height: 0;
    margin: 0;
  }
  .detail-art > .eyebrow {
    position: absolute;
    left: 20px;
    top: 23px;
    font-size: var(--t-fine);
  }
  .detail-art > .fine-print {
    position: absolute;
    bottom: 16px;
    right: 15px;
    font-size: var(--t-fine);
  }
  .detail-copy {
    padding: 28px 25px;
  }
  .detail-copy h2 {
    font-size: 37px;
  }
  .detail-copy > .eyebrow {
    font-size: var(--t-fine);
  }
  .detail-copy .detail-tags {
    margin-top: 18px;
  }
  .detail-save {
    margin-top: 20px;
  }
  .star-button {
    min-width: 44px;
    min-height: 44px;
  }
  .star-button .icon {
    width: 27px;
    height: 27px;
  }
  .rating-stars > span {
    font-size: var(--t-fine);
  }
  .wide-dialog {
    max-width: calc(100vw - 20px);
  }
  .wide-dialog .wine-grid,
  .dialog-padding .wine-grid {
    gap: 22px 12px;
  }
  .wide-dialog .wine-art {
    height: 215px;
  }
  .wide-dialog .bottle {
    height: 195px;
  }
  .wide-dialog .wine-name {
    font-size: 21px;
  }
  .wide-dialog h2 {
    font-size: 34px;
  }
  .wide-dialog h2 em {
    font-size: 38px;
  }
  .scan-modal {
    max-width: calc(100vw - 20px);
  }
  .upload-zone {
    padding: 23px 15px;
  }
  .upload-zone strong {
    font-size: 12px;
  }
  .upload-zone > span {
    font-size: var(--t-fine);
  }
  .guide section {
    gap: 14px;
  }
  .guide h3 {
    font-size: 24px;
  }
  .guide section p {
    font-size: 12px;
  }
  .skeleton-card > div {
    height: 245px;
  }
}
@media (max-width: 380px) {
  .page-width {
    padding-inline: 19px;
  }
  .site-header {
    padding-inline: 19px;
  }
  .hero h1 {
    font-size: 43px;
    letter-spacing: -2px;
  }
  .hero h1 em {
    letter-spacing: -1.8px;
  }
  .hero-description {
    font-size: var(--t-fine);
  }
  .hero-actions {
    gap: 9px;
  }
  .hero-actions .button {
    font-size: var(--t-fine);
    gap: 8px;
    padding-inline: 12px;
  }
  .hero-actions .button-quiet {
    padding-inline: 0;
  }
  .hero-actions .button .icon {
    width: 14px;
    height: 14px;
  }
  .hero-visual {
    height: 305px;
  }
  .hero-footnote {
    font-size: var(--t-fine);
    gap: 8px;
  }
  .wine-grid {
    gap: 24px 12px;
  }
  .wine-art {
    height: 220px;
  }
  .wine-art .bottle {
    height: 197px;
  }
  .wine-name {
    font-size: 20px;
  }
  .palate-banner {
    margin-inline: 19px;
    padding: 27px 23px;
  }
  .section-heading h2 {
    font-size: 28px;
  }
  .section-heading h2 em {
    font-size: 33px;
  }
  .page-heading h1 {
    font-size: 43px;
  }
  .page-heading h1 em {
    font-size: 47px;
  }
  .chip {
    padding-inline: 10px;
  }
  .site-footer {
    margin-inline: 19px;
  }
  .detail-copy {
    padding-inline: 21px;
  }
  .rating-stars > span {
    display: block;
    margin-left: 0;
  }
  .dialog-padding {
    padding-inline: 21px;
  }
}
@media (prefers-reduced-motion: reduce) {
  *,
  *:before,
  *:after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
  .wine-card:hover .bottle {
    transform: none;
  }
}
@media (prefers-reduced-transparency: reduce) {
  .photo-note,
  .save-button,
  .mobile-nav {
    backdrop-filter: none;
    background: var(--paper);
  }
  dialog::backdrop {
    backdrop-filter: none;
    background: var(--backdrop-solid);
  }
}

/*
 * Forced colours — Windows High Contrast and anything like it.
 *
 * The system throws away every colour in this sheet and paints with four of its own, so
 * each piece of this design that says what it is with a wash and no border arrives as an
 * unbordered rectangle exactly the colour of the page: a category tile, a chip, a card, a
 * bottle. The rules below give those an explicit edge, and hand the pieces that carry
 * meaning in colour — the focus ring, the chosen chip, a filled star, a filled track — a
 * *system* colour, which is the only kind of colour that survives in this mode.
 *
 * What cannot be repaired here is the category dots: five wine colours all become one ink
 * and the difference is gone. That is why the category also has to be in the markup as a
 * word (see .visually-hidden), rather than only in the pixel.
 */
@media (forced-colors: active) {
  /* Surfaces the design draws as a wash: give each one a border it did not need before. */
  .wine-art,
  .detail-art,
  .journal-card,
  .empty-state,
  .palate-banner,
  .hero-stamp,
  .search-form,
  .upload-zone,
  .toast,
  .match-tag,
  .avatar,
  .nav-count,
  .appearance-option,
  .mode-button,
  .kind-switch,
  dialog {
    border: 1px solid CanvasText;
  }
  /* Controls, in the system's button ink. */
  .chip,
  .listing-chip,
  .button,
  .icon-button {
    border: 1px solid ButtonText;
    color: ButtonText;
  }
  /* Chosen, current, selected: all three say so with a wash, and Highlight is the one
     colour a forced palette guarantees for exactly that. */
  .chip.active,
  .mode-button[aria-pressed="true"],
  .appearance-option[aria-pressed="true"],
  .mobile-nav > a[aria-current],
  .desktop-nav > a[aria-current],
  .kind-switch > a[aria-current] {
    background: Highlight;
    color: HighlightText;
    border-color: Highlight;
  }
  .desktop-nav > a[aria-current]:after {
    background: Highlight;
  }
  /* The ring, in the colour the platform uses to say "here". */
  button:focus-visible,
  a:focus-visible,
  input:focus-visible,
  textarea:focus-visible,
  select:focus-visible,
  .upload-zone:focus-within,
  #main:focus-visible {
    outline: 3px solid Highlight;
  }
  /* A star's value is its fill, and that is what has to survive: an empty star keeps its
     stroke and nothing inside it, a chosen one is filled with the page's own ink. */
  .star-button .icon {
    stroke: ButtonText;
    fill: none;
  }
  .star-button.selected .icon {
    fill: ButtonText;
  }
  /* A length of colour is a length of nothing without this. */
  .structure-track {
    border: 1px solid CanvasText;
  }
  .structure-track > span {
    background: CanvasText;
  }
  /* Generated bottle art is a stack of coloured blocks; an outline keeps its silhouette. */
  .wine-art .bottle,
  .detail-art .bottle {
    border: 1px solid CanvasText;
  }
}

/* Keep supporting copy readable at normal zoom on compact displays. */
.eyebrow {
  font-size: var(--t-fine);
}
.desktop-nav {
  font-size: 13px;
}
.hero-description {
  font-size: 14px;
}
.wine-meta {
  font-size: var(--t-fine);
}
.wine-card-info > .eyebrow {
  font-size: var(--t-fine);
}
.wine-type {
  font-size: var(--t-fine);
}
.chip {
  font-size: var(--t-fine);
}
.hero-footnote {
  font-size: var(--t-fine);
}
.intent-strip > :is(a, button) small {
  font-size: var(--t-fine);
}
.discovery-controls > .subtle {
  font-size: var(--t-fine);
}
.photo-index {
  font-size: var(--t-fine);
}
.journal-number {
  font-size: var(--t-fine);
}
.section-heading .eyebrow {
  font-size: var(--t-fine);
}
.fine-print {
  font-size: var(--t-fine);
}
@media (max-width: 700px) {
  .hero .eyebrow,
  .page-heading .eyebrow,
  .section-heading .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.089em;
  }
  .hero-description {
    font-size: 13px;
  }
  .hero-footnote {
    font-size: var(--t-fine);
    line-height: 1.6;
  }
  .hero-footnote strong {
    display: block;
  }
  .wine-card-info > .eyebrow {
    font-size: var(--t-fine);
  }
  .wine-meta {
    font-size: var(--t-fine);
  }
  .wine-type {
    font-size: var(--t-fine);
  }
  .chip {
    font-size: var(--t-fine);
  }
  .photo-index {
    font-size: var(--t-fine);
  }
  .journal-card > span:last-of-type {
    font-size: var(--t-fine);
  }
  .mobile-nav > a {
    font-size: var(--t-fine);
  }
  .dialog-padding > .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.067em;
  }
  .palate-banner .eyebrow {
    font-size: var(--t-fine);
    letter-spacing: 0.087em;
  }
  .palate-banner p:not(.eyebrow) {
    font-size: 12px;
  }
  .collection-summary .collection-storage {
    font-size: var(--t-fine);
  }
  .upload-zone > span {
    font-size: var(--t-fine);
  }
  .dialog-padding .fine-print {
    font-size: var(--t-fine);
  }
}

body { background: var(--paper); background-image: var(--ground-texture); }
body, .site-header, .wine-art, .detail-art, .journal-card,
.palate-banner, .mobile-nav, dialog, .mode-switch, .mode-button {
  transition: background-color .45s ease, color .35s ease, border-color .35s ease;
}
.hero-visual > :is(img, svg) { filter: var(--hero-filter); transition: filter .6s ease; }
.hero-stamp, .palate-banner {
  background: var(--slab);
  background-image: var(--slab-texture);
  background-size: var(--slab-texture-size);
  color: var(--on-slab);
}
.palate-banner .button-light { color: var(--slab-button-ink); background: var(--on-slab); }
/*
 * The layer's texture in forced colours. It is ornament, and a forced palette would draw
 * it as ink: a texture on the page ground (the UA drops a gradient already; this says so),
 * and the ring behind a card's bottle, whose edge — even beer's `transparent` one — comes
 * back as a solid CanvasText line. Whether the ring stays is the layer's
 * (`--art-ring-forced`): wine keeps main's, its tilted ellipse drawn in CanvasText, and
 * beer, which draws none, hides it. This block sits after the rules it undoes, at their
 * specificity.
 */
@media (forced-colors: active) {
  :root,
  body {
    background-image: none;
  }
  .wine-art:after {
    display: var(--art-ring-forced);
  }
}
.photo-note { background: var(--glass); color: var(--ink); }
.hero-description { white-space: pre-line; }
.mood-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-top: 26px;
}
.mood-intro { display: flex; align-items: center; gap: 13px; }
.mood-intro p { margin: 0 0 4px; font-size: 14px; }
.mood-intro em { font: italic 19px var(--serif); }
.mood-intro [data-mode-status] { font-size: var(--t-fine); color: var(--muted); }
.mood-orb {
  width: 31px; height: 31px; flex-shrink: 0; border-radius: 50%;
  background: radial-gradient(circle at 32% 27%, var(--orb-light), var(--orb-deep) var(--orb-stop));
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--orb) 12%, transparent);
}
.mode-switch {
  display: flex; gap: 3px; padding: 4px; border: 1px solid var(--line);
  border-radius: 30px; background: var(--white);
}
.mode-button {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 44px; padding: 9px 14px; border-radius: 30px;
  color: var(--muted); font-size: var(--t-fine);
}
.mode-button .icon { width: 16px; height: 16px; }
.mode-button:hover { background: var(--surface); color: var(--ink); }
.mode-button[aria-pressed="true"] { color: var(--button-text); background: var(--accent); }
.mood-bar + .hero { padding-top: 48px; }
.appearance-toggle { position: relative; border: 1px solid var(--line); }
.appearance-toggle .icon { width: 19px; height: 19px; }
.appearance-options { display: grid; gap: 10px; margin-top: 28px; }
.appearance-option {
  display: flex; align-items: center; gap: 16px; text-align: left;
  padding: 12px 16px 12px 12px; border: 1px solid var(--line);
  border-radius: 12px; background: var(--white);
  transition: border-color .2s, background-color .2s;
}
.appearance-option[aria-pressed="true"] { border-color: var(--accent); background: var(--surface); }
.appearance-option strong { display: block; font-size: 14px; font-weight: 500; }
.appearance-option small { display: block; margin-top: 5px; font-size: var(--t-fine); color: var(--muted); }
.mode-preview {
  display: grid; place-items: center; width: 52px; height: 52px;
  flex-shrink: 0; border-radius: 9px; color: var(--preview-ink);
}
.preview-auto { background: linear-gradient(135deg, var(--preview-auto-from) 50%, var(--preview-auto-to) 50%); }
.preview-morning { background: linear-gradient(135deg, var(--preview-morning-from), var(--preview-morning-to)); }
.preview-evening { background: linear-gradient(135deg, var(--preview-evening-from), var(--preview-evening-to)); }
.preview-dark { background: linear-gradient(135deg, var(--preview-dark-from), var(--preview-dark-to)); color: var(--preview-dark-ink); }
.mode-check { margin-left: auto; color: var(--accent); opacity: 0; width: 19px; flex-shrink: 0; }
[aria-pressed="true"] > .mode-check { opacity: 1; }
.appearance-dialog .appearance-schedule { font-size: var(--t-fine); line-height: 1.8; }
.appearance-dialog .appearance-status { color: var(--accent); font-size: var(--t-fine); }
/*
 * One alpha-preserving sheet per drink: a single cached image for all of its styles, one
 * style to a column. The sheet is described once, in `ART` in public/js/components.js, and
 * bottle() writes its geometry onto each bottle as three tokens (how many columns the
 * sheet has, the aspect of one column, and which column is this style's), so nothing here
 * knows wine's sheet and a row drawn from another drink's sheet can sit in the same list.
 */
.bottle {
  display: block; position: relative; overflow: hidden;
  aspect-ratio: var(--art-aspect); width: auto; flex-shrink: 0;
  filter: drop-shadow(7px 12px 8px var(--shadow-bottle));
}
.bottle > img {
  position: absolute; top: 0; left: calc(var(--art-column) * -100%);
  width: calc(var(--art-columns) * 100%); height: 100%; max-width: none;
}
.detail-art .bottle { width: auto; flex: 0 1 auto; }
/*
 * The can and the shelf (public/js/art-beer.js).
 *
 * One drawing, inline SVG, no colour in it: each part is a class this sheet fills from the
 * tokens the family rule above sets on the nearest `.can-art` — so the can follows the
 * appearance the moment <html> changes, and every colour it wears is one the contrast
 * gate measures. A piece declares its own default before it reads a token, as
 * `.wine-dot` and `.wine-art` do.
 */
.can-art { --can-body: var(--muted); --can-band: var(--ink); --can-cap: var(--surface); }
.bottle > svg { display: block; width: 100%; height: 100%; overflow: visible; }
.can-body { fill: var(--can-body); }
.can-band { fill: var(--can-band); }
.can-ring { fill: none; stroke: var(--can-band); stroke-width: 3; }
.can-rims { fill: none; stroke: var(--ink); stroke-opacity: .28; stroke-width: 1.5; }
.can-lid { fill: var(--can-cap); stroke: var(--ink); stroke-opacity: .5; stroke-width: 1; }
.can-tab { fill: none; stroke: var(--ink); stroke-opacity: .6; stroke-width: 1.6; stroke-linecap: round; }
/* The hero's fridge shelf: six cans on a straw field under a flat sun, a hard rule and a
   floor the colour of the neutral surface. */
.hero-shelf { display: block; width: 100%; height: 100%; }
.shelf-field { fill: var(--tint-3); }
.shelf-sun { fill: var(--orb); }
.shelf-rule { fill: var(--line); }
.shelf-floor { fill: var(--surface); }
/*
 * Beer in forced colours, right after the can and shelf rules above: they undo those at the
 * same specificity, so source order decides. The halftone is ornament and goes; the can
 * names system colours so every engine draws the same silhouette whether or not it forces
 * SVG fill and stroke.
 */
@media (forced-colors: active) {
  .hero-stamp, .palate-banner { background-image: none; }
  .can-body, .can-lid, .shelf-field, .shelf-floor { fill: Canvas; stroke: CanvasText; stroke-opacity: 1; }
  .can-band, .shelf-rule { fill: CanvasText; }
  .can-ring, .can-rims, .can-tab { stroke: CanvasText; stroke-opacity: 1; }
  .shelf-sun { fill: none; stroke: CanvasText; stroke-width: 2; }
}
.wine-art { border-radius: var(--art-radius); }
.wine-art::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(ellipse at 28% 22%, #ffffff30, transparent 70%);
}
.wine-card .bottle { transform: rotate(-5deg); }
.wine-card:nth-child(even) .bottle { transform: rotate(5deg); }
.wine-card:hover .bottle { transform: rotate(0) translateY(-6px); }
.wine-card:focus-within .wine-art { outline: 1px solid var(--accent); outline-offset: 3px; }
.detail-art > .fine-print { text-align: center; line-height: 1.6; color: var(--muted); }
.journal-card { border-radius: 12px; transition: transform .35s var(--ease), background-color .45s; }
.journal-card:hover { transform: translateY(-5px); }
.taste-drawing, .pair-drawing, .label-drawing { color: var(--muted); }
.save-button.is-saved .icon { animation: save-bloom .4s var(--ease); }
.wine-card { animation: card-in .5s var(--ease) both; }
.hero-copy, .page-heading { animation-name: card-in; }
.wine-card:nth-child(2) { animation-delay: .045s; }
.wine-card:nth-child(3) { animation-delay: .09s; }
.wine-card:nth-child(4) { animation-delay: .135s; }
@keyframes card-in { from { transform: translateY(12px); } to { transform: translateY(0); } }
@keyframes save-bloom { 50% { transform: scale(1.22); } }
@media (min-width: 701px) and (max-width: 1100px) {
  .header-actions { gap: 8px; }
  .desktop-nav { gap: 18px; }
}
@media (max-width: 700px) {
  .mood-bar { align-items: stretch; flex-direction: column; gap: 17px; padding-top: 23px; }
  .mood-intro p { font-size: 13px; }
  .mood-intro [data-mode-status] { font-size: var(--t-fine); }
  .mode-switch { align-self: stretch; }
  .mode-button { flex: 1; padding: 8px 6px; min-height: 44px; font-size: var(--t-fine); }
  .mood-bar + .hero { padding-top: 35px; }
  /* On a phone the sun shrinks to 36px so the header still reads as a header beside the
     wordmark — the same trade the account disc makes. And like the account disc, the ink
     is what shrinks: the box a thumb has to find stays 44px. (-5px, not -4px: the toggle
     has a 1px border that its padding box, which `inset` is measured from, sits inside.) */
  .appearance-toggle { width: 36px; height: 36px; }
  .appearance-toggle:before { content: ""; position: absolute; inset: -5px; }
  .header-actions { gap: 9px; }
  .appearance-option { gap: 12px; }
  .appearance-option small { font-size: var(--t-fine); }
}
@media (prefers-reduced-motion: reduce) {
  .wine-card .bottle, .wine-card:nth-child(even) .bottle,
  .wine-card:hover .bottle, .journal-card:hover { transform: none; }
}

/* ── Provenance, shipping and bottle details (wave 2a-D) ──
 *
 * Where a bottle is sold, what it cost when we last looked, and the bottles a reader
 * keeps. Everything here is quieter than the wine it sits beside: a shop badge is a fact
 * about a listing, not a call to action, and the province picker is a preference rather
 * than a filter most readers want. Tokens only — a hex here is a pixel no appearance can
 * reach.
 */

/* The shop badge under a card's price. */
.wine-shops {
  margin-top: 7px;
  font-size: var(--t-fine);
  line-height: 1.6;
  color: var(--muted);
  /* Two shops fit on one line; a wine sold by five used to lose the rest of them. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
}
.wine-shops .ships-flag {
  color: var(--accent);
}

/* Explore: buying from, and the opt-in filter beside it. */
/* Same arithmetic as `.chips`: "Only what ships to me" is a chip, it wraps under the
   province picker on a phone, and 10px between rows left 2px of the boundary to it. */
.ship-tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px 14px;
  margin-top: 18px;
}
.ship-picker {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  border: 1px solid var(--line);
  border-radius: 30px;
  min-height: 35px;
  padding: 0 14px;
  color: var(--muted);
}
.ship-picker > .eyebrow {
  font-size: var(--t-fine);
}
.ship-picker select {
  background: none;
  border: 0;
  color: var(--ink);
  font-size: var(--t-fine);
  max-width: 170px;
  padding: 9px 0;
  min-height: 44px;
}
.ship-toggle:disabled {
  cursor: default;
}
.ship-caption {
  flex: 1 1 240px;
  min-width: 0;
  font-size: var(--t-fine);
}

/* The wine dialog: where to buy. */
.buy-block {
  margin: 24px 0 4px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
.buy-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.buy-head > .eyebrow {
  color: var(--muted);
}
.buy-head > .subtle {
  font-size: var(--t-fine);
}
.buy-list {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--line);
}
.listing {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
}
a.listing:hover {
  color: var(--accent);
}
.listing > .icon {
  width: 15px;
  height: 15px;
  margin-top: 3px;
  color: var(--muted);
}
.listing.is-gone {
  opacity: 0.72;
}
.listing-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}
.listing-shop {
  font-size: 12px;
}
.listing-place,
.listing-seen,
.listing-extra,
.listing-nothing,
.listing-note {
  font-size: var(--t-fine);
  color: var(--muted);
}
.listing-state {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
/* Its own name rather than a shared `.status-chip`: the tasting night declares one of
 * those in its own stylesheet, and two files reaching for the same class is how a chip
 * changes colour because somebody restyled a different screen. */
.listing-chip {
  display: inline-flex;
  align-items: center;
  border-radius: 20px;
  padding: 4px 9px;
  font: var(--t-fine) var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--surface);
  color: var(--muted);
}
.listing-chip.is-stocked,
.listing-chip.is-ship {
  color: var(--accent);
}
.listing-price {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  text-align: right;
  white-space: nowrap;
}
.listing-amount {
  font-size: 13px;
}

/* The wine dialog: the bottles a reader keeps. */
.bottle-details {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
.bottle-details > .eyebrow {
  color: var(--muted);
  margin-bottom: 14px;
}
.bottle-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px 16px;
  font-size: 12px;
  margin-bottom: 14px;
}
.stepper {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--line);
  border-radius: 30px;
  padding: 2px;
}
.stepper .icon-button {
  width: 33px;
  height: 33px;
  font-size: 15px;
  line-height: 1;
}
.stepper output {
  min-width: 34px;
  text-align: center;
  font: 13px/1 var(--mono);
}
.bottle-field .years {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: var(--t-fine);
  color: var(--muted);
}
.bottle-field input[type="number"] {
  width: 82px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 9px 10px;
  color: var(--ink);
  font: 12px/1.4 var(--mono);
}
.bottle-details .chips {
  gap: 7px;
}
.bottle-details > .text-link {
  margin-top: 4px;
  font-size: var(--t-fine);
}

@media (max-width: 700px) {
  .ship-tools {
    gap: 9px 10px;
  }
  .ship-picker select {
    max-width: 132px;
  }
  .ship-caption {
    flex-basis: 100%;
  }
  .buy-block {
    margin-top: 20px;
  }
  .listing {
    gap: 10px;
  }
  .bottle-field {
    align-items: flex-start;
    flex-direction: column;
    gap: 8px;
  }
}

/* ── Sign-in doors and account (wave 2b-C) ──
 *
 * Three ways in, drawn as one column: the email form the dialog already styles, a quiet
 * line under it for the code, and — only where it can actually work — a passkey below a
 * rule. The order is the rule. Email is first and unconditional, and everything here is
 * lighter than it: a shortcut that shouts starts to look like the way in. Tokens only, so
 * all three appearances reach every pixel of it.
 */

/* The line that swaps one email door for the other. */
.auth-switch {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
  margin-top: 14px;
}
.auth-switch > .text-link {
  font-size: var(--t-fine);
}

/* Six digits, spaced so they read as digits rather than as a word. */
.code-field {
  width: 100%;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 14px;
  color: var(--ink);
  font: 20px/1.3 var(--mono);
  letter-spacing: 8px;
  text-indent: 8px;
}
.code-field::placeholder {
  color: var(--line);
  letter-spacing: 8px;
}

/* The passkey door, and the rule that keeps it below the email one. */
.auth-passkey > .button {
  width: 100%;
}
.auth-or {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 22px 0 16px;
  color: var(--muted);
  font: var(--t-fine)/1.5 var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.auth-or::before,
.auth-or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}
.auth-note:not(:empty) {
  margin-top: 12px;
  color: var(--accent);
  font-size: 12px;
  line-height: 1.6;
}
/*
 * A live region draws nothing until it has something to say.
 *
 * Every door on the sign-in dialog carries two of these — a `role="status"` and a
 * `role="alert"`, both there from the moment the door is drawn, because a region whose
 * politeness is decided in the same task as its sentence is a region a screen reader may
 * never announce (see `setStatus` in dialogs/account.js). Only one of the pair ever holds
 * words; the other is an empty paragraph that must not take a line of the layout with it.
 */
.auth-line:empty {
  display: none;
}
/* The same idea inside the account: "Waiting for your device…" is written into a line
   that was already there, rather than into markup drawn at the same moment. It is also
   where focus is parked while the platform's own prompt is up — `tabindex="-1"` in the
   markup, and a paragraph, so the ring above (buttons, links and fields only) leaves it
   alone without anyone having to write `outline: none`. */
.passkey-busy:not(:empty) {
  margin-top: 14px;
  color: var(--muted);
}

/* The passkeys on an account, inside the signed-in dialog. */
.passkey-card {
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}
.passkey-card > .eyebrow {
  color: var(--muted);
}
.passkey-lead {
  margin-top: 12px;
  font-size: 13px;
  line-height: 1.65;
  color: var(--muted);
}
.passkey-list {
  list-style: none;
  padding-left: 0;
  margin-top: 16px;
}
.passkey-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
}
.passkey-name {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  font-size: 13px;
}
.passkey-card > .button {
  width: 100%;
  margin-top: 18px;
}
.passkey-card > .fine-print {
  margin-top: 14px;
}

/* What the account has agreed to. A native checkbox, because a consent is the one control
   whose meaning has to survive every browser, screen reader and forced-colours mode
   unchanged; only its colour is ours. The whole label is the target. The second selector
   outranks `.dialog-padding form label`, which the day-one question sits inside. */
.consent-row,
.dialog-padding form .consent-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 16px 0 0;
  font-size: 13px;
  line-height: 1.5;
  cursor: pointer;
}
.consent-row > input {
  flex: none;
  width: 18px;
  height: 18px;
  margin: 1px 0 0;
  accent-color: var(--accent);
}
.consent-card #consent-body > .fine-print,
.consent-ask > .fine-print {
  margin-top: 10px;
}
/* The same question, asked once when an account is made (account.js, `askConsent`). */
.consent-ask {
  margin-top: 8px;
}
.consent-ask > .button {
  margin-top: 22px;
}
/* "What do you call it?" (account.js, `placeCard`): a card like the two above it, with a
   field for each served kind. The field is drawn like the email field. Its default name
   is the placeholder, in `--muted`, so an empty field reads as "ours". A second kind's
   field sits one step below the first. The form is closer to its lead than a sign-in
   form is to its heading, because the lead is what explains the field. */
.dialog-padding .place-form {
  margin-top: 16px;
}
.place-form input + label {
  margin-top: 18px;
}

@media (max-width: 700px) {
  .auth-switch {
    gap: 4px 16px;
  }
  .code-field {
    font-size: 18px;
    letter-spacing: 6px;
  }
  .passkey-card {
    margin-top: 26px;
  }
  .passkey-row {
    align-items: flex-start;
  }
}

/* ---------------------------------------------------------------------------
   The dish on Discover: a card's pairing line, and the dinner step's own rows.

   The pairing tag follows .match-tag's shape — the glass ground, wine ink, a 20px
   radius — but sits in the card's copy rather than over the art, because the two are
   different facts: the badge says how the wine and the reader get on, the tag how the
   wine and the dish do (docs/pairing/formula.md §5). Three levels, three surfaces the
   palettes already define, so every appearance paints it without a hex of its own:
   "natural" wears the wine, "good" the gold surface, "fair" nothing but a line.
   --------------------------------------------------------------------------- */
.pairing-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  margin-top: 6px;
  font-size: var(--t-fine);
  line-height: 1.5;
  color: var(--muted);
}
.pairing-tag {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 4px 9px;
  font: var(--t-fine)/1.3 var(--mono);
  letter-spacing: 0.067em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--glass);
}
.pairing-tag.natural {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--button-text);
}
.pairing-tag.good {
  background: var(--tint-3);
  border-color: var(--tint-3);
  color: var(--accent);
}
.pairing-tag.fair {
  background: transparent;
  color: var(--muted);
}

/* The dish step: a label over its own search shell, which is one row of the panel's grid
   like the grape field, so it drops the shell's bottom margin the same way. */
.finder-field-label {
  display: block;
  font-size: var(--t-fine);
  line-height: 1.5;
  color: var(--muted);
  margin-bottom: -6px;
}
/* The described dish, as the server read it back: "Fried potatoes, with added cheese". */
.finder-running {
  font: 17px/1.35 var(--serif);
  letter-spacing: -0.2px;
  color: var(--ink);
}
/* The six anchors: an attribute's name, its five stops, and the Guide's phrase beneath. */
.finder-adjust {
  display: grid;
  gap: 18px;
}
.finder-adjust-row {
  display: grid;
  gap: 8px;
}
.finder-adjust-row > .eyebrow {
  color: var(--muted);
}
.finder-adjust-row > .fine-print {
  margin: 0;
}
.finder-panel .chip:disabled {
  opacity: 0.45;
  cursor: default;
}

@media (max-width: 700px) {
  .pairing-line {
    font-size: var(--t-fine);
  }
  .pairing-tag {
    font-size: var(--t-fine);
    padding: 3px 8px;
  }
  .finder-running {
    font-size: 15px;
  }
  .finder-adjust {
    gap: 14px;
  }
}

/* "How did it taste?" — the slot under the stars in the wine dialog (dialogs/taste.js).
   A question with five stops is `.scale-row`: the finder's anchors row, made neutral so
   a second caller does not have to pretend to be a finder. */
.scale-row {
  display: grid;
  gap: 8px;
}
.scale-row > .eyebrow {
  color: var(--muted);
}
.scale-row > .fine-print {
  margin: 0;
  /* One line is held open whether or not a stop is pressed, so choosing one does not
     shove the rest of the step down under the reader's thumb. */
  min-height: 1.65em;
}
.taste-slot {
  margin: 0 0 26px;
}
.taste-slot .chip {
  min-height: 44px;
  white-space: normal;
}
.taste-slot .chip:disabled,
.family-tile:disabled {
  opacity: 0.45;
  cursor: default;
}
.taste-quiet {
  margin: -8px 0 0;
}
.taste-card,
.taste-step {
  display: grid;
  gap: 14px;
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--white);
}
.taste-card > .eyebrow,
.taste-step > .eyebrow {
  color: var(--muted);
}
.taste-card p,
.taste-step p {
  margin: 0;
  font-size: var(--t-small);
  line-height: 1.65;
}
.taste-step h3 {
  font: 24px/1.2 var(--serif);
  letter-spacing: -0.5px;
}
.taste-how strong {
  font-weight: 500;
}
.taste-hint {
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.taste-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
  margin-top: 4px;
}
/* Every row already ends in the line held open for its caption, which is the gap. */
.taste-rows {
  display: grid;
  gap: 4px;
}
.taste-flavours-head {
  color: var(--muted);
  margin-top: 6px;
}
.taste-summary,
.taste-examples {
  display: grid;
  gap: 8px 20px;
  margin: 0;
  font-size: var(--t-small);
}
.taste-summary {
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.taste-examples {
  grid-template-columns: 1fr 1fr;
}
.taste-summary dt,
.taste-examples dt {
  font: var(--t-fine)/1.5 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
.taste-summary dd,
.taste-examples dd {
  margin: 2px 0 0;
  line-height: 1.5;
}
.taste-card .detail-tags {
  margin-top: 0;
}
.family-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.family {
  display: grid;
  gap: 10px;
  align-content: start;
}
/* A family that is open takes the row, so its notes have the width to wrap in. */
.family:has(> .taste-notes) {
  grid-column: 1 / -1;
}
.family-tile {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 56px;
  padding: 10px 14px;
  text-align: left;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper);
  color: var(--ink);
  transition:
    border-color 0.2s,
    background 0.2s;
}
.family-tile:hover:not(:disabled) {
  border-color: var(--accent);
}
.family-tile.active {
  border-color: var(--accent);
  background: var(--tint-1);
}
.family-tile strong {
  display: block;
  font-size: var(--t-small);
  font-weight: 500;
}
.family-tile small {
  display: block;
  font-size: var(--t-fine);
  line-height: 1.45;
  color: var(--muted);
}
.family-dot {
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
}
.taste-notes {
  padding: 0 2px 8px;
}
/* My palate: what each bar is built from, the flavours the reader keeps finding, and the
   rated bottles still waiting to be described. */
.structure-source {
  font-size: var(--t-fine);
  line-height: 1.5;
  color: var(--muted);
  margin-top: 6px;
}
.palate-families {
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
}
.palate-families > .detail-tags {
  margin-top: 14px;
}
.palate-families > .fine-print {
  font-size: var(--t-fine);
  margin-top: 12px;
}
.palate-invite {
  margin-top: 48px;
  padding: 26px;
  border-radius: 14px;
  background: var(--tint-2);
  display: grid;
  gap: 10px;
}
.palate-invite h3 {
  font: 24px/1.2 var(--serif);
  letter-spacing: -0.5px;
}
.palate-invite p:not(.eyebrow) {
  font-size: var(--t-small);
  line-height: 1.65;
  color: var(--muted);
  max-width: 520px;
}
.palate-invite-list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 26px;
  margin-top: 6px;
}
@media (max-width: 700px) {
  .taste-card,
  .taste-step {
    padding: 16px;
  }
  .taste-step h3 {
    font-size: 21px;
  }
  .family-grid,
  .taste-examples {
    grid-template-columns: 1fr;
  }
}

/*
 * Editorial photographs.
 *
 * Discover's palate banner and its three journal cards can each carry a photograph, and
 * `public/js/plates.js` is the one place that says which photographs exist. Every rule
 * below is written against `[data-plate]`, which nothing carries until a file has been
 * made and named there, so this whole section is dormant in a build with no photographs
 * and those surfaces render exactly as they did before it was written. The hero needs no
 * rule at all: its slot is one full-bleed image either way, so a photograph lands in the
 * geometry the still life already had.
 *
 * The idea underneath is that a photograph never has to carry the words. Each slot keeps
 * its own ground — the banner's wine, the card's tint — as opaque paint exactly where the
 * copy sits, and clears it toward the part of the frame that the prompts in
 * `docs/ui/appearance-design.md` reserve for the picture. So the contrast behind every
 * line of type is the same contrast test/contrast.test.js measures for a slot with no
 * photograph in it, whatever the photograph turns out to look like — an image that comes
 * back brighter or busier than expected changes the art, never the legibility. The
 * feathered edge is the only place the two meet, and nothing is read there.
 *
 * Stacking is explicit rather than left to tree order: the photograph is 0, the ground
 * laid over it is 1, and anything with words in it is above both.
 */
.palate-banner[data-plate],
.journal-card[data-plate] {
  --plate-panel: 300px;
}
.palate-banner[data-plate] > .plate-photo,
.journal-card[data-plate] > .plate-photo {
  position: absolute;
  z-index: 0;
  object-fit: cover;
}
.palate-banner[data-plate]::before,
.journal-card[data-plate]::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}
/*
 * The ornament a photograph stands in for; the two are never on screen together.
 *
 * The banner's fleuron is *hidden rather than removed* because it is a grid item: take it
 * out of the flow and the copy slides into the column the picture is standing in, which
 * is the one way this can go wrong. The card's drawing is already out of the flow, so it
 * can simply go.
 */
.palate-banner[data-plate] > .palate-mark {
  visibility: hidden;
}
.journal-card[data-plate] > .journal-drawing {
  display: none;
}

/*
 * The banner: a photograph bled into the left edge, the wine ground carrying the copy.
 *
 * The fleuron's column becomes the picture's, widened to `--plate-panel` and stripped of
 * the padding that kept it off the edge. The copy column begins one 40px gap past that
 * panel, and the ground is solid from the panel's edge rightward, so every word sits on
 * the same wine it always did.
 */
.palate-banner[data-plate] {
  grid-template-columns: var(--plate-panel) 1fr auto;
  padding-left: 0;
}
.palate-banner[data-plate] > .plate-photo {
  inset: 0 auto 0 0;
  width: var(--plate-panel);
  height: 100%;
  object-position: 58% center;
}
.palate-banner[data-plate]::before {
  background: linear-gradient(
    90deg,
    transparent calc(var(--plate-panel) - 96px),
    var(--slab) var(--plate-panel)
  );
}
/*
 * Everything with words in it sits above the ground. The fleuron is left out on purpose:
 * it is positioned differently at every width — a grid item holding the picture's column
 * on a desktop, out of the flow entirely on a phone — and giving it a position here made
 * a hidden 235px row on the phone that pushed the copy down the banner.
 */
.palate-banner[data-plate] > div:not(.palate-mark) {
  position: relative;
  z-index: 2;
}

/*
 * A journal card: the words at the top on the card's own tint, the picture beneath them.
 *
 * The tint is opaque down to 58% of the card, which is below the last line of type at
 * every width, and gone by the bottom edge. The card grows to make room for the picture;
 * a card with no photograph keeps the height it has always had.
 */
.journal-card[data-plate] {
  --card-ground: var(--surface);
  min-height: 320px;
}
.journal-card[data-plate]:nth-child(2) {
  --card-ground: var(--tint-1);
}
.journal-card[data-plate]:nth-child(3) {
  --card-ground: var(--tint-2);
}
.journal-card[data-plate] > .plate-photo {
  inset: 0;
  width: 100%;
  height: 100%;
  object-position: center 42%;
}
.journal-card[data-plate]::before {
  background: linear-gradient(
    180deg,
    var(--card-ground) 0%,
    var(--card-ground) 58%,
    color-mix(in srgb, var(--card-ground) 42%, transparent) 79%,
    transparent 100%
  );
}

@media (min-width: 701px) and (max-width: 960px) {
  /* The banner loses 400px of its width here and the panel would start crowding the
     copy, so the picture narrows with it. */
  .palate-banner[data-plate] {
    --plate-panel: 220px;
  }
}

@media (max-width: 700px) {
  /* A phone has no room for a panel beside the copy, so the picture becomes a band above
     it and the ground starts where the band ends. */
  .palate-banner[data-plate] {
    grid-template-columns: 1fr;
    padding: 200px 27px 30px;
  }
  .palate-banner[data-plate] > .plate-photo {
    inset: 0 0 auto 0;
    width: 100%;
    height: 190px;
    object-position: center 45%;
  }
  .palate-banner[data-plate]::before {
    background: linear-gradient(180deg, transparent 104px, var(--slab) 190px);
  }
}

@media (forced-colors: active) {
  /*
   * The system repaints backgrounds and type in four colours of its own but leaves an
   * <img> alone, which would put forced text over an untouched photograph. Each slot
   * gives its photograph up here and takes its ornament back instead.
   */
  .plate-photo {
    display: none;
  }
  .palate-banner[data-plate] > .palate-mark {
    visibility: visible;
  }
  .journal-card[data-plate] > .journal-drawing {
    display: block;
  }
  /* The fleuron takes the panel the picture was holding, centred in it. */
  .palate-banner[data-plate] > .palate-mark {
    justify-self: center;
  }
}

@media (forced-colors: active) and (max-width: 700px) {
  /* The phone band is gone with the photograph, so the copy takes the padding back —
     the same 30px 27px the banner has on a phone with no photograph in it. */
  .palate-banner[data-plate] {
    padding: 30px 27px;
  }
}
